From 6cc842c9aa76d19448141e5117ac59452d7a1ff3 Mon Sep 17 00:00:00 2001 From: Andre Heinecke Date: Wed, 11 Jul 2018 16:18:24 +0200 Subject: [PATCH] json: Add with-sec-fprs param to export * src/gpgme-json.c (add_secret_fprs): New helper. (op_export, hlp_export): Extend for with-sec fprs. -- This is a request from Mailvelope, to import an export they need the information for which keys from the export a secret key is also available. For simplicity it is much preferred to get this information in a single call without the need to do and parse a keylisting additionally in a second native-messaging call. So we make it optional to include that info in the export. --- src/gpgme-json.c | 73 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 5 deletions(-) diff --git a/src/gpgme-json.c b/src/gpgme-json.c index 1604d2f1..ecdcc08e 100644 --- a/src/gpgme-json.c +++ b/src/gpgme-json.c @@ -720,6 +720,54 @@ create_keylist_patterns (cjson_t request, const char *name) } +/* Do a secret keylisting for protocol proto and add the fingerprints of + the secret keys for patterns to the result as "sec-fprs" array. */ +static gpg_error_t +add_secret_fprs (const char **patterns, gpgme_protocol_t protocol, + cjson_t result) +{ + gpgme_ctx_t ctx; + gpg_error_t err; + gpgme_key_t key = NULL; + cjson_t j_fprs = xjson_CreateArray (); + + ctx = create_onetime_context (protocol); + + gpgme_set_keylist_mode (ctx, GPGME_KEYLIST_MODE_LOCAL | + GPGME_KEYLIST_MODE_WITH_SECRET); + + err = gpgme_op_keylist_ext_start (ctx, patterns, 1, 0); + + if (err) + { + gpg_error_object (result, err, "Error listing keys: %s", + gpg_strerror (err)); + goto leave; + } + + while (!(err = gpgme_op_keylist_next (ctx, &key))) + { + if (!key || !key->fpr) + continue; + cJSON_AddItemToArray (j_fprs, cJSON_CreateString (key->fpr)); + gpgme_key_unref (key); + key = NULL; + } + err = 0; + + release_onetime_context (ctx); + ctx = NULL; + + xjson_AddItemToObject (result, "sec-fprs", j_fprs); + +leave: + release_onetime_context (ctx); + gpgme_key_unref (key); + + return err; +} + + /* Create sigsum json array */ static cjson_t sigsum_to_json (gpgme_sigsum_t summary) @@ -2438,13 +2486,17 @@ static const char hlp_export[] = "minimal: Add EXPORT_MODE_MINIMAL.\n" "raw: Add EXPORT_MODE_RAW.\n" "pkcs12: Add EXPORT_MODE_PKCS12.\n" + "with-sec-fprs: Add the sec-fprs array to the result.\n" "\n" "Response on success:\n" - "type: \"keys\"\n" - "data: Unless armor mode is used a Base64 encoded binary.\n" - " In armor mode a string with an armored\n" - " OpenPGP or a PEM / PKCS12 key.\n" - "base64: Boolean indicating whether data is base64 encoded.\n"; + "type: \"keys\"\n" + "data: Unless armor mode is used a Base64 encoded binary.\n" + " In armor mode a string with an armored\n" + " OpenPGP or a PEM / PKCS12 key.\n" + "base64: Boolean indicating whether data is base64 encoded.\n" + "sec-fprs: Optional, only if with-secret is set. An array containing\n" + " the fingerprints of the keys in the export for which a secret\n" + " key is available"; static gpg_error_t op_export (cjson_t request, cjson_t result) { @@ -2453,6 +2505,7 @@ op_export (cjson_t request, cjson_t result) gpgme_protocol_t protocol; char **patterns = NULL; int abool; + int with_secret = 0; gpgme_export_mode_t mode = 0; gpgme_data_t output = NULL; @@ -2493,6 +2546,11 @@ op_export (cjson_t request, cjson_t result) if (abool) mode |= GPGME_EXPORT_MODE_PKCS12; + if ((err = get_boolean_flag (request, "with-sec-fprs", 0, &abool))) + goto leave; + if (abool) + with_secret = 1; + /* Get the export patterns. */ patterns = create_keylist_patterns (request, "keys"); @@ -2519,6 +2577,11 @@ op_export (cjson_t request, cjson_t result) "keys", !gpgme_get_armor (ctx)); output = NULL; + if (!err && with_secret) + { + err = add_secret_fprs ((const char **) patterns, protocol, result); + } + leave: xfree_array (patterns); release_context (ctx);