json: Add subkey_algo and defaults to createkey
authorAndre Heinecke <aheinecke@intevation.de>
Mon, 20 Aug 2018 14:38:36 +0000 (16:38 +0200)
committerAndre Heinecke <aheinecke@intevation.de>
Mon, 20 Aug 2018 14:38:36 +0000 (16:38 +0200)
* src/gpgme-json.c (op_createkey, hlp_createkey): Add subkey_algo
handling.
(hlp_createkey): Fix documentation of expiry.
--
Due to the funny quick-gen-key interface generating a key
with an explicit algo would result in bad defaults (only an SC key),
without a subkey.

This adds handling that should probably be in GnuPG proper to fix
the semantics of createkey by adding default subkey_algo handling.

src/gpgme-json.c

index 5a9b9cf..99c6652 100644 (file)
@@ -2878,8 +2878,15 @@ static const char hlp_createkey[] =
   "userid:  The user id. E.g. \"Foo Bar <foo@bar.baz>\"\n"
   "\n"
   "Optional parameters:\n"
-  "algo:    Algo of the key as string. See doc for gpg --quick-gen-key.\n"
-  "expires: Seconds since epoch to expiry as Number. 0 means no expiry.\n"
+  "algo:        Algo of the key as string. See doc for gpg --quick-gen-key.\n"
+  "subkey-algo: Algo of the encryption subkey. If ommited the same as algo\n"
+  "             is used.\n"
+  "             Except for dsa and ed25519 where the according\n"
+  "             elg / cv25519 algo will be used as subkey-algo.\n"
+  "\n"
+  "             If algo is omitted or default or future-default subkey-algo\n"
+  "             is ignored.\n"
+  "expires:     Seconds from now to expiry as Number. 0 means no expiry.\n"
   "\n"
   "Response on success:\n"
   "fingerprint:   The fingerprint of the created key.\n"
@@ -2891,12 +2898,14 @@ op_createkey (cjson_t request, cjson_t result)
 {
   gpg_error_t err;
   gpgme_ctx_t ctx = NULL;
-  unsigned int flags = 0;
+  unsigned int flags = GPGME_CREATE_FORCE; /* Always force as the GUI should
+                                              handle checks, if required. */
   unsigned long expires = 0;
   cjson_t j_tmp;
   const char *algo = "default";
   const char *userid;
   gpgme_genkey_result_t res;
+  char *new_fpr = NULL;
 
 #ifdef GPG_AGENT_ALLOWS_KEYGEN_TRHOUGH_BROWSER
   /* GnuPG forbids keygen through the browser socket so for
@@ -2950,9 +2959,58 @@ op_createkey (cjson_t request, cjson_t result)
       goto leave;
     }
 
-  xjson_AddStringToObject0 (result, "fingerprint", res->fpr);
+  /* Dup the fpr as the result might become invalid after context reuse. */
+  new_fpr = xstrdup (res->fpr);
+
+  if (algo && strcmp ("default", algo) && strcmp ("future-default", algo))
+    {
+      /* We need to add the encryption subkey manually */
+      gpgme_ctx_t keylistctx = create_onetime_context (GPGME_PROTOCOL_OpenPGP);
+      gpgme_key_t new_key = NULL;
+      char *subkey_algo = NULL;
+
+      j_tmp = cJSON_GetObjectItem (request, "subkey_algo");
+      if (j_tmp && cjson_is_string (j_tmp))
+        {
+          subkey_algo = xstrdup (j_tmp->valuestring);
+        }
+
+      if (!subkey_algo)
+        {
+          subkey_algo = strdup (algo);
+          if (!strncmp ("dsa", subkey_algo, 3))
+            {
+              subkey_algo[0] = 'e';
+              subkey_algo[1] = 'l';
+              subkey_algo[2] = 'g';
+            }
+          if (!strcmp ("ed25519", subkey_algo))
+            {
+              strcpy (subkey_algo, "cv25519");
+            }
+        }
+
+      err = gpgme_get_key (keylistctx, new_fpr, &new_key, 1);
+      release_onetime_context (keylistctx);
+      if (err)
+        {
+          gpg_error_object (result, err, "Error finding created key: %s",
+                            gpg_strerror (err));
+          xfree (subkey_algo);
+          goto leave;
+        }
+
+      err = gpgme_op_createsubkey (ctx, new_key, subkey_algo,
+                                   0, expires, flags |= GPGME_CREATE_ENCR);
+      xfree (subkey_algo);
+      if (err)
+        goto leave;
+    }
+
+  xjson_AddStringToObject0 (result, "fingerprint", new_fpr);
 
 leave:
+  xfree (new_fpr);
 #ifdef GPG_AGENT_ALLOWS_KEYGEN_TRHOUGH_BROWSER
   release_context (ctx);
 #else