From b622e64209d10af2ac87409c8358ebe0959ac98a Mon Sep 17 00:00:00 2001 From: Christian Hohnstaedt Date: Tue, 19 Apr 2011 07:09:08 +0200 Subject: [PATCH] consolidate Password and Pin input dialogs change storage type of passwords from char[] to QByteArray Create PwDialog class and drop passWrite and passRead Create Passwd class derived from QBytearray move PKCS12 password input to PwDialog --- lib/Makefile | 2 +- lib/Passwd.cpp | 24 ++++ lib/Passwd.h | 29 +++++ lib/db_key.cpp | 6 +- lib/db_x509.cpp | 33 ++---- lib/exception.h | 7 +- lib/func.cpp | 49 +++++++- lib/func.h | 1 + lib/load_obj.cpp | 5 +- lib/main.cpp | 7 +- lib/pkcs11.cpp | 38 +++---- lib/pki_evp.cpp | 129 ++++++++++----------- lib/pki_evp.h | 14 +-- lib/pki_key.cpp | 2 +- lib/pki_key.h | 1 - lib/pki_multi.cpp | 11 +- lib/pki_pkcs12.cpp | 32 +++--- lib/pki_pkcs12.h | 6 +- ui/PassRead.ui | 182 ------------------------------ ui/{PassWrite.ui => PwDialog.ui} | 39 +++---- widgets/MW_database.cpp | 26 +++-- widgets/MW_menu.cpp | 20 ++-- widgets/MainWindow.cpp | 186 ++++++++----------------------- widgets/MainWindow.h | 14 +-- widgets/Makefile | 2 +- widgets/PwDialog.cpp | 131 ++++++++++++++++++++++ widgets/PwDialog.h | 42 +++++++ 27 files changed, 501 insertions(+), 537 deletions(-) create mode 100644 lib/Passwd.cpp create mode 100644 lib/Passwd.h delete mode 100644 ui/PassRead.ui rename ui/{PassWrite.ui => PwDialog.ui} (87%) create mode 100644 widgets/PwDialog.cpp create mode 100644 widgets/PwDialog.h diff --git a/lib/Makefile b/lib/Makefile index 82059f90..72916f7f 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -8,7 +8,7 @@ MOCNAMES=db_crl db_key db_temp db_x509 db_x509req db_x509super db_base db_token\ pki_base pki_multi pki_evp pki_scard pass_info pki_pkcs7 NAMES=$(MOCNAMES) asn1int oid x509rev asn1time \ x509v3ext func load_obj main x509name db import \ - pk11_attribute pkcs11 pkcs11_lib + pk11_attribute pkcs11 pkcs11_lib Passwd OBJS=$(patsubst %, %.o, $(NAMES)) $(patsubst %, moc_%.o, $(MOCNAMES)) diff --git a/lib/Passwd.cpp b/lib/Passwd.cpp new file mode 100644 index 00000000..6723e7cc --- /dev/null +++ b/lib/Passwd.cpp @@ -0,0 +1,24 @@ +/* vi: set sw=4 ts=4: + * + * Copyright (C) 2011 Christian Hohnstaedt. + * + * All rights reserved. + */ + +#include +#include "Passwd.h" + +void Passwd::cleanse() +{ + memset(data(), 0, size()); +} + +Passwd::~Passwd() +{ + Passwd::cleanse(); +} +unsigned char *Passwd::constUchar() const +{ + return size() ? (unsigned char *)constData() : NULL; +} + diff --git a/lib/Passwd.h b/lib/Passwd.h new file mode 100644 index 00000000..697fd878 --- /dev/null +++ b/lib/Passwd.h @@ -0,0 +1,29 @@ +/* vi: set sw=4 ts=4: + * + * Copyright (C) 2011 Christian Hohnstaedt. + * + * All rights reserved. + */ + +#ifndef __PASSWD_H +#define __PASSWD_H + +#include + +class Passwd: public QByteArray +{ + public: + void cleanse(); + ~Passwd(); + unsigned char *constUchar() const; + Passwd & operator= (const char *p) + { + return (Passwd&)QByteArray::operator=(p); + } + Passwd & operator= (const QByteArray &other) + { + return (Passwd&)QByteArray::operator=(other); + } +}; + +#endif diff --git a/lib/db_key.cpp b/lib/db_key.cpp index 0d71f3a9..3823802f 100644 --- a/lib/db_key.cpp +++ b/lib/db_key.cpp @@ -23,7 +23,7 @@ #include "ui_NewKey.h" #include "pkcs11.h" -#include "widgets/MainWindow.h" +#include "widgets/PwDialog.h" #include "widgets/ExportKey.h" #include "widgets/KeyDetail.h" #include "widgets/NewKey.h" @@ -301,9 +301,9 @@ void db_key::store() if (dlg->exportPrivate->isChecked() && !targetKey->isToken()) { pki_evp *evpKey = (pki_evp *)targetKey; if (dlg->exportPkcs8->isChecked()) { - evpKey->writePKCS8(fname, enc, &MainWindow::passWrite, pem); + evpKey->writePKCS8(fname, enc, PwDialog::pwCallback, pem); } else { - evpKey->writeKey(fname, enc, &MainWindow::passWrite, pem); + evpKey->writeKey(fname, enc, PwDialog::pwCallback, pem); } } else { targetKey->writePublic(fname, pem); diff --git a/lib/db_x509.cpp b/lib/db_x509.cpp index 98ae24f5..c2f56583 100644 --- a/lib/db_x509.cpp +++ b/lib/db_x509.cpp @@ -10,13 +10,14 @@ #include "pki_pkcs7.h" #include "pki_evp.h" #include "pki_scard.h" +#include "pass_info.h" #include "widgets/CertDetail.h" #include "widgets/CertExtend.h" #include "widgets/ExportDialog.h" #include "widgets/MainWindow.h" +#include "widgets/PwDialog.h" #include "ui_TrustState.h" #include "ui_CaProperties.h" -#include "ui_PassWrite.h" #include "ui_About.h" #include "ui_Revoke.h" #include @@ -484,34 +485,19 @@ void db_x509::newCert(NewX509 *dlg) cert->setTrust(1); #ifdef WG_QA_SERIAL } else if (dlg->selfQASignRB->isChecked()){ - Ui::PassWrite ui; - QDialog *dlg1 = new QDialog(mainwin); - ui.setupUi(dlg1); - ui.image->setPixmap( *MainWindow::keyImg ); - ui.description->setText(tr("Please enter the new hexadecimal secret number for the QA process.")); - dlg1->setWindowTitle(XCA_TITLE); - ui.passA->setFocus(); + Passwd pass; + pass_info p(XCA_TITLE, tr("Please enter the new hexadecimal secret number for the QA process.")); +#if 0 ui.passA->setValidator(new QRegExpValidator(QRegExp("[0-9a-fA-F]*"), ui.passA)); ui.passB->setValidator(new QRegExpValidator(QRegExp("[0-9a-fA-F]*"), ui.passB)); - QString A = "x", B=""; - - while (dlg1->exec()) { - A = ui.passA->text(); - B = ui.passB->text(); - if (A==B) - break; - else - QMessageBox::warning(mainwin, XCA_TITLE, - tr("The two secret numbers don't match.")); - } - delete dlg1; - if (A!=B) +#endif + if (PwDialog::execute(&p, &pass, true) != 1) throw errorEx(tr("The QA process has been terminated by the user.")); signcert = cert; signkey = clientkey; - serial.setHex(A); + serial.setHex(pass); cert->setTrust(2); #endif } else { @@ -824,8 +810,7 @@ void db_x509::writePKCS12(pki_x509 *cert, QString s, bool chain) if (s.isEmpty()) return; s = QDir::convertSeparators(s); - pki_pkcs12 *p12 = new pki_pkcs12(cert->getIntName(), cert, privkey, - MainWindow::passWrite); + pki_pkcs12 *p12 = new pki_pkcs12(cert->getIntName(), cert, privkey); pki_x509 *signer = cert->getSigner(); while ((signer != NULL ) && (signer != cert) && chain) { p12->addCaCert(signer); diff --git a/lib/exception.h b/lib/exception.h index 88201818..1be4393f 100644 --- a/lib/exception.h +++ b/lib/exception.h @@ -12,20 +12,25 @@ #include #include "base.h" +#define E_PASSWD 1 + class errorEx { private: QString msg; public: - errorEx(QString txt = "", QString className = "") + int info; + errorEx(QString txt = "", QString className = "", int inf = 0) { msg = txt; if (!className.isEmpty()) msg += " (" + className + ")"; + info = inf; } errorEx(const errorEx &e) { msg = e.msg; + info = e.info; } void appendString(QString s) { diff --git a/lib/func.cpp b/lib/func.cpp index 42a08572..b4e71c9f 100644 --- a/lib/func.cpp +++ b/lib/func.cpp @@ -13,6 +13,8 @@ #include #include #include +#include +#include #if defined(Q_WS_MAC) #include @@ -336,8 +338,9 @@ void _openssl_error(const QString txt, const char *file, int line) while (int i = ERR_get_error() ) { error += QString(ERR_error_string(i, NULL)) + "\n"; - fprintf(stderr, CCHAR(QString("OpenSSL error (%1:%2) : %3\n"). - arg(file).arg(line).arg(ERR_error_string(i, NULL)))); + fputs(CCHAR(QString("OpenSSL error (%1:%2) : %3\n"). + arg(file).arg(line).arg(ERR_error_string(i, NULL))), + stderr); } if (!error.isEmpty()) { if (!txt.isEmpty()) @@ -378,3 +381,45 @@ void inc_progress_bar(int, int, void *p) } } +static long mem_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + BUF_MEM *bm = (BUF_MEM *)b->ptr; + if (!bm->data || !(b->flags & BIO_FLAGS_MEM_RDONLY)) + return BIO_s_mem()->ctrl(b, cmd, num, ptr); + + switch (cmd) { + case BIO_C_FILE_SEEK: + if (num > bm->max) + num = bm->max; + bm->data -= (bm->max - bm->length) - num; + bm->length = bm->max - num; + case BIO_C_FILE_TELL: + return bm->max - bm->length; + } + return BIO_s_mem()->ctrl(b, cmd, num, ptr); +} + +void BIO_seekable_romem(BIO *b) +{ + static BIO_METHOD *mymeth = NULL; + static BIO_METHOD _meth; + + if (!(b->flags & BIO_FLAGS_MEM_RDONLY) || + (b->method->type != BIO_TYPE_MEM)) + { + return; + } + if (!mymeth) { + _meth = *BIO_s_mem(); + _meth.ctrl = mem_ctrl; + mymeth = &_meth; + } + b->method = mymeth; +} + +BIO *BIO_QBA_mem_buf(QByteArray &a) +{ + BIO *b = BIO_new_mem_buf(a.data(), a.size()); + BIO_seekable_romem(b); + return b; +} diff --git a/lib/func.h b/lib/func.h index 65d2840d..a8464fee 100644 --- a/lib/func.h +++ b/lib/func.h @@ -45,6 +45,7 @@ bool _ign_openssl_error(const QString txt, const char *file, int line); QByteArray i2d_bytearray(int(*i2d)(const void*, unsigned char**), const void*); void *d2i_bytearray(void *(*d2i)(void*, unsigned char**, long), QByteArray &ba); +BIO *BIO_QBA_mem_buf(QByteArray &a); #define I2D_VOID(a) ((int (*)(const void *, unsigned char **))(a)) #define D2I_VOID(a) ((void *(*)(void *, unsigned char **, long))(a)) diff --git a/lib/load_obj.cpp b/lib/load_obj.cpp index 4233780b..0228de33 100644 --- a/lib/load_obj.cpp +++ b/lib/load_obj.cpp @@ -12,7 +12,8 @@ #include "pki_pkcs7.h" #include "pki_pkcs12.h" #include "pki_multi.h" -#include "widgets/MainWindow.h" +#include "pki_temp.h" +#include "pki_crl.h" load_base::load_base() { @@ -108,7 +109,7 @@ load_pkcs12::load_pkcs12() pki_base * load_pkcs12::loadItem(QString s) { - pki_base *p12 = new pki_pkcs12(s, MainWindow::passRead); + pki_base *p12 = new pki_pkcs12(s); return p12; } diff --git a/lib/main.cpp b/lib/main.cpp index f6c43546..1626d990 100644 --- a/lib/main.cpp +++ b/lib/main.cpp @@ -91,9 +91,10 @@ int main( int argc, char *argv[] ) a.setMainwin(mw); mw->read_cmdline(); if (mw->exitApp == 0) { - mw->open_default_db(); - mw->show(); - ret = a.exec(); + if (mw->open_default_db() != 2) { + mw->show(); + ret = a.exec(); + } } } catch (errorEx &ex) { mw->Error(ex); diff --git a/lib/pkcs11.cpp b/lib/pkcs11.cpp index 0bafabb3..74049e0c 100644 --- a/lib/pkcs11.cpp +++ b/lib/pkcs11.cpp @@ -12,6 +12,7 @@ #include "db_base.h" #include "func.h" #include "pass_info.h" +#include "Passwd.h" #include #include @@ -19,6 +20,7 @@ #include #include "ui_SelectToken.h" +#include "widgets/PwDialog.h" pkcs11_lib_list pkcs11::libs; @@ -238,8 +240,7 @@ static QDialog *newPinPadBox() QString pkcs11::tokenLogin(QString name, bool so, bool force) { - char _pin[256], *pin = _pin; - int pinlen; + Passwd pin; bool need_login; QString text = so ? @@ -253,8 +254,7 @@ QString pkcs11::tokenLogin(QString name, bool so, bool force) if (!need_login) logout(); if (tokenInfo().protAuthPath()) { - pin[0] = '\0'; - pinlen = 0; + pin.clear(); QDialog *pinpadbox = newPinPadBox(); pinpadbox->show(); pinPadLoginThread ppt(this, so); @@ -267,15 +267,14 @@ QString pkcs11::tokenLogin(QString name, bool so, bool force) if (!ppt.err.isEmpty()) throw errorEx(ppt.err); } else { - pinlen = MainWindow::passRead(pin, 256, 0, &p); - if (pinlen == -1) + if (PwDialog::execute(&p, &pin, false) != 1) return QString(); } - login((unsigned char*)pin, pinlen, so); + login(pin.constUchar(), pin.size(), so); } else { return QString(""); } - return QString::fromLocal8Bit(pin, pinlen); + return QString(pin); } bool pkcs11::selectToken(slotid *slot, QWidget *w) @@ -331,7 +330,7 @@ static QString newPinTxt = QObject::tr( void pkcs11::changePin(slotid slot, bool so) { - char newPin[MAX_PASS_LENGTH], *pinp; + Passwd newPin, pinp; QString pin; startSession(slot, true); @@ -350,20 +349,18 @@ void pkcs11::changePin(slotid slot, bool so) pass_info p(XCA_TITLE, msg.arg(ti.label()) + "\n" + ti.pinInfo()); p.setPin(); - int newPinLen = MainWindow::passWrite(newPin, MAX_PASS_LENGTH, 0, &p); - pinp = strdup(CCHAR(pin)); - if (newPinLen != -1) { - setPin((unsigned char*)pinp, pin.length(), - (unsigned char*)newPin, newPinLen); + if (PwDialog::execute(&p, &newPin, true) == 1) { + pinp = pin.toAscii(); + setPin(pinp.constUchar(), pinp.size(), + newPin.constUchar(), newPin.size()); } - free(pinp); logout(); } void pkcs11::initPin(slotid slot) { - char newPin[MAX_PASS_LENGTH], *pinp = NULL; - int newPinLen = 0; + Passwd newPin, pinp; + int ret = 1; QString pin; startSession(slot, true); @@ -377,15 +374,14 @@ void pkcs11::initPin(slotid slot) p.setPin(); if (!ti.protAuthPath()) { - newPinLen = MainWindow::passWrite(newPin, - MAX_PASS_LENGTH, 0, &p); + ret = PwDialog::execute(&p, &newPin, true); pinp = newPin; } p11slot.isValid(); - if (newPinLen != -1) { + if (ret == 1) { WAITCURSOR_START; CK_RV rv = p11slot.p11()->C_InitPIN(session, - (unsigned char*)pinp, newPinLen); + pinp.constUchar(), pinp.size()); WAITCURSOR_END; if (rv != CKR_OK) pk11error("C_InitPIN", rv); diff --git a/lib/pki_evp.cpp b/lib/pki_evp.cpp index 0c5e6009..12a5d0b5 100644 --- a/lib/pki_evp.cpp +++ b/lib/pki_evp.cpp @@ -8,9 +8,10 @@ #include "pki_evp.h" #include "pass_info.h" +#include "Passwd.h" #include "func.h" #include "db.h" -#include "widgets/MainWindow.h" +#include "widgets/PwDialog.h" #include #include @@ -20,8 +21,8 @@ #include #include -char pki_evp::passwd[MAX_PASS_LENGTH]={0,}; -char pki_evp::oldpasswd[MAX_PASS_LENGTH]={0,}; +Passwd pki_evp::passwd; +Passwd pki_evp::oldpasswd; QString pki_evp::passHash = QString(); @@ -33,28 +34,6 @@ size_t pki_evp::num_curves = 0; unsigned char *pki_evp::curve_flags = NULL; #endif -void pki_evp::erasePasswd() -{ - memset(passwd, 0, MAX_PASS_LENGTH); -} - -void pki_evp::eraseOldPasswd() -{ - memset(oldpasswd, 0, MAX_PASS_LENGTH); -} - -void pki_evp::setPasswd(const char *pass) -{ - strncpy(passwd, pass, MAX_PASS_LENGTH); - passwd[MAX_PASS_LENGTH-1] = '\0'; -} - -void pki_evp::setOldPasswd(const char *pass) -{ - strncpy(oldpasswd, pass, MAX_PASS_LENGTH); - oldpasswd[MAX_PASS_LENGTH-1] = '\0'; -} - void pki_evp::init(int type) { key->type = type; @@ -207,18 +186,32 @@ QList pki_evp::possibleHashNids() return nids; }; +void pki_evp::openssl_pw_error(QString fname) +{ + switch (ERR_peek_error() & 0xff000fff) { + case ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_DECRYPT): + case ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_PASSWORD_READ): + case ERR_PACK(ERR_LIB_EVP, 0, EVP_R_BAD_DECRYPT): + pki_ign_openssl_error(); + throw errorEx(tr("Failed to decrypt the key (bad password) ")+ + fname, class_name, E_PASSWD); + } +} + void pki_evp::fromPEM_BIO(BIO *bio, QString name) { EVP_PKEY *pkey; int pos; - pass_info p(XCA_TITLE, QObject::tr( - "Please enter the password to decrypt the private key.")); + pass_info p(XCA_TITLE, + tr("Please enter the password to decrypt the private key.") + + " " + name); pos = BIO_tell(bio); - pkey = PEM_read_bio_PrivateKey(bio, NULL, MainWindow::passRead, &p); + pkey = PEM_read_bio_PrivateKey(bio, NULL, PwDialog::pwCallback, &p); + openssl_pw_error(name); if (!pkey){ pki_ign_openssl_error(); pos = BIO_seek(bio, pos); - pkey = PEM_read_bio_PUBKEY(bio, NULL, MainWindow::passRead, &p); + pkey = PEM_read_bio_PUBKEY(bio, NULL, PwDialog::pwCallback, &p); } if (pkey){ if (key) @@ -267,7 +260,7 @@ void pki_evp::fload(const QString fname) { pass_info p(XCA_TITLE, tr("Please enter the password to decrypt the private key from file:\n%1"). arg(compressFilename(fname))); - pem_password_cb *cb = MainWindow::passRead; + pem_password_cb *cb = PwDialog::pwCallback; FILE *fp = fopen(QString2filename(fname), "r"); EVP_PKEY *pkey; @@ -277,13 +270,11 @@ void pki_evp::fload(const QString fname) return; } pkey = PEM_read_PrivateKey(fp, NULL, cb, &p); - if (!pkey) { - if (ERR_get_error() == 0x06065064) { - fclose(fp); - pki_ign_openssl_error(); - throw errorEx(tr("Failed to decrypt the key (bad password) ") + - fname, class_name); - } + try { + openssl_pw_error(fname); + } catch (errorEx &err) { + fclose(fp); + throw err; } if (!pkey) { pki_ign_openssl_error(); @@ -368,7 +359,8 @@ EVP_PKEY *pki_evp::decryptKey() const EVP_PKEY *tmpkey; EVP_CIPHER_CTX ctx; const EVP_CIPHER *cipher = EVP_des_ede3_cbc(); - char ownPassBuf[MAX_PASS_LENGTH] = ""; + Passwd ownPassBuf; + int ret; if (isPubKey()) { unsigned char *q; @@ -383,29 +375,23 @@ EVP_PKEY *pki_evp::decryptKey() const } /* This key has its own password */ if (ownPass == ptPrivate) { - int ret; pass_info pi(XCA_TITLE, tr("Please enter the password to decrypt the private key: '%1'").arg(getIntName())); - ret = MainWindow::passRead(ownPassBuf, MAX_PASS_LENGTH, 0, &pi); - if (ret < 0) + ret = PwDialog::execute(&pi, &ownPassBuf, false); + if (ret != 1) throw errorEx(tr("Password input aborted"), class_name); } else if (ownPass == ptBogus) { // BOGUS pass - ownPassBuf[0] = '\0'; + ownPassBuf = "Bogus"; } else { - memcpy(ownPassBuf, passwd, MAX_PASS_LENGTH); - //printf("Orig password: '%s' len:%d\n", passwd, strlen(passwd)); + ownPassBuf = passwd; while (md5passwd(ownPassBuf) != passHash && sha512passwd(ownPassBuf, passHash) != passHash) { - int ret; - //printf("Passhash= '%s', new hash= '%s', passwd= '%s'\n", - //CCHAR(passHash), CCHAR(md5passwd(ownPassBuf)), ownPassBuf); pass_info p(XCA_TITLE, tr("Please enter the database password for decrypting the key '%1'").arg(getIntName())); - ret = MainWindow::passRead(ownPassBuf, MAX_PASS_LENGTH, 0, &p); - if (ret < 0) + ret = PwDialog::execute(&p, &ownPassBuf, false); + if (ret != 1) throw errorEx(tr("Password input aborted"), class_name); } } - //printf("Using decrypt Pass: %s\n", ownPassBuf); p = (unsigned char *)OPENSSL_malloc(encKey.count()); check_oom(p); pki_openssl_error(); @@ -414,8 +400,9 @@ EVP_PKEY *pki_evp::decryptKey() const memcpy(iv, encKey.constData(), 8); /* recover the iv */ /* generate the key */ - EVP_BytesToKey(cipher, EVP_sha1(), iv, (unsigned char *)ownPassBuf, - strlen(ownPassBuf), 1, ckey,NULL); + EVP_BytesToKey(cipher, EVP_sha1(), iv, + ownPassBuf.constUchar(), + ownPassBuf.size(), 1, ckey, NULL); /* we use sha1 as message digest, * because an md5 version of the password is * stored in the database... @@ -428,7 +415,7 @@ EVP_PKEY *pki_evp::decryptKey() const decsize = outl; EVP_DecryptFinal(&ctx, p + decsize , &outl); decsize += outl; - //printf("Decrypt decsize=%d, encKey_len=%d\n", decsize, encKey_len); + //printf("Decrypt decsize=%d, encKey_len=%d\n", decsize, encKey.count() -8); pki_openssl_error(); tmpkey = d2i_PrivateKey(key->type, NULL, &p1, decsize); pki_openssl_error(); @@ -479,30 +466,31 @@ void pki_evp::encryptKey(const char *password) const EVP_CIPHER *cipher = EVP_des_ede3_cbc(); unsigned char iv[EVP_MAX_IV_LENGTH], *punenc, *punenc1; unsigned char ckey[EVP_MAX_KEY_LENGTH]; - char ownPassBuf[MAX_PASS_LENGTH]; + Passwd ownPassBuf; /* This key has its own, private password */ if (ownPass == ptPrivate) { int ret; pass_info p(XCA_TITLE, tr("Please enter the password to protect the private key: '%1'"). arg(getIntName())); - ret = MainWindow::passWrite(ownPassBuf, MAX_PASS_LENGTH, 0, &p); - if (ret < 0) + ret = PwDialog::execute(&p, &ownPassBuf, true); + if (ret != 1) throw errorEx("Password input aborted", class_name); } else if (ownPass == ptBogus) { // BOGUS password - ownPassBuf[0] = '\0'; + ownPassBuf = "Bogus"; } else { if (password) { - /* use the password parameter if this is a common password */ - strncpy(ownPassBuf, password, MAX_PASS_LENGTH); + /* use the password parameter + * if this is a common password */ + ownPassBuf = password; } else { int ret = 0; - memcpy(ownPassBuf, passwd, MAX_PASS_LENGTH); + ownPassBuf = passwd; pass_info p(XCA_TITLE, tr("Please enter the database password for encrypting the key")); while (md5passwd(ownPassBuf) != passHash && sha512passwd(ownPassBuf, passHash) != passHash ) { - ret = MainWindow::passRead(ownPassBuf, MAX_PASS_LENGTH, 0,&p); + ret = PwDialog::execute(&p, &ownPassBuf, true); if (ret < 0) throw errorEx("Password input aborted", class_name); } @@ -512,8 +500,9 @@ void pki_evp::encryptKey(const char *password) /* Prepare Encryption */ memset(iv, 0, EVP_MAX_IV_LENGTH); RAND_pseudo_bytes(iv,8); /* Generate a salt */ - EVP_BytesToKey(cipher, EVP_sha1(), iv, (unsigned char *)ownPassBuf, - strlen(ownPassBuf), 1, ckey, NULL); + EVP_BytesToKey(cipher, EVP_sha1(), iv, + ownPassBuf.constUchar(), + ownPassBuf.size(), 1, ckey, NULL); EVP_CIPHER_CTX_init (&ctx); pki_openssl_error(); @@ -702,7 +691,7 @@ QVariant pki_evp::getIcon(int id) return QVariant(*icon[pixnum]); } -QString pki_evp::md5passwd(const char *pass) +QString pki_evp::md5passwd(QByteArray pass) { EVP_MD_CTX mdctx; @@ -711,7 +700,7 @@ QString pki_evp::md5passwd(const char *pass) int j; unsigned char m[EVP_MAX_MD_SIZE]; EVP_DigestInit(&mdctx, EVP_md5()); - EVP_DigestUpdate(&mdctx, pass, strlen(pass)); + EVP_DigestUpdate(&mdctx, pass.constData(), pass.size()); EVP_DigestFinal(&mdctx, m, (unsigned*)&n); for (j=0; j #include #include "pki_key.h" +#include "Passwd.h" #define CURVE_X962 1 #define CURVE_OTHER 2 @@ -26,17 +27,14 @@ class pki_evp: public pki_key QByteArray encKey; void init(int type = EVP_PKEY_RSA); void veryOldFromData(unsigned char *p, int size); + void openssl_pw_error(QString fname); public: static QPixmap *icon[2]; static QString passHash; - static char passwd[MAX_PASS_LENGTH]; - static char oldpasswd[MAX_PASS_LENGTH]; - static void erasePasswd(); - static void eraseOldPasswd(); - static void setPasswd(const char *pass); - static void setOldPasswd(const char *pass); - static QString md5passwd(const char *pass); - static QString sha512passwd(QString pass, QString salt); + static Passwd passwd; + static Passwd oldpasswd; + static QString md5passwd(QByteArray pass); + static QString sha512passwd(QByteArray pass, QString salt); #ifndef OPENSSL_NO_EC static EC_builtin_curve *curves; static size_t num_curves; diff --git a/lib/pki_key.cpp b/lib/pki_key.cpp index 49fb3b3f..638951a3 100644 --- a/lib/pki_key.cpp +++ b/lib/pki_key.cpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include "widgets/PwDialog.h" pki_key::pki_key(const QString name) :pki_base(name) diff --git a/lib/pki_key.h b/lib/pki_key.h index 2025a427..b1e3bbf4 100644 --- a/lib/pki_key.h +++ b/lib/pki_key.h @@ -16,7 +16,6 @@ #include "pki_base.h" #define MAX_KEY_LENGTH 4096 -#define MAX_PASS_LENGTH 128 class pki_key: public pki_base { diff --git a/lib/pki_multi.cpp b/lib/pki_multi.cpp index 71a30a11..bad0a4cc 100644 --- a/lib/pki_multi.cpp +++ b/lib/pki_multi.cpp @@ -126,7 +126,7 @@ void pki_multi::fromPEM_BIO(BIO *bio, QString name) continue; } pos += startpos; - if (BIO_seek(bio, pos)) + if (BIO_seek(bio, pos) == -1) throw errorEx(tr("Seek failed")); item->fromPEM_BIO(bio, name); if (pos == BIO_tell(bio)) { @@ -159,10 +159,6 @@ void pki_multi::probeAnything(const QString fname) new load_crl() << new load_req() << new load_key() << new load_temp(); - fload(fname); - if (multi.count() > 0) - return; - foreach(lb, lbs) { try { item = lb->loadItem(fname); @@ -171,7 +167,10 @@ void pki_multi::probeAnything(const QString fname) break; } } catch (errorEx &err) { - ; // ignore + if (err.info == E_PASSWD) { + MainWindow::Error(err); + break; + } } } while (!lbs.isEmpty()) diff --git a/lib/pki_pkcs12.cpp b/lib/pki_pkcs12.cpp index fcf7652b..1093cbba 100644 --- a/lib/pki_pkcs12.cpp +++ b/lib/pki_pkcs12.cpp @@ -10,30 +10,29 @@ #include "pass_info.h" #include "exception.h" #include "func.h" +#include "widgets/PwDialog.h" #include #include -pki_pkcs12::pki_pkcs12(const QString d, pki_x509 *acert, pki_evp *akey, pem_password_cb *cb): - pki_base(d) +pki_pkcs12::pki_pkcs12(const QString d, pki_x509 *acert, pki_evp *akey) + :pki_base(d) { class_name="pki_pkcs12"; key = new pki_evp(akey); cert = new pki_x509(acert); certstack = sk_X509_new_null(); - passcb = cb; openssl_error(); } -pki_pkcs12::pki_pkcs12(const QString fname, pem_password_cb *cb) +pki_pkcs12::pki_pkcs12(const QString fname) :pki_base(fname) { FILE *fp; - char pass[MAX_PASS_LENGTH]; + Passwd pass; EVP_PKEY *mykey = NULL; X509 *mycert = NULL; key=NULL; cert=NULL; - passcb = cb; class_name="pki_pkcs12"; certstack = sk_X509_new_null(); pass_info p(XCA_TITLE, tr("Please enter the password to decrypt the PKCS#12 file:\n%1").arg(compressFilename(fname))); @@ -47,18 +46,18 @@ pki_pkcs12::pki_pkcs12(const QString fname, pem_password_cb *cb) throw errorEx(tr("Unable to load the PKCS#12 (pfx) file %1.").arg(fname)); } if (PKCS12_verify_mac(pkcs12, "", 0) || PKCS12_verify_mac(pkcs12, NULL, 0)) - pass[0] = '\0'; - else if (passcb(pass, MAX_PASS_LENGTH, 0, &p) < 0) { + pass.clear(); + else if (PwDialog::execute(&p, &pass) != 1) { /* cancel pressed */ PKCS12_free(pkcs12); - throw errorEx("",""); + throw errorEx("","", E_PASSWD); } - PKCS12_parse(pkcs12, pass, &mykey, &mycert, &certstack); + PKCS12_parse(pkcs12, pass.constData(), &mykey, &mycert, &certstack); int error = ERR_peek_error(); if (ERR_GET_REASON(error) == PKCS12_R_MAC_VERIFY_FAILURE) { ign_openssl_error(); PKCS12_free(pkcs12); - throw errorEx(getClassName(), tr("The supplied password was wrong (%1)").arg(ERR_reason_error_string(error))); + throw errorEx(getClassName(), tr("The supplied password was wrong (%1)").arg(ERR_reason_error_string(error)), E_PASSWD); } ign_openssl_error(); if (mycert) { @@ -109,7 +108,7 @@ void pki_pkcs12::addCaCert(pki_x509 *ca) void pki_pkcs12::writePKCS12(const QString fname) { - char pass[MAX_PASS_LENGTH]; + Passwd pass; pass_info p(XCA_TITLE, tr("Please enter the password to encrypt the PKCS#12 file")); if (cert == NULL || key == NULL) { my_error(tr("No key or no Cert and no pkcs12")); @@ -117,14 +116,17 @@ void pki_pkcs12::writePKCS12(const QString fname) FILE *fp = fopen(QString2filename(fname), "wb"); if (fp != NULL) { - passcb(pass, MAX_PASS_LENGTH, 0, &p); - PKCS12 *pkcs12 = PKCS12_create(pass, + if (PwDialog::execute(&p, &pass, true) != 1) { + fclose(fp); + return; + } + PKCS12 *pkcs12 = PKCS12_create(pass.data(), getIntName().toUtf8().data(), key->decryptKey(), cert->getCert(), certstack, 0, 0, 0, 0, 0); i2d_PKCS12_fp(fp, pkcs12); - openssl_error(); fclose (fp); + openssl_error(); PKCS12_free(pkcs12); } else fopen_error(fname); diff --git a/lib/pki_pkcs12.h b/lib/pki_pkcs12.h index d674fe11..0547ce6c 100644 --- a/lib/pki_pkcs12.h +++ b/lib/pki_pkcs12.h @@ -28,12 +28,10 @@ class pki_pkcs12: public pki_base pki_x509 *cert; pki_evp *key; STACK_OF(X509) *certstack; - pem_password_cb *passcb; public: - pki_pkcs12(const QString d, pki_x509 *acert, pki_evp *akey, - pem_password_cb *cb); - pki_pkcs12(const QString fname, pem_password_cb *cb); + pki_pkcs12(const QString d, pki_x509 *acert, pki_evp *akey); + pki_pkcs12(const QString fname); ~pki_pkcs12(); void addCaCert(pki_x509 *acert); diff --git a/ui/PassRead.ui b/ui/PassRead.ui deleted file mode 100644 index 00a7d5d6..00000000 --- a/ui/PassRead.ui +++ /dev/null @@ -1,182 +0,0 @@ - - - PassRead - - - - 0 - 0 - 400 - 220 - - - - Password - - - - - - 6 - - - 0 - - - - - - Arial - 14 - 50 - false - false - false - false - - - - - - - - Qt::Horizontal - - - QSizePolicy::Expanding - - - - 20 - 20 - - - - - - - - - 95 - 40 - - - - - 95 - 40 - - - - true - - - - - - - - - - - - true - - - - - - - QFrame::Box - - - QFrame::Sunken - - - - - - - - - QLineEdit::Password - - - - - - - The password is parsed as 2-digit hex code. It must have an equal number of digits (0-9 and a-f) - - - Take as HEX string - - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - pass - - - - - pass - returnPressed() - PassRead - accept() - - - 148 - 123 - - - 158 - 157 - - - - - buttonBox - accepted() - PassRead - accept() - - - 144 - 195 - - - 5 - 171 - - - - - buttonBox - rejected() - PassRead - reject() - - - 241 - 197 - - - 275 - 78 - - - - - diff --git a/ui/PassWrite.ui b/ui/PwDialog.ui similarity index 87% rename from ui/PassWrite.ui rename to ui/PwDialog.ui index cc18bf8b..0459065e 100644 --- a/ui/PassWrite.ui +++ b/ui/PwDialog.ui @@ -1,7 +1,7 @@ - PassWrite - + PwDialog + 0 @@ -144,7 +144,7 @@ passB returnPressed() - PassWrite + PwDialog accept() @@ -159,35 +159,22 @@ buttonBox - accepted() - PassWrite - accept() + clicked(QAbstractButton*) + PwDialog + buttonPress(QAbstractButton*) - 199 - 219 + 113 + 231 - 6 - 202 - - - - - buttonBox - rejected() - PassWrite - reject() - - - 294 - 214 - - - 66 - 198 + 125 + 53 + + buttonPress(QAbstractButton*) + diff --git a/widgets/MW_database.cpp b/widgets/MW_database.cpp index 4011236e..08c00bde 100644 --- a/widgets/MW_database.cpp +++ b/widgets/MW_database.cpp @@ -17,16 +17,18 @@ #include "lib/func.h" #include "widgets/ImportMulti.h" -void MainWindow::init_database() +int MainWindow::init_database() { + int ret = 2; fprintf(stderr, "Opening database: %s\n", QString2filename(dbfile)); keys = NULL; reqs = NULL; certs = NULL; temps = NULL; crls = NULL; certView->setRootIsDecorated(db_x509::treeview); try { - if (!initPass()) - return; + ret = initPass(); + if (ret == 2) + return ret; keys = new db_key(dbfile, this); reqs = new db_x509req(dbfile, this); certs = new db_x509(dbfile, this); @@ -36,7 +38,7 @@ void MainWindow::init_database() catch (errorEx &err) { Error(err); dbfile = ""; - return; + return ret; } connect( keys, SIGNAL(newKey(pki_key *)), @@ -136,16 +138,17 @@ void MainWindow::init_database() } } catch (errorEx &err) { Error(err); - return; + return ret; } setWindowTitle(tr(XCA_TITLE)); setItemEnabled(true); - if (pki_evp::passwd[0] == '\0') + if (pki_evp::passwd.isEmpty()) QMessageBox::information(this, XCA_TITLE, tr("Using or exporting private keys will not be possible without providing the correct password")); dbindex->setText(tr("Database") + ":" + dbfile); load_engine(); + return ret; } void MainWindow::dump_database() @@ -218,14 +221,14 @@ void MainWindow::undelete() delete dlgi; } -void MainWindow::open_default_db() +int MainWindow::open_default_db() { if (!dbfile.isEmpty()) - return; + return 0; FILE *fp = fopen(QString2filename(getUserSettingsDir() + QDir::separator() + "defaultdb"), "r"); if (!fp) - return; + return 0; char buff[256]; size_t len = fread(buff, 1, 255, fp); @@ -233,7 +236,8 @@ void MainWindow::open_default_db() buff[len] = 0; dbfile = filename2QString(buff).trimmed(); if (QFile::exists(dbfile)) - init_database(); + return init_database(); + return 0; } void MainWindow::default_database() @@ -291,7 +295,7 @@ void MainWindow::close_database() temps = NULL; keys = NULL; - pki_evp::erasePasswd(); + pki_evp::passwd.cleanse(); if (!crls) return; diff --git a/widgets/MW_menu.cpp b/widgets/MW_menu.cpp index f69a74f2..34e79c2e 100644 --- a/widgets/MW_menu.cpp +++ b/widgets/MW_menu.cpp @@ -7,6 +7,7 @@ #include "MainWindow.h" +#include "PwDialog.h" #include "Options.h" #include "lib/load_obj.h" #include "lib/pass_info.h" @@ -89,14 +90,14 @@ void MainWindow::init_menu() scardList += token; } -void MainWindow::changeDB(QString fname) +int MainWindow::changeDB(QString fname) { if (fname.isEmpty()) - return; + return 1; close_database(); homedir = fname.mid(0, fname.lastIndexOf(QDir::separator())); dbfile = fname; - init_database(); + return init_database(); } void MainWindow::new_database() @@ -123,12 +124,12 @@ void MainWindow::load_database() void MainWindow::import_dbdump() { extern int read_dump(const char *, db_base **, char *, int); + Passwd pass; char buf[50]; db_base *dbl[] = { keys, reqs, certs, temps, crls }; if (!keys) return; - QString pass; QString file = QFileDialog::getOpenFileName(this, tr(XCA_TITLE), homedir, tr("Database dump ( *.dump );;All files ( * )")); @@ -137,21 +138,20 @@ void MainWindow::import_dbdump() pass_info p(tr("Import password"), tr("Please enter the password of the old database"), this); - if (passRead(buf, 50, 0, &p) <0) + if (PwDialog::execute(&p, &pass) != 1) return; - pass = buf; try { - read_dump(CCHAR(file), dbl, buf, 50); - if (pki_evp::md5passwd(CCHAR(pass)) != buf) { + read_dump(CCHAR(file), dbl, buf, sizeof(buf)); + if (pki_evp::md5passwd(pass) != buf) { int ret = QMessageBox::warning(this, tr(XCA_TITLE), tr("Password verification error. Ignore keys ?"), tr("Import anyway"), tr("Cancel")); if (ret) return; } - pki_evp::setOldPasswd(CCHAR(pass)); + pki_evp::oldpasswd = pass; read_dump(CCHAR(file), dbl, NULL, 0); - pki_evp::eraseOldPasswd(); + pki_evp::oldpasswd.cleanse(); } catch (errorEx &err) { Error(err); } diff --git a/widgets/MainWindow.cpp b/widgets/MainWindow.cpp index 3285f479..b95ea623 100644 --- a/widgets/MainWindow.cpp +++ b/widgets/MainWindow.cpp @@ -9,6 +9,7 @@ //#define MDEBUG #include "MainWindow.h" #include "ImportMulti.h" +#include "lib/Passwd.h" #include @@ -22,7 +23,6 @@ #include #include #include -#include #include #include "lib/exception.h" @@ -34,10 +34,8 @@ #include "lib/pass_info.h" #include "lib/func.h" #include "lib/pkcs11.h" -#include "ui_PassRead.h" -#include "ui_PassWrite.h" #include "ui_About.h" - +#include "PwDialog.h" QPixmap *MainWindow::keyImg = NULL, *MainWindow::csrImg = NULL, *MainWindow::certImg = NULL, *MainWindow::tempImg = NULL, @@ -347,10 +345,14 @@ void MainWindow::read_cmdline() } QString file = filename2QString(arg); if (force_load) { - changeDB(file); + if (changeDB(file) == 2) + exitApp = 1; force_load = 0; } else { - pki_multi *pki = probeAnything(file); + int ret; + pki_multi *pki = probeAnything(file, &ret); + if (!pki && ret == 2) + exitApp = 1; if (pki && !pki->count()) failed << file; dlgi->addItem(pki); @@ -382,24 +384,27 @@ void MainWindow::pastePem() ui.button->setText(tr("Import PEM data")); input->setWindowTitle(tr(XCA_TITLE)); if (input->exec()) { - QString txt = textbox->toPlainText(); - QTemporaryFile f; - f.open(); - f.write(textbox->toPlainText().toAscii()); - f.flush(); + QByteArray pemdata = textbox->toPlainText().toAscii(); + BIO *b = BIO_QBA_mem_buf(pemdata); + check_oom(b); pki_multi *pem = NULL; ImportMulti *dlgi = NULL; try { pem = new pki_multi(); dlgi = new ImportMulti(this); - pem->fload(f.fileName()); + pem->fromPEM_BIO(b, QString("paste")); dlgi->addItem(pem); + pem = NULL; dlgi->execute(1); } catch (errorEx &err) { Error(err); } - delete dlgi; + if (dlgi) + delete dlgi; + if (pem) + delete pem; + BIO_free(b); } delete input; } @@ -412,8 +417,8 @@ void MainWindow::initToken() try { pkcs11 p11; slotid slot; - char pin[MAX_PASS_LENGTH]; - int pinlen; + Passwd pin; + int ret; if (!p11.selectToken(&slot, this)) return; @@ -427,20 +432,20 @@ void MainWindow::initToken() arg(slotname) + "\n" + ti.pinInfo()); p.setPin(); if (ti.tokenInitialized()) { - pinlen = passRead(pin, MAX_PASS_LENGTH, 0, &p); + ret = PwDialog::execute(&p, &pin, false); } else { p.setDescription(tr("Please enter the new SO PIN (PUK) of the token '%1'"). arg(slotname) + "\n" + ti.pinInfo()); - pinlen = passWrite(pin, MAX_PASS_LENGTH, 0, &p); + ret = PwDialog::execute(&p, &pin, true); } - if (pinlen < 0) + if (ret != 1) return; QString label = QInputDialog::getText(this, XCA_TITLE, tr("The new label of the token '%1'"). arg(slotname), QLineEdit::Normal, QString(), &ok); if (!ok) return; - p11.initToken(slot, (unsigned char*)pin, pinlen, label); + p11.initToken(slot, pin.constUchar(), pin.size(), label); } catch (errorEx &err) { Error(err); } @@ -593,17 +598,14 @@ QString makeSalt(void) void MainWindow::changeDbPass() { - char pass[MAX_PASS_LENGTH] = { 0, }; - int keylen; + Passwd pass; pass_info p(tr("New Password"), tr("Please enter the new password " "to encrypt your private keys in the database-file"), this); - keylen = passWrite(pass, MAX_PASS_LENGTH-1, 0, &p); - if (keylen < 0) + if (PwDialog::execute(&p, &pass, true) != 1) return; - pass[keylen] = '\0'; QString tempn = dbfile + "{new}"; try { if (!QFile::copy(dbfile, tempn)) @@ -616,7 +618,7 @@ void MainWindow::changeDbPass() mydb.mv(new_file); close_database(); pki_evp::passHash = passhash; - strncpy(pki_evp::passwd, pass, MAX_PASS_LENGTH); + pki_evp::passwd = pass; init_database(); } catch (errorEx &ex) { QFile::remove(tempn); @@ -624,7 +626,7 @@ void MainWindow::changeDbPass() } } -QString MainWindow::updateDbPassword(QString newdb, char *pass) +QString MainWindow::updateDbPassword(QString newdb, Passwd pass) { db mydb(newdb); @@ -674,7 +676,7 @@ QString MainWindow::updateDbPassword(QString newdb, char *pass) { EVP_PKEY *evp = key->decryptKey(); key->set_evp_key(evp); - key->encryptKey(pass); + key->encryptKey(pass.constData()); klist << key; } else if (key) delete key; @@ -698,10 +700,13 @@ int MainWindow::initPass() char *pass; pki_evp::passHash = QString(); QString salt; + int ret; pass_info p(tr("New Password"), tr("Please enter a password, " "that will be used to encrypt your private keys " - "in the database file:\n%1").arg(compressFilename(dbfile)), this); + "in the database file:\n%1"). + arg(compressFilename(dbfile)), this); + if (!mydb.find(setting, "pwhash")) { if ((pass = (char *)mydb.load(NULL))) { pki_evp::passHash = pass; @@ -709,28 +714,28 @@ int MainWindow::initPass() } } if (pki_evp::passHash.isEmpty()) { - int keylen = passWrite((char *)pki_evp::passwd, - MAX_PASS_LENGTH-1, 0, &p); - if (keylen < 0) - return 0; - pki_evp::passwd[keylen]='\0'; + ret = PwDialog::execute(&p, &pki_evp::passwd, true, true); + if (ret != 1) + return ret; salt = makeSalt(); pki_evp::passHash = pki_evp::sha512passwd(pki_evp::passwd,salt); mydb.set((const unsigned char *)CCHAR(pki_evp::passHash), pki_evp::passHash.length()+1, 1, setting, "pwhash"); } else { - int keylen=0; + ret = 0; while (pki_evp::sha512passwd(pki_evp::passwd, pki_evp::passHash) != pki_evp::passHash) { - if (keylen !=0) QMessageBox::warning(this,tr(XCA_TITLE), + if (ret) + QMessageBox::warning(this, XCA_TITLE, tr("Password verify error, please try again")); p.setTitle(tr("Password")); p.setDescription(tr("Please enter the password for unlocking the database:\n%1").arg(compressFilename(dbfile))); - keylen = passRead(pki_evp::passwd, MAX_PASS_LENGTH-1, 0, &p); - if (keylen < 0) - return 1; - pki_evp::passwd[keylen]='\0'; + ret = PwDialog::execute(&p, &pki_evp::passwd, + false, true); + printf("RET: %d\n", ret); + if (ret != 1) + return ret; if (pki_evp::passHash.left(1) == "S") continue; /* Start automatic update from md5 to salted sha512 @@ -752,102 +757,6 @@ int MainWindow::initPass() return 1; } -static int hex2bin(QString &x, char *buf, int buflen) -{ - int len = x.length(); - bool ok = false; - if (len % 2) - return -1; - len /= 2; - if (len > buflen) - return -1; - - for (int i=0; igetWidget()); - ui.setupUi(dlg); - if (p != NULL) { - ui.image->setPixmap(p->getImage()); - ui.description->setText(p->getDescription()); - ui.title->setText(p->getType()); - ui.label->setText(p->getType()); - dlg->setWindowTitle(p->getTitle()); - if (p->getType() != "PIN") - ui.takeHex->hide(); - } - - while (dlg->exec()) { - QString x = ui.pass->text(); - if (ui.takeHex->isChecked()) { - ret = hex2bin(x, buf, size); - if (ret != -1) - break; - } else { - strncpy(buf, x.toAscii(), size); - ret = x.length(); - break; - } - QMessageBox::warning(p->getWidget(), XCA_TITLE, hexwarn); - } - delete dlg; - return ret; -} - -int MainWindow::passWrite(char *buf, int size, int, void *userdata) -{ - int ret = -1; - pass_info *p = (pass_info *)userdata; - Ui::PassWrite ui; - QDialog *dlg = new QDialog(p->getWidget()); - ui.setupUi(dlg); - if (p != NULL) { - ui.image->setPixmap(p->getImage()) ; - ui.description->setText(p->getDescription()); - ui.title->setText(p->getType()); - ui.label->setText(p->getType()); - ui.repeatLabel->setText(tr("Repeat %1").arg(p->getType())); - dlg->setWindowTitle(p->getTitle()); - if (p->getType() != "PIN") - ui.takeHex->hide(); - } - - while (dlg->exec()) { - QString A = ui.passA->text(); - QString B = ui.passB->text(); - if (A == B) { - if (ui.takeHex->isChecked()) { - ret = hex2bin(A, buf, size); - if (ret != -1) - break; - } else { - strncpy(buf, A.toAscii(), size); - ret = A.length(); - break; - } - QMessageBox::warning(p->getWidget(), XCA_TITLE, - hexwarn); - } else { - QMessageBox::warning(p->getWidget(), XCA_TITLE, - tr("%1 missmatch").arg(p->getType())); - } - } - delete dlg; - return ret; -} - void MainWindow::Error(errorEx &err) { if (err.isEmpty()) @@ -893,17 +802,20 @@ void MainWindow::importAnything(QString file) delete dlgi; } -pki_multi *MainWindow::probeAnything(QString file) +pki_multi *MainWindow::probeAnything(QString file, int *ret) { pki_multi *pki = new pki_multi(); try { if (file.endsWith(".xdb")) { try { + int r; db mydb(file); mydb.verify_magic(); - changeDB(file); + r = changeDB(file); delete pki; + if (ret) + *ret = r; return NULL; } catch (errorEx &err) { } diff --git a/widgets/MainWindow.h b/widgets/MainWindow.h index 695e8c04..bd00f642 100644 --- a/widgets/MainWindow.h +++ b/widgets/MainWindow.h @@ -17,6 +17,7 @@ #include "lib/db_crl.h" #include "lib/exception.h" #include "lib/oid.h" +#include "lib/Passwd.h" #include #include #include @@ -47,7 +48,7 @@ class MainWindow: public QMainWindow, public Ui::MainWindow NIDlist *read_nidlist(QString name); QLabel *statusLabel; QString homedir; - void changeDB(QString fname); + int changeDB(QString fname); public: static db_x509 *certs; @@ -71,9 +72,6 @@ class MainWindow: public QMainWindow, public Ui::MainWindow int initPass(); void read_cmdline(); void load_engine(); - static int passRead(char *buf, int size, int rwflag, void *userdata); - static int passWrite(char *buf, int size, int rwflag, void *userdata); - //static void Qt::SocketError(errorEx &err); static void Error(errorEx &err); void cmd_version(); void cmd_help(const char* msg); @@ -82,16 +80,16 @@ class MainWindow: public QMainWindow, public Ui::MainWindow void setPath(QString path); bool mkDir(QString dir); void setItemEnabled(bool enable); - QString updateDbPassword(QString newdb, char *pass); + QString updateDbPassword(QString newdb, Passwd pass); void enableTokenMenu(bool enable); - pki_multi *probeAnything(QString file); + pki_multi *probeAnything(QString file, int *ret = NULL); void importAnything(QString file); void dropEvent(QDropEvent *event); void dragEnterEvent(QDragEnterEvent *event); - void open_default_db(); + int open_default_db(); public slots: - void init_database(); + int init_database(); void new_database(); void load_database(); void close_database(); diff --git a/widgets/Makefile b/widgets/Makefile index 67b08c97..e24f62bd 100644 --- a/widgets/Makefile +++ b/widgets/Makefile @@ -4,7 +4,7 @@ TOPDIR=.. endif MOC_NAMES=MainWindow KeyDetail clicklabel XcaTreeView ExportKey NewX509 \ - validity v3ext distname CertDetail CertExtend \ + validity v3ext distname CertDetail CertExtend PwDialog \ ImportMulti CrlDetail ExportDialog hashBox Options NewKey kvView NewCrl NAMES=$(MOC_NAMES) NewX509_ext MW_menu MW_help MW_database diff --git a/widgets/PwDialog.cpp b/widgets/PwDialog.cpp new file mode 100644 index 00000000..8adf064a --- /dev/null +++ b/widgets/PwDialog.cpp @@ -0,0 +1,131 @@ +/* vi: set sw=4 ts=4: + * + * Copyright (C) 2011 Christian Hohnstaedt. + * + * All rights reserved. + */ + + +#include "PwDialog.h" +#include "lib/base.h" +#include "lib/Passwd.h" +#include "widgets/MainWindow.h" +#include +#include + +static int hex2bin(QString &x, Passwd *final) +{ + bool ok = false; + int len = x.length(); + + if (len % 2) + return -1; + len /= 2; + + final->clear(); + + for (int i=0; iappend((x.mid(i*2, 2).toInt(&ok, 16)) & 0xff); + if (!ok) + return -1; + } + return len; +} + +int PwDialog::execute(pass_info *p, Passwd *passwd, bool write, bool abort) +{ + PwDialog *dlg; + int ret; + dlg = new PwDialog(p, write); + if (abort) + dlg->addAbortButton(); + ret = dlg->exec(); + *passwd = dlg->getPass(); + delete dlg; + return ret; +} + +int PwDialog::pwCallback(char *buf, int size, int rwflag, void *userdata) +{ + int ret; + + pass_info *p = (pass_info *)userdata; + PwDialog *dlg = new PwDialog(p, rwflag); + + ret = dlg->exec(); + QByteArray pw = dlg->getPass(); + size = MIN(size, pw.size()); + memcpy(buf, pw.constData(), size); + delete dlg; + return ret == 1 ? size : 0; +} + +PwDialog::PwDialog(pass_info *p, bool write) + :QDialog(p->getWidget()) +{ + pi = p; + setupUi(this); + setWindowTitle(XCA_TITLE); + image->setPixmap(pi->getImage()); + description->setText(pi->getDescription()); + title->setText(pi->getType()); + setWindowTitle(pi->getTitle()); + if (pi->getType() != "PIN") + takeHex->hide(); + setRW(write); +} + +void PwDialog::setRW(bool write) +{ + wrDialog = write; + if (write) { + label->setText(pi->getType()); + repeatLabel->setText(tr("Repeat %1").arg(pi->getType())); + label->show(); + passA->show(); + } else { + repeatLabel->setText(pi->getType()); + label->hide(); + passA->hide(); + } +} + +void PwDialog::accept() +{ + if (wrDialog && (passA->text() != passB->text())) { + QMessageBox::warning(this, XCA_TITLE, + tr("%1 missmatch").arg(pi->getType())); + return; + } + QString pw = passB->text(); + if (takeHex->isChecked()) { + int ret = hex2bin(pw, &final); + if (ret == -1) { + QMessageBox::warning(this, XCA_TITLE, tr("Hex password must only contain the characters '0' - '9' and 'a' - 'f' and it must consist of an even number of characters")); + return; + } + } else { + final = pw.toAscii(); + } + QDialog::accept(); +} + +void PwDialog::buttonPress(QAbstractButton *but) +{ + switch (buttonBox->standardButton(but)) { + case QDialogButtonBox::Ok: + accept(); + break; + case QDialogButtonBox::Cancel: + reject(); + break; + case QDialogButtonBox::Abort: + default: + done(2); + } +} + +void PwDialog::addAbortButton() +{ + buttonBox->addButton(tr("E&xit"), QDialogButtonBox::ResetRole); +} diff --git a/widgets/PwDialog.h b/widgets/PwDialog.h new file mode 100644 index 00000000..cc45b0b1 --- /dev/null +++ b/widgets/PwDialog.h @@ -0,0 +1,42 @@ +/* vi: set sw=4 ts=4: + * + * Copyright (C) 2011 Christian Hohnstaedt. + * + * All rights reserved. + */ + +#ifndef __PWDIALOG_H +#define __PWDIALOG_H + +#include +#include "ui_PwDialog.h" +#include "lib/Passwd.h" +#include "lib/pki_x509.h" +#include "lib/pass_info.h" + +class PwDialog: public QDialog, public Ui::PwDialog +{ + Q_OBJECT + + private: + bool wrDialog; + Passwd final; + pass_info *pi; + + public: + PwDialog(pass_info *p, bool write = false); + Passwd getPass() { + return final; + } + void addAbortButton(); + void setRW(bool write); + + static int execute(pass_info *p, Passwd *passwd, + bool write = false, bool abort = false); + static int pwCallback(char *buf, int size, int rwflag, void *userdata); + + public slots: + void accept(); + void buttonPress(QAbstractButton *but); +}; +#endif