From dae20bc28ee17f967657ae7eca66e872ffdff8fe Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 5 Jun 2006 23:14:38 +0200 Subject: [PATCH] Fix Password input and key encryption Add CA properties --- lib/db_base.cpp | 4 - lib/db_key.cpp | 7 +- lib/db_x509.cpp | 98 +++++++++++---- lib/db_x509.h | 2 + lib/pki_key.cpp | 95 +++++++++++---- lib/pki_key.h | 6 +- ui/CaProperties.ui | 257 ++++++++++++++++++++++++++++++++++++++++ ui/CertExtend.ui | 10 -- widgets/MW_database.cpp | 7 +- widgets/MW_menu.cpp | 14 ++- widgets/MainWindow.cpp | 38 ++---- widgets/MainWindow.h | 2 - 12 files changed, 438 insertions(+), 102 deletions(-) create mode 100644 ui/CaProperties.ui diff --git a/lib/db_base.cpp b/lib/db_base.cpp index 6651d100..b2c0ed36 100644 --- a/lib/db_base.cpp +++ b/lib/db_base.cpp @@ -268,10 +268,6 @@ void db_base::insertSortChild(pki_base *parent, pki_base *child) int row; QModelIndex idx = QModelIndex(); - if (parent == NULL) - printf("Parent is null !!??\n"); - if (child == NULL) - printf("Parent is null !!??\n"); if (parent == child || parent == NULL) parent = rootItem; diff --git a/lib/db_key.cpp b/lib/db_key.cpp index 25fd7755..c4c497cf 100644 --- a/lib/db_key.cpp +++ b/lib/db_key.cpp @@ -218,6 +218,7 @@ void db_key::showContextMenu(QContextMenuEvent *e, const QModelIndex &index) QMenu *menu = new QMenu(mainwin); currentIdx = index; + pki_key *key = static_cast(currentIdx.internalPointer()); menu->addAction(tr("New Key"), this, SLOT(newItem())); menu->addAction(tr("Import"), this, SLOT(load())); @@ -225,8 +226,10 @@ void db_key::showContextMenu(QContextMenuEvent *e, const QModelIndex &index) menu->addAction(tr("Show Details"), this, SLOT(showItem())); menu->addAction(tr("Export"), this, SLOT(store())); menu->addAction(tr("Delete"), this, SLOT(delete_ask())); - menu->addAction(tr("Change password"), this, SLOT(setOwnPass())); - menu->addAction(tr("Reset password"), this, SLOT(resetOwnPass())); + if (!key->getOwnPass()) + menu->addAction(tr("Change password"), this, SLOT(setOwnPass())); + else + menu->addAction(tr("Reset password"), this, SLOT(resetOwnPass())); } menu->exec(e->globalPos()); delete menu; diff --git a/lib/db_x509.cpp b/lib/db_x509.cpp index b5d3407f..99bac713 100644 --- a/lib/db_x509.cpp +++ b/lib/db_x509.cpp @@ -54,6 +54,7 @@ #include "widgets/CertExtend.h" #include "widgets/ExportCert.h" #include "ui/TrustState.h" +#include "ui/CaProperties.h" #include #include #include @@ -573,10 +574,7 @@ void db_x509::showContextMenu(QContextMenuEvent *e, const QModelIndex &index) itemTrust = menu->addAction(tr("Trust"), this, SLOT(setTrust())); menu->addSeparator(); subCa = menu->addMenu(tr("CA")); - subCa->addAction(tr("Serial"), this, SLOT(setSerial())); - subCa->addAction(tr("CRL days"), this, SLOT(setCrlDays())); - itemTemplate = subCa->addAction(tr("Signing Template"), - this, SLOT(setTemplate())); + subCa->addAction(tr("Properties"), this, SLOT(caProperties())); subCa->addAction(tr("Generate CRL"), this, SLOT(genCrl())); subP7 = menu->addMenu(tr("PKCS#7")); @@ -585,29 +583,26 @@ void db_x509::showContextMenu(QContextMenuEvent *e, const QModelIndex &index) menu->addSeparator(); itemExtend = menu->addAction(tr("Renewal"), this, SLOT(extendCert())); - if (cert) { - if (cert->isRevoked()) { - itemRevoke = menu->addAction(tr("Unrevoke"), - this, SLOT(unRevoke())); - itemTrust->setEnabled(false); - } else { - itemRevoke = menu->addAction(tr("Revoke"), - this, SLOT(revoke())); - } - parentCanSign = (cert->getSigner() && cert->getSigner()->canSign() - && (cert->getSigner() != cert)); - canSign = cert->canSign(); -#warning templates - hasTemplates = mainwin->temps->getDesc().count() > 0 ; - hasPrivkey = cert->getRefKey(); + if (cert->isRevoked()) { + itemRevoke = menu->addAction(tr("Unrevoke"), + this, SLOT(unRevoke())); + itemTrust->setEnabled(false); + } else { + itemRevoke = menu->addAction(tr("Revoke"), + this, SLOT(revoke())); } - itemExtend->setEnabled(parentCanSign); + parentCanSign = (cert->getSigner() && cert->getSigner()->canSign() + && (cert->getSigner() != cert)); + canSign = cert->canSign(); +#warning templates + hasTemplates = mainwin->temps->getDesc().count() > 0 ; + hasPrivkey = cert->getRefKey(); itemRevoke->setEnabled(parentCanSign); + itemExtend->setEnabled(parentCanSign); subCa->setEnabled(canSign); itemReq->setEnabled(hasPrivkey); itemtca->setEnabled(canSign); subP7->setEnabled(hasPrivkey); - itemTemplate->setEnabled(hasTemplates); } menu->exec(e->globalPos()); @@ -949,7 +944,8 @@ void db_x509::extendCert() void db_x509::revoke() { pki_x509 *cert = static_cast(currentIdx.internalPointer()); - if (!cert) return; + if (!cert) + return; cert->setRevoked(true); updatePKI(cert); } @@ -957,7 +953,8 @@ void db_x509::revoke() void db_x509::unRevoke() { pki_x509 *cert = static_cast(currentIdx.internalPointer()); - if (!cert) return; + if (!cert) + return; cert->setRevoked(false); updatePKI(cert); } @@ -968,6 +965,25 @@ void db_x509::genCrl() mainwin->crls->newItem(cert); } + +void db_x509::toRequest() +{ + pki_x509 *cert = static_cast(currentIdx.internalPointer()); + if (!cert) + return; + + try { + pki_x509req *req = new pki_x509req(); + req->setIntName(cert->getIntName()); + req->createReq(cert->getRefKey(), cert->getSubject(), + cert->getRefKey()->getDefaultMD(), cert->getExt()); + mainwin->reqs->insert(req); + } + catch (errorEx &err) { + mainwin->Error(err); + } +} + #if 0 void db_x509::setSerial() { @@ -1002,6 +1018,7 @@ void db_x509::setCrlDays() tr("Please enter the CRL renewal periode in days"), crlDays, 1, 2147483647, 1, &ok, this ); if (ok && (crlDays != nCrlDays)) { + int crlDays = cert->getCrlDays(); cert->setCrlDays(nCrlDays); db->updatePKI(cert); } @@ -1029,3 +1046,38 @@ void db_x509::setTemplate() } } #endif + +void db_x509::caProperties() +{ + Ui::CaProperties ui; + int i; + printf("CA Prop UI\n"); + pki_x509 *cert = static_cast(currentIdx.internalPointer()); + if (!cert) + return; + QDialog *dlg = new QDialog(mainwin); + ui.setupUi(dlg); + ui.serial->setText(cert->getCaSerial().toHex()); + ui.days->setValue(cert->getCrlDays()); + ui.image->setPixmap(*MainWindow::certImg); + QString templ = cert->getTemplate(); + QStringList tempList = mainwin->temps->getDesc(); + for (i=0; iaddItems(tempList); + ui.temp->setCurrentIndex(i); + ui.certName->setText(cert->getIntName()); + if (dlg->exec()) { + a1int nserial; + cert->setCrlDays(ui.days->value()); + nserial.setHex(ui.serial->text()); + if (nserial > cert->getCaSerial()) + cert->setCaSerial(nserial); + cert->setTemplate(ui.temp->currentText()); + updatePKI(cert); + } + delete dlg; +} + diff --git a/lib/db_x509.h b/lib/db_x509.h index 2d9873d1..c5f539a5 100644 --- a/lib/db_x509.h +++ b/lib/db_x509.h @@ -106,6 +106,8 @@ class db_x509: public db_x509super void revoke(); void unRevoke(); void genCrl(); + void caProperties(); + void toRequest(); signals: void connNewX509(NewX509 *dlg); }; diff --git a/lib/pki_key.cpp b/lib/pki_key.cpp index 8a05fd16..abb7ede9 100644 --- a/lib/pki_key.cpp +++ b/lib/pki_key.cpp @@ -59,6 +59,7 @@ #include char pki_key::passwd[40]={0,}; +QString pki_key::passHash = QString(); QPixmap *pki_key::icon[2]= { NULL, NULL }; @@ -127,7 +128,7 @@ QString pki_key::removeTypeFromIntName(QString n) void pki_key::setOwnPass(int x) { - EVP_PKEY *pk; + EVP_PKEY *pk, *pk_back; printf("Set own pass: %d -> %d\n",ownPass,x); if (x) x=1; if (ownPass == x) return; @@ -135,10 +136,19 @@ void pki_key::setOwnPass(int x) pk = decryptKey(); if (pk == NULL) return; - EVP_PKEY_free(key); + pk_back = key; key = pk; ownPass = x; - encryptKey(); + try { + encryptKey(); + } + catch (errorEx &err) { + EVP_PKEY_free(key); + key = pk_back; + ownPass ^= 1; + throw(err); + } + EVP_PKEY_free(pk_back); } void pki_key::generate(int bits, int type, QProgressBar *progress) @@ -339,24 +349,34 @@ EVP_PKEY *pki_key::decryptKey() EVP_PKEY *tmpkey; EVP_CIPHER_CTX ctx; const EVP_CIPHER *cipher = EVP_des_ede3_cbc(); - char ownPassBuf[MAX_PASS_LENGTH]; + char ownPassBuf[MAX_PASS_LENGTH] = ""; /* This key has its own password */ if (ownPass == 1) { - pass_info pi(XCA_TITLE, qApp->translate("MainWindow", "Please enter the password to decrypt the private key: '") + getIntName() + "'"); - MainWindow::passRead(ownPassBuf, MAX_PASS_LENGTH, 0, &pi); + int ret; + pass_info pi(XCA_TITLE, qApp->translate("MainWindow", + "Please enter the password to decrypt the private key: '") + + getIntName() + "'"); + ret = MainWindow::passRead(ownPassBuf, MAX_PASS_LENGTH, 0, &pi); + if (ret < 0) + throw errorEx("Password input aborted", class_name); } else { - printf("Orig password: '%s' len:%d\n",passwd, strlen(passwd)); - if (strlen(passwd) == 0) { - int retlen = 0; - pass_info p(XCA_TITLE, qApp->translate("MainWindow", - "Please enter the default password")); - while (strlen(passwd) == 0 && retlen == 0) { - retlen = MainWindow::passRead(passwd, MAX_PASS_LENGTH, 0, &p); + if (md5passwd(passwd) != passHash) { + printf("Orig password: '%s' len:%d\n", passwd, strlen(passwd)); + while (md5passwd(ownPassBuf) != passHash) { + int ret; + printf("Passhash= '%s', new hash= '%s', passwd= '%s'\n", + CCHAR(passHash), CCHAR(md5passwd(ownPassBuf)), ownPassBuf); + pass_info p(XCA_TITLE, qApp->translate("MainWindow", + "Please enter the default password")); + ret = MainWindow::passRead(ownPassBuf, MAX_PASS_LENGTH, 0, &p); + if (ret < 0) + throw errorEx("Password input aborted", class_name); } + } else { + memcpy(ownPassBuf, passwd, MAX_PASS_LENGTH); } - memcpy(ownPassBuf, passwd, MAX_PASS_LENGTH); } printf("Using decrypt Pass: %s\n", ownPassBuf); p = (unsigned char *)OPENSSL_malloc(encKey_len); @@ -422,19 +442,27 @@ void pki_key::encryptKey() /* This key has its own, private password ? */ if (ownPass == 1) { + int ret; pass_info p(XCA_TITLE, qApp->translate("MainWindow", "Please enter the password to protect the private key: '") + getIntName() + "'"); - while (!MainWindow::passWrite(ownPassBuf, MAX_PASS_LENGTH, 0, &p) ); + ret = MainWindow::passWrite(ownPassBuf, MAX_PASS_LENGTH, 0, &p); + if (ret < 0) + throw errorEx("Password input aborted", class_name); } else { - int retlen = 0; - pass_info p(XCA_TITLE, qApp->translate("MainWindow", - "Please enter the default password for encrypting keys")); - while (retlen >= 0) { - retlen = MainWindow::passWrite(passwd, MAX_PASS_LENGTH, 0, &p); + if (md5passwd(passwd) != passHash) { + int ret = 0; + pass_info p(XCA_TITLE, qApp->translate("MainWindow", + "Please enter the database password for encrypting the key")); + while (md5passwd(ownPassBuf) != passHash) { + ret = MainWindow::passRead(ownPassBuf, MAX_PASS_LENGTH, 0,&p); + if (ret < 0) + throw errorEx("Password input aborted", class_name); + } + } else { + memcpy(ownPassBuf, passwd, MAX_PASS_LENGTH); } - memcpy(ownPassBuf, passwd, MAX_PASS_LENGTH); } /* Prepare Encryption */ @@ -707,7 +735,7 @@ int pki_key::getUcount() const EVP_MD *pki_key::getDefaultMD(){ const EVP_MD *md; switch (key->type) { - case EVP_PKEY_RSA: md = EVP_md5(); break; + case EVP_PKEY_RSA: md = EVP_sha1(); break; case EVP_PKEY_DSA: md = EVP_dss1(); break; default: md = NULL; break; } @@ -735,3 +763,26 @@ QVariant pki_key::getIcon() return QVariant(*icon[pixnum]); } +QString pki_key::md5passwd(const char *pass, char *md5, int *len) +{ + + EVP_MD_CTX mdctx; + QString str; + unsigned int n; + int j; + char zs[4]; + unsigned char m[EVP_MAX_MD_SIZE]; + EVP_DigestInit(&mdctx, EVP_md5()); + EVP_DigestUpdate(&mdctx, pass, strlen(pass)); + EVP_DigestFinal(&mdctx, m, &n); + for (j=0; j<(int)n; j++) { + sprintf(zs, "%02X%c",m[j], (j+1 == (int)n) ?'\0':':'); + str += zs; + } + if (md5 && len) { + *len = (*len>n) ? n : *len; + memcpy(md5, m, *len); + } + return str; +} + diff --git a/lib/pki_key.h b/lib/pki_key.h index 3e71d614..2cd33948 100644 --- a/lib/pki_key.h +++ b/lib/pki_key.h @@ -67,10 +67,10 @@ class pki_key: public pki_base { protected: + int ownPass; // if we have our own private password EVP_PKEY *key; unsigned char *encKey; int encKey_len; - int ownPass; // if we have our own private password int ucount; // usage counter QString BN2QString(BIGNUM *bn); void init(int type = EVP_PKEY_RSA); @@ -78,10 +78,14 @@ class pki_key: public pki_base void encryptKey(); public: static QPixmap *icon[2]; + static QString passHash; static char passwd[MAX_PASS_LENGTH]; static void erasePasswd(); + static QString md5passwd(const char *pass, + char *md5 = NULL, int *len = NULL); void generate(int bits, int type, QProgressBar *progress); void setOwnPass(int x); + int getOwnPass(void) {return ownPass;}; pki_key(const QString name = "", int type = EVP_PKEY_RSA); pki_key(EVP_PKEY *pkey); EVP_PKEY *decryptKey(); diff --git a/ui/CaProperties.ui b/ui/CaProperties.ui new file mode 100644 index 00000000..eda6ba43 --- /dev/null +++ b/ui/CaProperties.ui @@ -0,0 +1,257 @@ + + + + + CaProperties + + + + 0 + 0 + 484 + 375 + + + + Dialog + + + + 9 + + + 6 + + + + + 0 + + + 6 + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 20 + 20 + + + + + + + + + 200 + 94 + + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 20 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 20 + + + + + + + + + Arial + 14 + 50 + false + false + false + false + + + + TextLabel + + + + + + + Qt::Vertical + + + + 20 + 20 + + + + + + + + CA properties + + + + 9 + + + 6 + + + + + + + + Next serial for signing + + + + + + + + + + Days until next CRL issuing + + + + + + + + + + Default template + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 0 + + + 6 + + + + + Qt::Horizontal + + + + 131 + 31 + + + + + + + + OK + + + + + + + Cancel + + + + + + + + + + + + okButton + clicked() + CaProperties + accept() + + + 278 + 253 + + + 96 + 254 + + + + + cancelButton + clicked() + CaProperties + reject() + + + 369 + 253 + + + 179 + 282 + + + + + diff --git a/ui/CertExtend.ui b/ui/CertExtend.ui index f47ee4c9..c572b2cc 100644 --- a/ui/CertExtend.ui +++ b/ui/CertExtend.ui @@ -304,16 +304,6 @@ - - - - 0 - 0 - 100 - 30 - - - diff --git a/widgets/MW_database.cpp b/widgets/MW_database.cpp index 93d28f8b..8d28c108 100644 --- a/widgets/MW_database.cpp +++ b/widgets/MW_database.cpp @@ -133,12 +133,17 @@ void MainWindow::dump_database() void MainWindow::close_database() { + keyView->setModel(NULL); + reqView->setModel(NULL); + certView->setModel(NULL); + tempView->setModel(NULL); + crlView->setModel(NULL); + delete(crls); delete(reqs); delete(certs); delete(temps); delete(keys); - //delete(settings); crls = NULL; reqs = NULL; diff --git a/widgets/MW_menu.cpp b/widgets/MW_menu.cpp index f49f3eef..38e51737 100644 --- a/widgets/MW_menu.cpp +++ b/widgets/MW_menu.cpp @@ -79,27 +79,29 @@ void MainWindow::init_menu() void MainWindow::load_database() { - load_key l; + load_db l; QString fname; QFileDialog *dlg = new QFileDialog(this); dlg->setWindowTitle(l.caption); dlg->setFilters(l.filter); dlg->setFileMode( QFileDialog::AnyFile ); - dlg->setDirectory(baseDir); + dlg->setDirectory(getPath()); if (dlg->exec()) { fname = dlg->selectedFiles()[0]; + setPath(dlg->directory().path()); } delete dlg; - if (fname.isEmpty()) return; + if (fname.isEmpty()) + return; dbfile = fname; close_database(); - fprintf(stderr, "Dir: %s, File: %s\n", baseDir.data(), dbfile.data() ); - emit init_database(); + fprintf(stderr, "Dir: %s, File: %s\n", CCHAR(baseDir), CCHAR(dbfile)); + init_database(); } void MainWindow::load_def_database() { dbfile = DBFILE; close_database(); - emit init_database(); + init_database(); } diff --git a/widgets/MainWindow.cpp b/widgets/MainWindow.cpp index 6742b4d9..ef284987 100644 --- a/widgets/MainWindow.cpp +++ b/widgets/MainWindow.cpp @@ -345,28 +345,28 @@ int MainWindow::initPass() { db mydb(dbfile); char *pass; + pki_key::passHash = QString(); pass_info p(tr("New Password"), tr("Please enter a password, that will be used to encrypt your private keys in the database-file")); - QString passHash; if (!mydb.find(setting, "pwhash")) { if ((pass = (char *)mydb.load(NULL))) { - passHash = pass; + pki_key::passHash = pass; free(pass); } } - if (passHash.isEmpty()) { + if (pki_key::passHash.isEmpty()) { int keylen = passWrite((char *)pki_key::passwd, 25, 0, &p); if (keylen < 0) return 0; pki_key::passwd[keylen]='\0'; - passHash = md5passwd(pki_key::passwd); - mydb.set((const unsigned char *)CCHAR(passHash), - passHash.length()+1, 1, setting, "pwhash"); + pki_key::passHash = pki_key::md5passwd(pki_key::passwd); + mydb.set((const unsigned char *)CCHAR(pki_key::passHash), + pki_key::passHash.length()+1, 1, setting, "pwhash"); } else { int keylen=0; - while (md5passwd(pki_key::passwd) != passHash) { + while (pki_key::md5passwd(pki_key::passwd) != pki_key::passHash) { if (keylen !=0) QMessageBox::warning(this,tr(XCA_TITLE), tr("Password verify error, please try again")); p.setTitle(tr("Password")); @@ -386,7 +386,6 @@ int MainWindow::passRead(char *buf, int size, int rwflag, void *userdata) { int ret = -1; pass_info *p = (pass_info *)userdata; - printf("Userdata called\n"); Ui::PassRead ui; QDialog *dlg = new QDialog(qApp->activeWindow()); ui.setupUi(dlg); @@ -437,29 +436,6 @@ int MainWindow::passWrite(char *buf, int size, int rwflag, void *userdata) return ret; } -QString MainWindow::md5passwd(const char *pass, char *md5, int *len) -{ - - EVP_MD_CTX mdctx; - QString str; - unsigned int n; - int j; - char zs[4]; - unsigned char m[EVP_MAX_MD_SIZE]; - EVP_DigestInit(&mdctx, EVP_md5()); - EVP_DigestUpdate(&mdctx, pass, strlen(pass)); - EVP_DigestFinal(&mdctx, m, &n); - for (j=0; j<(int)n; j++) { - sprintf(zs, "%02X%c",m[j], (j+1 == (int)n) ?'\0':':'); - str += zs; - } - if (md5 && len) { - *len = (*len>n) ? n : *len; - memcpy(md5, m, *len); - } - return str; -} - void MainWindow::Error(errorEx &err) { if (err.isEmpty()) return; diff --git a/widgets/MainWindow.h b/widgets/MainWindow.h index d6e01dec..a9738d0d 100644 --- a/widgets/MainWindow.h +++ b/widgets/MainWindow.h @@ -103,8 +103,6 @@ class MainWindow: public QMainWindow, private Ui::MainWindow static int passRead(char *buf, int size, int rwflag, void *userdata); static int passWrite(char *buf, int size, int rwflag, void *userdata); static NewX509 *newX509(); - static QString md5passwd(const char *pass, - char *md5 = NULL, int *len = NULL); //static void Qt::SocketError(errorEx &err); static void Error(errorEx &err); void cmd_help(const char* msg);