From bdfa10d4d502b21a70a82322ded1b4cef2ede69a Mon Sep 17 00:00:00 2001 From: Christian Hohnstaedt Date: Sun, 1 Jul 2018 09:55:16 +0200 Subject: [PATCH] Close #45: Unable to view Public Key Allow displaying the public key of a certificate or request without importing it. When importing certificates or CRLs, display the issuer if it exists in the database. --- lib/pki_base.cpp | 9 +++++++ lib/pki_base.h | 1 + lib/pki_crl.cpp | 16 +++++++++--- lib/pki_crl.h | 1 + lib/pki_evp.cpp | 3 +++ lib/pki_key.cpp | 6 +++++ lib/pki_key.h | 1 + lib/pki_temp.cpp | 1 + lib/pki_x509.cpp | 11 ++++---- lib/pki_x509req.cpp | 3 --- lib/pki_x509super.cpp | 13 ++++++++-- lib/pki_x509super.h | 1 + ui/KeyDetail.ui | 2 +- widgets/CertDetail.cpp | 34 ++++++++++++++++++++++-- widgets/CertDetail.h | 5 +++- widgets/ImportMulti.cpp | 57 +++++++++++++++++++++++++++++------------ 16 files changed, 129 insertions(+), 35 deletions(-) diff --git a/lib/pki_base.cpp b/lib/pki_base.cpp index 31e33362..53c9073f 100644 --- a/lib/pki_base.cpp +++ b/lib/pki_base.cpp @@ -36,6 +36,12 @@ QString pki_base::comboText() const { return desc; } + +void pki_base::autoIntName() +{ + setIntName(""); +} + void pki_base::deleteFromToken() { }; void pki_base::deleteFromToken(slotid) { }; void pki_base::writeDefault(const QString) { } @@ -121,6 +127,9 @@ void pki_base::fromPEMbyteArray(QByteArray &ba, QString name) BIO *bio = BIO_new_mem_buf(ba.data(), ba.length()); fromPEM_BIO(bio, name); BIO_free(bio); + autoIntName(); + if (getIntName().isEmpty()) + setIntName(rmslashdot(name)); } QString pki_base::rmslashdot(const QString &s) diff --git a/lib/pki_base.h b/lib/pki_base.h index b8bc9808..fbe6b711 100644 --- a/lib/pki_base.h +++ b/lib/pki_base.h @@ -88,6 +88,7 @@ class pki_base : public QObject { desc = d; } + virtual void autoIntName(); QString getComment() const { return comment; diff --git a/lib/pki_crl.cpp b/lib/pki_crl.cpp index 4b56b909..6241e917 100644 --- a/lib/pki_crl.cpp +++ b/lib/pki_crl.cpp @@ -32,7 +32,6 @@ void pki_crl::fromPEM_BIO(BIO *bio, QString name) openssl_error(name); X509_CRL_free(crl); crl = _crl; - setIntName(rmslashdot(name)); } QString pki_crl::getMsg(msg_type msg) const @@ -53,7 +52,7 @@ QString pki_crl::getMsg(msg_type msg) const return pki_base::getMsg(msg); } -QSqlError pki_crl::insertSqlData() +QSqlError pki_crl::lookupIssuer() { XSqlQuery q; unsigned name_hash = getSubject().hashNum(); @@ -74,12 +73,23 @@ QSqlError pki_crl::insertSqlData() } verify(x); } + return q.lastError(); +} + +QSqlError pki_crl::insertSqlData() +{ + QSqlError e = lookupIssuer(); + + if (e.isValid()) + return e; + + XSqlQuery q; SQL_PREPARE(q, "INSERT INTO crls (item, hash, num, iss_hash, issuer, crl) " "VALUES (?, ?, ?, ?, ?, ?)"); q.bindValue(0, sqlItemId); q.bindValue(1, hash()); q.bindValue(2, numRev()); - q.bindValue(3, name_hash); + q.bindValue(3, (uint)getSubject().hashNum()); q.bindValue(4, issuer ? issuer->getSqlItemId() : QVariant()); q.bindValue(5, i2d_b64()); q.exec(); diff --git a/lib/pki_crl.h b/lib/pki_crl.h index f4a8ba9c..be228c01 100644 --- a/lib/pki_crl.h +++ b/lib/pki_crl.h @@ -78,6 +78,7 @@ class pki_crl: public pki_x509name a1int getCrlNumber() const; BIO *pem(BIO *, int); bool visible() const; + QSqlError lookupIssuer(); QSqlError insertSqlData(); QSqlError deleteSqlData(); void restoreSql(const QSqlRecord &rec); diff --git a/lib/pki_evp.cpp b/lib/pki_evp.cpp index d82fe4e2..7a5cd0cc 100644 --- a/lib/pki_evp.cpp +++ b/lib/pki_evp.cpp @@ -274,6 +274,9 @@ void pki_evp::fromPEMbyteArray(QByteArray &ba, QString name) setIntName(rmslashdot(name)); set_EVP_PKEY(pkey); + autoIntName(); + if (getIntName().isEmpty()) + setIntName(rmslashdot(name)); } static void search_ec_oid(EVP_PKEY *pkey) diff --git a/lib/pki_key.cpp b/lib/pki_key.cpp index 846d4947..10eb2d20 100644 --- a/lib/pki_key.cpp +++ b/lib/pki_key.cpp @@ -50,6 +50,12 @@ pki_key::~pki_key() EVP_PKEY_free(key); } +void pki_key::autoIntName() +{ + setIntName(QString("%1 %2%3").arg(length(), getTypeString(), + isPubKey() ? QString(" ") + tr("Public key") : QString(""))); +} + void pki_key::d2i(QByteArray &ba) { EVP_PKEY *k = (EVP_PKEY*)d2i_bytearray(D2I_VOID(d2i_PUBKEY), ba); diff --git a/lib/pki_key.h b/lib/pki_key.h index 41a6ddab..4f10ce9c 100644 --- a/lib/pki_key.h +++ b/lib/pki_key.h @@ -47,6 +47,7 @@ class pki_key: public pki_base pki_key(const pki_key *pk); virtual ~pki_key(); static builtin_curves builtinCurves; + void autoIntName(); QString length() const; QString comboText() const; QString getKeyTypeString(void) const; diff --git a/lib/pki_temp.cpp b/lib/pki_temp.cpp index e40e9686..7c7d9eb4 100644 --- a/lib/pki_temp.cpp +++ b/lib/pki_temp.cpp @@ -435,6 +435,7 @@ void pki_temp::try_fload(QString fname, const char *mode) try { fromPEM_BIO(b, fname); BIO_free(b); + setIntName(rmslashdot(fname)); return; } catch (errorEx &err) { BIO_free(b); diff --git a/lib/pki_x509.cpp b/lib/pki_x509.cpp index 57b41246..5d7418c6 100644 --- a/lib/pki_x509.cpp +++ b/lib/pki_x509.cpp @@ -206,16 +206,13 @@ pki_x509 *pki_x509::findIssuer() return NULL; } -void pki_x509::fromPEM_BIO(BIO *bio, QString name) +void pki_x509::fromPEM_BIO(BIO *bio, QString) { X509 *_cert; _cert = PEM_read_bio_X509(bio, NULL, NULL, NULL); pki_openssl_error(); X509_free(cert); cert = _cert; - autoIntName(); - if (getIntName().isEmpty()) - setIntName(rmslashdot(name)); } void pki_x509::fload(const QString fname) @@ -738,7 +735,9 @@ bool pki_x509::verify(pki_x509 *signer) return true; if ((psigner != NULL) || (signer == NULL)) return false; - if (signer == this && signerSqlId == sqlItemId) + if (signer == this && + signerSqlId == sqlItemId && + signerSqlId != QVariant()) return true; if (verify_only(signer)) { @@ -894,7 +893,7 @@ int pki_x509::sigAlg() const pki_x509 *pki_x509::getSigner() { - return static_cast(psigner); + return psigner; } bool pki_x509::isRevoked() const diff --git a/lib/pki_x509req.cpp b/lib/pki_x509req.cpp index b27ea13a..6ae815f1 100644 --- a/lib/pki_x509req.cpp +++ b/lib/pki_x509req.cpp @@ -138,9 +138,6 @@ void pki_x509req::fromPEM_BIO(BIO *bio, QString name) openssl_error(name); X509_REQ_free(request); request = req; - autoIntName(); - if (getIntName().isEmpty()) - setIntName(rmslashdot(name)); } void pki_x509req::fload(const QString fname) diff --git a/lib/pki_x509super.cpp b/lib/pki_x509super.cpp index 6fba3713..4c5dab3a 100644 --- a/lib/pki_x509super.cpp +++ b/lib/pki_x509super.cpp @@ -20,7 +20,7 @@ pki_x509super::~pki_x509super() { } -QSqlError pki_x509super::insertSqlData() +QSqlError pki_x509super::lookupKey() { XSqlQuery q; unsigned hash = pubHash(); @@ -43,13 +43,22 @@ QSqlError pki_x509super::insertSqlData() break; } } + return q.lastError(); +} +QSqlError pki_x509super::insertSqlData() +{ + QSqlError e = lookupKey(); + if (e.isValid()) + return e; + + XSqlQuery q; SQL_PREPARE(q, "INSERT INTO x509super (item, subj_hash, pkey, key_hash) " "VALUES (?, ?, ?, ?)"); q.bindValue(0, sqlItemId); q.bindValue(1, (uint)getSubject().hashNum()); q.bindValue(2, privkey ? privkey->getSqlItemId() : QVariant()); - q.bindValue(3, hash); + q.bindValue(3, pubHash()); q.exec(); return q.lastError(); } diff --git a/lib/pki_x509super.h b/lib/pki_x509super.h index e1059df4..6a1918f3 100644 --- a/lib/pki_x509super.h +++ b/lib/pki_x509super.h @@ -52,6 +52,7 @@ class pki_x509super : public pki_x509name QVariant column_data(const dbheader *hd) const; void opensslConf(QString fname); bool visible() const; + QSqlError lookupKey(); QSqlError insertSqlData(); QSqlError deleteSqlData(); void restoreSql(const QSqlRecord &rec); diff --git a/ui/KeyDetail.ui b/ui/KeyDetail.ui index 26e46a13..b9c05d42 100644 --- a/ui/KeyDetail.ui +++ b/ui/KeyDetail.ui @@ -6,7 +6,7 @@ 0 0 - 532 + 572 403 diff --git a/widgets/CertDetail.cpp b/widgets/CertDetail.cpp index cb1c114c..d3936ec9 100644 --- a/widgets/CertDetail.cpp +++ b/widgets/CertDetail.cpp @@ -7,6 +7,7 @@ #include "CertDetail.h" +#include "KeyDetail.h" #include "MainWindow.h" #include "distname.h" #include "clicklabel.h" @@ -24,6 +25,7 @@ CertDetail::CertDetail(QWidget *parent) showConf = false; keySqlId = QVariant(); issuerSqlId = QVariant(); + myPubKey = NULL; } void CertDetail::on_showExt_clicked() @@ -46,6 +48,7 @@ void CertDetail::setX509super(pki_x509super *x) // examine the key pki_key *key= x->getRefKey(); + myPubKey = x->getPubKey(); if (key) { privKey->setText(key->getIntName()); privKey->setClickText(key->getSqlItemId().toString()); @@ -55,6 +58,13 @@ void CertDetail::setX509super(pki_x509super *x) privKey->setRed(); } keySqlId = key->getSqlItemId(); + } else if (myPubKey) { + privKey->setText(tr("Show public key")); + privKey->setRed(); + connect(privKey, SIGNAL(doubleClicked(QString)), + this, SLOT(showPubKey())); + myPubKey->setIntName(x->getIntName()); + myPubKey->setComment(tr("This key is not in the database.")); } else { privKey->setText(tr("Not available")); privKey->setDisabled(true); @@ -94,11 +104,11 @@ void CertDetail::setCert(pki_x509 *cert) tabwidget->removeTab(3); // examine the signature - if ( cert->getSigner() == NULL) { + if (cert->getSigner() == NULL) { signature->setText(tr("Signer unknown")); signature->setDisabled(true); signature->disableToolTip(); - } else if ( cert == cert->getSigner()) { + } else if (cert == cert->getSigner()) { signature->setText(tr("Self signed")); signature->setGreen(); signature->disableToolTip(); @@ -243,3 +253,23 @@ void CertDetail::itemChanged(pki_base *pki) if (pki->getSqlItemId() == issuerSqlId) signature->setText(pki->getIntName()); } + +void CertDetail::showPubKey() +{ + if (!myPubKey) + return; + KeyDetail *dlg = new KeyDetail(this); + if (!dlg) + return; + dlg->setKey(myPubKey); + dlg->keyDesc->setReadOnly(true); + dlg->comment->setReadOnly(true); + dlg->exec(); + delete dlg; +} + +CertDetail::~CertDetail() +{ + if (myPubKey) + delete myPubKey; +} diff --git a/widgets/CertDetail.h b/widgets/CertDetail.h index 785e6a82..f33a11c2 100644 --- a/widgets/CertDetail.h +++ b/widgets/CertDetail.h @@ -23,15 +23,18 @@ class CertDetail: public QDialog, public Ui::CertDetail QString conf, exts; QLabel *labelFromAsn1String(ASN1_STRING *s); void setX509super(pki_x509super *x); + pki_key *myPubKey; public: - CertDetail( QWidget *parent); + CertDetail(QWidget *parent); + ~CertDetail(); void setCert(pki_x509 *cert); void setReq(pki_x509req *req); private slots: void on_showExt_clicked(); void itemChanged(pki_base *pki); + void showPubKey(); }; #endif diff --git a/widgets/ImportMulti.cpp b/widgets/ImportMulti.cpp index 2f1e24e6..05d9735a 100644 --- a/widgets/ImportMulti.cpp +++ b/widgets/ImportMulti.cpp @@ -77,10 +77,24 @@ void ImportMulti::addItem(pki_base *pki) pki->pkiSource = imported; const std::type_info &t = typeid(*pki); - - if (t == typeid(pki_x509) || t == typeid(pki_evp) || - t == typeid(pki_x509req) || t == typeid(pki_crl) || - t == typeid(pki_temp) || t == typeid(pki_scard)) + if (t == typeid(pki_x509)) { + pki_x509 *x = static_cast(pki); + x->setSigner(x->findIssuer()); + x->lookupKey(); + mcont->inToCont(pki); + } + else if (t == typeid(pki_x509req)) { + pki_x509req *x = static_cast(pki); + x->lookupKey(); + mcont->inToCont(pki); + } + else if (t == typeid(pki_crl)) { + pki_crl *x = static_cast(pki); + x->lookupIssuer(); + mcont->inToCont(pki); + } + else if (t == typeid(pki_evp) || t == typeid(pki_temp) || + t == typeid(pki_scard)) { mcont->inToCont(pki); } @@ -287,28 +301,38 @@ void ImportMulti::on_butDetails_clicked() const std::type_info &t = typeid(*pki); try { if (t == typeid(pki_x509)){ - CertDetail *dlg; - dlg = new CertDetail(mainwin); + CertDetail *dlg = new CertDetail(mainwin); dlg->setCert(static_cast(pki)); - dlg->exec(); + connect(dlg->privKey, SIGNAL(doubleClicked(QString)), + mainwin->keys, SLOT(showItem(QString))); + connect(dlg->signature, + SIGNAL(doubleClicked(QString)), + mainwin->certs, SLOT(showItem(QString))); + if (dlg->exec()) + pki->setIntName(dlg->descr->text()); delete dlg; } else if (t == typeid(pki_evp) || t == typeid(pki_scard)) { - KeyDetail *dlg; - dlg = new KeyDetail(mainwin); + KeyDetail *dlg = new KeyDetail(mainwin); dlg->setKey(static_cast(pki)); - dlg->exec(); + if (dlg->exec()) + pki->setIntName(dlg->keyDesc->text()); delete dlg; } else if (t == typeid(pki_x509req)) { - CertDetail *dlg; - dlg = new CertDetail(mainwin); + CertDetail *dlg = new CertDetail(mainwin); dlg->setReq(static_cast(pki)); - dlg->exec(); + connect(dlg->privKey, SIGNAL(doubleClicked(QString)), + mainwin->keys, SLOT(showItem(QString))); + if (dlg->exec()) + pki->setIntName(dlg->descr->text()); delete dlg; } else if (t == typeid(pki_crl)) { - CrlDetail *dlg; - dlg = new CrlDetail(mainwin); + CrlDetail *dlg = new CrlDetail(mainwin); dlg->setCrl(static_cast(pki)); - dlg->exec(); + connect(dlg->issuerIntName, + SIGNAL(doubleClicked(QString)), + mainwin->certs, SLOT(showItem(QString))); + if (dlg->exec()) + pki->setIntName(dlg->descr->text()); delete dlg; } else if (t == typeid(pki_temp)) { XCA_WARN(tr("Details of the item '%1' cannot be shown") @@ -319,7 +343,6 @@ void ImportMulti::on_butDetails_clicked() catch (errorEx &err) { mainwin->Error(err); } - } ImportMulti::~ImportMulti()