Fix PEM_BIO loading by using QByteArray instead of BIO and fmemopen

This commit is contained in:
Christian Hohnstaedt 2017-07-14 17:21:59 +02:00
parent 5fbd102493
commit ac780d3e77
9 changed files with 30 additions and 84 deletions

View File

@ -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)

View File

@ -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");

View File

@ -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("\\", "/");

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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"));

View File

@ -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();

View File

@ -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;
}