json: Implement encrypt-sign

* src/gpgme-json.c (op_encrypt): Add optional signing_keys param.
(get_keys, create_keylist_patterns): Add param for json object name.

--
If the optional parameter signing_keys is provided to encrypt
it becomes an encrypt-sign operation.
This commit is contained in:
Andre Heinecke 2018-05-25 15:48:39 +02:00
parent 73dc5e933d
commit 7aa00917c7
No known key found for this signature in database
GPG Key ID: 2978E9D40CBABA5C

View File

@ -467,12 +467,13 @@ get_chunksize (cjson_t json, size_t *r_chunksize)
} }
/* Extract the keys from the "keys" array in the JSON object. On /* Extract the keys from the array or string with the name "name"
* success a string with the keys identifiers is stored at R_KEYS. * in the JSON object. On success a string with the keys identifiers
* is stored at R_KEYS.
* The keys in that string are LF delimited. On failure an error code * The keys in that string are LF delimited. On failure an error code
* is returned. */ * is returned. */
static gpg_error_t static gpg_error_t
get_keys (cjson_t json, char **r_keystring) get_keys (cjson_t json, const char *name, char **r_keystring)
{ {
cjson_t j_keys, j_item; cjson_t j_keys, j_item;
int i, nkeys; int i, nkeys;
@ -481,7 +482,7 @@ get_keys (cjson_t json, char **r_keystring)
*r_keystring = NULL; *r_keystring = NULL;
j_keys = cJSON_GetObjectItem (json, "keys"); j_keys = cJSON_GetObjectItem (json, name);
if (!j_keys) if (!j_keys)
return gpg_error (GPG_ERR_NO_KEY); return gpg_error (GPG_ERR_NO_KEY);
if (!cjson_is_array (j_keys) && !cjson_is_string (j_keys)) if (!cjson_is_array (j_keys) && !cjson_is_string (j_keys))
@ -664,7 +665,7 @@ data_from_base64_string (gpgme_data_t *r_data, cjson_t json)
* string array which can be used as patterns for * string array which can be used as patterns for
* op_keylist_ext or NULL. */ * op_keylist_ext or NULL. */
static char ** static char **
create_keylist_patterns (cjson_t request) create_keylist_patterns (cjson_t request, const char *name)
{ {
char *keystring; char *keystring;
char *p; char *p;
@ -673,7 +674,7 @@ create_keylist_patterns (cjson_t request)
int cnt = 1; int cnt = 1;
int i = 0; int i = 0;
if (get_keys (request, &keystring)) if (get_keys (request, name, &keystring))
return NULL; return NULL;
for (p = keystring; p; p++) for (p = keystring; p; p++)
@ -1250,6 +1251,8 @@ static const char hlp_encrypt[] =
"Optional parameters:\n" "Optional parameters:\n"
"protocol: Either \"openpgp\" (default) or \"cms\".\n" "protocol: Either \"openpgp\" (default) or \"cms\".\n"
"chunksize: Max number of bytes in the resulting \"data\".\n" "chunksize: Max number of bytes in the resulting \"data\".\n"
"signing_keys: Similar to the keys parameter for added signing.\n"
" (openpgp only)"
"\n" "\n"
"Optional boolean flags (default is false):\n" "Optional boolean flags (default is false):\n"
"base64: Input data is base64 encoded.\n" "base64: Input data is base64 encoded.\n"
@ -1275,6 +1278,7 @@ op_encrypt (cjson_t request, cjson_t result)
gpg_error_t err; gpg_error_t err;
gpgme_ctx_t ctx = NULL; gpgme_ctx_t ctx = NULL;
gpgme_protocol_t protocol; gpgme_protocol_t protocol;
char **signing_patterns = NULL;
size_t chunksize; size_t chunksize;
int opt_mime; int opt_mime;
char *keystring = NULL; char *keystring = NULL;
@ -1322,7 +1326,7 @@ op_encrypt (cjson_t request, cjson_t result)
/* Get the keys. */ /* Get the keys. */
err = get_keys (request, &keystring); err = get_keys (request, "keys", &keystring);
if (err) if (err)
{ {
/* Provide a custom error response. */ /* Provide a custom error response. */
@ -1331,6 +1335,37 @@ op_encrypt (cjson_t request, cjson_t result)
goto leave; goto leave;
} }
/* Do we have signing keys ? */
signing_patterns = create_keylist_patterns (request, "signing_keys");
if (signing_patterns)
{
gpgme_ctx_t keylist_ctx = get_context (protocol);
gpgme_key_t key;
gpgme_set_keylist_mode (keylist_ctx, GPGME_KEYLIST_MODE_LOCAL);
err = gpgme_op_keylist_ext_start (keylist_ctx,
(const char **) signing_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 (keylist_ctx, &key)))
{
if ((err = gpgme_signers_add (ctx, key)))
{
gpg_error_object (result, err, "Error adding signer: %s",
gpg_strerror (err));
goto leave;
}
gpgme_key_unref (key);
}
release_context (keylist_ctx);
}
if ((err = get_string_data (request, result, "data", &input))) if ((err = get_string_data (request, result, "data", &input)))
goto leave; goto leave;
@ -1348,8 +1383,17 @@ op_encrypt (cjson_t request, cjson_t result)
} }
/* Encrypt. */ /* Encrypt. */
err = gpgme_op_encrypt_ext (ctx, NULL, keystring, encrypt_flags, if (!signing_patterns)
input, output); {
err = gpgme_op_encrypt_ext (ctx, NULL, keystring, encrypt_flags,
input, output);
}
else
{
err = gpgme_op_encrypt_sign_ext (ctx, NULL, keystring, encrypt_flags,
input, output);
}
/* encrypt_result = gpgme_op_encrypt_result (ctx); */ /* encrypt_result = gpgme_op_encrypt_result (ctx); */
if (err) if (err)
{ {
@ -1366,6 +1410,7 @@ op_encrypt (cjson_t request, cjson_t result)
output = NULL; output = NULL;
leave: leave:
xfree_array (signing_patterns);
xfree (keystring); xfree (keystring);
release_context (ctx); release_context (ctx);
gpgme_data_release (input); gpgme_data_release (input);
@ -1547,7 +1592,7 @@ op_sign (cjson_t request, cjson_t result)
gpgme_set_sender (ctx, j_tmp->valuestring); gpgme_set_sender (ctx, j_tmp->valuestring);
} }
patterns = create_keylist_patterns (request); patterns = create_keylist_patterns (request, "keys");
if (!patterns) if (!patterns)
{ {
gpg_error_object (result, err, "Error getting keys: %s", gpg_error_object (result, err, "Error getting keys: %s",
@ -1561,14 +1606,15 @@ op_sign (cjson_t request, cjson_t result)
gpgme_set_protocol (keylist_ctx, protocol); gpgme_set_protocol (keylist_ctx, protocol);
gpgme_set_keylist_mode (keylist_ctx, GPGME_KEYLIST_MODE_LOCAL); gpgme_set_keylist_mode (keylist_ctx, GPGME_KEYLIST_MODE_LOCAL);
err = gpgme_op_keylist_ext_start (ctx, (const char **) patterns, 1, 0); err = gpgme_op_keylist_ext_start (keylist_ctx,
(const char **) patterns, 1, 0);
if (err) if (err)
{ {
gpg_error_object (result, err, "Error listing keys: %s", gpg_error_object (result, err, "Error listing keys: %s",
gpg_strerror (err)); gpg_strerror (err));
goto leave; goto leave;
} }
while (!(err = gpgme_op_keylist_next (ctx, &key))) while (!(err = gpgme_op_keylist_next (keylist_ctx, &key)))
{ {
if ((err = gpgme_signers_add (ctx, key))) if ((err = gpgme_signers_add (ctx, key)))
{ {
@ -1963,7 +2009,7 @@ op_keylist (cjson_t request, cjson_t result)
} }
/* Get the keys. */ /* Get the keys. */
patterns = create_keylist_patterns (request); patterns = create_keylist_patterns (request, "keys");
/* Do a keylisting and add the keys */ /* Do a keylisting and add the keys */
gpgme_set_keylist_mode (ctx, mode); gpgme_set_keylist_mode (ctx, mode);
@ -2148,7 +2194,7 @@ op_export (cjson_t request, cjson_t result)
mode |= GPGME_EXPORT_MODE_PKCS12; mode |= GPGME_EXPORT_MODE_PKCS12;
/* Get the export patterns. */ /* Get the export patterns. */
patterns = create_keylist_patterns (request); patterns = create_keylist_patterns (request, "keys");
/* Create an output data object. */ /* Create an output data object. */
err = gpgme_data_new (&output); err = gpgme_data_new (&output);