Allow exporting secret keys.

Requests the passphrase with a popup.

As from GPGME 1.15.0, the loopback pinentry is functional when exporting secret keys. It works fine when the exact passphrase is provided. If it's a wrong passphrase, GPGME does not generate an ::Error, but the app crashes with 'free(): double free detected in tcache 2'.

Hence, this patch cannot be committed to master.

Status : dangerous
Result : works and works not
Reason : a wrong passphrase means a crash
This commit is contained in:
SET
2020-11-20 22:41:29 +01:00
parent bb174075df
commit 82b8810f62
15 changed files with 241 additions and 142 deletions

View File

@@ -9,37 +9,6 @@
#include "GpgMECWorker.h"
#ifdef DEVTIME
/**
* This callback is never called when exporting private keys.
* From gpgme-1.14.0/tests/run-support.h
*/
gpgme_error_t passphrase_cb(void *opaque, const char *uid_hint, const char *passphrase_info,
int last_was_bad, int fd)
{
int res;
char pass[] = "test_pwd\n";
int passlen = strlen(pass);
int off = 0;
(void) opaque;
(void) uid_hint;
(void) passphrase_info;
(void) last_was_bad;
do
{
res = gpgme_io_write(fd, &pass[off], passlen - off);
if (res > 0)
off += res;
}
while (res > 0 && off != passlen);
return off == passlen ? 0 : gpgme_error_from_errno(errno);
}
#endif
GpgMECWorker::GpgMECWorker()
{
gpgme_error_t c_err = gpgme_new(&c_ctx);
@@ -68,66 +37,3 @@ bool GpgMECWorker::DeleteKey(const char * fpr, bool secret, GpgME::Error& e)
}
return true;
}
#ifdef DEVTIME
/**
* Much code here is obtained from gpgme-1.14.0/tests/run-export.c
* @param fpr
* @param e
* @return
*/
bool GpgMECWorker::ExportPrivateKey(const char* fpr, GpgME::Error& e)
{
gpgme_key_t c_key;
gpgme_data_t out;
gpgme_set_armor(c_ctx, 1);
gpgme_error_t c_err = gpgme_get_key(c_ctx, fpr, &c_key, true);
if (c_key == NULL)
{
e = GpgME::Error::fromCode(c_err);
return false;
}
FILE * kFp = fopen("/tmp/data", "wb");
if (kFp == NULL)
return false;
c_err = gpgme_data_new_from_stream(&out, kFp);
if (c_err != 0)
{
fclose(kFp);
e = GpgME::Error::fromCode(c_err);
return false;
}
gpgme_key_t aKeys[2];
aKeys[0] = c_key;
aKeys[1] = NULL;
c_err = gpgme_set_pinentry_mode(c_ctx, GPGME_PINENTRY_MODE_LOOPBACK);
if (c_err != 0)
{
fclose(kFp);
e = GpgME::Error::fromCode(c_err);
return false;
}
gpgme_set_passphrase_cb(c_ctx, passphrase_cb, NULL);
gpgme_export_mode_t flags = GPGME_EXPORT_MODE_SECRET;
c_err = gpgme_op_export_keys(c_ctx, aKeys, flags, out);
if (c_err != 0)
{
fclose(kFp);
gpgme_data_release(out);
e = GpgME::Error::fromCode(c_err);
return false;
}
fflush(NULL);
fclose(kFp);
gpgme_data_release(out);
return true;
}
#endif