From 9085ecbd4eeff624f976342bd7d39c7b10f9023f Mon Sep 17 00:00:00 2001 From: Christian Hohnstaedt Date: Thu, 22 Jul 2010 06:57:32 +0200 Subject: [PATCH] More support for public keys Extract public key from cert and request Show public keys in requests- and cert-details in red Allow using public keys for certs. Useful if not selfsigning --- lib/db_x509.cpp | 5 ++++- lib/db_x509req.cpp | 3 +++ lib/db_x509super.cpp | 28 +++++++++++++++++++++------- lib/db_x509super.h | 2 +- lib/pki_key.cpp | 3 ++- lib/pki_x509super.cpp | 2 +- lib/x509v3ext.cpp | 15 +++++++++++---- ui/CertDetail.ui | 2 +- ui/ReqDetail.ui | 2 +- widgets/CertDetail.cpp | 11 +++++++---- widgets/NewX509.cpp | 32 ++++++++++++++++++++++++++------ widgets/ReqDetail.cpp | 15 ++++++++------- 12 files changed, 86 insertions(+), 34 deletions(-) diff --git a/lib/db_x509.cpp b/lib/db_x509.cpp index a1337591..6d8194b3 100644 --- a/lib/db_x509.cpp +++ b/lib/db_x509.cpp @@ -604,8 +604,12 @@ void db_x509::showContextMenu(QContextMenuEvent *e, const QModelIndex &index) menu->addAction(tr("Import PKCS#12"), this, SLOT(loadPKCS12())); menu->addAction(tr("Import from PKCS#7"), this, SLOT(loadPKCS7())); if (index != QModelIndex()) { + privkey = cert->getRefKey(); menu->addAction(tr("Rename"), this, SLOT(edit())); menu->addAction(tr("Show Details"), this, SLOT(showItem())); + if (!privkey) + menu->addAction(tr("Extract public Key"), + this, SLOT(extractPubkey())); subExport = menu->addMenu(tr("Export")); subExport->addAction(tr("File"), this, SLOT(store())); itemReq = subExport->addAction(tr("Request"), @@ -645,7 +649,6 @@ void db_x509::showContextMenu(QContextMenuEvent *e, const QModelIndex &index) && (cert->getSigner() != cert)); canSign = cert->canSign(); hasTemplates = mainwin->temps->getDesc().count() > 0 ; - privkey = cert->getRefKey(); hasScard = pkcs11::loaded(); itemRevoke->setEnabled(parentCanSign); diff --git a/lib/db_x509req.cpp b/lib/db_x509req.cpp index d598f403..d2d688a6 100644 --- a/lib/db_x509req.cpp +++ b/lib/db_x509req.cpp @@ -171,6 +171,9 @@ void db_x509req::showContextMenu(QContextMenuEvent *e, const QModelIndex &index) menu->addAction(tr("New Request"), this, SLOT(newItem())); menu->addAction(tr("Import"), this, SLOT(load())); if (index != QModelIndex()) { + if (!req->getRefKey()) + menu->addAction(tr("Extract public Key"), + this, SLOT(extractPubkey())); menu->addAction(tr("Rename"), this, SLOT(edit())); menu->addAction(tr("Show Details"), this, SLOT(showItem())); menu->addAction(tr("Sign"), this, SLOT(signReq())); diff --git a/lib/db_x509super.cpp b/lib/db_x509super.cpp index 757bab2f..5debdfcb 100644 --- a/lib/db_x509super.cpp +++ b/lib/db_x509super.cpp @@ -8,6 +8,7 @@ #include "db_x509super.h" #include "widgets/MainWindow.h" #include "ui_About.h" +#include db_x509super::db_x509super(QString db, MainWindow *mw) :db_base(db, mw) @@ -35,13 +36,9 @@ pki_key *db_x509super::findKey(pki_x509super *ref) if (!refkey) return NULL; key = (pki_key *)mainwin->keys->getByReference(refkey); - if (key && key->isPubKey()) { - key = NULL; - } else { - ref->setRefKey(key); - } - if (refkey) - delete(refkey); + ref->setRefKey(key); + delete(refkey); + return key; } @@ -59,6 +56,23 @@ pki_x509super *db_x509super::findByByPubKey(pki_key *refkey) return NULL; } +void db_x509super::extractPubkey() +{ + pki_key *key; + pki_x509super *pki = static_cast(currentIdx.internalPointer()); + if (!pki) + return; + key = pki->getPubKey(); + key->setIntName(pki->getIntName()); + if (!key) + return; + key = (pki_key*)mainwin->keys->insert(key); + if (!key) + return; + QMessageBox::information(mainwin, XCA_TITLE, + key->getMsg(pki_base::msg_import).arg(pki->getIntName())); +} + void db_x509super::toTemplate() { pki_x509super *pki = static_cast(currentIdx.internalPointer()); diff --git a/lib/db_x509super.h b/lib/db_x509super.h index 59ba4714..0bf5900c 100644 --- a/lib/db_x509super.h +++ b/lib/db_x509super.h @@ -25,7 +25,7 @@ class db_x509super: public db_base void delKey(pki_key *delkey); void newKey(pki_key *newKey); void toTemplate(); - + void extractPubkey(); }; #endif diff --git a/lib/pki_key.cpp b/lib/pki_key.cpp index 55d7b143..ac79a2b7 100644 --- a/lib/pki_key.cpp +++ b/lib/pki_key.cpp @@ -136,7 +136,8 @@ QString pki_key::getMsg(msg_type msg) QString pki_key::getIntNameWithType() { - return getIntName() + " (" + getTypeString() + ")"; + return QString("%1 (%2%3)").arg(getIntName()).arg(getTypeString()). + arg(isPubKey() ? QString(" ") + tr("public key") : QString("")); } QString pki_key::removeTypeFromIntName(QString n) diff --git a/lib/pki_x509super.cpp b/lib/pki_x509super.cpp index 4bed89af..d06d9a0e 100644 --- a/lib/pki_x509super.cpp +++ b/lib/pki_x509super.cpp @@ -27,7 +27,7 @@ pki_key *pki_x509super::getRefKey() const void pki_x509super::setRefKey(pki_key *ref) { - if (ref == NULL || ref->isPubKey() || privkey != NULL ) + if (ref == NULL || privkey != NULL ) return; pki_key *mk = getPubKey(); if (ref->compare(mk)) { diff --git a/lib/x509v3ext.cpp b/lib/x509v3ext.cpp index 5e904425..f62421e0 100644 --- a/lib/x509v3ext.cpp +++ b/lib/x509v3ext.cpp @@ -380,12 +380,13 @@ bool x509v3ext::parse_Crldp(QString *single, QString *adv) const { QString othersect; QStringList crldps; + const char *sn = OBJ_nid2sn(nid()); STACK_OF(DIST_POINT) *crld = (STACK_OF(DIST_POINT)*)d2i(); if (sk_DIST_POINT_num(crld) == 1 && single) { DIST_POINT *point = sk_DIST_POINT_value(crld, 0); if (point->distpoint && !point->reasons && !point->CRLissuer && - !point->distpoint->type && single) + !point->distpoint->type) { QString sect, ret; if (!genNameStack2conf(point->distpoint->name.fullname, @@ -393,7 +394,11 @@ bool x509v3ext::parse_Crldp(QString *single, QString *adv) const goto could_not_parse; if (sect.isEmpty()) { - *single = parse_critical() +ret; + if (single) + *single = parse_critical() +ret; + else if (adv) + *adv = QString("%1=%2\n").arg(sn). + arg(parse_critical() +ret) +*adv; return true; } } @@ -436,8 +441,10 @@ bool x509v3ext::parse_Crldp(QString *single, QString *adv) const if (crldps.size() == 0) return true; if (adv) { - *adv = "crlDistributionPoints=" + parse_critical() + - crldps.join(", ") + "\n" + *adv + othersect; + *adv = QString("%1=%2\n").arg(sn). + arg(parse_critical() + crldps.join(", ")) + + *adv + othersect; + #if OPENSSL_VERSION_NUMBER < 0x10000000L *adv = QString( "\n" "# This syntax only works for openssl >= 1.0.0\n" diff --git a/ui/CertDetail.ui b/ui/CertDetail.ui index 91f8c1e4..05811273 100644 --- a/ui/CertDetail.ui +++ b/ui/CertDetail.ui @@ -216,7 +216,7 @@ - Private key + Key diff --git a/ui/ReqDetail.ui b/ui/ReqDetail.ui index 2b8e6a10..90c29969 100644 --- a/ui/ReqDetail.ui +++ b/ui/ReqDetail.ui @@ -83,7 +83,7 @@ - 1 + 0 diff --git a/widgets/CertDetail.cpp b/widgets/CertDetail.cpp index 6a8f0b3d..543d918f 100644 --- a/widgets/CertDetail.cpp +++ b/widgets/CertDetail.cpp @@ -46,11 +46,14 @@ void CertDetail::setCert(pki_x509 *cert) // examine the key pki_key *key= cert->getRefKey(); - if (key && key->isPrivKey()) { + if (key) { privKey->setText(key->getIntName()); - privKey->setGreen(); - } - else { + if (key->isPrivKey()) { + privKey->setGreen(); + } else { + privKey->setRed(); + } + } else { privKey->setText(tr("Not available")); privKey->setDisabled(true); privKey->disableToolTip(); diff --git a/widgets/NewX509.cpp b/widgets/NewX509.cpp index 920a5ce8..7adeae08 100644 --- a/widgets/NewX509.cpp +++ b/widgets/NewX509.cpp @@ -915,7 +915,8 @@ void NewX509::accept() { gotoTab(1); QMessageBox msg(QMessageBox::Warning, XCA_TITLE, - tr("There is no Key selected for signing."), QMessageBox::NoButton, this); + tr("There is no Key selected for signing."), + QMessageBox::NoButton, this); msg.addButton(QMessageBox::Ok)->setText(tr("Select key")); msg.addButton(QMessageBox::Close)->setText(tr("Abort rollout")); if (msg.exec() == QMessageBox::Close) { @@ -966,9 +967,29 @@ void NewX509::accept() break; } } - pki_x509 *signer = getSelectedSigner(); - if (signer && notBefore->getDate() < signer->getNotBefore() && - !selfSignRB->isChecked()) { + pki_x509 *signer = NULL; + if (!selfSignRB->isChecked()) + signer = getSelectedSigner(); + + pki_key *signkey = getSelectedKey(); + if (signer) + signkey = signer->getRefKey(); + + if (!signkey || signkey->isPubKey()) { + QString txt; + gotoTab(signer ? 0 : 1); + QMessageBox msg(QMessageBox::Warning, XCA_TITLE, + tr("The key you selected for signing is not a private one."), + QMessageBox::NoButton, this); + txt = signer ? tr("Select other signer"):tr("Select other key"); + msg.addButton(QMessageBox::Ok)->setText(txt); + msg.addButton(QMessageBox::Close)->setText(tr("Abort rollout")); + if (msg.exec() == QMessageBox::Close) { + reject(); + } + return; + } + if (signer && notBefore->getDate() < signer->getNotBefore()) { gotoTab(2); QString text = tr("The certificate will be earlier valid than the signer. This is probably not what you want."); QMessageBox msg(QMessageBox::Warning, XCA_TITLE, @@ -992,8 +1013,7 @@ void NewX509::accept() } } if (signer && notAfter->getDate() > signer->getNotAfter() && - !noWellDefinedExpDate->isChecked() && - !selfSignRB->isChecked()) { + !noWellDefinedExpDate->isChecked()) { gotoTab(2); QString text = tr("The certificate will be longer valid than the signer. This is probably not what you want."); QMessageBox msg(QMessageBox::Warning, XCA_TITLE, diff --git a/widgets/ReqDetail.cpp b/widgets/ReqDetail.cpp index 543d4a0a..696ac72c 100644 --- a/widgets/ReqDetail.cpp +++ b/widgets/ReqDetail.cpp @@ -33,13 +33,11 @@ void ReqDetail::setReq(pki_x509req *req) if (!req->verify() ) { verify->setRed(); verify->setText("Failed"); - } - else { + } else { verify->setGreen(); if (req->isSpki()) { verify->setText("SPKAC"); - } - else { + } else { verify->setText("PKCS#10"); } } @@ -48,9 +46,12 @@ void ReqDetail::setReq(pki_x509req *req) pki_key *key =req->getRefKey(); if (key) { privKey->setText(key->getIntName()); - privKey->setGreen(); - } - else { + if (key->isPrivKey()) { + privKey->setGreen(); + } else { + privKey->setRed(); + } + } else { privKey->setText(tr("Not available")); privKey->setDisabled(true); privKey->disableToolTip();