From ac780d3e774ebe005705a113ba71e7bf59005dcf Mon Sep 17 00:00:00 2001 From: Christian Hohnstaedt Date: Fri, 14 Jul 2017 17:21:59 +0200 Subject: [PATCH] Fix PEM_BIO loading by using QByteArray instead of BIO and fmemopen --- lib/func.cpp | 31 -------------------------- lib/func.h | 3 --- lib/pki_base.cpp | 8 +++++++ lib/pki_base.h | 1 + lib/pki_evp.cpp | 9 ++++---- lib/pki_evp.h | 2 +- lib/pki_multi.cpp | 50 +++++++++++------------------------------- lib/pki_multi.h | 2 +- widgets/MainWindow.cpp | 8 +------ 9 files changed, 30 insertions(+), 84 deletions(-) diff --git a/lib/func.cpp b/lib/func.cpp index 1ac69525..a142e901 100644 --- a/lib/func.cpp +++ b/lib/func.cpp @@ -224,37 +224,6 @@ QString filename2QString(const char *fname) #endif } -#if defined(WIN32) || defined (Q_OS_MAC) -static QString xca_tmpfile() -{ - return getHomeDir() + "\\" + "tmp_file.dat"; -} -#endif - -void fp_from_data_finish(FILE *fp) -{ - if (fp) - fclose(fp); -#if defined(WIN32) || defined (Q_OS_MAC) - QFile::remove(xca_tmpfile()); -#endif -} - -FILE *fp_from_data(QByteArray data) -{ -#if defined(WIN32) || defined (Q_OS_MAC) - QFile::remove(xca_tmpfile()); - FILE *fp = fopen_write(xca_tmpfile()); - if (!fp) - return NULL; - fwrite(data.data(), data.size(), 1, fp); - return fp; -#else - return fmemopen(data.data(), data.size(), "rb"); -#endif -} - - QString compressFilename(QString filename, int maxlen) { if (filename.length() < maxlen) diff --git a/lib/func.h b/lib/func.h index fbfb2fd9..bdf0049b 100644 --- a/lib/func.h +++ b/lib/func.h @@ -57,9 +57,6 @@ void *d2i_bytearray(void *(*d2i)(void*, unsigned char**, long), #define QString2filename(str) filename2bytearray(str).constData() -FILE *fp_from_data(QByteArray data); -void fp_from_data_finish(FILE*); - static inline FILE *fopen_read(QString s) { return fopen(QString2filename(s), "rb"); diff --git a/lib/pki_base.cpp b/lib/pki_base.cpp index 430578d8..b6e8dc83 100644 --- a/lib/pki_base.cpp +++ b/lib/pki_base.cpp @@ -101,6 +101,14 @@ void pki_base::my_error(const QString error) const } } + +void pki_base::fromPEMbyteArray(QByteArray &ba, QString name) +{ + BIO *bio = BIO_new_mem_buf(ba.data(), ba.length()); + fromPEM_BIO(bio, name); + BIO_free(bio); +} + QString pki_base::rmslashdot(const QString &s) { QByteArray a = s.toLatin1().replace("\\", "/"); diff --git a/lib/pki_base.h b/lib/pki_base.h index dd94980b..9e5025c7 100644 --- a/lib/pki_base.h +++ b/lib/pki_base.h @@ -88,6 +88,7 @@ class pki_base : public QObject }; uint32_t intFromData(QByteArray &ba); virtual void fromPEM_BIO(BIO *, QString) {}; + virtual void fromPEMbyteArray(QByteArray &, QString); virtual void deleteFromToken() { }; virtual void deleteFromToken(slotid) { }; virtual int renameOnToken(slotid, QString) diff --git a/lib/pki_evp.cpp b/lib/pki_evp.cpp index 05ede2a5..de3ed5b5 100644 --- a/lib/pki_evp.cpp +++ b/lib/pki_evp.cpp @@ -229,21 +229,22 @@ void pki_evp::openssl_pw_error(QString fname) } } -void pki_evp::fromPEM_BIO(BIO *bio, QString name) +void pki_evp::fromPEMbyteArray(QByteArray &ba, QString name) { + BIO *bio = BIO_new_mem_buf(ba.data(), ba.length()); EVP_PKEY *pkey; - int pos; 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, PwDialog::pwCallback, &p); openssl_pw_error(name); if (!pkey){ pki_ign_openssl_error(); - pos = BIO_seek(bio, pos); + BIO_free(bio); + bio = BIO_new_mem_buf(ba.data(), ba.length()); pkey = PEM_read_bio_PUBKEY(bio, NULL, PwDialog::pwCallback, &p); } + BIO_free(bio); if (pkey){ if (key) EVP_PKEY_free(key); diff --git a/lib/pki_evp.h b/lib/pki_evp.h index 2ae75273..5430864b 100644 --- a/lib/pki_evp.h +++ b/lib/pki_evp.h @@ -48,7 +48,7 @@ class pki_evp: public pki_key EVP_PKEY *priv2pub(EVP_PKEY* key); static QString removeTypeFromIntName(QString n); - void fromPEM_BIO(BIO *bio, QString name); + void fromPEMbyteArray(QByteArray &ba, QString name); void fload(const QString fname); void writeDefault(const QString fname); void fromData(const unsigned char *p, db_header_t *head); diff --git a/lib/pki_multi.cpp b/lib/pki_multi.cpp index 28bdd0d3..d253761d 100644 --- a/lib/pki_multi.cpp +++ b/lib/pki_multi.cpp @@ -95,53 +95,28 @@ static pki_base *pkiByPEM(QString text, int *skip) void pki_multi::fload(const QString fname) { - FILE * fp; - BIO *bio = NULL; + QFile file(fname); + QByteArray ba; - fp = fopen_read(fname); - if (!fp) { + if (file.error()) { fopen_error(fname); return; } - bio = BIO_new_fp(fp, BIO_CLOSE); - fromPEM_BIO(bio, fname); - BIO_free(bio); + ba = file.readAll(); + fromPEMbyteArray(ba, fname); }; -#define BUFLEN 1024 -void pki_multi::fromPEM_BIO(BIO *bio, QString name) +void pki_multi::fromPEMbyteArray(QByteArray &ba, QString name) { - QString text; pki_base *item = NULL; - char buf[BUFLEN]; - int len, startpos; + int startpos; for (;;) { try { - int pos = BIO_tell(bio); - len = BIO_read(bio, buf, BUFLEN-1); - buf[len] = '\0'; - text = buf; - item = pkiByPEM(text, &startpos); - if (!item) { - if (startpos <= 0) - break; - if (BIO_seek(bio, pos + startpos) == -1) - throw errorEx(tr("Seek failed")); - continue; - } - pos += startpos; - if (BIO_seek(bio, pos) == -1) - throw errorEx(tr("Seek failed")); - item->fromPEM_BIO(bio, name); - if (pos == BIO_tell(bio)) { - /* No progress, do it manually */ - if (BIO_seek(bio, pos + 1)) - throw errorEx(tr("Seek failed")); - printf("Could not load: %s\n", - CCHAR(item->getClassName())); - delete item; - continue; - } + item = pkiByPEM(QString::fromLatin1(ba), &startpos); + if (!item || startpos < 0) + break; + ba.remove(0, startpos); + item->fromPEMbyteArray(ba, name); openssl_error(); multi.append(item); } catch (errorEx &err) { @@ -150,6 +125,7 @@ void pki_multi::fromPEM_BIO(BIO *bio, QString name) delete item; item = NULL; } + ba.remove(0, sizeof BEGIN -1); } if (multi.size() == 0) throw errorEx(tr("No known PEM encoded items found")); diff --git a/lib/pki_multi.h b/lib/pki_multi.h index 8207b3c7..c0aa4170 100644 --- a/lib/pki_multi.h +++ b/lib/pki_multi.h @@ -23,7 +23,7 @@ class pki_multi: public pki_base public: pki_multi(const QString name = ""); ~pki_multi(); - void fromPEM_BIO(BIO *bio, QString name); + void fromPEMbyteArray(QByteArray &ba, QString name); void fload(const QString fname); void probeAnything(const QString fname); pki_base *pull(); diff --git a/widgets/MainWindow.cpp b/widgets/MainWindow.cpp index 834b6192..f3111899 100644 --- a/widgets/MainWindow.cpp +++ b/widgets/MainWindow.cpp @@ -345,17 +345,13 @@ bool MainWindow::pastePem(QString text) QByteArray pemdata = text.toLatin1(); if (pemdata.size() == 0) return false; - FILE *fp = fp_from_data(pemdata); - check_oom(fp); - BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); - check_oom(b); pki_multi *pem = NULL; ImportMulti *dlgi = NULL; try { pem = new pki_multi(); dlgi = new ImportMulti(this); - pem->fromPEM_BIO(b, QString("paste")); + pem->fromPEMbyteArray(pemdata, QString("paste")); success = pem->count() != 0; dlgi->addItem(pem); pem = NULL; @@ -364,12 +360,10 @@ bool MainWindow::pastePem(QString text) catch (errorEx &err) { Error(err); } - fp_from_data_finish(fp); if (dlgi) delete dlgi; if (pem) delete pem; - BIO_free(b); return success; }