core: New function gpgme_op_adduid.
authorWerner Koch <wk@gnupg.org>
Wed, 14 Sep 2016 09:40:34 +0000 (11:40 +0200)
committerWerner Koch <wk@gnupg.org>
Wed, 14 Sep 2016 09:40:34 +0000 (11:40 +0200)
* src/genkey.c: Replace most error codes GPG_ERR_INV_VALUE by
GPG_ERR_INV_ARG.
(struct op_data_t): Add field UIDMODE.
(genkey_status_handler): Use UIDMODE.
(adduid_start): New.
(gpgme_op_adduid_start, gpgme_op_adduid): New.
* src/gpgme.def, src/libgpgme.vers: Add them.
* tests/run-genkey.c: Add option --adduid.

Signed-off-by: Werner Koch <wk@gnupg.org>
NEWS
src/engine-gpg.c
src/genkey.c
src/gpgme.def
src/gpgme.h.in
src/libgpgme.vers
tests/run-genkey.c

diff --git a/NEWS b/NEWS
index 9445f7f..621ce3f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -19,6 +19,8 @@ Noteworthy changes in version 1.7.0 (unreleased) [C25/A14/R_]
  gpgme_op_createkey_start       NEW.
  gpgme_op_createsubkey          NEW.
  gpgme_op_createsubkey_start    NEW.
+ gpgme_op_adduid_start          NEW.
+ gpgme_op_adduid                NEW.
  gpgme_genkey_result_t          EXTENDED: New fields pubkey and seckey.
  gpgme_signature_t              EXTENDED: New field key.
  gpgme_key_t                    EXTENDED: New field fpr.
index 5a16f80..d2b6dd3 100644 (file)
@@ -2114,11 +2114,25 @@ gpg_addkey (engine_gpg_t gpg,
 
 static gpgme_error_t
 gpg_adduid (engine_gpg_t gpg,
-            const char *userid,
-            unsigned int flags,
-            int use_armor)
+            gpgme_key_t key,
+            const char *userid)
 {
-  return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+  gpgme_error_t err;
+
+  if (!key || !key->fpr || !userid)
+    return gpg_error (GPG_ERR_INV_ARG);
+
+  err = add_arg (gpg, "--quick-adduid");
+  if (!err)
+    err = add_arg (gpg, "--");
+  if (!err)
+    err = add_arg (gpg, key->fpr);
+  if (!err)
+    err = add_arg (gpg, userid);
+
+  if (!err)
+    err = start (gpg);
+  return err;
 }
 
 
@@ -2170,7 +2184,7 @@ gpg_genkey (void *engine,
   else if (!userid && key)
     err = gpg_addkey (gpg, algo, expires, key, flags, use_armor);
   else if (userid && key && !algo)
-    err = gpg_adduid (gpg, userid, flags, use_armor);
+    err = gpg_adduid (gpg, key, userid);
   else
     err = gpg_error (GPG_ERR_INV_VALUE);
 
index 26bcca6..b93abb8 100644 (file)
@@ -42,6 +42,9 @@ typedef struct
   /* The error code from certain ERROR status lines or 0.  */
   gpg_error_t error_code;
 
+  /* Flag to indicate that a UID is to be added.  */
+  gpg_error_t uidmode;
+
   /* The key parameters passed to the crypto engine.  */
   gpgme_data_t key_parameter;
 } *op_data_t;
@@ -142,7 +145,10 @@ genkey_status_handler (void *priv, gpgme_status_code_t code, char *args)
       if (args && *args)
        {
          if (*args == 'B' || *args == 'P')
-           opd->result.primary = 1;
+            {
+              opd->result.primary = 1;
+              opd->result.uid = 1;
+            }
          if (*args == 'B' || *args == 'S')
            opd->result.sub = 1;
          if (args[1] == ' ')
@@ -171,10 +177,12 @@ genkey_status_handler (void *priv, gpgme_status_code_t code, char *args)
     case GPGME_STATUS_EOF:
       if (opd->error_code)
         return opd->error_code;
-      else if (!opd->result.primary && !opd->result.sub)
+      else if (!opd->uidmode && !opd->result.primary && !opd->result.sub)
        return gpg_error (GPG_ERR_GENERAL);
       else if (opd->failure_code)
         return opd->failure_code;
+      else if (opd->uidmode)
+        opd->result.uid = 1;  /* We have no status line, thus this hack.  */
       break;
 
     case GPGME_STATUS_INQUIRE_MAXLEN:
@@ -277,7 +285,7 @@ gpgme_op_genkey_start (gpgme_ctx_t ctx, const char *parms,
   TRACE_LOGBUF (parms, strlen (parms));
 
   if (!ctx)
-    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
+    return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
 
   err = genkey_start (ctx, 0, parms, pubkey, seckey);
   return TRACE_ERR (err);
@@ -298,7 +306,7 @@ gpgme_op_genkey (gpgme_ctx_t ctx, const char *parms, gpgme_data_t pubkey,
   TRACE_LOGBUF (parms, strlen (parms));
 
   if (!ctx)
-    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
+    return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
 
   err = genkey_start (ctx, 1, parms, pubkey, seckey);
   if (!err)
@@ -323,7 +331,7 @@ createkey_start (gpgme_ctx_t ctx, int synchronous,
     return err;
 
   if (reserved || anchorkey || !userid)
-    return gpg_error (GPG_ERR_INV_VALUE);
+    return gpg_error (GPG_ERR_INV_ARG);
 
   err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook,
                               sizeof (*opd), release_op_data);
@@ -360,7 +368,7 @@ gpgme_op_createkey_start (gpgme_ctx_t ctx, const char *userid, const char *algo,
              "userid='%s', algo='%s' flags=0x%x", userid, algo, flags);
 
   if (!ctx)
-    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
+    return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
 
   err = createkey_start (ctx, 0,
                          userid, algo, reserved, expires, anchorkey, flags);
@@ -379,7 +387,7 @@ gpgme_op_createkey (gpgme_ctx_t ctx, const char *userid, const char *algo,
              "userid='%s', algo='%s' flags=0x%x", userid, algo, flags);
 
   if (!ctx)
-    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
+    return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
 
   err = createkey_start (ctx, 1,
                          userid, algo, reserved, expires, anchorkey, flags);
@@ -409,7 +417,7 @@ createsubkey_start (gpgme_ctx_t ctx, int synchronous,
     return err;
 
   if (reserved || !key)
-    return gpg_error (GPG_ERR_INV_VALUE);
+    return gpg_error (GPG_ERR_INV_ARG);
 
   err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook,
                               sizeof (*opd), release_op_data);
@@ -447,7 +455,7 @@ gpgme_op_createsubkey_start (gpgme_ctx_t ctx, gpgme_key_t key, const char *algo,
              "key=%p, algo='%s' flags=0x%x", key, algo, flags);
 
   if (!ctx)
-    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
+    return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
 
   err = createsubkey_start (ctx, 0, key, algo, reserved, expires, flags);
   return TRACE_ERR (err);
@@ -465,10 +473,92 @@ gpgme_op_createsubkey (gpgme_ctx_t ctx, gpgme_key_t key, const char *algo,
              "key=%p, algo='%s' flags=0x%x", key, algo, flags);
 
   if (!ctx)
-    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
+    return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
 
   err = createsubkey_start (ctx, 1, key, algo, reserved, expires, flags);
   if (!err)
     err = _gpgme_wait_one (ctx);
   return TRACE_ERR (err);
 }
+
+
+\f
+static gpgme_error_t
+adduid_start (gpgme_ctx_t ctx, int synchronous,
+              gpgme_key_t key, const char *userid, unsigned int flags)
+{
+  gpgme_error_t err;
+  void *hook;
+  op_data_t opd;
+
+  if (ctx->protocol != GPGME_PROTOCOL_OPENPGP)
+    return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
+
+  if (!key || !userid)
+    return gpg_error (GPG_ERR_INV_ARG);
+
+  err = _gpgme_op_reset (ctx, synchronous);
+  if (err)
+    return err;
+
+  err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook,
+                              sizeof (*opd), release_op_data);
+  opd = hook;
+  if (err)
+    return err;
+
+  opd->uidmode = 1;
+
+  _gpgme_engine_set_status_handler (ctx->engine, genkey_status_handler, ctx);
+
+  if (ctx->passphrase_cb)
+    {
+      err = _gpgme_engine_set_command_handler
+        (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
+      if (err)
+        return err;
+    }
+
+  return _gpgme_engine_op_genkey (ctx->engine,
+                                  userid, NULL, 0, 0,
+                                  key, flags,
+                                  NULL, ctx->use_armor, NULL, NULL);
+
+}
+
+
+/* Add USERID to an existing KEY.  */
+gpgme_error_t
+gpgme_op_adduid_start (gpgme_ctx_t ctx,
+                       gpgme_key_t key, const char *userid, unsigned int flags)
+{
+  gpgme_error_t err;
+
+  TRACE_BEG2 (DEBUG_CTX, "gpgme_op_adduid_start", ctx,
+             "uid='%s' flags=0x%x", userid, flags);
+
+  if (!ctx)
+    return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
+
+  err = adduid_start (ctx, 0, key, userid, flags);
+  return TRACE_ERR (err);
+}
+
+
+gpgme_error_t
+gpgme_op_adduid (gpgme_ctx_t ctx,
+                 gpgme_key_t key, const char *userid, unsigned int flags)
+{
+  gpgme_error_t err;
+
+  TRACE_BEG2 (DEBUG_CTX, "gpgme_op_adduid", ctx,
+             "uid='%s' flags=0x%x", userid, flags);
+
+  if (!ctx)
+    return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
+
+  err = adduid_start (ctx, 1, key, userid, flags);
+  if (!err)
+    err = _gpgme_wait_one (ctx);
+  return TRACE_ERR (err);
+}
index 7b7b1f2..54b04e0 100644 (file)
@@ -233,6 +233,8 @@ EXPORTS
     gpgme_op_createkey                    @173
     gpgme_op_createsubkey_start           @174
     gpgme_op_createsubkey                 @175
+    gpgme_op_adduid_start                 @176
+    gpgme_op_adduid                       @177
 
 ; END
 
index 0fdc927..ec436c8 100644 (file)
@@ -1835,8 +1835,11 @@ struct _gpgme_op_genkey_result
   /* A sub key was generated.  */
   unsigned int sub : 1;
 
+  /* A user id was generated.  */
+  unsigned int uid : 1;
+
   /* Internal to GPGME, do not use.  */
-  unsigned int _unused : 30;
+  unsigned int _unused : 29;
 
   /* The fingerprint of the generated key.  */
   char *fpr;
@@ -1888,6 +1891,14 @@ gpgme_error_t gpgme_op_createsubkey       (gpgme_ctx_t ctx,
                                            unsigned long expires,
                                            unsigned int flags);
 
+/* Add USERID to an existing KEY.  */
+gpgme_error_t gpgme_op_adduid_start (gpgme_ctx_t ctx,
+                                     gpgme_key_t key, const char *userid,
+                                     unsigned int flags);
+gpgme_error_t gpgme_op_adduid       (gpgme_ctx_t ctx,
+                                     gpgme_key_t key, const char *userid,
+                                     unsigned int flags);
+
 
 
 /* Retrieve a pointer to the result of a genkey, createkey, or
index 2a3e9fc..0cef9e0 100644 (file)
@@ -107,6 +107,8 @@ GPGME_1.1 {
     gpgme_op_createkey;
     gpgme_op_createsubkey_start;
     gpgme_op_createsubkey;
+    gpgme_op_adduid_start;
+    gpgme_op_adduid;
 };
 
 
index 3b64502..959e2ea 100644 (file)
@@ -199,9 +199,13 @@ parse_usage_string (const char *string)
 static int
 show_usage (int ex)
 {
-  fputs ("usage: " PGM " [options] USERID [ALGO [USAGE [EXPIRESECONDS]]]\n\n"
+  fputs ("usage: " PGM " [options] ARGS\n"
+         "         args: USERID [ALGO [USAGE [EXPIRESECONDS]]]\n"
+         "   for addkey: FPR    [ALGO [USAGE [EXPIRESECONDS]]]\n"
+         "   for adduid: FPR    USERID\n"
          "Options:\n"
-         "  --addkey         add a subkey to the key with USERID\n"
+         "  --addkey         add a subkey to the key with FPR\n"
+         "  --adduid         add a user id to the key with FPR\n"
          "  --verbose        run in verbose mode\n"
          "  --status         print status lines from the backend\n"
          "  --progress       print progress info\n"
@@ -226,8 +230,10 @@ main (int argc, char **argv)
   int print_progress = 0;
   int use_loopback = 0;
   int addkey = 0;
+  int adduid = 0;
   const char *userid;
   const char *algo = NULL;
+  const char *newuserid = NULL;
   unsigned int flags = 0;
   unsigned long expire = 0;
   gpgme_genkey_result_t result;
@@ -248,6 +254,13 @@ main (int argc, char **argv)
       else if (!strcmp (*argv, "--addkey"))
         {
           addkey = 1;
+          adduid = 0;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--adduid"))
+        {
+          addkey = 0;
+          adduid = 1;
           argc--; argv++;
         }
       else if (!strcmp (*argv, "--verbose"))
@@ -294,15 +307,25 @@ main (int argc, char **argv)
         show_usage (1);
     }
 
-  if (!argc || argc > 4)
-    show_usage (1);
-  userid = argv[0];
-  if (argc > 1)
-    algo = argv[1];
-  if (argc > 2)
-    flags |= parse_usage_string (argv[2]);
-  if (argc > 3)
-    expire = parse_expire_string (argv[3]);
+  if (adduid)
+    {
+      if (argc != 2)
+        show_usage (1);
+      userid = argv[0];
+      newuserid = argv[1];
+    }
+  else
+    {
+      if (!argc || argc > 4)
+        show_usage (1);
+      userid = argv[0];
+      if (argc > 1)
+        algo = argv[1];
+      if (argc > 2)
+        flags |= parse_usage_string (argv[2]);
+      if (argc > 3)
+        expire = parse_expire_string (argv[3]);
+    }
 
   init_gpgme (protocol);
 
@@ -323,7 +346,7 @@ main (int argc, char **argv)
       gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
     }
 
-  if (addkey)
+  if (addkey || adduid)
     {
       gpgme_key_t akey;
 
@@ -335,12 +358,25 @@ main (int argc, char **argv)
           exit (1);
         }
 
-      err = gpgme_op_createsubkey (ctx, akey, algo, 0, expire, flags);
-      if (err)
+      if (addkey)
         {
-          fprintf (stderr, PGM ": gpgme_op_createsubkey failed: %s\n",
-                   gpg_strerror (err));
-          exit (1);
+          err = gpgme_op_createsubkey (ctx, akey, algo, 0, expire, flags);
+          if (err)
+            {
+              fprintf (stderr, PGM ": gpgme_op_createsubkey failed: %s\n",
+                       gpg_strerror (err));
+              exit (1);
+            }
+        }
+      else if (adduid)
+        {
+          err = gpgme_op_adduid (ctx, akey, newuserid, flags);
+          if (err)
+            {
+              fprintf (stderr, PGM ": gpgme_op_adduid failed: %s\n",
+                       gpg_strerror (err));
+              exit (1);
+            }
         }
       gpgme_key_unref (akey);
     }
@@ -373,6 +409,8 @@ main (int argc, char **argv)
     fprintf (stderr, PGM": primary key was not generated\n");
   if (!result->sub)
     fprintf (stderr, PGM": sub key was not generated\n");
+  if (!result->uid)
+    fprintf (stderr, PGM": uid was not generated\n");
 
   gpgme_release (ctx);
   return 0;