aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2014-07-23 13:12:43 +0000
committerWerner Koch <[email protected]>2014-07-23 13:12:43 +0000
commitea186540db5b418bc6f6e5ca90337672c9981c88 (patch)
tree9ad7ba700ed2261c1443e273907598ed41b0ada7
parentcommon: Add cpr_get_answer_is_yes_def() (diff)
downloadgnupg-ea186540db5b418bc6f6e5ca90337672c9981c88.tar.gz
gnupg-ea186540db5b418bc6f6e5ca90337672c9981c88.zip
gpg: Add command --quick-gen-key
* g10/gpg.c (aQuickKeygen): New. * g10/misc.c (is_valid_user_id): New stub. * g10/keygen.c (quickgen_set_para): New. (quick_generate_keypair): New. -- Note that the validation of the specified user id has not yet been implemented.
-rw-r--r--doc/gpg.texi21
-rw-r--r--g10/gpg.c13
-rw-r--r--g10/keygen.c124
-rw-r--r--g10/main.h2
-rw-r--r--g10/misc.c14
5 files changed, 171 insertions, 3 deletions
diff --git a/doc/gpg.texi b/doc/gpg.texi
index 3370ff2c4..e0b0039a9 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -592,14 +592,29 @@ This section explains the main commands for key management
@table @gnupgtabopt
+@ifset gpgtwoone
+@item --quick-gen-key @code{user-id}
+@opindex quick-gen-key
+This is simple command to generate a standard key with one user id.
+In contrast to @option{--gen-key} the key is generated directly
+without the need to answer a bunch of prompts. Unless the option
+@option{--yes} is given, the key creation will be canceled if the
+given user id already exists in the key ring.
+
+If invoked directly on the console without any special options an
+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.
+@end ifset
+
@item --gen-key
@opindex gen-key
Generate a new key pair. This command is normally only used
interactively.
-There is an experimental feature which allows you to create keys in
-batch mode. See the file @file{doc/DETAILS} in the source distribution
-on how to use this.
+There is also a feature which allows you to create keys in batch
+mode. See the file @file{doc/DETAILS} in the source distribution on
+how to use this.
@item --gen-revoke @code{name}
@opindex gen-revoke
diff --git a/g10/gpg.c b/g10/gpg.c
index da664be9d..1f840c6ed 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -106,6 +106,7 @@ enum cmd_and_opt_values
aDecryptFiles,
aClearsign,
aStore,
+ aQuickKeygen,
aKeygen,
aSignEncr,
aSignEncrSym,
@@ -406,6 +407,8 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_c (aCheckKeys, "check-sigs",N_("list and check key signatures")),
ARGPARSE_c (oFingerprint, "fingerprint", N_("list keys and fingerprints")),
ARGPARSE_c (aListSecretKeys, "list-secret-keys", N_("list secret keys")),
+ ARGPARSE_c (aQuickKeygen, "quick-gen-key" ,
+ N_("quickly generate a new key pair")),
ARGPARSE_c (aKeygen, "gen-key", N_("generate a new key pair")),
ARGPARSE_c (aGenRevoke, "gen-revoke",N_("generate a revocation certificate")),
ARGPARSE_c (aDeleteKeys,"delete-keys",
@@ -2279,6 +2282,7 @@ main (int argc, char **argv)
case aSignKey:
case aLSignKey:
case aStore:
+ case aQuickKeygen:
case aExportOwnerTrust:
case aImportOwnerTrust:
case aRebuildKeydbCaches:
@@ -3612,6 +3616,7 @@ main (int argc, char **argv)
case aPasswd:
case aDeleteSecretKeys:
case aDeleteSecretAndPublicKeys:
+ case aQuickKeygen:
case aKeygen:
case aImport:
case aExportSecret:
@@ -3895,6 +3900,14 @@ main (int argc, char **argv)
free_strlist (sl);
break;
+ case aQuickKeygen:
+ if (argc != 1 )
+ wrong_args("--gen-key user-id");
+ username = make_username (fname);
+ quick_generate_keypair (username);
+ xfree (username);
+ break;
+
case aKeygen: /* generate a key */
if( opt.batch ) {
if( argc > 1 )
diff --git a/g10/keygen.c b/g10/keygen.c
index 450923144..d6b2dd091 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -1,6 +1,7 @@
/* keygen.c - generate a key pair
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
* 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
+ * Copyright (C) 2014 Werner Koch
*
* This file is part of GnuPG.
*
@@ -3408,6 +3409,129 @@ read_parameter_file( 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)
+{
+ struct para_data_s *r;
+
+ r = xmalloc_clear (sizeof *r + 20);
+ r->key = for_subkey? pSUBKEYUSAGE : pKEYUSAGE;
+ strcpy (r->u.value, for_subkey ? "encrypt" : "sign");
+ r->next = para;
+ para = r;
+ r = xmalloc_clear (sizeof *r + 20);
+ r->key = for_subkey? pSUBKEYTYPE : pKEYTYPE;
+ sprintf (r->u.value, "%d", algo);
+ r->next = para;
+ para = r;
+
+ if (curve)
+ {
+ r = xmalloc_clear (sizeof *r + strlen (curve));
+ r->key = for_subkey? pSUBKEYCURVE : pKEYCURVE;
+ strcpy (r->u.value, curve);
+ r->next = para;
+ para = r;
+ }
+ else
+ {
+ r = xmalloc_clear (sizeof *r + 20);
+ r->key = for_subkey? pSUBKEYLENGTH : pKEYLENGTH;
+ sprintf (r->u.value, "%u", nbits);
+ r->next = para;
+ para = r;
+ }
+
+ return para;
+}
+
+
+
+/*
+ * Unattended generaion of a standard key.
+ */
+void
+quick_generate_keypair (const char *uid)
+{
+ gpg_error_t err;
+ struct para_data_s *para = NULL;
+ struct para_data_s *r;
+ struct output_control_s outctrl;
+ int use_tty;
+
+ memset (&outctrl, 0, sizeof outctrl);
+
+ use_tty = (!opt.batch && !opt.answer_yes
+ && !cpr_enabled ()
+ && gnupg_isatty (fileno (stdin))
+ && gnupg_isatty (fileno (stdout))
+ && gnupg_isatty (fileno (stderr)));
+
+ r = xmalloc_clear (sizeof *r + strlen (uid));
+ r->key = pUSERID;
+ strcpy (r->u.value, uid);
+ r->next = para;
+ para = r;
+
+ uid = trim_spaces (r->u.value);
+ if (!*uid || (!opt.allow_freeform_uid && !is_valid_user_id (uid)))
+ {
+ log_error (_("Key generation failed: %s\n"),
+ gpg_strerror (GPG_ERR_INV_USER_ID));
+ goto leave;
+ }
+
+ /* If gpg is directly used on the console ask whether a key with the
+ given user id shall really be created. */
+ if (use_tty)
+ {
+ tty_printf (_("About to create a key for:\n \"%s\"\n\n"), uid);
+ if (!cpr_get_answer_is_yes_def ("quick_keygen.okay",
+ _("Continue? (Y/n) "), 1))
+ goto leave;
+ }
+
+ /* Check whether such a user ID already exists. */
+ {
+ KEYDB_HANDLE kdbhd;
+ KEYDB_SEARCH_DESC desc;
+
+ memset (&desc, 0, sizeof desc);
+ desc.mode = KEYDB_SEARCH_MODE_EXACT;
+ desc.u.name = uid;
+
+ kdbhd = keydb_new ();
+ err = keydb_search (kdbhd, &desc, 1, NULL);
+ keydb_release (kdbhd);
+ if (gpg_err_code (err) != GPG_ERR_NOT_FOUND)
+ {
+ log_info (_("A key for \"%s\" already exists\n"), uid);
+ if (opt.answer_yes)
+ ;
+ else if (!use_tty
+ || !cpr_get_answer_is_yes_def ("quick_keygen.force",
+ _("Create anyway? (y/N) "), 0))
+ {
+ log_inc_errorcount (); /* we used log_info */
+ goto leave;
+ }
+ log_info (_("creating anyway\n"));
+ }
+ }
+
+ para = quickgen_set_para (para, 0, PUBKEY_ALGO_RSA, 2048, NULL);
+ para = quickgen_set_para (para, 1, PUBKEY_ALGO_RSA, 2048, NULL);
+ /* para = quickgen_set_para (para, 0, PUBKEY_ALGO_EDDSA, 0, "Ed25519"); */
+ /* para = quickgen_set_para (para, 1, PUBKEY_ALGO_ECDH, 0, "Curve25519"); */
+
+ proc_parameter_file (para, "[internal]", &outctrl, 0);
+ leave:
+ release_parameter_list (para);
+}
+
+
/*
* Generate a keypair (fname is only used in batch mode) If
* CARD_SERIALNO is not NULL the function will create the keys on an
diff --git a/g10/main.h b/g10/main.h
index d39c7c853..4ec4bbfd0 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -154,6 +154,7 @@ int parse_options(char *str,unsigned int *options,
struct parse_options *opts,int noisy);
int has_invalid_email_chars (const char *s);
int is_valid_mailbox (const char *name);
+int is_valid_user_id (const char *uid);
const char *get_libexecdir (void);
int path_access(const char *file,int mode);
@@ -247,6 +248,7 @@ void show_basic_key_info (KBNODE keyblock);
u32 parse_expire_string(const char *string);
u32 ask_expire_interval(int object,const char *def_expire);
u32 ask_expiredate(void);
+void quick_generate_keypair (const char *uid);
void generate_keypair (ctrl_t ctrl, const char *fname,
const char *card_serialno, int card_backup_key);
int keygen_set_std_prefs (const char *string,int personal);
diff --git a/g10/misc.c b/g10/misc.c
index e219d7623..0125da4b0 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -1499,6 +1499,20 @@ is_valid_mailbox (const char *name)
}
+/* Check whether UID is a valid standard user id of the form
+ "Heinrich Heine <[email protected]>"
+ and return true if this is the case. */
+int
+is_valid_user_id (const char *uid)
+{
+ if (!uid || !*uid)
+ return 0;
+
+ return 1;
+}
+
+
+
/* Similar to access(2), but uses PATH to find the file. */
int
path_access(const char *file,int mode)