1 /* vi: set sw=4 ts=4:
2  *
3  * Copyright (C) 2001 - 2020 Christian Hohnstaedt.
4  *
5  * All rights reserved.
6  */
7 
8 
9 #include "pki_x509.h"
10 #include "pki_x509req.h"
11 #include "pki_evp.h"
12 #include "pki_scard.h"
13 #include "pki_crl.h"
14 #include "db_base.h"
15 #include "func.h"
16 #include "base.h"
17 #include "exception.h"
18 #include "pass_info.h"
19 #include "openssl_compat.h"
20 #include "widgets/XcaWarning.h"
21 
pki_x509(X509 * c)22 pki_x509::pki_x509(X509 *c)
23 	:pki_x509super()
24 {
25 	init();
26 	cert = c;
27 	pki_openssl_error();
28 }
29 
pki_x509(const pki_x509 * crt)30 pki_x509::pki_x509(const pki_x509 *crt)
31 	:pki_x509super(crt)
32 {
33 	init();
34 	cert = X509_dup(crt->cert);
35 	pki_openssl_error();
36 	issuerSqlId = crt->issuerSqlId;
37 	setRefKey(crt->getRefKey());
38 	caTemplateSqlId = crt->caTemplateSqlId;
39 	revocation = crt->revocation;
40 	crlDays = crt->crlDays;
41 	crlExpire = crt->crlExpire;
42 	pki_openssl_error();
43 }
44 
pki_x509(const QString & name)45 pki_x509::pki_x509(const QString &name)
46 	:pki_x509super(name)
47 {
48 	init();
49 	cert = X509_new();
50 	X509_set_version(cert, 2);
51 	pki_openssl_error();
52 }
53 
getMsg(msg_type msg) const54 QString pki_x509::getMsg(msg_type msg) const
55 {
56 	/*
57 	 * We do not construct english sentences from fragments
58 	 * to allow proper translations.
59 	 * The drawback are all the slightly different duplicated messages
60 	 *
61 	 * %1 will be replaced by the internal name of the certificate
62 	 */
63 	switch (msg) {
64 	case msg_import: return tr("Successfully imported the certificate '%1'");
65 	case msg_delete: return tr("Delete the certificate '%1'?");
66 	case msg_create: return tr("Successfully created the certificate '%1'");
67 	/* %1: Number of certs; %2: list of cert names */
68 	case msg_delete_multi: return tr("Delete the %1 certificates: %2?");
69 	}
70 	return pki_base::getMsg(msg);
71 }
72 
resetX509ReqCount() const73 void pki_x509::resetX509ReqCount() const
74 {
75 	QList<pki_x509req *> reqs = Store.sqlSELECTpki<pki_x509req>(
76 		"SELECT item FROM x509super LEFT JOIN items ON items.id = x509super.item "
77 		"WHERE key_hash=? AND items.type=?",
78 		QList<QVariant>() << QVariant(pubHash()) << QVariant(x509_req));
79 
80 	foreach(pki_x509req *req, reqs)
81 		req->resetX509count();
82 }
83 
insertSqlData()84 QSqlError pki_x509::insertSqlData()
85 {
86 	XSqlQuery q;
87 	a1time now;
88 	pki_x509 *signer = findIssuer();
89 	QSqlError e = pki_x509super::insertSqlData();
90 	if (e.isValid())
91 		return e;
92 
93 	SQL_PREPARE(q, "INSERT INTO certs (item, hash, iss_hash, serial, issuer, "
94 				"ca, cert) "
95 		  "VALUES (?, ?, ?, ?, ?, ?, ?)");
96 	q.bindValue(0, sqlItemId);
97 	q.bindValue(1, hash());
98 	q.bindValue(2, getIssuerName().hashNum());
99 	q.bindValue(3, getSerial().toHex());
100 	q.bindValue(4, signer ? signer->getSqlItemId() : QVariant());
101 	q.bindValue(5, (int)isCA());
102 	q.bindValue(6, i2d_b64());
103 	q.exec();
104 
105 	resetX509ReqCount();
106 
107 	if (!isCA())
108 		return q.lastError();
109 
110 	SQL_PREPARE(q, "INSERT INTO authority (item, template, crlExpire, crlNo, crlDays) "
111 			"VALUES (?, ?, ?, 0, ?)");
112 	q.bindValue(0, sqlItemId);
113 	q.bindValue(1, caTemplateSqlId);
114 	q.bindValue(2, crlExpire.toPlain());
115 	q.bindValue(3, crlDays);
116 	q.exec();
117 	if (fromDataRevList.size() > 0)
118 		fromDataRevList.sqlUpdate(sqlItemId);
119 	return q.lastError();
120 }
121 
restoreSql(const QSqlRecord & rec)122 void pki_x509::restoreSql(const QSqlRecord &rec)
123 {
124 	pki_x509super::restoreSql(rec);
125 	QByteArray ba = QByteArray::fromBase64(
126 				rec.value(VIEW_x509_cert).toByteArray());
127 	d2i(ba);
128 	issuerSqlId = rec.value(VIEW_x509_issuer);
129 	crlNumber.set(rec.value(VIEW_x509_auth_crlNo).toUInt());
130 	crlExpire.fromPlain(rec.value(VIEW_x509_auth_crlExpire).toString());
131 	caTemplateSqlId = rec.value(VIEW_x509_auth_template);
132 	if (!rec.isNull(VIEW_x509_auth_crlDays))
133 		crlDays = rec.value(VIEW_x509_auth_crlDays).toInt();
134 	else
135 		crlDays = 30;
136 	if (!rec.isNull(VIEW_x509_revocation))
137 		revocation = x509rev(rec, VIEW_x509_revocation);
138 }
139 
deleteSqlData()140 QSqlError pki_x509::deleteSqlData()
141 {
142 	XSqlQuery q;
143 	QSqlError e = pki_x509super::deleteSqlData();
144 	QStringList tasks; tasks
145 		<< "DELETE FROM certs WHERE item=?"
146 		<< "DELETE FROM authority WHERE item=?"
147 		<< "UPDATE crls SET issuer=NULL WHERE issuer=?"
148 		<< "UPDATE certs SET issuer=NULL WHERE issuer=?"
149 		<< "DELETE FROM revocations WHERE caId=?"
150 		;
151 	foreach(QString task, tasks) {
152 		SQL_PREPARE(q, task);
153 		q.bindValue(0, sqlItemId);
154 		q.exec();
155 		e = q.lastError();
156 		if (e.isValid())
157 			return e;
158 	}
159 	// Select affected items
160 	q = Store.sqlSELECTpki(
161 		"SELECT DISTINCT items.id FROM items, certs, crls "
162 		"WHERE (items.id = certs.item OR items.id = crls.item) "
163 		"AND crls.issuer = ? AND certs.issuer = ?",
164 		QList<QVariant>() << QVariant(sqlItemId)
165 				  << QVariant(sqlItemId));
166 
167 	while (q.next())
168 		AffectedItems(q.value(0));
169 
170 	resetX509ReqCount();
171 	return q.lastError();
172 }
173 
findIssuer()174 pki_x509 *pki_x509::findIssuer()
175 {
176 	XSqlQuery q;
177 	pki_x509 *issuer;
178 	unsigned hash;
179 
180 	if ((issuer = getSigner()) != NULL)
181 		return issuer;
182 	// first check for self-signed
183 	if (verify(this))
184 		return this;
185 
186 	hash = getIssuerName().hashNum();
187 	/* Select X509 CA certificates with subject-hash == hash */
188 	SQL_PREPARE(q, "SELECT x509super.item from x509super "
189 		"JOIN certs ON certs.item = x509super.item "
190 		"WHERE certs.ca=1 AND x509super.subj_hash=?");
191 	q.bindValue(0, hash);
192 	q.exec();
193 	while (q.next()) {
194 		issuer = Store.lookupPki<pki_x509>(q.value(0));
195 		if (!issuer) {
196 			qDebug("Certificate with id %d not found",
197                                 q.value(0).toInt());
198 		}
199 		if (verify(issuer)) {
200 			return issuer;
201 		}
202 	}
203 	return NULL;
204 }
205 
fromPEM_BIO(BIO * bio,const QString & fname)206 void pki_x509::fromPEM_BIO(BIO *bio, const QString &fname)
207 {
208 	X509 *_cert;
209 	_cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
210 	openssl_error(fname);
211 	X509_free(cert);
212 	cert = _cert;
213 }
214 
fload(const QString & fname)215 void pki_x509::fload(const QString &fname)
216 {
217 	X509 *_cert;
218 	XFile file(fname);
219 	file.open_read();
220 	_cert = PEM_read_X509(file.fp(), NULL, NULL, NULL);
221 	if (!_cert) {
222 		pki_ign_openssl_error();
223 		file.retry_read();
224 		_cert = d2i_X509_fp(file.fp(), NULL);
225 	}
226 	if (pki_ign_openssl_error() || !_cert) {
227 		if (_cert)
228 			X509_free(_cert);
229 		throw errorEx(tr("Unable to load the certificate in file %1. Tried PEM and DER certificate.").arg(fname));
230 	}
231 	X509_free(cert);
232 	cert = _cert;
233 }
234 
~pki_x509()235 pki_x509::~pki_x509()
236 {
237 	if (cert) {
238 		X509_free(cert);
239 	}
240 	pki_openssl_error();
241 }
242 
init()243 void pki_x509::init()
244 {
245 	caTemplateSqlId = QVariant();
246 	crlDays = 30;
247 	crlExpire.setUndefined();
248 	cert = NULL;
249 	pkiType = x509;
250 }
251 
setSerial(const a1int & serial)252 void pki_x509::setSerial(const a1int &serial)
253 {
254 	X509_set_serialNumber(cert, serial.get());
255 	pki_openssl_error();
256 }
257 
getSerial() const258 a1int pki_x509::getSerial() const
259 {
260 	a1int a(X509_get_serialNumber(cert));
261 	pki_openssl_error();
262 	return a;
263 }
264 
getBySerial(const a1int & a) const265 pki_x509 *pki_x509::getBySerial(const a1int &a) const
266 {
267 	foreach(pki_base *p, childItems) {
268 		pki_x509 *pki = static_cast<pki_x509 *>(p);
269 		if (a == pki->getSerial())
270 			return pki;
271 	}
272 	return NULL;
273 }
274 
hashInfo(const EVP_MD * md) const275 a1int pki_x509::hashInfo(const EVP_MD *md) const
276 {
277 	unsigned char digest[EVP_MAX_MD_SIZE];
278 	unsigned len = 0;
279 
280 	if (!X509_digest(cert, md, digest, &len))
281 		pki_openssl_error();
282 	a1int a;
283 	a.setRaw(digest,len);
284 	return a;
285 }
286 
load_token(pkcs11 & p11,CK_OBJECT_HANDLE object)287 void pki_x509::load_token(pkcs11 &p11, CK_OBJECT_HANDLE object)
288 {
289 	QString desc;
290 
291 	pk11_attr_ulong type(CKA_CERTIFICATE_TYPE);
292 	p11.loadAttribute(type, object);
293 	if (type.getValue() != CKC_X_509)
294 		throw errorEx(QString("Unsupported Certificate type %1"
295 			).arg(type.getValue()));
296 
297 	try {
298 		pk11_attr_data label(CKA_LABEL);
299 		p11.loadAttribute(label, object);
300 		desc = label.getText();
301 	} catch(errorEx &err) {
302 		qDebug("No Cert Label: %s", err.getCString());
303 		// IGNORE
304 	}
305 	pk11_attr_data x509(CKA_VALUE);
306 	p11.loadAttribute(x509, object);
307 	QByteArray der = x509.getData();
308 	d2i(der);
309 
310 	if (desc.isEmpty()) {
311 		try {
312 			x509name xn;
313 
314 			pk11_attr_data subj(CKA_SUBJECT);
315 			p11.loadAttribute(subj, object);
316 			QByteArray der = subj.getData();
317 			xn.d2i(der);
318 			desc = xn.getMostPopular();
319 			pki_openssl_error();
320 		} catch(errorEx &err) {
321 			qDebug("No Cert Subject: %s", err.getCString());
322 			// IGNORE
323 		}
324 	}
325 	setIntName(desc);
326 	pkiSource = token;
327 	pki_openssl_error();
328 }
329 
d2i(QByteArray & ba)330 void pki_x509::d2i(QByteArray &ba)
331 {
332         X509 *c = (X509*)d2i_bytearray(D2I_VOID(d2i_X509), ba);
333 	if (c) {
334 		X509_free(cert);
335 		cert = c;
336 	}
337 	pki_openssl_error();
338 }
339 
i2d() const340 QByteArray pki_x509::i2d() const
341 {
342 	return i2d_bytearray(I2D_VOID(i2d_X509), cert);
343 }
344 
store_token(bool alwaysSelect)345 void pki_x509::store_token(bool alwaysSelect)
346 {
347 	pki_scard *card = NULL;
348 	slotid slot;
349 	x509name xname;
350 	QList<CK_OBJECT_HANDLE> objects;
351 
352 	pkcs11 p11;
353 
354 	pki_key *privkey = getRefKey();
355 	if (!privkey || !privkey->isToken() || alwaysSelect) {
356 		if (!p11.selectToken(&slot, NULL))
357 			return;
358 	} else {
359 		card = dynamic_cast<pki_scard *>(privkey);
360 		if (!card || !card->prepare_card(&slot))
361 			return;
362 	}
363 
364 	pk11_attlist p11_atts;
365 	p11_atts <<
366 		pk11_attr_ulong(CKA_CLASS, CKO_CERTIFICATE) <<
367 		pk11_attr_ulong(CKA_CERTIFICATE_TYPE, CKC_X_509) <<
368 		pk11_attr_data(CKA_VALUE, i2d());
369 
370 	p11.startSession(slot, true);
371 
372 	QList<CK_OBJECT_HANDLE> objs = p11.objectList(p11_atts);
373 	if (objs.count() != 0) {
374 		XCA_WARN(tr("This certificate is already on the security token"));
375 		return;
376 	}
377 
378 	p11_atts <<
379 		pk11_attr_bool(CKA_TOKEN, true) <<
380 		pk11_attr_bool(CKA_PRIVATE, false) <<
381 		pk11_attr_data(CKA_SUBJECT, getSubject().i2d()) <<
382 		pk11_attr_data(CKA_ISSUER, getIssuerName().i2d()) <<
383 		pk11_attr_data(CKA_SERIAL_NUMBER, getSerial().i2d()) <<
384 		pk11_attr_data(CKA_LABEL, desc.toUtf8()) <<
385 		(card ? card->getIdAttr() : p11.findUniqueID(CKO_CERTIFICATE));
386 
387 	if (p11.tokenLogin(p11.tokenInfo().label(), false).isNull())
388 		return;
389 
390 	p11.createObject(p11_atts);
391 }
392 
deleteFromToken()393 void pki_x509::deleteFromToken()
394 {
395 	pki_key *privkey = getRefKey();
396 	pki_scard *card = dynamic_cast<pki_scard *>(privkey);
397 	slotidList p11_slots;
398 
399 	if (!card || !pkcs11::libraries.loaded())
400 		return;
401 
402 	if (privkey && privkey->isToken()) {
403 		slotid slot;
404 		if (!card->prepare_card(&slot))
405 			return;
406 		p11_slots << slot;
407 	} else {
408 		pkcs11 p11;
409 		p11_slots = p11.getSlotList();
410 	}
411 	for (int i=0; i<p11_slots.count(); i++) {
412 		deleteFromToken(p11_slots[i]);
413 	}
414 }
415 
objectAttributes()416 pk11_attlist pki_x509::objectAttributes()
417 {
418 	pk11_attlist attrs;
419         attrs <<
420                 pk11_attr_ulong(CKA_CLASS, CKO_CERTIFICATE) <<
421                 pk11_attr_ulong(CKA_CERTIFICATE_TYPE, CKC_X_509) <<
422                 pk11_attr_data(CKA_VALUE, i2d());
423 	return attrs;
424 }
425 
deleteFromToken(const slotid & slot)426 void pki_x509::deleteFromToken(const slotid &slot)
427 {
428 	pkcs11 p11;
429 	p11.startSession(slot, true);
430 
431 	pk11_attlist atts = objectAttributes();
432 	QList<CK_OBJECT_HANDLE> objs = p11.objectList(atts);
433 	if (!objs.count())
434 		return;
435 
436 	tkInfo ti = p11.tokenInfo();
437 	if (!XCA_YESNO(tr("Delete the certificate '%1' from the token '%2 (#%3)'?").
438 		arg(getIntName()).arg(ti.label()).arg(ti.serial())))
439 	{
440 		return;
441 	}
442 	if (p11.tokenLogin(ti.label(), false).isNull())
443 		return;
444 
445 	p11.deleteObjects(objs);
446 }
447 
renameOnToken(const slotid & slot,const QString & name)448 int pki_x509::renameOnToken(const slotid &slot, const QString &name)
449 {
450 
451 	pkcs11 p11;
452 	p11.startSession(slot, true);
453 	pk11_attlist attrs = objectAttributes();
454 
455 	QList<CK_OBJECT_HANDLE> objs = p11.objectList(attrs);
456 	if (!objs.count())
457 		return 0;
458 
459 	pk11_attr_data label(CKA_LABEL, name.toUtf8());
460 	tkInfo ti = p11.tokenInfo();
461 	if (p11.tokenLogin(ti.label(), false).isNull())
462                 return 0;
463 	p11.storeAttribute(label, objs[0]);
464 	return 1;
465 }
466 
setNotBefore(const a1time & a)467 void pki_x509::setNotBefore(const a1time &a)
468 {
469 	a1time t(a);
470 	X509_set_notBefore(cert, t.get_utc());
471 	pki_openssl_error();
472 }
473 
setNotAfter(const a1time & a)474 void pki_x509::setNotAfter(const a1time &a)
475 {
476 	a1time t(a);
477 	X509_set_notAfter(cert, t.get_utc());
478 	pki_openssl_error();
479 }
480 
getNotBefore() const481 a1time pki_x509::getNotBefore() const
482 {
483 	a1time a(X509_get_notBefore(cert));
484 	return a;
485 }
486 
getNotAfter() const487 a1time pki_x509::getNotAfter() const
488 {
489 	a1time a(X509_get_notAfter(cert));
490 	return a;
491 }
492 
getSubject() const493 x509name pki_x509::getSubject() const
494 {
495 	x509name x(X509_get_subject_name(cert));
496 	pki_openssl_error();
497 	return x;
498 }
499 
getIssuerName() const500 x509name pki_x509::getIssuerName() const
501 {
502 	x509name x(X509_get_issuer_name(cert));
503 	pki_openssl_error();
504 	return x;
505 }
506 
setSubject(const x509name & n)507 void pki_x509::setSubject(const x509name &n)
508 {
509 	X509_set_subject_name(cert, n.get());
510 	pki_openssl_error();
511 }
512 
setIssuer(const x509name & n)513 void pki_x509::setIssuer(const x509name &n)
514 {
515 	X509_set_issuer_name(cert, n.get());
516 	pki_openssl_error();
517 }
518 
addV3ext(const x509v3ext & e,bool skip_existing)519 bool pki_x509::addV3ext(const x509v3ext &e, bool skip_existing)
520 {
521 	if (!e.isValid())
522 		return false;
523 	if (skip_existing && X509_get_ext_by_NID(cert, e.nid(), -1) != -1)
524 		return false;
525 	X509_EXTENSION *ext = e.get();
526 	X509_add_ext(cert, ext, -1);
527 	X509_EXTENSION_free(ext);
528 	pki_openssl_error();
529 	return true;
530 }
531 
delSigner(pki_base * s)532 void pki_x509::delSigner(pki_base *s)
533 {
534 	if (s && (s->getSqlItemId() == issuerSqlId))
535 		issuerSqlId = QVariant();
536 }
537 
isCA() const538 bool pki_x509::isCA() const
539 {
540 	bool ca;
541 	int crit;
542 	BASIC_CONSTRAINTS *bc = (BASIC_CONSTRAINTS *)
543 		X509_get_ext_d2i(cert, NID_basic_constraints, &crit, NULL);
544 	pki_openssl_error();
545 	ca = bc && bc->ca;
546 	if (bc)
547 		BASIC_CONSTRAINTS_free(bc);
548 	return ca;
549 }
550 
canSign() const551 bool pki_x509::canSign() const
552 {
553 	pki_key *privkey = getRefKey();
554 	if (!privkey || privkey->isPubKey())
555 		return false;
556 	if (privkey->isToken() && !pkcs11::libraries.loaded())
557 		return false;
558 	return isCA();
559 }
560 
hasExtension(int nid) const561 bool pki_x509::hasExtension(int nid) const
562 {
563 	return getV3ext().idxByNid(nid) != -1;
564 }
565 
sign(pki_key * signkey,const EVP_MD * digest)566 void pki_x509::sign(pki_key *signkey, const EVP_MD *digest)
567 {
568 	EVP_PKEY *tkey;
569 	if (!signkey) {
570 		my_error(tr("There is no key for signing !"));
571 	}
572 	tkey = signkey->decryptKey();
573 	pki_openssl_error();
574 	X509_sign(cert, tkey, digest);
575 	pki_openssl_error();
576 	EVP_PKEY_free(tkey);
577 	pki_openssl_error();
578 }
579 
fromData(const unsigned char * p,db_header_t * head)580 void pki_x509::fromData(const unsigned char *p, db_header_t *head)
581 {
582 	int version, size;
583 	bool isRevoked = false;
584 
585 	version = head->version;
586 	size = head->len - sizeof(db_header_t);
587 
588 	QByteArray ba((const char*)p, size);
589 
590 	d2i(ba);
591 	pki_openssl_error();
592 	/* trust = */ db::intFromData(ba);
593 	if (version < 4) {
594 		a1time revoked;
595 		isRevoked = db::boolFromData(ba);
596 		revoked.d2i(ba);
597 		pki_openssl_error();
598 		if (isRevoked) {
599 			revocation.setDate(revoked);
600 			revocation.setSerial(getSerial());
601 		}
602 	}
603 	pki_openssl_error();
604 	/* Superflous CaSerial = */db::stringFromData(ba);
605 	QString caTemplate = db::stringFromData(ba);
606 	crlDays = db::intFromData(ba);
607 	crlExpire.d2i(ba);
608 	pki_openssl_error();
609 	if (version > 1)
610 		/* randomSerial = */ db::boolFromData(ba);
611 	if (version > 2)
612 		crlNumber.setHex(db::stringFromData(ba));
613 	pki_openssl_error();
614 	if (version > 2 && version < 4) {
615 		// load own revocation info, to tell daddy about it
616 		a1time invalDate;
617 		QString revoke_reason = db::stringFromData(ba);
618 		invalDate.d2i(ba);
619 		pki_openssl_error();
620 		if (isRevoked) {
621 			revocation.setReason(revoke_reason);
622 			revocation.setInvalDate(invalDate);
623 		}
624 	}
625 	pki_openssl_error();
626 	if (version > 3) {
627 		fromDataRevList.fromBA(ba);
628 		pki_openssl_error();
629 	}
630 	if (ba.count() > 0) {
631 		my_error(tr("Wrong Size %1").arg(ba.count()));
632 	}
633 	pki_openssl_error();
634 
635 	XSqlQuery q;
636 	SQL_PREPARE(q, "SELECT id FROM items WHERE name=? AND type=?");
637 	q.bindValue(0, caTemplate);
638 	q.bindValue(1, tmpl);
639 	q.exec();
640 	if (q.next())
641 		caTemplateSqlId = q.value(0);
642 }
643 
644 
writeDefault(const QString & dirname) const645 void pki_x509::writeDefault(const QString &dirname) const
646 {
647 	XFile file(get_dump_filename(dirname, ".crt"));
648 	file.open_write();
649 	writeCert(file, true);
650 }
651 
writeCert(XFile & file,bool PEM) const652 void pki_x509::writeCert(XFile &file, bool PEM) const
653 {
654 	if (!cert)
655 		return;
656 	if (PEM) {
657 		PEM_file_comment(file);
658 		PEM_write_X509(file.fp(), cert);
659 	} else {
660 		i2d_X509_fp(file.fp(), cert);
661 	}
662 	pki_openssl_error();
663 }
664 
getIndexEntry()665 QString pki_x509::getIndexEntry()
666 {
667 	QString flag = NULL;
668 	bool revoked = isRevoked();
669 
670 	if (revoked)
671 		flag = "R";
672 	else if (checkDate())
673 		flag = "V";
674 	else
675 		flag = "E";
676 
677 	return QString("%1\t%2\t%3\t%4\tunknown\t%5\n").arg(
678 		flag, getNotAfter().toPlainUTC(),
679 		revoked ? revocation.getDate().toPlainUTC() : "",
680 		getSerial(),
681 		QString(X509_NAME_oneline(getSubject().get(), NULL, 0)));
682 }
683 
pem(BioByteArray & b,int)684 bool pki_x509::pem(BioByteArray &b, int)
685 {
686 	return PEM_write_bio_X509(b, cert);
687 }
688 
cmpIssuerAndSerial(pki_x509 * refcert)689 bool pki_x509::cmpIssuerAndSerial(pki_x509 *refcert)
690 {
691 	bool ret =  X509_issuer_and_serial_cmp(cert, refcert->cert);
692 	pki_openssl_error();
693 	return ret;
694 
695 }
696 
verify_only(const pki_x509 * signer) const697 bool pki_x509::verify_only(const pki_x509 *signer) const
698 {
699 	const X509_NAME *subject = X509_get_subject_name(signer->cert);
700 	const X509_NAME *issuer = X509_get_issuer_name(cert);
701 	pki_openssl_error();
702 	if (X509_NAME_cmp(subject, issuer)) {
703 		return false;
704 	}
705 	EVP_PKEY *pub = X509_get_pubkey(signer->cert);
706 	if (!pub) {
707 		pki_ign_openssl_error();
708 		return false;
709 	}
710 	int i = X509_verify(cert, pub);
711 	EVP_PKEY_free(pub);
712 	pki_ign_openssl_error();
713 	return i>0;
714 }
715 
verify(pki_x509 * signer)716 bool pki_x509::verify(pki_x509 *signer)
717 {
718 	if (getSigner() || !signer)
719 		return false;
720 	if (signer == this &&
721 	    issuerSqlId == sqlItemId &&
722 	    issuerSqlId != QVariant())
723 		return true;
724 
725 	if (signer && verify_only(signer)) {
726 		int idx;
727 		x509rev r;
728 		x509revList rl(revocation);
729 		r.setSerial(getSerial());
730 		setSigner(signer);
731 		signer->mergeRevList(rl);
732 		rl = signer->getRevList();
733 		idx = rl.indexOf(r);
734 		if (idx != -1)
735 			revocation = rl[idx];
736 		return true;
737 	}
738 	return false;
739 }
740 
getRevList() const741 x509revList pki_x509::getRevList() const
742 {
743 	return isCA() ? x509revList::fromSql(sqlItemId) : x509revList();
744 }
745 
mergeRevList(x509revList & l)746 void pki_x509::mergeRevList(x509revList &l)
747 {
748 	x509revList revList = getRevList();
749 	revList.merge(l);
750 
751 	if (revList.merged)
752 		revList.sqlUpdate(sqlItemId);
753 }
754 
setRevocations(const x509revList & rl)755 void pki_x509::setRevocations(const x509revList &rl)
756 {
757 	x509rev rev;
758 	x509revList revList = rl;
759 
760 	foreach(pki_base *p, childItems) {
761 		pki_x509 *pki = static_cast<pki_x509 *>(p);
762 		rev.setSerial(pki->getSerial());
763 		int idx = revList.indexOf(rev);
764 		if (idx != -1)
765 			pki->revocation = revList[idx];
766 		else
767 			pki->revocation = x509rev();
768 	}
769 	revList.sqlUpdate(sqlItemId);
770 }
771 
getPubKey() const772 pki_key *pki_x509::getPubKey() const
773 {
774 	EVP_PKEY *pkey = X509_get_pubkey(cert);
775 	pki_ign_openssl_error();
776 	if (pkey == NULL)
777 		return NULL;
778 	pki_evp *key = new pki_evp(pkey);
779 	pki_openssl_error();
780 	return key;
781 }
782 
compareNameAndKey(pki_x509 * other)783 bool pki_x509::compareNameAndKey(pki_x509 *other)
784 {
785 	int r;
786 	X509_NAME *s1, *s2;
787 	EVP_PKEY *pub1, *pub2;
788 
789 	if (!cert || !other->cert)
790 		return false;
791 	s1 = X509_get_subject_name(cert);
792 	s2 = X509_get_subject_name(other->cert);
793 	pki_openssl_error();
794 	if (!s1 || !s2)
795 		return false;
796 	/* X509_NAME_cmp returns 0 if they match */
797 	r = X509_NAME_cmp(s1, s2);
798 	pki_openssl_error();
799 	if (r)
800 		return false;
801 	pub1 = X509_get_pubkey(cert);
802 	pub2 = X509_get_pubkey(other->cert);
803 	pki_ign_openssl_error();
804 	if (!pub1 || !pub2)
805 		return false;
806 	/* EVP_PKEY_cmp() return 1 if the keys match */
807 	r = EVP_PKEY_cmp(pub1, pub2);
808 	pki_openssl_error();
809 	return r == 1;
810 }
811 
setPubKey(pki_key * key)812 void pki_x509::setPubKey(pki_key *key)
813 {
814 	X509_set_pubkey(cert, key->getPubKey());
815 	pki_openssl_error();
816 }
817 
fingerprint(const EVP_MD * digest) const818 QString pki_x509::fingerprint(const EVP_MD *digest) const
819 {
820 	return ::fingerprint(i2d_bytearray(I2D_VOID(i2d_X509), cert), digest);
821 }
822 
checkDate()823 bool pki_x509::checkDate()
824 {
825 	a1time n, b, a;
826 
827 	n = a1time::now(),
828 	b = getNotBefore();
829 	a = getNotAfter();
830 	pki_openssl_error();
831 
832 	if (!a.isValid() || !b.isValid())
833 		return false;
834 	if (!a.isUndefined() && (a < n))
835 		return false;
836 	if (b > n)
837 		return false;
838 	pki_openssl_error();
839 	return true;
840 }
841 
getV3ext() const842 extList pki_x509::getV3ext() const
843 {
844 	extList el;
845 	el.setStack(X509_get0_extensions(cert));
846 	return el;
847 }
848 
getExtByNid(int nid) const849 x509v3ext pki_x509::getExtByNid(int nid) const
850 {
851 	extList el = getV3ext();
852 	int i = el.idxByNid(nid);
853 
854 	try {
855 		pki_openssl_error();
856 	} catch(errorEx &err) {
857 		XCA_WARN(err.getString());
858 	}
859 	if (i == -1)
860 		return x509v3ext();
861 	return el[i];
862 }
863 
sigAlg() const864 int pki_x509::sigAlg() const
865 {
866 	return X509_get_signature_nid(cert);
867 }
868 
getSigner()869 pki_x509 *pki_x509::getSigner()
870 {
871 	return Store.lookupPki<pki_x509>(issuerSqlId);
872 }
873 
isRevoked() const874 bool pki_x509::isRevoked() const
875 {
876 	return revocation.isValid();
877 }
878 
setRevoked(const x509rev & revok)879 void pki_x509::setRevoked(const x509rev &revok)
880 {
881 	revocation = revok;
882 }
883 
caAndPathLen(bool * ca,a1int * pathlen,bool * hasLen) const884 bool pki_x509::caAndPathLen(bool *ca, a1int *pathlen, bool *hasLen) const
885 {
886 	x509v3ext e = getExtByNid(NID_basic_constraints);
887 	if (e.nid() != NID_basic_constraints)
888 		return false;
889 	BASIC_CONSTRAINTS *bc = (BASIC_CONSTRAINTS *)e.d2i();
890 	if (hasLen)
891 		*hasLen = bc->pathlen ? true : false;
892 	if (pathlen && bc->pathlen)
893 		pathlen->set(bc->pathlen);
894 	if (ca)
895 		*ca = bc->ca;
896 	BASIC_CONSTRAINTS_free(bc);
897 	pki_openssl_error();
898 	return true;
899 }
900 
column_data(const dbheader * hd) const901 QVariant pki_x509::column_data(const dbheader *hd) const
902 {
903 	switch (hd->id) {
904 		case HD_cert_serial:
905 			return QVariant(getSerial().toHex());
906 		case HD_cert_md5fp:
907 			return QVariant(fingerprint(EVP_md5()));
908 		case HD_cert_sha1fp:
909 			return QVariant(fingerprint(EVP_sha1()));
910 		case HD_cert_sha256fp:
911 			return QVariant(fingerprint(EVP_sha256()));
912 		case HD_cert_ca: {
913 			a1int len;
914 			bool ca, haslen;
915 			if (caAndPathLen(&ca, &len, &haslen)) {
916 				if (ca && haslen)
917 					return QVariant(len.toDec());
918 				if (!ca)
919 					return QVariant(tr("No"));
920 				else
921 					return QVariant(tr("Yes"));
922 			}
923 			break;
924 		}
925 	}
926 	return pki_x509super::column_data(hd);
927 }
928 
column_a1time(const dbheader * hd) const929 a1time pki_x509::column_a1time(const dbheader *hd) const
930 {
931 	switch (hd->id) {
932 		case HD_cert_notBefore:
933 			return getNotBefore();
934 		case HD_cert_notAfter:
935 			return getNotAfter();
936 		case HD_cert_revocation:
937 			if (isRevoked())
938 				return revocation.getDate();
939 			break;
940 		case HD_cert_crl_expire:
941 			if (canSign())
942 				return crlExpire;
943 			break;
944 	}
945 	return pki_base::column_a1time(hd);
946 }
947 
icsVEVENT() const948 QStringList pki_x509::icsVEVENT() const
949 {
950 	return pki_base::icsVEVENT(getNotAfter(),
951 		tr("Renew certificate: %1").arg(getIntName()),
952 		tr("The XCA certificate '%1', issued on %2 "
953 		   "will expire on %3.\n"
954 		   "It is stored in the XCA database '%4'")
955 			.arg(getIntName())
956 			.arg(getNotBefore().toPretty())
957 			.arg(getNotAfter().toPretty())
958 			.arg(Database.name())
959 	);
960 }
961 
collect_properties(QMap<QString,QString> & prp) const962 void pki_x509::collect_properties(QMap<QString, QString> &prp) const
963 {
964 	prp["Issuer"] = getIssuerName().oneLine(XN_FLAG_RFC2253);
965 	prp["Serial"] = getSerial().toHex();
966 	prp["CA"] = isCA() ? "Yes" : "No";
967 	prp["Not Before"] = getNotBefore().toPretty();
968 	prp["Not After"] = getNotAfter().toPretty();
969 	prp["Self signed"] = verify_only(this) ? "Yes" : "No";
970 	pki_x509super::collect_properties(prp);
971 }
972 
print(BioByteArray & bba,enum print_opt opt) const973 void pki_x509::print(BioByteArray &bba, enum print_opt opt) const
974 {
975 	pki_x509super::print(bba, opt);
976 	switch (opt) {
977 	case print_openssl_txt:
978 		X509_print(bba, cert);
979 		break;
980 	case print_pem:
981 		PEM_write_bio_X509(bba, cert);
982 		break;
983 	case print_coloured:
984 		break;
985 	}
986 }
987 
icsVEVENT_ca() const988 QStringList pki_x509::icsVEVENT_ca() const
989 {
990 	QStringList ics;
991 	pki_crl *crl = NULL;
992 
993 	ics << icsVEVENT();
994 	foreach(pki_base *p, childItems) {
995 		pki_x509 *pki = static_cast<pki_x509 *>(p);
996 		if (pki->getNotAfter() > a1time() && !isRevoked())
997 			ics << pki->icsVEVENT();
998 	}
999 
1000 	QList<pki_crl*> list = Store.sqlSELECTpki<pki_crl>(
1001 		"SELECT item FROM crls WHERE issuer = ?",
1002 		QList<QVariant>() << QVariant(sqlItemId));
1003 
1004 	/* Get latest CRL */
1005 	foreach(pki_crl *pki, list) {
1006 		if (!crl || crl->getNextUpdate() < pki->getNextUpdate())
1007 			crl = pki;
1008 	}
1009 	if (crl)
1010 		ics << crl->icsVEVENT();
1011 
1012 	return ics;
1013 }
1014 
getIcon(const dbheader * hd) const1015 QVariant pki_x509::getIcon(const dbheader *hd) const
1016 {
1017 	int pixnum = 0;
1018 	bool ca;
1019 	QStringList icon_names {
1020 		":validcertIco", ":validcertkeyIco",
1021 		":invalidcertIco", ":invalidcertkeyIco"
1022 	};
1023 	switch (hd->id) {
1024 	case HD_cert_ca:
1025 		if (!caAndPathLen(&ca, NULL, NULL))
1026 			return QVariant();
1027 		if (!ca)
1028 			return QVariant();
1029 		return QVariant(QPixmap(":doneIco"));
1030 	case HD_internal_name:
1031 		if (hasPrivKey())
1032 			pixnum += 1;
1033 		if (isRevoked())
1034 			pixnum += 2;
1035 		break;
1036 	default:
1037 		return pki_x509super::getIcon(hd);
1038 	}
1039 	return QVariant(QPixmap(icon_names[pixnum]));
1040 }
1041 
visible() const1042 bool pki_x509::visible() const
1043 {
1044 	if (pki_x509super::visible())
1045 		return true;
1046 	if (getIssuerName().search(limitPattern))
1047 		return true;
1048 	if (fingerprint(EVP_md5()).contains(limitPattern))
1049 		return true;
1050 	if (fingerprint(EVP_sha1()).contains(limitPattern))
1051 		return true;
1052 	if (fingerprint(EVP_sha256()).contains(limitPattern))
1053 		return true;
1054 	if (getSerial().toHex().contains(limitPattern))
1055 		return true;
1056 	return false;
1057 }
1058 
bg_color(const dbheader * hd) const1059 QVariant pki_x509::bg_color(const dbheader *hd) const
1060 {
1061 #define BG_RED     QBrush(QColor(255,  0,  0))
1062 #define BG_YELLOW  QBrush(QColor(255,255,  0))
1063 #define BG_CYAN    QBrush(QColor(127,255,212))
1064 
1065 	if (Settings["no_expire_colors"])
1066 		return QVariant();
1067 
1068 	QString unit, cert_expiry_num = Settings["cert_expiry"];
1069 	unit = cert_expiry_num.right(1);
1070 	cert_expiry_num.chop(1);
1071 	int n = cert_expiry_num.toInt();
1072 
1073 	a1time nb, na, now, certwarn;
1074 
1075 	nb = getNotBefore();
1076 	na = getNotAfter();
1077 	now = a1time::now();
1078 
1079 	if (unit == "%") {
1080 		quint64 lifetime = nb.secsTo(na);
1081 		certwarn = nb.addSecs(lifetime *n /100);
1082 	} else if (unit == "D") {
1083 		certwarn = na.addDays(-n);
1084 	} else if (unit == "W") {
1085 		certwarn = na.addDays(-n*7);
1086 	}
1087 	switch (hd->id) {
1088 		case HD_cert_notBefore:
1089 			if (nb > now || !nb.isValid() || nb.isUndefined())
1090 				return QVariant(BG_RED);
1091 			break;
1092 		case HD_cert_notAfter: {
1093 			if (na.isUndefined())
1094 				return QVariant(BG_CYAN);
1095 			if (na < now)
1096 				return QVariant(BG_RED);
1097 			if (certwarn < now)
1098 				return QVariant(BG_YELLOW);
1099 			break;
1100 		}
1101 		case HD_cert_crl_expire:
1102 			if (canSign()) {
1103 				QDateTime crlwarn, crlex;
1104 				crlex = crlExpire;
1105 				if (!crlExpire.isUndefined()) {
1106 					crlwarn = crlex.addSecs(-2 *60*60*24);
1107 					if (crlex < now)
1108 						return QVariant(BG_RED);
1109 					if (crlwarn < now || !crlex.isValid())
1110 						return QVariant(BG_YELLOW);
1111 				}
1112 			}
1113 	}
1114 	return QVariant();
1115 }
1116