diff --git a/lib/db_crl.cpp b/lib/db_crl.cpp index 2d8a8a50..e948a02f 100644 --- a/lib/db_crl.cpp +++ b/lib/db_crl.cpp @@ -50,17 +50,19 @@ void db_crl::load() void db_crl::revokeCerts(pki_crl *crl) { - int numc, i; + x509revList revlist; + if (!mainwin->certs) return; - x509rev revok; pki_x509 *signer = crl->getIssuer(); if (!signer) return; - numc = crl->numRev(); - for (i=0; igetRev(i); - mainwin->certs->revokeCert(revok, signer); + revlist = crl->getRevList(); + signer->mergeRevList(revlist); + foreach(x509rev revok, revlist) { + pki_x509 *crt = signer->getBySerial(revok.getSerial()); + if (crt) + crt->setRevoked(revok); } } @@ -91,7 +93,6 @@ void db_crl::inToCont(pki_base *pki) } crl->setIssuer(iss); } - revokeCerts(crl); db_base::inToCont(pki); } @@ -105,6 +106,10 @@ pki_base *db_crl::insert(pki_base *item) return NULL; } insertPKI(crl); + revokeCerts(crl); + pki_x509 *issuer = crl->getIssuer(); + if (issuer) + mainwin->certs->updateAfterCrlLoad(issuer); return crl; } @@ -155,17 +160,17 @@ void db_crl::store() delete dlg; } -pki_crl *db_crl::newItem(pki_x509 *cert) +void db_crl::newItem(pki_x509 *cert) { if (!cert) - return NULL; + return; pki_crl *crl = NULL; NewCrl *dlg = new NewCrl(mainwin, cert); if (!dlg->exec()) { delete dlg; - return NULL; + return; } try { x509v3ext e; @@ -176,13 +181,9 @@ pki_crl *db_crl::newItem(pki_x509 *cert) crl = new pki_crl(); crl->createCrl(cert->getIntName(), cert); - QList list = mainwin->certs->getIssuedCerts(cert); - bool reason = dlg->revocationReasons->isChecked(); - for (int i =0; iisRevoked() ) { - crl->addRev(list.at(i)->getRev(reason)); - } - } + bool withReason = dlg->revocationReasons->isChecked(); + foreach(x509rev rev, cert->revList) + crl->addRev(rev, withReason); if (dlg->authKeyId->isChecked()) { crl->addV3ext(e.create(NID_authority_key_identifier, @@ -211,7 +212,7 @@ pki_crl *db_crl::newItem(pki_x509 *cert) crl = NULL; } delete dlg; - return crl; + return; } void db_crl::showContextMenu(QContextMenuEvent *e, const QModelIndex &index) diff --git a/lib/db_crl.h b/lib/db_crl.h index 61121e0b..e70f5fb6 100644 --- a/lib/db_crl.h +++ b/lib/db_crl.h @@ -27,13 +27,13 @@ class db_crl: public db_x509name void revokeCerts(pki_crl *crl); void inToCont(pki_base *pki); pki_base *insert(pki_base *item); - pki_crl *newItem(pki_x509 *cert); void showContextMenu(QContextMenuEvent *e, const QModelIndex &index); void removeSigner(pki_base *signer); public slots: void store(); void load(); void showPki(pki_base *pki); + void newItem(pki_x509 *cert); signals: void updateCertView(); }; diff --git a/lib/db_x509.cpp b/lib/db_x509.cpp index 8287121f..df3817cf 100644 --- a/lib/db_x509.cpp +++ b/lib/db_x509.cpp @@ -16,10 +16,10 @@ #include "widgets/ExportDialog.h" #include "widgets/MainWindow.h" #include "widgets/PwDialog.h" +#include "widgets/RevocationList.h" #include "ui_TrustState.h" #include "ui_CaProperties.h" #include "ui_About.h" -#include "ui_Revoke.h" #include #include #include @@ -36,6 +36,22 @@ db_x509::db_x509(QString DBfile, MainWindow *mw) loadContainer(); } +void db_x509::updateAfterCrlLoad(pki_x509 *pki) +{ + if (pki->revList.merged) { + fprintf(stderr, "Update '%s'\n", CCHAR(pki->getIntName())); + updatePKI(pki); + pki->revList.merged = false; + } +} + +void db_x509::updateAfterDbLoad() +{ + FOR_ALL_pki(pki, pki_x509) { + updateAfterCrlLoad(pki); + } +} + dbheaderList db_x509::getHeaders() { dbheaderList h = db_x509super::getHeaders(); @@ -229,20 +245,6 @@ void db_x509::inToCont(pki_base *pki) calcEffTrust(); } - -QList db_x509::getIssuedCerts(const pki_x509 *issuer) -{ - QList c; - c.clear(); - if (!issuer) - return c; - FOR_ALL_pki(pki, pki_x509) { - if (pki->getSigner() == issuer) - c.append(pki); - } - return c; -} - pki_x509 *db_x509::getBySubject(const x509name &xname, pki_x509 *last) { bool lastfound = false; @@ -261,23 +263,6 @@ pki_x509 *db_x509::getBySubject(const x509name &xname, pki_x509 *last) return NULL; } -void db_x509::revokeCert(const x509rev &revok, const pki_x509 *iss) -{ - pki_x509 *crt = getByIssSerial(iss, revok.getSerial()); - if (crt) - crt->setRevoked(revok.getDate()); -} - -pki_x509 *db_x509::getByIssSerial(const pki_x509 *issuer, const a1int &a) -{ - if (!issuer ) return NULL; - FOR_ALL_pki(pki, pki_x509) { - if ((pki->getSigner() == issuer) && (a == pki->getSerial())) - return pki; - } - return NULL; -} - void db_x509::writeAllCerts(const QString fname, bool onlyTrusted) { bool append = false; @@ -321,18 +306,16 @@ a1int db_x509::getUniqueSerial(pki_x509 *signer) { // returnes an unused unique serial a1int serial; - bool dup; - do { - dup = false; + x509rev rev; + while (true) { serial = signer->getIncCaSerial(); - FOR_ALL_pki(pki, pki_x509) - if (pki->getSigner() == signer) { - if (serial == pki->getSerial()) { - dup = true; - break; - } - } - } while (dup); + rev.setSerial(serial); + if (signer->revList.contains(rev)) + continue; + if (signer->getBySerial(serial)) + continue; + break; + } if (!signer->usesRandomSerial()) updatePKI(signer); return serial; @@ -668,6 +651,8 @@ void db_x509::showContextMenu(QContextMenuEvent *e, const QModelIndex &index) subCa = menu->addMenu(tr("CA")); subCa->addAction(tr("Properties"), this, SLOT(caProperties())); subCa->addAction(tr("Generate CRL"), this, SLOT(genCrl())); + subCa->addAction(tr("Manage revocations"), + this, SLOT(manageRevocations())); subCa->setEnabled(canSign); menu->addSeparator(); menu->addAction(tr("Renewal"), this, SLOT(extendCert()))-> @@ -944,6 +929,21 @@ void db_x509::deleteFromToken() } } +void db_x509::manageRevocations() +{ + pki_x509 *cert = static_cast(currentIdx.internalPointer()); + if (!cert) + return; + RevocationList *dlg = new RevocationList(mainwin); + dlg->setRevList(cert->revList, cert); + connect(dlg, SIGNAL(genCRL(pki_x509*)), + mainwin->crls, SLOT(newItem(pki_x509*))); + if (dlg->exec()) { + cert->setRevocations(dlg->getRevList()); + updatePKI(cert); + } +} + void db_x509::setTrust() { int state, newstate = 0; @@ -964,7 +964,6 @@ void db_x509::setTrust() if (state == 0 ) ui.trust0->setChecked(true); if (state == 1 ) ui.trust1->setChecked(true); if (state == 2 ) ui.trust2->setChecked(true); - ui.certName->setText(cert->getIntName()); if (dlg->exec()) { if (ui.trust0->isChecked()) newstate = 0; if (ui.trust1->isChecked()) newstate = 1; @@ -1016,6 +1015,9 @@ void db_x509::extendCert() newcert->sign(signkey, oldcert->getDigest()); newcert = (pki_x509 *)insert(newcert); createSuccess(newcert); + + if (dlg->revoke->isChecked()) + revoke(); } catch (errorEx &err) { MainWindow::Error(err); @@ -1032,25 +1034,37 @@ void db_x509::revoke() pki_x509 *cert = static_cast(currentIdx.internalPointer()); if (!cert) return; - Ui::Revoke ui; - QDialog *revoke = new QDialog(mainwin, 0); - ui.setupUi(revoke); - ui.invalid->setNow(); - ui.reason->addItems(x509rev::crlreasons()); + Revocation *revoke = new Revocation(mainwin, cert); if (revoke->exec()) { - cert->setRevoked(true, ui.invalid->getDate(), - ui.reason->currentText()); - updatePKI(cert); + const x509rev r = revoke->getRevocation(); + cert->setRevoked(r); + pki_x509 *iss = cert->getSigner(); + if (iss) { + x509revList rl(r); + iss->mergeRevList(rl); + updatePKI(iss); + } } } void db_x509::unRevoke() { pki_x509 *cert = static_cast(currentIdx.internalPointer()); + pki_x509 *sig; + int idx; + x509rev rev; + if (!cert) return; - cert->setRevoked(false); - updatePKI(cert); + sig = cert->getSigner(); + if (!sig) + return; + cert->setRevoked(x509rev()); + rev.setSerial(cert->getSerial()); + idx = sig->revList.indexOf(rev); + if (idx != -1) + sig->revList.takeAt(idx); + updatePKI(sig); } void db_x509::genCrl() @@ -1146,4 +1160,3 @@ void db_x509::caProperties() } delete dlg; } - diff --git a/lib/db_x509.h b/lib/db_x509.h index 32bfb2d7..44823c15 100644 --- a/lib/db_x509.h +++ b/lib/db_x509.h @@ -10,8 +10,8 @@ #define __DB_X509_H #include -#include #include +#include #include "widgets/ExportDialog.h" #include "db_key.h" #include "db_x509super.h" @@ -33,6 +33,9 @@ class db_x509: public db_x509super db_x509(QString DBfile, MainWindow *mw); pki_base *newPKI(db_header_t *head = NULL); pki_x509 *findSigner(pki_x509 *client); + void updateAfterDbLoad(); + void updateAfterCrlLoad(pki_x509 *pki); + bool updateView(); void updateViewAll(); void updateViewPKI(pki_base *pki); @@ -40,7 +43,6 @@ class db_x509: public db_x509super QStringList getPrivateDesc(); QStringList getSignerDesc(); void calcEffTrust(); - QList getIssuedCerts(const pki_x509 *issuer); QList getCerts(bool onlyTrusted); a1int searchSerial(pki_x509 *signer); void writeAllCerts(const QString fname, bool onlyTrusted); @@ -62,7 +64,6 @@ class db_x509: public db_x509super public slots: void load(void); void newItem(void); - void revokeCert(const x509rev &revok, const pki_x509 *issuer); void showPki(pki_base *pki); void setMultiTrust(QAbstractItemView* view); void setTrust(); @@ -80,6 +81,7 @@ class db_x509: public db_x509super void newCert(pki_x509req *); void loadPKCS12(); void loadPKCS7(); + void manageRevocations(); }; #endif diff --git a/lib/pki_crl.cpp b/lib/pki_crl.cpp index 469b8135..ec047128 100644 --- a/lib/pki_crl.cpp +++ b/lib/pki_crl.cpp @@ -154,9 +154,9 @@ QByteArray pki_crl::toData() return ba; } -void pki_crl::addRev(const x509rev &xrev) +void pki_crl::addRev(const x509rev &xrev, bool withReason) { - X509_CRL_add0_revoked(crl, xrev.get()); + X509_CRL_add0_revoked(crl, xrev.get(withReason)); pki_openssl_error(); } @@ -240,16 +240,18 @@ int pki_crl::numRev() { if (crl && crl->crl && crl->crl->revoked) return sk_X509_REVOKED_num(crl->crl->revoked); - else - return 0; + return 0; } -x509rev pki_crl::getRev(int num) +x509revList pki_crl::getRevList() { - x509rev ret; - if (crl && crl->crl && crl->crl->revoked) { - ret.set(sk_X509_REVOKED_value(crl->crl->revoked, num)); + x509revList ret; + int i, num = numRev(); + + for (i=0; icrl->revoked, i)); pki_openssl_error(); + ret << r; } return ret; } diff --git a/lib/pki_crl.h b/lib/pki_crl.h index 4992d727..7ea75cc6 100644 --- a/lib/pki_crl.h +++ b/lib/pki_crl.h @@ -33,7 +33,7 @@ class pki_crl: public pki_x509name void writeDefault(const QString fname); static QPixmap *icon; void createCrl(const QString d, pki_x509 *iss); - void addRev(const x509rev &rev); + void addRev(const x509rev &rev, bool withReason=true); void addExt(int nid, QString value); void write(QString fname); void addV3ext(const x509v3ext &e); @@ -55,9 +55,9 @@ class pki_crl: public pki_x509name void fromData(const unsigned char *p, db_header_t *head); void oldFromData(unsigned char *p, int size); QByteArray toData(); - int numRev(); bool verify(pki_key *pkey); - x509rev getRev(int num); + int numRev(); + x509revList getRevList(); QString printV3ext(); x509v3ext getExtByNid(int nid); a1int getVersion(); diff --git a/lib/pki_x509.cpp b/lib/pki_x509.cpp index db8caf25..cf546cd8 100644 --- a/lib/pki_x509.cpp +++ b/lib/pki_x509.cpp @@ -41,12 +41,11 @@ pki_x509::pki_x509(const pki_x509 *crt) setRefKey(crt->getRefKey()); trust = crt->trust; efftrust = crt->efftrust; - revoked = crt->revoked; caSerial = crt->caSerial; caTemplate = crt->caTemplate; + revocation = crt->revocation; crlDays = crt->crlDays; crlExpiry = crt->crlExpiry; - isrevoked = isrevoked; pki_openssl_error(); } @@ -134,18 +133,15 @@ void pki_x509::init() psigner = NULL; trust = 0; efftrust = 0; - revoked = a1time::now(); caSerial = 1; caTemplate = ""; crlDays = 30; crlExpiry.setUndefined(); class_name = "pki_x509"; cert = NULL; - isrevoked = false; - dataVersion = 3; + dataVersion = 4; pkiType = x509; randomSerial = false; - revoke_reason = ""; } void pki_x509::setSerial(const a1int &serial) @@ -164,6 +160,16 @@ a1int pki_x509::getSerial() const return a; } +pki_x509 *pki_x509::getBySerial(const a1int &a) const +{ + foreach(pki_base *p, childItems) { + pki_x509 *pki = static_cast(p); + if (a == pki->getSerial()) + return pki; + } + return NULL; +} + #define SERIAL_LEN 8 a1int pki_x509::getIncCaSerial() { @@ -493,6 +499,7 @@ void pki_x509::sign(pki_key *signkey, const EVP_MD *digest) void pki_x509::fromData(const unsigned char *p, db_header_t *head) { int version, size; + bool isRevoked; version = head->version; size = head->len - sizeof(db_header_t); @@ -502,8 +509,15 @@ void pki_x509::fromData(const unsigned char *p, db_header_t *head) d2i(ba); pki_openssl_error(); trust = db::intFromData(ba); - isrevoked = db::boolFromData(ba); - revoked.d2i(ba); + if (version < 4) { + a1time revoked; + isRevoked = db::boolFromData(ba); + revoked.d2i(ba); + if (isRevoked) { + revocation.setDate(revoked); + revocation.setSerial(getSerial()); + } + } caSerial.setHex(db::stringFromData(ba)); caTemplate = db::stringFromData(ba); crlDays = db::intFromData(ba); @@ -512,10 +526,22 @@ void pki_x509::fromData(const unsigned char *p, db_header_t *head) randomSerial = db::boolFromData(ba); else randomSerial = false; - if (version > 2) { + if (version > 2) crlNumber.setHex(db::stringFromData(ba)); - revoke_reason = db::stringFromData(ba); + if (version > 2 && version < 4) { + // load own revocation info, to tell daddy about it + a1time invalDate; + QString revoke_reason = db::stringFromData(ba); invalDate.d2i(ba); + if (isRevoked) { + revocation.setReason(revoke_reason); + revocation.setInvalDate(invalDate); + } + } + if (version > 3) { + x509revList curr(revList); + revList.fromBA(ba); + revList.merge(curr); } if (ba.count() > 0) { my_error(tr("Wrong Size %1").arg(ba.count())); @@ -530,8 +556,7 @@ QByteArray pki_x509::toData() ba += i2d(); // cert ba += db::intToData(trust); - ba += db::boolToData(isrevoked); - ba += revoked.i2d(); // revocation date + // version 4: don't store isrevoked, revoked // the serial if this is a CA ba += db::stringToData(caSerial.toHex()); @@ -542,8 +567,8 @@ QByteArray pki_x509::toData() ba += crlExpiry.i2d(); // last CRL date ba += db::boolToData(randomSerial); ba += db::stringToData(crlNumber.toHex()); - ba += db::stringToData(revoke_reason); - ba += invalDate.i2d(); + // version 4: don't store own revocation but client revocations + ba += revList.toBA(); pki_openssl_error(); return ba; } @@ -610,12 +635,34 @@ bool pki_x509::verify(pki_x509 *signer) int i = X509_verify(cert, pub); pki_ign_openssl_error(); if (i>0) { + int idx; + x509rev r; + r.setSerial(getSerial()); psigner = signer; + psigner->revList.merge(x509revList(revocation)); + idx = psigner->revList.indexOf(r); + if (idx != -1) + revocation = psigner->revList[idx]; return true; } return false; } +void pki_x509::setRevocations(const x509revList &rl) +{ + revList = rl; + x509rev rev; + + foreach(pki_base *p, childItems) { + pki_x509 *pki = static_cast(p); + rev.setSerial(pki->getSerial()); + int idx = revList.indexOf(rev); + if (idx != -1) + pki->revocation = revList[idx]; + else + pki->revocation = x509rev(); + } +} pki_key *pki_x509::getPubKey() const { @@ -727,34 +774,16 @@ void pki_x509::setEffTrust(int t) bool pki_x509::isRevoked() { - return isrevoked ; + return revocation.isValid(); } -void pki_x509::setRevoked(bool rev, a1time inval, QString reason) +void pki_x509::setRevoked(const x509rev &revok) { - if (rev) { + revocation = revok; + if (revok.isValid()) { setEffTrust(0); - revoked = a1time::now(); - pki_openssl_error(); - revoke_reason = reason; - invalDate = inval; + setTrust(0); } - isrevoked = rev; - pki_openssl_error(); -} - -a1time &pki_x509::getRevoked() -{ - return revoked; -} - -void pki_x509::setRevoked(const a1time &when) -{ - isrevoked = true; - revoked = when; - setEffTrust(0); - setTrust(0); - pki_openssl_error(); } int pki_x509::calcEffTrust() @@ -791,19 +820,6 @@ void pki_x509::setCrlExpiry(const a1time &time) pki_openssl_error(); } -x509rev pki_x509::getRev(bool reason) -{ - x509rev a; - a.setDate(getRevoked()); - a.setSerial(getSerial()); - if (reason) { - a.setReason(revoke_reason); - a.setInvalDate(invalDate); - } - pki_openssl_error(); - return a; -} - bool pki_x509::caAndPathLen(bool *ca, a1int *pathlen, bool *hasLen) { x509v3ext e = getExtByNid(NID_basic_constraints); @@ -837,7 +853,7 @@ QVariant pki_x509::column_data(dbheader *hd) return QVariant(truststatus[getTrust()]); case HD_cert_revocation: return QVariant(isRevoked() ? - getRevoked().toSortable() : ""); + revocation.getDate().toSortable() : ""); case HD_cert_crl_expire: if (canSign() && !crlExpiry.isUndefined()) return QVariant(crlExpiry.toSortable()); @@ -975,12 +991,14 @@ void pki_x509::oldFromData(unsigned char *p, int size) trust = intFromData(ba); sRev = intFromData(ba); if (sRev) { - if (version != 3) isrevoked = true; - revoked.d2i(ba); - } - else { - isrevoked = false; - revoked = a1time::now(); + a1time r; + r.d2i(ba); + if (version != 3) { + revocation.setSerial(getSerial()); + revocation.setDate(r); + } + } else { + revocation = x509rev(); } if (version == 1) { @@ -1016,7 +1034,6 @@ void pki_x509::oldFromData(unsigned char *p, int size) } else { // old version d2i(ba); - revoked = NULL; trust = 1; efftrust = 1; } @@ -1029,4 +1046,3 @@ void pki_x509::oldFromData(unsigned char *p, int size) my_error(tr("Wrong Size %1").arg(ba.count())); } } - diff --git a/lib/pki_x509.h b/lib/pki_x509.h index 830adad6..db884811 100644 --- a/lib/pki_x509.h +++ b/lib/pki_x509.h @@ -26,8 +26,8 @@ class pki_x509 : public pki_x509super Q_OBJECT private: pki_x509 *psigner; - a1time revoked, crlExpiry, invalDate; - bool isrevoked, randomSerial; + a1time crlExpiry; + bool randomSerial; int trust; int efftrust; a1int caSerial; @@ -35,14 +35,17 @@ class pki_x509 : public pki_x509super int crlDays; QString caTemplate; X509 *cert; - QString revoke_reason; void init(); + x509rev revocation; + protected: ASN1_OBJECT *sigAlg(); + public: static QPixmap *icon[6]; static bool dont_colorize_expiries; static bool disable_netscape; + x509revList revList; pki_x509(X509 *c); pki_x509(const pki_x509 *crt); pki_x509(const QString name = ""); @@ -93,9 +96,9 @@ class pki_x509 : public pki_x509super void setEffTrust(int t); void setRevoked(bool rev, a1time inval = a1time(), QString reason = QString()); - void setRevoked(const a1time &when); - a1time &getRevoked(); + void setRevoked(const x509rev &revok); bool isRevoked(); + pki_x509 *getBySerial(const a1int &a) const; int calcEffTrust(); a1int getIncCaSerial(); a1int getCaSerial() @@ -136,13 +139,16 @@ class pki_x509 : public pki_x509super { randomSerial = r; } + x509rev getRevocation() + { + return revocation; + } pk11_attlist objectAttributes(); void setCrlExpiry(const a1time &time); bool hasExtension(int nid); bool cmpIssuerAndSerial(pki_x509 *refcert); bool visible(); void updateView(); - x509rev getRev(bool reason = true); x509v3ext getExtByNid(int nid); QVariant column_data(dbheader *hd); QVariant getIcon(dbheader *hd); @@ -154,6 +160,10 @@ class pki_x509 : public pki_x509super virtual int renameOnToken(slotid slot, QString name); BIO *pem(BIO *, int); virtual QVariant bg_color(dbheader *hd); + void mergeRevList(x509revList l) { + revList.merge(l); + } + void setRevocations(const x509revList &rl); }; #endif diff --git a/lib/x509rev.cpp b/lib/x509rev.cpp index 95433ccb..0321266a 100644 --- a/lib/x509rev.cpp +++ b/lib/x509rev.cpp @@ -6,8 +6,10 @@ */ #include "x509rev.h" +#include "db.h" #include "base.h" #include "func.h" +#include "exception.h" #include #include @@ -47,153 +49,158 @@ QStringList x509rev::crlreasons() return l; } -static X509_REVOKED *X509_REVOKED_dup(const X509_REVOKED *n) -{ - int len; - X509_REVOKED *ret; - unsigned char *buf, *p; - - len = i2d_X509_REVOKED((X509_REVOKED *)n, NULL); - buf = (unsigned char *)OPENSSL_malloc(len); - p = buf; - i2d_X509_REVOKED((X509_REVOKED *)n, &p); - p = buf; - ret = d2i_X509_REVOKED(NULL, (const unsigned char **)&p, len); - OPENSSL_free(buf); - return(ret); -} - -x509rev::x509rev() -{ - rev = X509_REVOKED_new(); -} - -x509rev::x509rev(const X509_REVOKED *n) -{ - rev = X509_REVOKED_dup(n); -} - -x509rev::x509rev(const x509rev &n) -{ - rev = NULL; - set(n.rev); -} - -x509rev::~x509rev() -{ - X509_REVOKED_free(rev); -} - -x509rev &x509rev::set(const X509_REVOKED *n) -{ - if (rev != NULL) - X509_REVOKED_free(rev); - rev = X509_REVOKED_dup(n); - return *this; -} - -bool x509rev::operator == (const x509rev &x) const -{ - return (getSerial() == x.getSerial() && - getDate() == x.getDate()); -} - -x509rev &x509rev::operator = (const x509rev &x) -{ - set(x.rev); - return *this; -} - -void x509rev::setSerial(const a1int &i) -{ - if (rev->serialNumber != NULL) - ASN1_INTEGER_free(rev->serialNumber); - rev->serialNumber = i.get(); -} - -void x509rev::setDate(const a1time &a) -{ - a1time t(a); - X509_REVOKED_set_revocationDate(rev, t.get_utc()); -} - -a1int x509rev::getSerial() const -{ - a1int a(rev->serialNumber); - return a; -} - -a1time x509rev::getDate() const -{ - a1time t(rev->revocationDate); - return t; -} - -void x509rev::setInvalDate(const a1time &date) -{ - a1time t(date); - X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, t.get(), 0, 0); - openssl_error(); -} - -void x509rev::setReason(const QString &reason) -{ - /* RFC says to not add the extension if it is "unspecified" */ - if (reason == crl_reasons[0].lname) - return; - ASN1_ENUMERATED *a = ASN1_ENUMERATED_new(); - openssl_error(); - - for (int i=0; crl_reasons[i].lname; i++) { - if (reason == crl_reasons[i].lname) { - ASN1_ENUMERATED_set(a, crl_reasons[i].bitnum); - break; - } - } - openssl_error(); - X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, a, 0, 0); - openssl_error(); - ASN1_ENUMERATED_free(a); -} - QString x509rev::getReason() const { - ASN1_ENUMERATED *reason; - int j, r; - reason = (ASN1_ENUMERATED *)X509_REVOKED_get_ext_d2i(rev, - NID_crl_reason, &j, NULL); - openssl_error(); - if (j == -1) - return QString(crl_reasons[0].lname); - r = ASN1_ENUMERATED_get(reason); - openssl_error(); - ASN1_ENUMERATED_free(reason); - for (int i=0; crl_reasons[i].lname; i++) { - if (r == crl_reasons[i].bitnum) { - return QString(crl_reasons[i].lname); - } - } - return QString(); + return crl_reasons[reason_idx].lname; } -a1time x509rev::getInvalDate() const +void x509rev::fromREVOKED(const X509_REVOKED *rev) { + ASN1_ENUMERATED *reason; ASN1_TIME *at; - a1time a; - int j; - at = (ASN1_TIME *)X509_REVOKED_get_ext_d2i(rev, + int j = -1, r; + + if (!rev) + return; + serial = a1int(rev->serialNumber); + date = a1time(rev->revocationDate); + + reason = (ASN1_ENUMERATED *)X509_REVOKED_get_ext_d2i( + (X509_REVOKED *)rev, NID_crl_reason, &j, NULL); + openssl_error(); + reason_idx = 0; + if (reason) { + r = ASN1_ENUMERATED_get(reason); + openssl_error(); + for (int i=0; crl_reasons[i].lname; i++) { + if (r == crl_reasons[i].bitnum) { + reason_idx = i; + } + } + ASN1_ENUMERATED_free(reason); + } + ivalDate.setUndefined(); + at = (ASN1_TIME *)X509_REVOKED_get_ext_d2i((X509_REVOKED *)rev, NID_invalidity_date, &j, NULL); openssl_error(); - if (j == -1) { - a.setUndefined(); - return a; + if (at) { + ivalDate = a1time(at); + ASN1_GENERALIZEDTIME_free(at); } - a.set(at); - ASN1_GENERALIZEDTIME_free(at); - return a; + //dump(); } -X509_REVOKED *x509rev::get() const +X509_REVOKED *x509rev::toREVOKED(bool withReason) const { - return X509_REVOKED_dup(rev); + a1time i = ivalDate; + a1time d = date; + X509_REVOKED *rev = X509_REVOKED_new(); + check_oom(rev); + rev->serialNumber = serial.get(); + X509_REVOKED_set_revocationDate(rev, d.get_utc()); + + X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, + i.get(), 0, 0); + + /* RFC says to not add the extension if it is "unspecified" */ + if (reason_idx != 0 && withReason) { + ASN1_ENUMERATED *a = ASN1_ENUMERATED_new(); + ASN1_ENUMERATED_set(a, crl_reasons[reason_idx].bitnum); + X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, a, 0, 0); + ASN1_ENUMERATED_free(a); + } + openssl_error(); + //dump(); + return rev; +} + +void x509rev::d2i(QByteArray &ba) +{ + X509_REVOKED *r; + r = (X509_REVOKED *)d2i_bytearray(D2I_VOID(d2i_X509_REVOKED), ba); + if (!r) + return; + fromREVOKED(r); + X509_REVOKED_free(r); +} + +QByteArray x509rev::i2d() const +{ + QByteArray ba; + X509_REVOKED *r = toREVOKED(); + ba = i2d_bytearray(I2D_VOID(i2d_X509_REVOKED), r); + X509_REVOKED_free(r); + return ba; +} + +void x509rev::set(const x509rev &x) +{ + serial = x.serial; + date = x.date; + ivalDate = x.ivalDate; + reason_idx = x.reason_idx; +} + +bool x509rev::identical(const x509rev &x) const +{ + return serial == x.serial && + date == x.date && + ivalDate == x.ivalDate && + reason_idx == x.reason_idx; +} + +void x509rev::dump() const +{ + fprintf(stderr, "Rev: %s D:%s I:%s Reason: %d '%s'\n", + CCHAR(serial.toHex()), CCHAR(date.toSortable()), + CCHAR(ivalDate.toSortable()), reason_idx, + CCHAR(crl_reasons[reason_idx].lname)); +} + +void x509revList::fromBA(QByteArray &ba) +{ + int i, num = db::intFromData(ba); + x509rev r; + clear(); + merged = false; + for (i=0; i +#include #include #include "asn1time.h" #include "asn1int.h" @@ -16,25 +16,111 @@ class x509rev { private: - X509_REVOKED *rev; + a1int serial; + a1time date, ivalDate; + int reason_idx; + void set(const x509rev &x); + + X509_REVOKED *toREVOKED(bool withReason=true) const; + void fromREVOKED(const X509_REVOKED *rev); + void dump() const; + public: - x509rev(); - x509rev(const X509_REVOKED *n); - x509rev(const x509rev &n); - ~x509rev(); static QStringList crlreasons(); - x509rev &set(const X509_REVOKED *n); - x509rev &operator = (const x509rev &x); - bool operator == (const x509rev &x) const; - void setSerial(const a1int &i); - void setDate(const a1time &t); - a1int getSerial() const; - a1time getDate() const; - void setInvalDate(const a1time &date); - a1time getInvalDate() const; - void setReason(const QString &reason); + void d2i(QByteArray &ba); + QByteArray i2d() const; QString getReason() const; - X509_REVOKED *get() const; + bool identical(const x509rev &x) const; + + x509rev() + { + reason_idx = 0; + date.setUndefined(); + } + x509rev(X509_REVOKED *n) + { + fromREVOKED(n); + } + x509rev(const x509rev &n) + { + set(n); + } + + bool isValid() const + { + return serial.getLong() != 0 && + !date.isUndefined(); + } + x509rev &set(const X509_REVOKED *r) + { + fromREVOKED(r); + return *this; + } + bool operator == (const x509rev &x) const + { + return serial == x.serial; + } + x509rev &operator = (const x509rev &x) + { + set(x); + return *this; + } + void setSerial(const a1int &i) + { + serial = i; + } + void setDate(const a1time &t) + { + date = t; + } + void setInvalDate(const a1time &t) + { + ivalDate = t; + } + void setReason(const QString &reason) + { + reason_idx = crlreasons().indexOf(reason); + } + a1int getSerial() const + { + return serial; + } + a1time getDate() const + { + return date; + } + a1time getInvalDate() const + { + return ivalDate; + } + X509_REVOKED *get(bool withReason=true) const + { + return toREVOKED(); + } }; +class x509revList : public QList +{ + public: + bool merged; + QByteArray toBA(); + void fromBA(QByteArray &ba); + void merge(const x509revList &other); + bool identical(const x509revList &other) const; + x509revList() : QList() + { + merged = false; + } + x509revList(const x509revList &r) : QList(r) + { + merged = r.merged; + } + x509revList(const x509rev &r) : QList() + { + if (r.isValid()) { + merged = false; + append(r); + } + } +}; #endif diff --git a/ui/CertExtend.ui b/ui/CertExtend.ui index a114ef2d..30dcdb53 100644 --- a/ui/CertExtend.ui +++ b/ui/CertExtend.ui @@ -6,8 +6,8 @@ 0 0 - 760 - 288 + 411 + 416 @@ -95,126 +95,130 @@ - - - 6 + + + Validity - - 0 - - - - - Validity - - - - 6 - - - 8 - - - - - 0 - - - 6 - - - - - Not before - - - - - - - Not after - - - - - - - true - - - - - - - true - - - - - - - - - - - - Time range - - - - - - - - - - Days - - - - - Months - - - - - Years - - - - - - + + + 8 + + + + + - Apply + Not before - + - Midnight + Not after + + + + + + + true - - - Local time - - - - - - - No well-defined expiration + + + true - - - + + + + + + + + Time range + + + + + + Local time + + + + + + + + Days + + + + + Months + + + + + Years + + + + + + + + No well-defined expiration + + + + + + + Midnight + + + + + + + Apply + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 2 + + + + + + + + Revoke old certificate + + + true + + @@ -269,8 +273,8 @@ hideTimeCheck(int) - 456 - 193 + 453 + 197 231 @@ -289,8 +293,8 @@ 193 - 351 - 194 + 331 + 200 @@ -301,8 +305,8 @@ hideTimeCheck(int) - 456 - 193 + 453 + 197 239 @@ -353,8 +357,8 @@ 182 - 487 - 176 + 544 + 197 @@ -369,8 +373,8 @@ 189 - 344 - 151 + 331 + 164 @@ -385,8 +389,8 @@ 190 - 334 - 191 + 331 + 200 diff --git a/ui/CrlDetail.ui b/ui/CrlDetail.ui index 5c829a7f..c2757930 100644 --- a/ui/CrlDetail.ui +++ b/ui/CrlDetail.ui @@ -6,22 +6,13 @@ 0 0 - 488 - 352 + 530 + 381 - - - - - 6 - - - 0 - @@ -80,16 +71,13 @@ - 0 + 3 &Status - - 6 - 8 @@ -121,17 +109,8 @@ 8 - - 6 - - - 6 - - - 0 - @@ -203,9 +182,6 @@ 8 - - 6 - @@ -252,9 +228,6 @@ &Issuer - - 6 - 11 @@ -268,9 +241,6 @@ &Extensions - - 6 - 11 @@ -291,9 +261,6 @@ &Revocation list - - 6 - 11 @@ -305,15 +272,9 @@ QAbstractItemView::NoSelection - - false - - - true - - 0 + 1 @@ -358,8 +319,8 @@ accept() - 349 - 321 + 355 + 376 169 diff --git a/ui/Makefile b/ui/Makefile index c2797f69..facba885 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -8,7 +8,8 @@ UI_H = ui_About.h ui_CaProperties.h ui_CertDetail.h ui_CertExtend.h \ ui_CrlDetail.h ui_ExportDialog.h ui_Help.h \ ui_ImportMulti.h ui_KeyDetail.h ui_MainWindow.h ui_NewCrl.h \ ui_NewKey.h ui_NewX509.h ui_Options.h ui_PwDialog.h ui_Revoke.h \ - ui_SelectToken.h ui_TrustState.h ui_v3ext.h ui_SearchPkcs11.h + ui_SelectToken.h ui_TrustState.h ui_v3ext.h ui_SearchPkcs11.h \ + ui_RevocationList.h include $(TOPDIR)/Rules.mak diff --git a/ui/RevocationList.ui b/ui/RevocationList.ui new file mode 100644 index 00000000..48dcf0e0 --- /dev/null +++ b/ui/RevocationList.ui @@ -0,0 +1,168 @@ + + + RevocationList + + + + 0 + 0 + 628 + 320 + + + + + + + + + + Arial + 14 + 50 + false + false + false + false + + + + Manage revocations + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 20 + 20 + + + + + + + + + 95 + 40 + + + + + 95 + 40 + + + + true + + + + + + + + + + + true + + + QAbstractItemView::MultiSelection + + + QAbstractItemView::SelectRows + + + + 1 + + + + + + + + + + Add + + + + + + + Delete + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + QDialogButtonBox::Abort|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + RevocationList + accept() + + + 341 + 291 + + + 292 + 254 + + + + + buttonBox + rejected() + RevocationList + reject() + + + 445 + 292 + + + 445 + 237 + + + + + diff --git a/ui/Revoke.ui b/ui/Revoke.ui index 7e6d5a35..f74d1bf5 100644 --- a/ui/Revoke.ui +++ b/ui/Revoke.ui @@ -6,46 +6,126 @@ 0 0 - 400 - 195 + 417 + 282 + + + + + + + Arial + 14 + 50 + false + false + false + false + + + + Certificate revocation + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 78 + 20 + + + + + + + + + 95 + 40 + + + + + 95 + 40 + + + + true + + + + + + + + + Qt::Vertical + + + + 20 + 10 + + + + Revocation details - - - - Invalid since - - - - - - true - - + - - - - Local time - - - - + Revocation reason + + + + true + + + + + + Local time + + + + + + + Invalid since + + + + + + + Serial + + + + @@ -57,7 +137,7 @@ Qt::Horizontal - QDialogButtonBox::Ok + QDialogButtonBox::Cancel|QDialogButtonBox::Ok @@ -100,12 +180,12 @@ localTime(int) - 244 - 82 + 397 + 122 - 244 - 55 + 389 + 93 diff --git a/ui/TrustState.ui b/ui/TrustState.ui index 5059d36a..281d4664 100644 --- a/ui/TrustState.ui +++ b/ui/TrustState.ui @@ -7,7 +7,7 @@ 0 0 435 - 288 + 211 @@ -16,12 +16,6 @@ - - 6 - - - 0 - @@ -36,7 +30,7 @@ - Set trustment of the Certificate + Certificate trust @@ -93,31 +87,12 @@ - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - Trustment - - 6 - 8 @@ -154,13 +129,6 @@ - - - ClickLabel - QLabel -
widgets/clicklabel.h
-
-
trust0 trust1 diff --git a/widgets/CertDetail.cpp b/widgets/CertDetail.cpp index e609e95d..2c968861 100644 --- a/widgets/CertDetail.cpp +++ b/widgets/CertDetail.cpp @@ -125,10 +125,11 @@ void CertDetail::setCert(pki_x509 *cert) // validation of the Date dateValid->disableToolTip(); if (cert->isRevoked()) { + x509rev rev = cert->getRevocation(); dateValid->setText(tr("Revoked: ") + - cert->getRevoked().toPretty()); + rev.getDate().toPretty()); dateValid->setRed(); - dateValid->setToolTip(cert->getRevoked().toPrettyGMT()); + dateValid->setToolTip(rev.getDate().toPrettyGMT()); } else if (!cert->checkDate()) { dateValid->setText(tr("Not valid")); dateValid->setRed(); diff --git a/widgets/CrlDetail.cpp b/widgets/CrlDetail.cpp index d7b3acc8..b756342a 100644 --- a/widgets/CrlDetail.cpp +++ b/widgets/CrlDetail.cpp @@ -11,6 +11,7 @@ #include "lib/pki_crl.h" #include "widgets/distname.h" #include "widgets/clicklabel.h" +#include "widgets/RevocationList.h" #include #include #include @@ -22,25 +23,14 @@ CrlDetail::CrlDetail(MainWindow *mainwin) setupUi(this); setWindowTitle(tr(XCA_TITLE)); - certList->clear(); - certList->setColumnCount(3); - - QStringList sl; - sl << tr("Name") << tr("Serial") << tr("Revocation") << tr("Reason") << - tr("Invalidation"); - certList->setHeaderLabels(sl); - image->setPixmap(*MainWindow::revImg); descr->setReadOnly(true); } void CrlDetail::setCrl(pki_crl *crl) { - int numc, i; - pki_x509 *iss, *rev; - x509rev revit; + pki_x509 *iss; x509v3ext e1, e2; - QStringList sl; iss = crl->getIssuer(); signCheck->disableToolTip(); @@ -74,29 +64,7 @@ void CrlDetail::setCrl(pki_crl *crl) issuer->setX509name(crl->getSubject()); - numc = crl->numRev(); - for (i=0; igetRev(i); - rev = mw->certs->getByIssSerial(iss, revit.getSerial()); - certList->setColumnCount(5); - current = new QTreeWidgetItem(certList); - if (rev != NULL) { - current->setText(0, rev->getIntName() ); - } else { - current->setText(0, tr("Unknown certificate")); - } - current->setIcon(0, *pki_x509::icon[2]); - current->setText(1, revit.getSerial().toHex()) ; - current->setText(2, revit.getDate().toSortable()); - current->setText(3, revit.getReason()); - a = revit.getInvalDate(); - if (!a.isUndefined()) - current->setText(4, a.toSortable()); - } - for (i=0; i<5; i++) - certList->resizeColumnToContents(i); - certList->setSortingEnabled(true); + RevocationList::setupRevocationView(certList, crl->getRevList(), iss); + v3extensions->document()->setHtml(crl->printV3ext()); } diff --git a/widgets/MW_database.cpp b/widgets/MW_database.cpp index 5b850b49..91f67f44 100644 --- a/widgets/MW_database.cpp +++ b/widgets/MW_database.cpp @@ -52,6 +52,7 @@ int MainWindow::init_database() certs = new db_x509(dbfile, this); temps = new db_temp(dbfile, this); crls = new db_crl(dbfile, this); + certs->updateAfterDbLoad(); } catch (errorEx &err) { Error(err); diff --git a/widgets/MainWindow.cpp b/widgets/MainWindow.cpp index ebccf206..6cebb065 100644 --- a/widgets/MainWindow.cpp +++ b/widgets/MainWindow.cpp @@ -818,8 +818,9 @@ pki_multi *MainWindow::probeAnything(QString file, int *ret) if (file.endsWith(".xdb")) { try { int r; - db mydb(file); - mydb.verify_magic(); + db *mydb = new db(file); + mydb->verify_magic(); + delete mydb; r = changeDB(file); delete pki; if (ret) diff --git a/widgets/Makefile b/widgets/Makefile index d893fb17..df38e348 100644 --- a/widgets/Makefile +++ b/widgets/Makefile @@ -7,7 +7,7 @@ endif MOC_NAMES=MainWindow KeyDetail clicklabel XcaTreeView NewX509 \ validity v3ext distname CertDetail CertExtend PwDialog \ ImportMulti CrlDetail ExportDialog hashBox Options NewKey kvView \ - NewCrl SearchPkcs11 + NewCrl SearchPkcs11 RevocationList NAMES=$(MOC_NAMES) NewX509_ext MW_menu MW_help MW_database OBJS=$(patsubst %,moc_%.o,$(MOC_NAMES)) $(patsubst %,%.o,$(NAMES)) diff --git a/widgets/RevocationList.cpp b/widgets/RevocationList.cpp new file mode 100644 index 00000000..da368213 --- /dev/null +++ b/widgets/RevocationList.cpp @@ -0,0 +1,140 @@ +/* vi: set sw=4 ts=4: + * + * Copyright (C) 2015 Christian Hohnstaedt. + * + * All rights reserved. + */ + +#include "RevocationList.h" +#include "MainWindow.h" +#include "lib/asn1int.h" +#include "lib/pki_x509.h" + +enum revCol { Cserial, Cdate, Creason, CiDate }; + +static void addRevItem(QTreeWidget *certList, const x509rev &revit, + const pki_x509 *iss) +{ + QTreeWidgetItem *current; + pki_x509 *rev; + a1time a; + rev = iss->getBySerial(revit.getSerial()); + current = new QTreeWidgetItem(certList); + if (rev != NULL) { + current->setToolTip(Cserial, rev->getIntName() ); + } + current->setText(Cserial, revit.getSerial().toHex()) ; + current->setText(Cdate, revit.getDate().toSortable()); + current->setText(Creason, revit.getReason()); + a = revit.getInvalDate(); + if (!a.isUndefined()) + current->setText(CiDate, a.toSortable()); +} + +void RevocationList::setupRevocationView(QTreeWidget *certList, + const x509revList &revList, const pki_x509 *iss) +{ + QStringList sl; + int cols, i; + + certList->clear(); + + sl << tr("Serial") << tr("Revocation") << tr("Reason") << + tr("Invalidation"); + + cols = sl.size(); + certList->setColumnCount(cols); + certList->setHeaderLabels(sl); + certList->setItemsExpandable(false); + certList->setRootIsDecorated(false); + + foreach(x509rev revit, revList) { + addRevItem(certList, revit, iss); + } + for (i=0; iresizeColumnToContents(i); + certList->setSortingEnabled(true); +} + +RevocationList::RevocationList(QWidget *w) : QDialog(w) +{ + QPushButton *genCrl; + setupUi(this); + setWindowTitle(XCA_TITLE); + image->setPixmap(*MainWindow::revImg); + + genCrl = buttonBox->addButton(tr("Generate CRL"), + QDialogButtonBox::ActionRole); + connect(genCrl, SIGNAL(clicked(void)), this, SLOT(gencrl(void))); +} + +void RevocationList::gencrl(void) +{ + issuer->setRevocations(getRevList()); + emit genCRL(issuer); +} + +void RevocationList::setRevList(const x509revList &rl, pki_x509 *iss) +{ + issuer = iss; + revList = rl; + setupRevocationView(certList, revList, issuer); +} + +const x509revList &RevocationList::getRevList() +{ + return revList; +} + +void RevocationList::on_addRev_clicked(void) +{ + Revocation *revoke = new Revocation(this, NULL); + if (revoke->exec()) { + x509rev revit = revoke->getRevocation(); + revList << revit; + addRevItem(certList, revit, issuer); + } +} + +void RevocationList::on_delRev_clicked(void) +{ + QTreeWidgetItem *current = certList->currentItem(); + x509rev rev; + int idx; + a1int a1_serial; + + if (!current) + return; + idx = certList->indexOfTopLevelItem(current); + certList->takeTopLevelItem(idx); + a1_serial.setHex(current->text(Cserial)); + rev.setSerial(a1_serial); + idx = revList.indexOf(rev); + if (idx != -1) + revList.takeAt(idx); +} + +Revocation::Revocation(QWidget *w, pki_x509 *r) : QDialog(w) +{ + setupUi(this); + setWindowTitle(XCA_TITLE); + reason->addItems(x509rev::crlreasons()); + invalid->setNow(); + if (r) { + serial->setText(r->getSerial().toHex()); + serial->setEnabled(false); + } +} + +x509rev Revocation::getRevocation() +{ + x509rev r; + a1int i; + + i.setHex(serial->text()); + r.setSerial(i); + r.setDate(a1time::now()); + r.setInvalDate(invalid->getDate()); + r.setReason(reason->currentText()); + return r; +} diff --git a/widgets/RevocationList.h b/widgets/RevocationList.h new file mode 100644 index 00000000..8da33ea1 --- /dev/null +++ b/widgets/RevocationList.h @@ -0,0 +1,48 @@ +/* vi: set sw=4 ts=4: + * + * Copyright (C) 2015 Christian Hohnstaedt. + * + * All rights reserved. + */ + +#ifndef __REVOCATIONLIST_H +#define __REVOCATIONLIST_H + +#include "ui_RevocationList.h" +#include "ui_Revoke.h" +#include "lib/x509rev.h" + +class pki_x509; + +class RevocationList: public QDialog, public Ui::RevocationList +{ + Q_OBJECT + + private: + x509revList revList; + pki_x509 *issuer; + public: + static void setupRevocationView(QTreeWidget *certList, + const x509revList &revList, const pki_x509 *iss); + RevocationList(QWidget *w); + void setRevList(const x509revList &rl, pki_x509 *issuer); + const x509revList &getRevList(); + + public slots: + void on_addRev_clicked(void); + void on_delRev_clicked(void); + void gencrl(void); + + signals: + void genCRL(pki_x509 *iss); +}; + +class Revocation: public QDialog, public Ui::Revoke +{ + Q_OBJECT + + public: + Revocation(QWidget *w, pki_x509 *r); + x509rev getRevocation(); +}; +#endif diff --git a/xca.pro b/xca.pro index 72d43ac1..29d31291 100644 --- a/xca.pro +++ b/xca.pro @@ -81,6 +81,7 @@ HEADERS += local.h \ widgets/v3ext.h \ widgets/validity.h \ widgets/SearchPkcs11.h \ + widgets/RevocationList.h \ widgets/XcaTreeView.h FORMS += ui/About.ui \ @@ -103,6 +104,7 @@ FORMS += ui/About.ui \ ui/TrustState.ui \ ui/SearchPkcs11.ui \ ui/v3ext.ui \ + ui/RevocationList.ui SOURCES += lib/asn1int.cpp \ lib/asn1time.cpp \ @@ -165,6 +167,7 @@ SOURCES += lib/asn1int.cpp \ widgets/v3ext.cpp \ widgets/validity.cpp \ widgets/SearchPkcs11.cpp \ + widgets/RevocationList.cpp \ widgets/XcaTreeView.cpp TRANSLATIONS += lang/xca_de.ts lang/xca_es.ts lang/xca_ru.ts lang/xca.ts lang/xca_tr.ts lang/xca_fr.ts lang/xca_hr.ts