aboutsummaryrefslogtreecommitdiffstats
path: root/src/engine-gpg.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2016-09-13 16:57:38 +0000
committerWerner Koch <[email protected]>2016-09-13 16:59:10 +0000
commit00c501d296da287bec2fd6a0e3912abfbde90a98 (patch)
tree496dbb635f8062aaec7978e7f64719d0e1528481 /src/engine-gpg.c
parentpython: Handle slight differences between Python 2 and 3. (diff)
downloadgpgme-00c501d296da287bec2fd6a0e3912abfbde90a98.tar.gz
gpgme-00c501d296da287bec2fd6a0e3912abfbde90a98.zip
core: New function gpgme_op_create_key.
* src/engine-backend.h (engine_ops): Change prototype of genkey. * src/engine-gpgsm.c (gpgsm_genkey): Change accordingly. * src/engine-gpg.c (gpg_genkey): Change it to a dispatcher. (gpg_createkey_from_param): New for the old functionality. (gpg_createkey_legacy): New. Stub for now. (gpg_createkey): New. (gpg_addkey): New. Stub for now. (gpg_adduid): New. Stub for now. * src/engine.c (_gpgme_engine_op_genkey): Add new args. * src/genkey.c (op_data_t): Add field ERROR_CODE. (parse_error): New. (genkey_status_handler): Parse ERROR status line. (genkey_start): Use NULL/0 for the new args. (createkey_start): New. (gpgme_op_createkey_start, gpgme_op_createkey): New. * src/gpgme.def, src/libgpgme.vers: Add gpgme_op_createkey_start and gpgme_op_createkey. * src/gpgme.h.in (_gpgme_op_genkey_result): Add fields PUBKEY and SECKEY. (GPGME_CREATE_SIGN): New. (GPGME_CREATE_ENCR): New. (GPGME_CREATE_CERT): New. (GPGME_CREATE_AUTH): New. (GPGME_CREATE_NOPASSWD): New. (GPGME_CREATE_SELFSIGNED): New. (GPGME_CREATE_NOSTORE): New. (GPGME_CREATE_WANTPUB): New. (GPGME_CREATE_WANTSEC): New. (GPGME_CREATE_FORCE): New. * tests/run-genkey.c: New. * tests/Makefile.am (noinst_PROGRAMS): Add it. -- This function uses the new --quick-gen-key API of gpg. A limited compatibility mode to use older gpg versions and gpgsm will eventually be provided. Not all flags are currently implemented. ./run-genkey --unprotected --force [email protected] Create a new standard key with the given user id. --force is used to allow creating more than one key with that user id in the keyring. ./run-genkey --unprotected --force \ [email protected] default default 2145826800 Creates a new standard key with an expiration date of 2037-12-31. ./run-genkey --unprotected --force \ [email protected] future-default default 2145826800 Create a standard key using the fugure default algorithms. Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to 'src/engine-gpg.c')
-rw-r--r--src/engine-gpg.c162
1 files changed, 149 insertions, 13 deletions
diff --git a/src/engine-gpg.c b/src/engine-gpg.c
index 3f77ba87..289578b0 100644
--- a/src/engine-gpg.c
+++ b/src/engine-gpg.c
@@ -1964,22 +1964,11 @@ gpg_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
static gpgme_error_t
-gpg_genkey (void *engine, gpgme_data_t help_data, int use_armor,
- gpgme_data_t pubkey, gpgme_data_t seckey)
+gpg_createkey_from_param (engine_gpg_t gpg,
+ gpgme_data_t help_data, int use_armor)
{
- engine_gpg_t gpg = engine;
gpgme_error_t err;
- if (!gpg)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- /* We need a special mechanism to get the fd of a pipe here, so that
- we can use this for the %pubring and %secring parameters. We
- don't have this yet, so we implement only the adding to the
- standard keyrings. */
- if (pubkey || seckey)
- return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
-
err = add_arg (gpg, "--gen-key");
if (!err && use_armor)
err = add_arg (gpg, "--armor");
@@ -1987,9 +1976,156 @@ gpg_genkey (void *engine, gpgme_data_t help_data, int use_armor,
err = add_arg (gpg, "--");
if (!err)
err = add_data (gpg, help_data, -1, 0);
+ if (!err)
+ err = start (gpg);
+ return err;
+}
+
+
+/* This is used for gpg versions which do not support the quick-genkey
+ * command to emulate the gpgme_op_createkey API. */
+static gpgme_error_t
+gpg_createkey_legacy (engine_gpg_t gpg,
+ const char *userid, const char *algo,
+ unsigned long expires,
+ unsigned int flags,
+ int use_armor)
+{
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+}
+
+
+static gpgme_error_t
+gpg_createkey (engine_gpg_t gpg,
+ const char *userid, const char *algo,
+ unsigned long expires,
+ unsigned int flags,
+ int use_armor)
+{
+ gpgme_error_t err;
+
+ err = add_arg (gpg, "--quick-gen-key");
+ if (!err && use_armor)
+ err = add_arg (gpg, "--armor");
+ if (!err && (flags & GPGME_CREATE_NOPASSWD))
+ {
+ err = add_arg (gpg, "--passphrase");
+ if (!err)
+ err = add_arg (gpg, "");
+ }
+ if (!err && (flags & GPGME_CREATE_FORCE))
+ err = add_arg (gpg, "--yes");
+ if (!err)
+ err = add_arg (gpg, "--");
+ if (!err)
+ err = add_arg (gpg, userid);
+
+ /* This condition is only required to allow the use of gpg < 2.1.16 */
+ if (algo
+ || (flags & (GPGME_CREATE_SIGN | GPGME_CREATE_ENCR
+ | GPGME_CREATE_CERT | GPGME_CREATE_AUTH))
+ || expires)
+ {
+
+ if (!err)
+ err = add_arg (gpg, algo? algo : "default");
+ if (!err)
+ {
+ char tmpbuf[5*4+1];
+ snprintf (tmpbuf, sizeof tmpbuf, "%s%s%s%s",
+ (flags & GPGME_CREATE_SIGN)? " sign":"",
+ (flags & GPGME_CREATE_ENCR)? " encr":"",
+ (flags & GPGME_CREATE_CERT)? " cert":"",
+ (flags & GPGME_CREATE_AUTH)? " auth":"");
+ err = add_arg (gpg, *tmpbuf? tmpbuf : "default");
+ }
+ if (!err && expires)
+ {
+ char tmpbuf[8+20];
+ snprintf (tmpbuf, sizeof tmpbuf, "seconds=%lu", expires);
+ err = add_arg (gpg, tmpbuf);
+ }
+ }
if (!err)
err = start (gpg);
+ return err;
+}
+
+
+static gpgme_error_t
+gpg_addkey (engine_gpg_t gpg,
+ const char *algo,
+ unsigned long expires,
+ gpgme_key_t key,
+ unsigned int flags,
+ int use_armor)
+{
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+}
+
+
+static gpgme_error_t
+gpg_adduid (engine_gpg_t gpg,
+ const char *userid,
+ unsigned int flags,
+ int use_armor)
+{
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+}
+
+
+static gpgme_error_t
+gpg_genkey (void *engine,
+ const char *userid, const char *algo,
+ unsigned long reserved, unsigned long expires,
+ gpgme_key_t key, unsigned int flags,
+ gpgme_data_t help_data, int use_armor,
+ gpgme_data_t pubkey, gpgme_data_t seckey)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t err;
+
+ (void)reserved;
+
+ if (!gpg)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ /* If HELP_DATA is given the use of the old interface
+ * (gpgme_op_genkey) has been requested. The other modes are:
+ *
+ * USERID && !KEY - Create a new keyblock.
+ * !USERID && KEY - Add a new subkey to KEY (gpg >= 2.1.14)
+ * USERID && KEY && !ALGO - Add a new user id to KEY (gpg >= 2.1.14).
+ *
+ */
+ if (help_data)
+ {
+ /* We need a special mechanism to get the fd of a pipe here, so
+ that we can use this for the %pubring and %secring
+ parameters. We don't have this yet, so we implement only the
+ adding to the standard keyrings. */
+ if (pubkey || seckey)
+ err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ else
+ err = gpg_createkey_from_param (gpg, help_data, use_armor);
+ }
+ else if (userid && !key)
+ {
+ if (!have_gpg_version (gpg, "2.1.13"))
+ err = gpg_createkey_legacy (gpg, userid, algo, expires, flags,
+ use_armor);
+ else
+ err = gpg_createkey (gpg, userid, algo, expires, flags, use_armor);
+ }
+ else if (!have_gpg_version (gpg, "2.1.13"))
+ err = gpg_error (GPG_ERR_NOT_SUPPORTED);
+ 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);
+ else
+ err = gpg_error (GPG_ERR_INV_VALUE);
return err;
}