diff --git a/changelog b/changelog index c4fd46f5..477946be 100644 --- a/changelog +++ b/changelog @@ -1,3 +1,9 @@ + * remove extension and attribute tab in details dialog if + no extensions or attributes available + * documentation updated + * X509 request attributes (like challange password) can be set + and viewed. + xca 0.6.3 * show CRL signature algorithm information diff --git a/doc/xca.sgml b/doc/xca.sgml index 72c708a6..07d8ae2f 100644 --- a/doc/xca.sgml +++ b/doc/xca.sgml @@ -579,6 +579,37 @@ then a Certificate Revocation List should be created and will be stored in the database.

+Options +

+The options dialog can be found in the file menu. All options are saved +in the database and do not depend on the operating systems registry or +configuration files. +

+ +Mandatory subject entries +

+A list of mandatory distinguished name entries may be specified to +get a warning, whenever issuing a certificate with one of the listed +entry is empty. This requirement is not checked when editing templates, +because templates may have empty entries that will be filled during +the rollout of the certificate. +

+ +Allow multiple use of keys +

+When creating certificates or requests the list of keys only contains unused keys +to avoid a duplicate use of keys. This option allows the user to shoot herself +into the foot. If this option is checked, the key list will contain +all available keys. Usually, you don't want to enable this. +

+ +Default hash algorithm +

+Older Windows versions and OpenSSL versions can not handle +SHA256 and SHA512. This option allows to set the hash algorithm to SHA1 +for instance. +

+ Object IDs

diff --git a/lib/db_x509.cpp b/lib/db_x509.cpp index 3964f45e..98ea711f 100644 --- a/lib/db_x509.cpp +++ b/lib/db_x509.cpp @@ -500,17 +500,7 @@ void db_x509::newCert(NewX509 *dlg) cert->addV3ext(el[i]); } - cert->addV3ext(dlg->getBasicConstraints()); - cert->addV3ext(dlg->getSubKeyIdent()); - cert->addV3ext(dlg->getAuthKeyIdent()); - cert->addV3ext(dlg->getKeyUsage()); - cert->addV3ext(dlg->getEkeyUsage()); - cert->addV3ext(dlg->getSubAltName()); - cert->addV3ext(dlg->getIssAltName()); - cert->addV3ext(dlg->getCrlDist()); - cert->addV3ext(dlg->getAuthInfAcc()); - cert->addV3ext(dlg->getCertPol()); - extList ne = dlg->getNetscapeExt(); + extList ne = dlg->getAllExt(); int m = ne.count(); for (int i=0; iaddV3ext(ne[i]); @@ -536,7 +526,8 @@ void db_x509::newCert(NewX509 *dlg) catch (errorEx &err) { mainwin->Error(err); delete cert; - if (tempkey != NULL) delete(tempkey); + if (tempkey != NULL) + delete(tempkey); } } diff --git a/lib/db_x509req.cpp b/lib/db_x509req.cpp index 478832d3..94eb902d 100644 --- a/lib/db_x509req.cpp +++ b/lib/db_x509req.cpp @@ -69,6 +69,7 @@ void db_x509req::newItem(pki_temp *temp) req->setIntName(dlg->description->text()); dlg->initCtx(NULL, NULL, req); + dlg->addReqAttributes(req); req->createReq(key, xn, dlg->hashAlgo->currentHash(), dlg->getAllExt()); insert(req); } diff --git a/lib/func.cpp b/lib/func.cpp index 77bed125..1b2edd64 100644 --- a/lib/func.cpp +++ b/lib/func.cpp @@ -9,6 +9,8 @@ #include "func.h" #include "lib/asn1time.h" #include "widgets/validity.h" +#include +#include #include #include @@ -163,3 +165,11 @@ QString asn1ToQString(const ASN1_STRING *str) //printf("Convert %s string to '%s'\n", ASN1_tag2str(str->type),CCHAR(qs)); return qs; } + +/* returns an encoded ASN1 string from QString for a special nid*/ +ASN1_STRING *QStringToAsn1(const QString s, int nid) +{ + const unsigned char *utf8 = (const unsigned char *)s.toUtf8().constData(); + ASN1_STRING_set_by_NID(NULL, utf8, -1, MBSTRING_UTF8, nid); +} + diff --git a/lib/func.h b/lib/func.h index 95ea3456..11b4bb3c 100644 --- a/lib/func.h +++ b/lib/func.h @@ -20,4 +20,5 @@ QString getHomeDir(); void applyTD(QWidget *parent, int number, int range, bool mnc, Validity *nb, Validity *na); QString asn1ToQString(const ASN1_STRING *str); +ASN1_STRING *QStringToAsn1(QString s, int nid); #endif diff --git a/lib/pki_crl.cpp b/lib/pki_crl.cpp index f0aaa0f6..645ad9f3 100644 --- a/lib/pki_crl.cpp +++ b/lib/pki_crl.cpp @@ -25,7 +25,7 @@ pki_crl::pki_crl(const QString name ) void pki_crl::fload(const QString fname ) { - FILE * fp = fopen(CCHAR(fname), "r"); + FILE *fp = fopen(CCHAR(fname), "r"); if (fp != NULL) { crl = PEM_read_X509_CRL(fp, &crl, NULL, NULL); if (!crl) { diff --git a/lib/pki_x509req.cpp b/lib/pki_x509req.cpp index 1b39c91b..ae8386f0 100644 --- a/lib/pki_x509req.cpp +++ b/lib/pki_x509req.cpp @@ -125,6 +125,20 @@ void pki_x509req::fromData(const unsigned char *p, db_header_t *head ) openssl_error(); } +void pki_x509req::addAttribute(int nid, QString content) +{ + if (content.isEmpty()) + return; + + ASN1_STRING *a = QStringToAsn1(content, nid); + if (!a) { + openssl_error(); + return; + } + X509_REQ_add1_attr_by_NID(request, nid, a->type, a->data, a->length); + ASN1_STRING_free(a); +} + x509name pki_x509req::getSubject() const { x509name x(X509_REQ_get_subject_name(request)); diff --git a/lib/pki_x509req.h b/lib/pki_x509req.h index 677c4733..30eb6aa8 100644 --- a/lib/pki_x509req.h +++ b/lib/pki_x509req.h @@ -45,6 +45,7 @@ class pki_x509req : public pki_x509super bool isSpki() const; void writeReq(const QString fname, bool pem); X509_REQ *getReq() {return request;} + void addAttribute(int nid, QString content); int verify(); pki_key *getPubKey() const; diff --git a/lib/x509name.cpp b/lib/x509name.cpp index 983606f3..2d1a3792 100644 --- a/lib/x509name.cpp +++ b/lib/x509name.cpp @@ -9,6 +9,8 @@ #include "base.h" #include "func.h" #include +#include +#include "exception.h" x509name::x509name() { @@ -119,7 +121,7 @@ int x509name::nid(int i) const return nid; } -unsigned char *x509name::d2i(const unsigned char *p, int size) +const unsigned char *x509name::d2i(const unsigned char *p, int size) { X509_NAME *xn_sik = xn; xn = D2I_CLASH(d2i_X509_NAME, NULL, &p, size); @@ -127,14 +129,13 @@ unsigned char *x509name::d2i(const unsigned char *p, int size) xn = xn_sik; else X509_NAME_free(xn_sik); - return (unsigned char *)p; + return p; } unsigned char *x509name::i2d(unsigned char *p) { - unsigned char *mp = p; - i2d_X509_NAME(xn, &mp); - return mp; + i2d_X509_NAME(xn, &p); + return p; } bool x509name::operator == (const x509name &x) const @@ -158,52 +159,23 @@ int x509name::getNidByName(const QString &nid_name) return OBJ_txt2nid(nid_name.toAscii()); } -static int fix_data(int nid, int *type) -{ - if (nid == NID_pkcs9_emailAddress) - *type=V_ASN1_IA5STRING; - if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING)) - *type=V_ASN1_T61STRING; - if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING)) - *type=V_ASN1_T61STRING; - if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING)) - return(0); - if (nid == NID_pkcs9_unstructuredName) - *type=V_ASN1_IA5STRING; - return 1; -} - void x509name::addEntryByNid(int nid, const QString entry) { - if (entry.isEmpty()) return; - - // check for a UNICODE-String. - bool need_uc=false; - - for (int i=0;i127) { need_uc=true; break; } - - if (need_uc) { - unsigned char *data = (unsigned char *)OPENSSL_malloc(entry.length()*2); - - for (int i=0;i> 8; - data[2*i+1] = entry.at(i).unicode() & 0xff; + if (entry.isEmpty()) + return; + ASN1_STRING *a = QStringToAsn1(entry, nid); + if (!a) { + QString error = QString(OBJ_nid2ln(nid)) + ":\n"; + while (int i = ERR_get_error() ) { + fprintf(stderr, "OpenSSL error: %s\n", ERR_error_string(i ,NULL) ); + error += ERR_error_string(i, NULL); + error += "\n"; } - - X509_NAME_add_entry_by_NID(xn, nid, V_ASN1_BMPSTRING, - data,entry.length()*2,-1,0); - OPENSSL_free(data); - } - else { - unsigned char *x = (unsigned char*)CCHAR(entry); - int type = ASN1_PRINTABLE_type(x,-1); - - if (fix_data(nid, &type) == 0) - return; - - X509_NAME_add_entry_by_NID(xn, nid, type, x,-1,-1,0); + throw errorEx(error, "x509name"); + return; } + X509_NAME_add_entry_by_NID(xn, nid, a->type, a->data, a->length, -1, 0); + ASN1_STRING_free(a); } X509_NAME *x509name::get() const diff --git a/lib/x509name.h b/lib/x509name.h index e6403b34..4f705087 100644 --- a/lib/x509name.h +++ b/lib/x509name.h @@ -24,7 +24,7 @@ class x509name x509name &set(const X509_NAME *n); QString oneLine(unsigned long flags = XN_FLAG_ONELINE) const; int nid(int i) const; - unsigned char *d2i(const unsigned char *p, int size); + const unsigned char *d2i(const unsigned char *p, int size); unsigned char *i2d(unsigned char *p); QStringList entryList(int i) const; QString getEntryByNid(int nid ) const; diff --git a/lib/x509v3ext.cpp b/lib/x509v3ext.cpp index cee8ec5e..8041706e 100644 --- a/lib/x509v3ext.cpp +++ b/lib/x509v3ext.cpp @@ -42,14 +42,14 @@ x509v3ext &x509v3ext::set(const X509_EXTENSION *n) x509v3ext &x509v3ext::create(int nid, const QString &et, X509V3_CTX *ctx) { - if (ext) { - X509_EXTENSION_free(ext); - ext = NULL; - } + X509_EXTENSION *new_ext = NULL; if (!et.isEmpty()) { - ext = X509V3_EXT_conf_nid(NULL, ctx, nid, (char*)CCHAR(et)); + new_ext = X509V3_EXT_conf_nid(NULL, ctx, nid, (char*)CCHAR(et)); + } + if (new_ext) { + X509_EXTENSION_free(ext); + ext = new_ext; } - if (!ext) ext = X509_EXTENSION_new(); return *this; } diff --git a/ui/CertDetail.ui b/ui/CertDetail.ui index 62b1551f..e3f346c0 100644 --- a/ui/CertDetail.ui +++ b/ui/CertDetail.ui @@ -83,7 +83,7 @@ - + 0 @@ -474,11 +474,6 @@ - - CopyLabel - QLabel -

widgets/clicklabel.h
- ClickLabel QLabel @@ -490,6 +485,11 @@
widgets/distname.h
1
+ + CopyLabel + QLabel +
widgets/clicklabel.h
+
diff --git a/ui/NewX509.ui b/ui/NewX509.ui index 229adf53..ff8f329f 100644 --- a/ui/NewX509.ui +++ b/ui/NewX509.ui @@ -5,8 +5,8 @@ 0 0 - 596 - 580 + 587 + 610 @@ -119,44 +119,68 @@ Signing request - + - 8 + 9 6 - - - - Sign this Certificate signing &request - - - - - - - Copy extensions from the request - - - true - - - - - - - A certificate signing request can be signed, even if the private key of the request is not available. This is the intention of a CSR: + + + + + 0 + + + 6 + + + + + A certificate signing request can be signed, even if the private key of the request is not available. This is the intention of a CSR: Getting signed by a CA certificate, whoes certificate of course must be in the database Of course you need the private key of the CSR if you want to create a self-signed cert from it. - + + + + + + + Show request + + + + + + + Sign this Certificate signing &request + + + + + + + Copy extensions from the request + + + true + + + + - - - - Show request - + + + + + 0 + + + 6 + + @@ -627,7 +651,7 @@ If this list is disabled, you only can create a self-signed certificate. - 8 + 9 6 @@ -792,103 +816,105 @@ It also copies the issuer and serial number from the issuer certificate. Normall - - - 0 - - - 6 - - - - - Validity - - - - 8 + + + + 9 + + + 6 + + + + + Validity - - 6 - - - - - - - - - - - Not before - - - - - - - Not after - - - - - - - - - - Time range - - - - 8 - - - 6 - - - - - Apply - - - - - - + + + 8 + + + 6 + + + + + + + + + - Days + Not before - - + + + + - Months + Not after - - + + + + + + + + + Time range + + + + 8 + + + 6 + + + - Years + Apply - - - - - - - Set the time to 00:00:00 and 23:59:59 respectively - - - Midnight - - - - - - - - - - + + + + + + + Days + + + + + Months + + + + + Years + + + + + + + + Set the time to 00:00:00 and 23:59:59 respectively + + + Midnight + + + + + + + + + + + @@ -1034,16 +1060,6 @@ email:my@other.address, RID:1.2.3.4, DNS: ns.server.tld - - - - 0 - 0 - 100 - 30 - - - diff --git a/ui/ReqDetail.ui b/ui/ReqDetail.ui index 0d0546af..1c234703 100644 --- a/ui/ReqDetail.ui +++ b/ui/ReqDetail.ui @@ -80,7 +80,7 @@ - + 0 @@ -209,6 +209,22 @@ + + + Attributes + + + + 9 + + + 6 + + + + + + &Extensions diff --git a/ui/v3ext.ui b/ui/v3ext.ui index ce7b9788..2a7e1da6 100644 --- a/ui/v3ext.ui +++ b/ui/v3ext.ui @@ -1,15 +1,12 @@ - - - v3ext 0 0 - 424 - 203 + 386 + 232 @@ -22,6 +19,9 @@ 6 + + + @@ -38,6 +38,12 @@ + + + + + + @@ -160,36 +166,6 @@ - - - - 0 - 0 - 100 - 30 - - - - - - - 9 - 40 - 406 - 110 - - - - - - - 360 - 41 - 54 - 108 - - - diff --git a/widgets/CertDetail.cpp b/widgets/CertDetail.cpp index 414e674f..191e1825 100644 --- a/widgets/CertDetail.cpp +++ b/widgets/CertDetail.cpp @@ -98,7 +98,12 @@ void CertDetail::setCert(pki_x509 *cert) fpSHA1->setText(cert->fingerprint(EVP_sha1())); // V3 extensions - v3extensions->document()->setHtml(cert->printV3ext()); + QString cert_ext = cert->printV3ext(); + if (cert_ext.isEmpty()) { + tabwidget->removeTab(3); + } else { + v3extensions->document()->setHtml(cert_ext); + } // Algorithm sigAlgo->setText(cert->getSigAlg()); diff --git a/widgets/NewX509.cpp b/widgets/NewX509.cpp index 2d064934..426625c2 100644 --- a/widgets/NewX509.cpp +++ b/widgets/NewX509.cpp @@ -43,6 +43,8 @@ NewX509::NewX509(QWidget *parent) eku_nid = *MainWindow::eku_nid; dn_nid = *MainWindow::dn_nid; aia_nid = *MainWindow::aia_nid; + attr_nid << NID_pkcs9_unstructuredName << NID_pkcs9_challengePassword; + QStringList sl; setupUi(this); @@ -123,21 +125,42 @@ NewX509::NewX509(QWidget *parent) name_ptr[5] = commonName; name_ptr[6] = emailAddress; + // Setup Request Attributes + if (attrWidget->layout()) + delete attrWidget->layout(); + QGridLayout *attrLayout = new QGridLayout(attrWidget); + attrLayout->setAlignment(Qt::AlignTop); + attrLayout->setSpacing(6); + attrLayout->setMargin(0); + attr_edit.clear(); + for (i=0; i < attr_nid.count(); i++) { + QLabel *label; + QLineEdit *edit; + int nid = attr_nid[i]; + label = new QLabel(this); + label->setText(QString(OBJ_nid2ln(nid))); + label->setToolTip(QString(OBJ_nid2sn(nid))); + edit = new QLineEdit(this); + attr_edit << edit; + attrLayout->addWidget(label, i, 0); + attrLayout->addWidget(edit, i, 1); + } // last polish on_certList_currentIndexChanged(0); certList->setDisabled(true); checkAuthKeyId(); - toggleOkBut(); tabWidget->setCurrentIndex(0); + attrWidget->hide(); pt = none; } void NewX509::setRequest() { - requestBox->setEnabled(false); + reqWidget->hide(); + attrWidget->show(); + signerBox->setEnabled(false); - validityBox->setEnabled(false); - rangeBox->setEnabled(false); + timewidget->setEnabled(false); capt->setText(tr("Create Certificate signing request")); setImage(MainWindow::csrImg); pt = x509_req; @@ -148,6 +171,13 @@ NewX509::~NewX509() } +void NewX509::addReqAttributes(pki_x509req *req) +{ + for (int i=0; i < attr_nid.count(); i++) { + req->addAttribute(attr_nid[i], attr_edit[i]->text()); + } +} + void NewX509::setTemp(pki_temp *temp) { QString text = tr("Create "); @@ -162,7 +192,6 @@ void NewX509::setTemp(pki_temp *temp) validityBox->setEnabled(false); setImage(MainWindow::tempImg); pt = tmpl; - toggleOkBut(); } void NewX509::setCert() @@ -317,7 +346,6 @@ void NewX509::on_fromReqCB_clicked() copyReqExtCB->setEnabled(request); showReqBut->setEnabled(request); switchHashAlgo(); - toggleOkBut(); } @@ -350,25 +378,6 @@ void NewX509::switchHashAlgo() hashAlgo->setDsa(false); } -void NewX509::toggleOkBut() -{ - bool ok = ! description->text().isEmpty() && - countryName->text().length() !=1 && - ( keyList->count() > 0 || !keyList->isEnabled() ); - ok |= fromReqCB->isChecked(); - //okButton->setEnabled(ok); -} - -void NewX509::on_description_textChanged(QString) -{ - toggleOkBut(); -} - -void NewX509::on_countryName_textChanged(QString) -{ - toggleOkBut(); -} - void NewX509::on_showReqBut_clicked() { QString req = reqList->currentText(); @@ -475,7 +484,6 @@ void NewX509::newKeyDone(QString name) { keyList->insertItem(0, name); keyList->setCurrentIndex(0); - toggleOkBut(); } pki_key *NewX509::getSelectedKey() @@ -494,20 +502,28 @@ pki_x509req *NewX509::getSelectedReq() return (pki_x509req *)MainWindow::reqs->getByName(reqList->currentText()); } -x509name NewX509::getX509name() +x509name NewX509::getX509name(int _throw) { x509name x; - int j, row; + int j, row, nid; - for (j = 0; jtext()); - } - - row = extDNlist->rowCount(); - for (j=0; jitem(j,0)->text())); - x.addEntryByNid(nid, CCHAR(extDNlist->item(j,1)->text())); + try { + for (j = 0; jtext()); + } + row = extDNlist->rowCount(); + for (j=0; jitem(j,0)->text())); + x.addEntryByNid(nid, extDNlist->item(j,1)->text()); + } + } catch (errorEx &err) { + if (!err.isEmpty()) { + if (_throw) + throw err; + else + QMessageBox::warning(this, XCA_TITLE, err.getString()); + } } return x; } @@ -649,6 +665,17 @@ QString NewX509::mandatoryDnRemain() void NewX509::on_okButton_clicked() { + try { + getX509name(1); + } catch (errorEx &err) { + if (QMessageBox::warning(this, tr(XCA_TITLE), err.getString(), + tr("Ok"), tr("Abort rollout")) == 1) + { + reject(); + } + return; + } + if (description->text().isEmpty() && !fromReqCB->isChecked()) { if (commonName->text().isEmpty()) { if (QMessageBox::warning(this, tr(XCA_TITLE), @@ -664,16 +691,6 @@ void NewX509::on_okButton_clicked() } } - if (countryName->text().length() == 1) { - if (QMessageBox::warning(this, tr(XCA_TITLE), - tr("The Country name must be either empty or 2 digits long."), - tr("Ok"), tr("Abort rollout")) == 1) - { - reject(); - } - return; - } - if ( keyList->count() == 0 && keyList->isEnabled() && !fromReqCB->isChecked()) diff --git a/widgets/NewX509.h b/widgets/NewX509.h index ad9fefef..6161a84f 100644 --- a/widgets/NewX509.h +++ b/widgets/NewX509.h @@ -34,6 +34,8 @@ class NewX509: public QDialog, public Ui::NewX509 NIDlist eku_nid; NIDlist dn_nid; NIDlist aia_nid; + NIDlist attr_nid; + QList attr_edit; #define EXPLICIT_NAME_CNT 7 static int name_nid[EXPLICIT_NAME_CNT]; QLineEdit *name_ptr[EXPLICIT_NAME_CNT]; @@ -61,7 +63,7 @@ class NewX509: public QDialog, public Ui::NewX509 pki_key *getSelectedKey(); pki_x509 *getSelectedSigner(); pki_x509req *getSelectedReq(); - x509name getX509name(); + x509name getX509name(int _throw = 0); void setX509name(const x509name &n); void setImage(QPixmap *image); void setAuthInfAcc_string(QString aia_txt); @@ -81,14 +83,13 @@ class NewX509: public QDialog, public Ui::NewX509 void initCtx(pki_x509 *subj, pki_x509 *iss, pki_x509req *req); void setBasicConstraints(const x509v3ext &e); void setExt(const x509v3ext &ext); - QString createRequestText(); void checkAuthKeyId(); void switchHashAlgo(); + void addReqAttributes(pki_x509req *req); public slots: void on_fromReqCB_clicked(); void on_keyList_currentIndexChanged(const QString &); void on_reqList_currentIndexChanged(const QString &); - void toggleOkBut(); void newKeyDone(QString name); void on_extDNadd_clicked(); void on_extDNdel_clicked(); @@ -102,8 +103,6 @@ class NewX509: public QDialog, public Ui::NewX509 void on_subKey_clicked(); void on_genKeyBUT_clicked(); void on_showReqBut_clicked(); - void on_description_textChanged(QString text); - void on_countryName_textChanged(QString); void on_certList_currentIndexChanged(int index); void on_applyTemplate_clicked(); void on_okButton_clicked(); diff --git a/widgets/NewX509_ext.cpp b/widgets/NewX509_ext.cpp index 6c3bd809..7a079f70 100644 --- a/widgets/NewX509_ext.cpp +++ b/widgets/NewX509_ext.cpp @@ -61,7 +61,7 @@ x509v3ext NewX509::getAuthKeyIdent() if (foreignSignRB->isChecked()) ext.create(NID_authority_key_identifier, "keyid,issuer:always", &ext_ctx); - else + else ext.create(NID_authority_key_identifier, "keyid:always", &ext_ctx); } @@ -171,7 +171,8 @@ void NewX509::setAuthInfAcc_string(QString aia_txt) aia = aia_txt.split(';'); - if (aia.count() != 2) return; + if (aia.count() != 2) + return; nid = OBJ_sn2nid(CCHAR(aia[0])); @@ -217,6 +218,8 @@ extList NewX509::getAllExt() ne << getSubAltName(); ne << getIssAltName(); ne << getCrlDist(); + ne << getAuthInfAcc(); + ne << getCertPol(); ne += getNetscapeExt(); return ne; @@ -272,19 +275,3 @@ void NewX509::setExt(const x509v3ext &ext) } } -QString NewX509::createRequestText() -{ - return "---"; - extList ne; - - ne << getBasicConstraints(); - ne << getSubKeyIdent(); - ne << getAuthKeyIdent(); - ne << getKeyUsage(); - ne << getEkeyUsage(); - ne << getSubAltName(); - ne << getIssAltName(); - ne << getCrlDist(); - - return ne.getHtml("
") + getNetscapeExt().getHtml("
"); -} diff --git a/widgets/ReqDetail.cpp b/widgets/ReqDetail.cpp index 48859eb5..3c5d7c76 100644 --- a/widgets/ReqDetail.cpp +++ b/widgets/ReqDetail.cpp @@ -11,6 +11,7 @@ #include "distname.h" #include "clicklabel.h" #include "lib/pki_x509req.h" +#include "lib/func.h" #include #include @@ -60,7 +61,59 @@ void ReqDetail::setReq(pki_x509req *req) // The extensions extList el = req->getV3Ext(); - v3extensions->document()->setHtml(el.getHtml("
")); + if (el.count() == 0) { + tabwidget->removeTab(3); + } else { + v3extensions->document()->setHtml(el.getHtml("
")); + } + // The non extension attributes + int cnt = X509_REQ_get_attr_count(req->getReq()); + int added = 0; + QGridLayout *attrLayout = new QGridLayout(attributes); + attrLayout->setAlignment(Qt::AlignTop); + attrLayout->setSpacing(6); + attrLayout->setMargin(11); + + for (int i = 0; igetReq(), i); + nid = OBJ_obj2nid(att->object); + if (X509_REQ_extension_nid(nid)) { + continue; + } + label = new QLabel(this); + label->setText(QString(OBJ_nid2ln(nid))); + label->setToolTip(QString(OBJ_nid2sn(nid))); + attrLayout->addWidget(label, i, 0); + added++; + + if (att->single) { + label = labelFromAsn1Type(att->value.single); + attrLayout->addWidget(label, i, 1); + continue; + } + int count = sk_ASN1_TYPE_num(att->value.set); + for (int j=0; jvalue.set, j)); + attrLayout->addWidget(label, i, j +1); + } + } + if (!added) { + tabwidget->removeTab(2); + } } +QLabel *ReqDetail::labelFromAsn1Type(ASN1_TYPE *at) +{ + QLabel *label; + ASN1_STRING *st = at->value.asn1_string; + + label = new CopyLabel(this); + label->setText(asn1ToQString(st)); + label->setToolTip(QString(ASN1_tag2str(st->type))); + label->setFrameShape(QFrame::Panel); + label->setFrameShadow(QFrame::Sunken); + return label; +} diff --git a/widgets/ReqDetail.h b/widgets/ReqDetail.h index e031ee29..f336c276 100644 --- a/widgets/ReqDetail.h +++ b/widgets/ReqDetail.h @@ -10,6 +10,7 @@ #include "ui_ReqDetail.h" #include +#include class pki_x509req; @@ -20,6 +21,7 @@ class ReqDetail: public QDialog, public Ui::ReqDetail public: ReqDetail( QWidget *parent); void setReq(pki_x509req *req); + QLabel *labelFromAsn1Type(ASN1_TYPE *at); }; #endif diff --git a/widgets/distname.cpp b/widgets/distname.cpp index 2ca5c687..a694e491 100644 --- a/widgets/distname.cpp +++ b/widgets/distname.cpp @@ -23,7 +23,7 @@ DistName::DistName(QWidget* parent) lineEdit = new QLineEdit(this); DistNameLayout = new QGridLayout(); - DistNameLayout->setAlignment( Qt::AlignTop ); + DistNameLayout->setAlignment(Qt::AlignTop); DistNameLayout->setSpacing(6); DistNameLayout->setMargin(11); v->setSpacing(6);