diff --git a/img/imgres.rcc b/img/imgres.rcc index e9fb1cd4..3e0af8dd 100644 --- a/img/imgres.rcc +++ b/img/imgres.rcc @@ -22,5 +22,6 @@ validcertkey.png validcert.png done.png + warn.png diff --git a/img/warn.png b/img/warn.png new file mode 100644 index 00000000..4dab5f8c Binary files /dev/null and b/img/warn.png differ diff --git a/ui/NewX509.ui b/ui/NewX509.ui index 76bcfd8f..e22bc4a4 100644 --- a/ui/NewX509.ui +++ b/ui/NewX509.ui @@ -562,12 +562,6 @@ If this list is disabled, you only can create a self-signed certificate. true - - true - - - 200 - @@ -925,24 +919,53 @@ It also copies the issuer and serial number from the issuer certificate. Normall - - - + + + - Authority Info Access + subject alternative name - Authority Info Access + subject alternative name - - - - CRL distribution point + + + + + 20 + 20 + + + + + 20 + 20 + - CRL distribution point + + + + + + + + DNS: IP: URI: email: RID: + + + The subject alternative name extension allows various literal values to be used. These include "email" (an email address) , "URI" a uniform resource indicator, "DNS" (a DNS domain name) , RID (a registered ID: OBJECT IDENTIFIER) and IP (an IP address). +Examples: +email:my@other.address, IP: 1.1.1.1 , URI:http://my.url.here/ +email:my@other.address, RID:1.2.3.4, DNS: ns.server.tld + + + + + + + Edit @@ -956,7 +979,56 @@ It also copies the issuer and serial number from the issuer certificate. Normall - + + + + DNS: IP: URI: email: RID: + + + The issuer alternative name extension allows various literal values to be used. These include "email" (an email address) , "URI" a uniform resource indicator, "DNS" (a DNS domain name), RID (a registered ID: OBJECT IDENTIFIER) and IP (an IP address). +Examples: +email:my@other.address, IP: 1.1.1.1 , URI:http://my.url.here/ +email:my@other.address, RID:1.2.3.4, DNS: ns.server.tld + + + + + + + Edit + + + + + + + CRL distribution point + + + CRL distribution point + + + + + + + + 20 + 20 + + + + + 20 + 20 + + + + + + + + URI: @@ -972,28 +1044,50 @@ URI:http://www.my.com/my.crl, URI:http://www.oth.com/my.crl + + + + Edit + + + + + + + Authority Info Access + + + Authority Info Access + + + + + + + 20 + 20 + + + + + 20 + 20 + + + + + + + + can be altered by the file "aia.txt" - - - - Edit - - - - - - - Edit - - - - + DNS: IP: URI: email: RID: @@ -1008,53 +1102,29 @@ caIssuers;URI:http://my.ca/ca.html - - - - DNS: IP: URI: email: RID: - - - The subject alternative name extension allows various literal values to be used. These include "email" (an email address) , "URI" a uniform resource indicator, "DNS" (a DNS domain name) , RID (a registered ID: OBJECT IDENTIFIER) and IP (an IP address). -Examples: -email:my@other.address, IP: 1.1.1.1 , URI:http://my.url.here/ -email:my@other.address, RID:1.2.3.4, DNS: ns.server.tld - - - - - - - Edit - - - - - - - subject alternative name - - - subject alternative name - - - - + Edit - - - - DNS: IP: URI: email: RID: + + + + + 20 + 20 + - - The issuer alternative name extension allows various literal values to be used. These include "email" (an email address) , "URI" a uniform resource indicator, "DNS" (a DNS domain name), RID (a registered ID: OBJECT IDENTIFIER) and IP (an IP address). -Examples: -email:my@other.address, IP: 1.1.1.1 , URI:http://my.url.here/ -email:my@other.address, RID:1.2.3.4, DNS: ns.server.tld + + + 20 + 20 + + + + diff --git a/widgets/MainWindow.cpp b/widgets/MainWindow.cpp index 2d4fb653..524a1ced 100644 --- a/widgets/MainWindow.cpp +++ b/widgets/MainWindow.cpp @@ -41,7 +41,7 @@ QPixmap *MainWindow::keyImg = NULL, *MainWindow::csrImg = NULL, *MainWindow::certImg = NULL, *MainWindow::tempImg = NULL, *MainWindow::nsImg = NULL, *MainWindow::revImg = NULL, *MainWindow::appIco = NULL, *MainWindow::scardImg = NULL, - *MainWindow::doneIco = NULL; + *MainWindow::doneIco = NULL, *MainWindow::warnIco = NULL; db_key *MainWindow::keys = NULL; db_x509req *MainWindow::reqs = NULL; @@ -270,6 +270,7 @@ void MainWindow::init_images() scardImg = loadImg("bigscard.png"); appIco = loadImg("key.xpm"); doneIco = loadImg("done.png"); + warnIco = loadImg("warn.png"); bigKey->setPixmap(*keyImg); bigCsr->setPixmap(*csrImg); bigCert->setPixmap(*certImg); diff --git a/widgets/MainWindow.h b/widgets/MainWindow.h index 8d5b72d0..b217a1ae 100644 --- a/widgets/MainWindow.h +++ b/widgets/MainWindow.h @@ -57,7 +57,7 @@ class MainWindow: public QMainWindow, public Ui::MainWindow static db_crl *crls; static QPixmap *keyImg, *csrImg, *certImg, *tempImg, *nsImg, *revImg, *appIco, *scardImg, - *doneIco; + *doneIco, *warnIco; static NIDlist *eku_nid, *dn_nid, *aia_nid; static QString mandatory_dn; int exitApp; diff --git a/widgets/NewX509.cpp b/widgets/NewX509.cpp index 96db2c1c..e29a5a84 100644 --- a/widgets/NewX509.cpp +++ b/widgets/NewX509.cpp @@ -60,6 +60,15 @@ NewX509::NewX509(QWidget *parent) connect(extDNlist->itemDelegateForColumn(1), SIGNAL(setupLineEdit(const QString &, QLineEdit *)), this, SLOT(setupExtDNwidget(const QString &, QLineEdit *))); + connect(subAltName, SIGNAL(textChanged(const QString &)), + this, SLOT(checkSubAltName(const QString &))); + connect(issAltName, SIGNAL(textChanged(const QString &)), + this, SLOT(checkIssAltName(const QString &))); + connect(crlDist, SIGNAL(textChanged(const QString &)), + this, SLOT(checkCrlDist(const QString &))); + connect(authInfAcc, SIGNAL(textChanged(const QString &)), + this, SLOT(checkAuthInfAcc(const QString &))); + setWindowTitle(XCA_TITLE); for (i=0; icount(); i++) { @@ -724,80 +733,163 @@ void NewX509::editV3ext(QLineEdit *le, QString types, int n) void NewX509::on_adv_validate_clicked() { if (!nconf_data->isReadOnly()) { - QString errtxt; - extList el; - ign_openssl_error(); - QString result; - setupTmpCtx(); - v3ext_backup = nconf_data->toPlainText(); - if (fromReqCB->isChecked() && copyReqExtCB->isChecked()) { - el = getSelectedReq()->getV3ext(); - } - if (el.size() > 0) { - result = "

"; - result += tr("From PKCS#10 request") + - "

\n"; - result += el.getHtml("
"); - } - try { - el = getGuiExt(); - el += getNetscapeExt(); - el.delInvalid(); - } catch (errorEx &err) { - errtxt = err.getString(); - el.clear(); - } - if (el.size() > 0) { - if (!result.isEmpty()) - result += "\n


\n"; - result += "

"; - result += tr("Other Tabs") + "

\n"; - result += el.getHtml("
"); - } - try { - el = getAdvanced(); - } catch (errorEx &err) { - errtxt += err.getString(); - el.clear(); - } - if (el.size() > 0) { - if (!result.isEmpty()) - result += "\n


\n"; - result += "

"; - result += tr("Advanced Tab") + "

\n"; - result += el.getHtml("
"); - } - if (!errtxt.isEmpty()) { - if (!result.isEmpty()) - result += "\n


\n"; - result += "

"; - result += tr("Errors") + "

\n"; - result += errtxt; - } - nconf_data->document()->setHtml(result); - nconf_data->setReadOnly(true); - - adv_validate->setText(tr("Edit")); - valid_htmltext = result; - checkExtDuplicates(); + /* switch from edit to display mode */ + do_validateExtensions(); } else { - nconf_data->document()->setPlainText(v3ext_backup); - nconf_data->setReadOnly(false); - adv_validate->setText(tr("Validate")); - valid_htmltext = ""; + /* switch back to edit mode */ + undo_validateExtensions(); + } +} + +void NewX509::checkIcon(const QString &text, int nid, QLabel *img) +{ + if (text.isEmpty()) { + img->clear(); + return; } ign_openssl_error(); + switch (nid) { + case NID_subject_alt_name: + getSubAltName(); + break; + case NID_issuer_alt_name: + getIssAltName(); + break; + case NID_crl_distribution_points: + getCrlDist(); + break; + case NID_info_access: + getAuthInfAcc(); + break; + } + if (ign_openssl_error()) { + img->setPixmap(*MainWindow::warnIco); + return; + } + img->setPixmap(*MainWindow::doneIco); +} + +void NewX509::checkSubAltName(const QString & text) +{ + checkIcon(text, NID_subject_alt_name, subAltIco); +} + +void NewX509::checkIssAltName(const QString & text) +{ + checkIcon(text, NID_issuer_alt_name, issAltIco); +} + +void NewX509::checkCrlDist(const QString & text) +{ + checkIcon(text, NID_crl_distribution_points, crlDistIco); +} + +void NewX509::checkAuthInfAcc(const QString & text) +{ + checkIcon(text, NID_info_access, authInfAccIco); +} + +int NewX509::do_validateExtensions() +{ + QString result; + int ret = 0; + + if (!nconf_data->isReadOnly()) { + v3ext_backup = nconf_data->toPlainText(); + } + ret = validateExtensions(v3ext_backup, result); + nconf_data->document()->setHtml(result); + nconf_data->setReadOnly(true); + adv_validate->setText(tr("Edit")); + return ret; +} + +void NewX509::undo_validateExtensions() +{ + if (nconf_data->isReadOnly()) { + nconf_data->document()->setPlainText(v3ext_backup); + } + nconf_data->setReadOnly(false); + adv_validate->setText(tr("Validate")); +} + +int NewX509::validateExtensions(QString nconf, QString &result) +{ + int ret = 0; + QStringList errors; + extList el; + ign_openssl_error(); + setupTmpCtx(); + if (fromReqCB->isChecked() && copyReqExtCB->isChecked()) { + el = getSelectedReq()->getV3ext(); + } + if (el.size() > 0) { + result = "

"; + result += tr("From PKCS#10 request") +"

\n"; + result += el.getHtml("
"); + } + try { + el = getGuiExt(); + el += getNetscapeExt(); + el.delInvalid(); + } catch (errorEx &err) { + errors += err.getString(); + el.clear(); + } + if (el.size() > 0) { + if (!result.isEmpty()) + result += "\n


\n"; + result += "

"; + result += tr("Other Tabs") + "

\n"; + result += el.getHtml("
"); + } + try { + el = getAdvanced(); + } catch (errorEx &err) { + errors += err.getString(); + el.clear(); + } + if (el.size() > 0) { + if (!result.isEmpty()) + result += "\n


\n"; + result += "

"; + result += tr("Advanced Tab") + "

\n"; + result += el.getHtml("
"); + } + if (errors.size()) { + if (!result.isEmpty()) + result += "\n


\n"; + result += "

"; + result += tr("Errors") + "

  • \n"; + result += errors.join("
  • \n"); + result += "
"; + ret = 1; + } + el = getExtDuplicates(); + if (el.size() > 0) { + QString errtxt; + ret = 1; + errtxt = "

Error:" + "duplicate extensions:

    \n"; + for(int i = 0; i< el.size(); i++) { + errtxt += "
  • " +el[i].getObject() +"
  • \n"; + } + errtxt += "
\n
\n"; + result = errtxt + result; + } + ign_openssl_error(); + return ret; } void NewX509::on_editSubAlt_clicked() { - QString s = "email,RID,URI,DNS,IP,otherName"; + QString s = "URI,email,RID,DNS,IP,otherName"; editV3ext(subAltName, s, NID_subject_alt_name); } void NewX509::on_editIssAlt_clicked() { - QString s = "email,RID,URI,DNS,IP,otherName,issuer"; + QString s = "URI,email,RID,DNS,IP,otherName,issuer"; editV3ext(issAltName, s, NID_issuer_alt_name); } @@ -808,14 +900,13 @@ void NewX509::on_editCrlDist_clicked() void NewX509::on_editAuthInfAcc_clicked() { - editV3ext(authInfAcc, "email,RID,URI,DNS,IP", NID_info_access); + editV3ext(authInfAcc, "URI,email,RID,DNS,IP", NID_info_access); } -void NewX509::on_tabWidget_currentChanged(int) +void NewX509::on_tabWidget_currentChanged(int tab) { - /* reset advanced tab to editable text */ - if (nconf_data->isReadOnly()) - on_adv_validate_clicked(); + if (tabWidget->tabText(tab) == tabnames[5]) + do_validateExtensions(); } QString NewX509::mandatoryDnRemain() @@ -1038,10 +1129,9 @@ void NewX509::accept() break; } } - on_adv_validate_clicked(); - if (checkExtDuplicates()) { + if (do_validateExtensions()) { gotoTab(5); - QString text = tr("The certificate contains duplicated extensions. Check the validation on the advanced tab."); + QString text = tr("The certificate contains invalid or duplicate extensions. Check the validation on the advanced tab."); QMessageBox msg(QMessageBox::Warning, XCA_TITLE, text, QMessageBox::NoButton, this); msg.addButton(QMessageBox::Ok)->setText(tr("Edit extensions")); diff --git a/widgets/NewX509.h b/widgets/NewX509.h index fff05aec..8ac6f057 100644 --- a/widgets/NewX509.h +++ b/widgets/NewX509.h @@ -47,8 +47,9 @@ class NewX509: public QDialog, public Ui::NewX509 QStringList private_keys, private_keys0, tabnames; pki_x509 *ctx_cert; QString v3ext_backup; - QString valid_htmltext; kvmodel *extDNmodel; + extList getExtDuplicates(); + void checkIcon(const QString &text, int nid, QLabel*img); public: static int name_nid[EXPLICIT_NAME_CNT]; @@ -97,6 +98,9 @@ class NewX509: public QDialog, public Ui::NewX509 pki_temp *currentTemplate(); void gotoTab(int tab); void setupLineEditByNid(int nid, QLineEdit *l); + int validateExtensions(QString nconf, QString &result); + int do_validateExtensions(); + void undo_validateExtensions(); public slots: void on_fromReqCB_clicked(); @@ -121,6 +125,10 @@ class NewX509: public QDialog, public Ui::NewX509 void on_reqSubChange_clicked(); void accept(); void setupExtDNwidget(const QString &s, QLineEdit *w); + void checkSubAltName(const QString & text); + void checkIssAltName(const QString & text); + void checkCrlDist(const QString & text); + void checkAuthInfAcc(const QString & text); signals: void genKey(QString); diff --git a/widgets/NewX509_ext.cpp b/widgets/NewX509_ext.cpp index 21a70e76..4a739e31 100644 --- a/widgets/NewX509_ext.cpp +++ b/widgets/NewX509_ext.cpp @@ -36,7 +36,6 @@ x509v3ext NewX509::getBasicConstraints() } ext.create(NID_basic_constraints, cont.join(", "), &ext_ctx); } - openssl_error(); return ext; } @@ -45,7 +44,6 @@ x509v3ext NewX509::getSubKeyIdent() x509v3ext ext; if (subKey->isChecked()) ext.create(NID_subject_key_identifier, "hash", &ext_ctx); - openssl_error(); return ext; } @@ -63,7 +61,6 @@ x509v3ext NewX509::getAuthKeyIdent() x = "keyid:always,issuer:always"; } ext.create(NID_authority_key_identifier, x, &ext_ctx); - openssl_error(); return ext; } @@ -87,7 +84,6 @@ x509v3ext NewX509::getKeyUsage() if (kuCritical->isChecked() && cont.count() > 0) cont.prepend("critical"); ext.create(NID_key_usage, cont.join(", "), &ext_ctx); - openssl_error(); return ext; } @@ -107,7 +103,6 @@ x509v3ext NewX509::getEkeyUsage() if (ekuCritical->isChecked() && cont.count() > 0) cont.prepend("critical"); ext.create(NID_ext_key_usage, cont.join(", "), &ext_ctx); - openssl_error(); return ext; } @@ -124,7 +119,6 @@ x509v3ext NewX509::getSubAltName() s = sn.join(","); } ext.create(NID_subject_alt_name, s, &ext_ctx); - openssl_error(); return ext; } @@ -141,7 +135,6 @@ x509v3ext NewX509::getIssAltName() s = sn.join(","); } ext.create(NID_issuer_alt_name, s, &ext_ctx); - openssl_error(); return ext; } @@ -151,7 +144,6 @@ x509v3ext NewX509::getCrlDist() if (!crlDist->text().isEmpty()) { ext.create(NID_crl_distribution_points, crlDist->text(), &ext_ctx); } - openssl_error(); return ext; } @@ -195,7 +187,6 @@ x509v3ext NewX509::getAuthInfAcc() if (!aia_txt.isEmpty()) { ext.create(NID_info_access, aia_txt, &ext_ctx); } - openssl_error(); return ext; } @@ -211,9 +202,10 @@ extList NewX509::getAdvanced() int ret, start; if (nconf_data->isReadOnly()) { - on_adv_validate_clicked(); + conf_str = v3ext_backup; + } else { + conf_str = nconf_data->toPlainText(); } - conf_str = nconf_data->toPlainText(); if (conf_str.isEmpty()) return elist; @@ -266,6 +258,7 @@ extList NewX509::getGuiExt() ne << getIssAltName(); ne << getCrlDist(); ne << getAuthInfAcc(); + openssl_error(); return ne; } @@ -319,7 +312,7 @@ void NewX509::initCtx(pki_x509 *subj, pki_x509 *iss, pki_x509req *req) X509V3_set_ctx(&ext_ctx, s, s1, r, NULL, 0); } -int NewX509::checkExtDuplicates() +extList NewX509::getExtDuplicates() { int i, start, cnt, n1, n; x509v3ext e; @@ -330,7 +323,7 @@ int NewX509::checkExtDuplicates() if (ext_ctx.subject_cert) { sk = ext_ctx.subject_cert->cert_info->extensions; } else - return 0; + return el_dup; el.setStack(sk, 0); if (fromReqCB->isChecked() && copyReqExtCB->isChecked()) { @@ -351,23 +344,7 @@ int NewX509::checkExtDuplicates() } } } - if (el_dup.size() <= 0) - return 0; - - tabWidget->setCurrentIndex(tabWidget->count() -1); - if (!nconf_data->isReadOnly()) { - on_adv_validate_clicked(); - } - - olist = "

Error: " - "duplicate extensions:

    \n"; - for(int i = 0; i< el_dup.size(); i++) { - olist += "
  • " + el_dup[i].getObject() + "
  • \n"; - } - olist += "
\n
\n"; - olist += valid_htmltext; - nconf_data->document()->setHtml(olist); - return el_dup.size(); + return el_dup; } void NewX509::setExt(const x509v3ext &ext) diff --git a/widgets/v3ext.cpp b/widgets/v3ext.cpp index 7dcc16fb..d061af7b 100644 --- a/widgets/v3ext.cpp +++ b/widgets/v3ext.cpp @@ -61,6 +61,7 @@ void v3ext::addInfo(QLineEdit *myle, const QStringList &sl, int n, le = myle; ext_ctx = ctx; tab->setKeys(sl); + keys = sl; tab->setInfoLabel(infoLabel); connect(tab->itemDelegateForColumn(1), SIGNAL(setupLineEdit(const QString &, QLineEdit *)), @@ -127,12 +128,15 @@ void v3ext::addEntry(QString line) int idx = line.indexOf(':'); QString type, value; if (idx == -1) { - type = line; - value = ""; + value = line; } else { type = line.left(idx); value = line.mid(idx+1); } + if (!keys.contains(type)) { + type = keys[0]; + value = line; + } tab->addRow(QStringList(type) << value); } diff --git a/widgets/v3ext.h b/widgets/v3ext.h index 965d9099..1ec0978a 100644 --- a/widgets/v3ext.h +++ b/widgets/v3ext.h @@ -26,6 +26,7 @@ class v3ext: public QDialog, public Ui::v3ext int nid; X509V3_CTX *ext_ctx; bool __validate(bool showSuccess); + QStringList keys; public: v3ext( QWidget *parent); void addItem(QString list);