gpg: Extend the --quick-gen-key command.
authorWerner Koch <wk@gnupg.org>
Thu, 2 Jun 2016 16:38:10 +0000 (18:38 +0200)
committerWerner Koch <wk@gnupg.org>
Thu, 2 Jun 2016 16:38:10 +0000 (18:38 +0200)
* g10/keygen.c (quickgen_set_para): Add arg 'use'.
(quick_generate_keypair): Add args 'algostr', 'usagestr', and
'expirestr'.  Implement primary only key mode.
(parse_algo_usage_expire): Set NBITS for the default algo.
* g10/gpg.c (main): Extend --quick-gen-key command.

Signed-off-by: Werner Koch <wk@gnupg.org>
doc/gpg.texi
g10/gpg.c
g10/keygen.c
g10/main.h

index 9b0f1ba..4559958 100644 (file)
@@ -599,7 +599,7 @@ This section explains the main commands for key management
 
 @table @gnupgtabopt
 
-@item --quick-gen-key @code{user-id}
+@item --quick-gen-key @code{user-id} [@code{algo} [@code{usage} [@code{expire}]]]
 @opindex quick-gen-key
 This is a simple command to generate a standard key with one user id.
 In contrast to @option{--gen-key} the key is generated directly
@@ -612,6 +612,13 @@ answer to a ``Continue?'' style confirmation prompt is required.  In
 case the user id already exists in the key ring a second prompt to
 force the creation of the key will show up.
 
+If any of the optional arguments are given, only the primary key is
+created and no prompts are shown.  For a description of these optional
+arguments see the command @code{--quick-addkey}.  The @code{usage}
+accepts also the value ``cert'' which can be used to create a
+certification only primary key; the default is to a create
+certification and signing key.
+
 If this command is used with @option{--batch},
 @option{--pinentry-mode} has been set to @code{loopback}, and one of
 the passphrase options (@option{--passphrase},
index 2795330..b193fcd 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -4096,11 +4096,29 @@ main (int argc, char **argv)
        break;
 
       case aQuickKeygen:
-        if (argc != 1 )
-          wrong_args("--gen-key user-id");
-        username = make_username (fname);
-        quick_generate_keypair (ctrl, username);
-        xfree (username);
+        {
+          const char *x_algo, *x_usage, *x_expire;
+
+          if (argc < 1 || argc > 4)
+            wrong_args("--quick-gen-key USER-ID [ALGO [USAGE [EXPIRE]]]");
+          username = make_username (fname);
+          argv++, argc--;
+          x_algo = "";
+          x_usage = "";
+          x_expire = "";
+          if (argc)
+            {
+              x_algo = *argv++; argc--;
+              if (argc)
+                {
+                  x_usage = *argv++; argc--;
+                  if (argc)
+                    x_expire = *argv++; argc--;
+                }
+            }
+          quick_generate_keypair (ctrl, username, x_algo, x_usage, x_expire);
+          xfree (username);
+        }
         break;
 
       case aKeygen: /* generate a key */
index 69b6a0d..940cb16 100644 (file)
@@ -136,6 +136,12 @@ static byte zip_prefs[MAX_PREFS];
 static int nzip_prefs;
 static int mdc_available,ks_modify;
 
+static gpg_error_t parse_algo_usage_expire (ctrl_t ctrl, int for_subkey,
+                                     const char *algostr, const char *usagestr,
+                                     const char *expirestr,
+                                     int *r_algo, unsigned int *r_usage,
+                                     u32 *r_expire,
+                                     unsigned int *r_nbits, char **r_curve);
 static void do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
                                 struct output_control_s *outctrl, int card );
 static int write_keyblock (iobuf_t out, kbnode_t node);
@@ -3467,13 +3473,20 @@ read_parameter_file (ctrl_t ctrl, const char *fname )
 /* Helper for quick_generate_keypair.  */
 static struct para_data_s *
 quickgen_set_para (struct para_data_s *para, int for_subkey,
-                   int algo, int nbits, const char *curve)
+                   int algo, int nbits, const char *curve, unsigned int use)
 {
   struct para_data_s *r;
 
-  r = xmalloc_clear (sizeof *r + 20);
+  r = xmalloc_clear (sizeof *r + 30);
   r->key = for_subkey? pSUBKEYUSAGE :  pKEYUSAGE;
-  strcpy (r->u.value, for_subkey ? "encrypt" : "sign");
+  if (use)
+    snprintf (r->u.value, 30, "%s%s%s%s",
+              (use & PUBKEY_USAGE_ENC)?  "encr " : "",
+              (use & PUBKEY_USAGE_SIG)?  "sign " : "",
+              (use & PUBKEY_USAGE_AUTH)? "auth " : "",
+              (use & PUBKEY_USAGE_CERT)? "cert " : "");
+  else
+    strcpy (r->u.value, for_subkey ? "encr" : "sign");
   r->next = para;
   para = r;
   r = xmalloc_clear (sizeof *r + 20);
@@ -3507,7 +3520,8 @@ quickgen_set_para (struct para_data_s *para, int for_subkey,
  * Unattended generation of a standard key.
  */
 void
-quick_generate_keypair (ctrl_t ctrl, const char *uid)
+quick_generate_keypair (ctrl_t ctrl, const char *uid, const char *algostr,
+                        const char *usagestr, const char *expirestr)
 {
   gpg_error_t err;
   struct para_data_s *para = NULL;
@@ -3518,6 +3532,7 @@ quick_generate_keypair (ctrl_t ctrl, const char *uid)
   memset (&outctrl, 0, sizeof outctrl);
 
   use_tty = (!opt.batch && !opt.answer_yes
+             && !*algostr && !*usagestr && !*expirestr
              && !cpr_enabled ()
              && gnupg_isatty (fileno (stdin))
              && gnupg_isatty (fileno (stdout))
@@ -3578,12 +3593,39 @@ quick_generate_keypair (ctrl_t ctrl, const char *uid)
       }
   }
 
-  para = quickgen_set_para (para, 0,
-                            DEFAULT_STD_ALGO, DEFAULT_STD_KEYSIZE,
-                            DEFAULT_STD_CURVE);
-  para = quickgen_set_para (para, 1,
-                            DEFAULT_STD_SUBALGO, DEFAULT_STD_SUBKEYSIZE,
-                            DEFAULT_STD_SUBCURVE);
+  if (*algostr || *usagestr || *expirestr)
+    {
+      /* Extended unattended mode.  Creates only the primary key. */
+      int algo;
+      unsigned int use;
+      u32 expire;
+      unsigned int nbits;
+      char *curve;
+
+      err = parse_algo_usage_expire (ctrl, 0, algostr, usagestr, expirestr,
+                                     &algo, &use, &expire, &nbits, &curve);
+      if (err)
+        {
+          log_error (_("Key generation failed: %s\n"), gpg_strerror (err) );
+          goto leave;
+        }
+
+      para = quickgen_set_para (para, 0, algo, nbits, curve, use);
+      r = xmalloc_clear (sizeof *r + 20);
+      r->key = pKEYEXPIRE;
+      r->u.expire = expire;
+      r->next = para;
+      para = r;
+    }
+  else
+    {
+      para = quickgen_set_para (para, 0,
+                                DEFAULT_STD_ALGO, DEFAULT_STD_KEYSIZE,
+                                DEFAULT_STD_CURVE, 0);
+      para = quickgen_set_para (para, 1,
+                                DEFAULT_STD_SUBALGO, DEFAULT_STD_SUBKEYSIZE,
+                                DEFAULT_STD_SUBCURVE, 0);
+    }
 
   /* If the pinentry loopback mode is not and we have a static
      passphrase (i.e. set with --passphrase{,-fd,-file} while in batch
@@ -3601,6 +3643,7 @@ quick_generate_keypair (ctrl_t ctrl, const char *uid)
     }
 
   proc_parameter_file (ctrl, para, "[internal]", &outctrl, 0);
+
  leave:
   release_parameter_list (para);
 }
@@ -3844,10 +3887,10 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
                    , "--full-gen-key" );
       para = quickgen_set_para (para, 0,
                                 DEFAULT_STD_ALGO, DEFAULT_STD_KEYSIZE,
-                                DEFAULT_STD_CURVE);
+                                DEFAULT_STD_CURVE, 0);
       para = quickgen_set_para (para, 1,
                                 DEFAULT_STD_SUBALGO, DEFAULT_STD_SUBKEYSIZE,
-                                DEFAULT_STD_SUBCURVE);
+                                DEFAULT_STD_SUBCURVE, 0);
     }
 
 
@@ -4318,7 +4361,7 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
 }
 
 
-gpg_error_t
+static gpg_error_t
 parse_algo_usage_expire (ctrl_t ctrl, int for_subkey,
                          const char *algostr, const char *usagestr,
                          const char *expirestr,
@@ -4340,8 +4383,9 @@ parse_algo_usage_expire (ctrl_t ctrl, int for_subkey,
   if (!algostr || !*algostr
       || !strcmp (algostr, "default") || !strcmp (algostr, "-"))
     {
-      algo = DEFAULT_STD_SUBALGO;
-      use = DEFAULT_STD_SUBKEYUSE;
+      algo = for_subkey? DEFAULT_STD_SUBALGO : DEFAULT_STD_ALGO;
+      use = for_subkey?  DEFAULT_STD_SUBKEYUSE : DEFAULT_STD_KEYUSE;
+      nbits = for_subkey?DEFAULT_STD_SUBKEYSIZE : DEFAULT_STD_KEYSIZE;
     }
   else if (*algostr == '&' && strlen (algostr) == 41)
     {
index 0ca4d39..46b4ead 100644 (file)
@@ -298,7 +298,8 @@ u32 parse_expire_string(const char *string);
 u32 ask_expire_interval(int object,const char *def_expire);
 u32 ask_expiredate(void);
 unsigned int ask_key_flags (int algo, int subkey, unsigned int current);
-void quick_generate_keypair (ctrl_t ctrl, const char *uid);
+void quick_generate_keypair (ctrl_t ctrl, const char *uid, const char *algostr,
+                             const char *usagestr, const char *expirestr);
 void generate_keypair (ctrl_t ctrl, int full, const char *fname,
                        const char *card_serialno, int card_backup_key);
 int keygen_set_std_prefs (const char *string,int personal);