diff options
author | Werner Koch <[email protected]> | 2009-06-16 11:42:21 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2009-06-16 11:42:21 +0000 |
commit | b8726059416659707762f9cf97e3989cc26f6268 (patch) | |
tree | 6274a80a7696d17eb02572547861e531e908240f /src | |
parent | 2009-06-15 Marcus Brinkmann <[email protected]> (diff) | |
download | gpgme-b8726059416659707762f9cf97e3989cc26f6268.tar.gz gpgme-b8726059416659707762f9cf97e3989cc26f6268.zip |
Add new functions to import and export keys specified by gpgme_key_t.
Allow exporting keys to a keyserver.
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog | 31 | ||||
-rw-r--r-- | src/engine-backend.h | 7 | ||||
-rw-r--r-- | src/engine-gpg.c | 90 | ||||
-rw-r--r-- | src/engine-gpgsm.c | 40 | ||||
-rw-r--r-- | src/engine.c | 9 | ||||
-rw-r--r-- | src/engine.h | 7 | ||||
-rw-r--r-- | src/export.c | 148 | ||||
-rw-r--r-- | src/gpgme.def | 5 | ||||
-rw-r--r-- | src/gpgme.h.in | 31 | ||||
-rw-r--r-- | src/import.c | 80 | ||||
-rw-r--r-- | src/libgpgme.vers | 5 |
11 files changed, 377 insertions, 76 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 35622ee6..dc1e1164 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,34 @@ +2009-06-16 Werner Koch <[email protected]> + + * gpgme.h.in (gpgme_op_export_keys_start, gpgme_op_export_keys): New. + * gpgme.def, libgpgme.vers: Add them. + * export.c (gpgme_op_export_keys_start, gpgme_op_export_keys): New. + (export_keys_start): New. + + * gpgme.h.in (gpgme_export_mode_t, GPGME_EXPORT_MODE_EXTERN): New. + (gpgme_op_export_start, gpgme_op_export, gpgme_op_export_ext_start) + (gpgme_op_export_ext): Change arg RESERVED to MODE of new + compatible type. + * export.c (gpgme_export_ext_start, gpgme_op_export) + (gpgme_op_export_ext_start, gpgme_op_export_ext): Ditto. + (export_start): Ditto. + * engine.c (_gpgme_engine_op_export): Ditto. + * engine-backend.h (struct engine_ops): Ditto. + * engine-gpgsm.c (gpgsm_export, gpgsm_export_ext): Ditto. + * engine-gpg.c (gpg_export, gpg_export_ext): Ditto. Implement + mode EXTERN. + (gpg_export, gpg_export_ext): Factor common code out to .. + (export_common): .. this. + + * gpgme.h.in (gpgme_op_import_keys_start, gpgme_op_import_keys): New. + * gpgme.def, libgpgme.vers: Add them. + * import.c (gpgme_op_import_keys_start, gpgme_op_import_keys): New. + (_gpgme_op_import_keys_start): New. + * engine.c (_gpgme_engine_op_import): Add arg KEYARRAY. + * engine-backend.h (struct engine_ops): Ditto. + * engine-gpgsm.c (gpgsm_import): Ditto. Not functional. + * engine-gpg.c (gpg_import): Ditto. Implement it. + 2009-06-15 Marcus Brinkmann <[email protected]> * gpgme.h.in (gpgme_result_ref, gpgme_result_unref): Add diff --git a/src/engine-backend.h b/src/engine-backend.h index d656d9d6..1fe600d0 100644 --- a/src/engine-backend.h +++ b/src/engine-backend.h @@ -77,14 +77,15 @@ struct engine_ops gpgme_data_t plain, gpgme_data_t ciph, int use_armor, gpgme_ctx_t ctx /* FIXME */); gpgme_error_t (*export) (void *engine, const char *pattern, - unsigned int reserved, gpgme_data_t keydata, + gpgme_export_mode_t mode, gpgme_data_t keydata, int use_armor); gpgme_error_t (*export_ext) (void *engine, const char *pattern[], - unsigned int reserved, gpgme_data_t keydata, + gpgme_export_mode_t mode, gpgme_data_t keydata, int use_armor); gpgme_error_t (*genkey) (void *engine, gpgme_data_t help_data, int use_armor, gpgme_data_t pubkey, gpgme_data_t seckey); - gpgme_error_t (*import) (void *engine, gpgme_data_t keydata); + gpgme_error_t (*import) (void *engine, gpgme_data_t keydata, + gpgme_key_t *keyarray); gpgme_error_t (*keylist) (void *engine, const char *pattern, int secret_only, gpgme_keylist_mode_t mode); gpgme_error_t (*keylist_ext) (void *engine, const char *pattern[], diff --git a/src/engine-gpg.c b/src/engine-gpg.c index eec3fa67..3c06edf8 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -678,7 +678,7 @@ command_handler (void *opaque, int fd) /* The Fnc will be called to get a value for one of the commands with - a key KEY. If the Code pssed to FNC is 0, the function may release + a key KEY. If the Code passed to FNC is 0, the function may release resources associated with the returned value from another call. To match such a second call to a first call, the returned value from the first call is passed as keyword. */ @@ -1704,23 +1704,42 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], static gpgme_error_t -gpg_export (void *engine, const char *pattern, unsigned int reserved, - gpgme_data_t keydata, int use_armor) +export_common (engine_gpg_t gpg, gpgme_export_mode_t mode, + gpgme_data_t keydata, int use_armor) { - engine_gpg_t gpg = engine; gpgme_error_t err; - if (reserved) - return gpg_error (GPG_ERR_INV_VALUE); + if ((mode & ~GPGME_EXPORT_MODE_EXTERN)) + return gpg_error (GPG_ERR_NOT_SUPPORTED); - err = add_arg (gpg, "--export"); - if (!err && use_armor) - err = add_arg (gpg, "--armor"); - if (!err) - err = add_data (gpg, keydata, 1, 1); + if ((mode & GPGME_EXPORT_MODE_EXTERN)) + { + err = add_arg (gpg, "--send-keys"); + } + else + { + err = add_arg (gpg, "--export"); + if (!err && use_armor) + err = add_arg (gpg, "--armor"); + if (!err) + err = add_data (gpg, keydata, 1, 1); + } if (!err) err = add_arg (gpg, "--"); + return err; +} + + +static gpgme_error_t +gpg_export (void *engine, const char *pattern, gpgme_export_mode_t mode, + gpgme_data_t keydata, int use_armor) +{ + engine_gpg_t gpg = engine; + gpgme_error_t err; + + err = export_common (gpg, mode, keydata, use_armor); + if (!err && pattern && *pattern) err = add_arg (gpg, pattern); @@ -1732,22 +1751,13 @@ gpg_export (void *engine, const char *pattern, unsigned int reserved, static gpgme_error_t -gpg_export_ext (void *engine, const char *pattern[], unsigned int reserved, +gpg_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode, gpgme_data_t keydata, int use_armor) { engine_gpg_t gpg = engine; gpgme_error_t err; - if (reserved) - return gpg_error (GPG_ERR_INV_VALUE); - - err = add_arg (gpg, "--export"); - if (!err && use_armor) - err = add_arg (gpg, "--armor"); - if (!err) - err = add_data (gpg, keydata, 1, 1); - if (!err) - err = add_arg (gpg, "--"); + err = export_common (gpg, mode, keydata, use_armor); if (pattern) { @@ -1795,16 +1805,40 @@ gpg_genkey (void *engine, gpgme_data_t help_data, int use_armor, static gpgme_error_t -gpg_import (void *engine, gpgme_data_t keydata) +gpg_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray) { engine_gpg_t gpg = engine; gpgme_error_t err; + int idx; - err = add_arg (gpg, "--import"); - if (!err) - err = add_arg (gpg, "--"); - if (!err) - err = add_data (gpg, keydata, -1, 0); + if (keydata && keyarray) + gpg_error (GPG_ERR_INV_VALUE); /* Only one is allowed. */ + + if (keyarray) + { + err = add_arg (gpg, "--recv-keys"); + if (!err) + err = add_arg (gpg, "--"); + for (idx=0; !err && keyarray[idx]; idx++) + { + if (keyarray[idx]->protocol != GPGME_PROTOCOL_OpenPGP) + ; + else if (!keyarray[idx]->subkeys) + ; + else if (keyarray[idx]->subkeys->fpr && *keyarray[idx]->subkeys->fpr) + err = add_arg (gpg, keyarray[idx]->subkeys->fpr); + else if (*keyarray[idx]->subkeys->keyid) + err = add_arg (gpg, keyarray[idx]->subkeys->keyid); + } + } + else + { + err = add_arg (gpg, "--import"); + if (!err) + err = add_arg (gpg, "--"); + if (!err) + err = add_data (gpg, keydata, -1, 0); + } if (!err) err = start (gpg); diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c index 2d92732c..71ef221b 100644 --- a/src/engine-gpgsm.c +++ b/src/engine-gpgsm.c @@ -1379,15 +1379,18 @@ gpgsm_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, static gpgme_error_t -gpgsm_export (void *engine, const char *pattern, unsigned int reserved, +gpgsm_export (void *engine, const char *pattern, gpgme_export_mode_t mode, gpgme_data_t keydata, int use_armor) { engine_gpgsm_t gpgsm = engine; gpgme_error_t err = 0; char *cmd; - if (!gpgsm || reserved) + if (!gpgsm) return gpg_error (GPG_ERR_INV_VALUE); + + if (mode) + return gpg_error (GPG_ERR_NOT_SUPPORTED); if (!pattern) pattern = ""; @@ -1414,7 +1417,7 @@ gpgsm_export (void *engine, const char *pattern, unsigned int reserved, static gpgme_error_t -gpgsm_export_ext (void *engine, const char *pattern[], unsigned int reserved, +gpgsm_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode, gpgme_data_t keydata, int use_armor) { engine_gpgsm_t gpgsm = engine; @@ -1424,9 +1427,12 @@ gpgsm_export_ext (void *engine, const char *pattern[], unsigned int reserved, int length = 7 + 1; char *linep; - if (!gpgsm || reserved) + if (!gpgsm) return gpg_error (GPG_ERR_INV_VALUE); + if (mode) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + if (pattern && *pattern) { const char **pat = pattern; @@ -1534,7 +1540,7 @@ gpgsm_genkey (void *engine, gpgme_data_t help_data, int use_armor, static gpgme_error_t -gpgsm_import (void *engine, gpgme_data_t keydata) +gpgsm_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray) { engine_gpgsm_t gpgsm = engine; gpgme_error_t err; @@ -1542,13 +1548,23 @@ gpgsm_import (void *engine, gpgme_data_t keydata) if (!gpgsm) return gpg_error (GPG_ERR_INV_VALUE); - gpgsm->input_cb.data = keydata; - err = gpgsm_set_fd (gpgsm, INPUT_FD, map_data_enc (gpgsm->input_cb.data)); - if (err) - return err; - gpgsm_clear_fd (gpgsm, OUTPUT_FD); - gpgsm_clear_fd (gpgsm, MESSAGE_FD); - gpgsm->inline_data = NULL; + if (keydata && keyarray) + gpg_error (GPG_ERR_INV_VALUE); /* Only one is allowed. */ + + if (keyarray) + { + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + } + else + { + gpgsm->input_cb.data = keydata; + err = gpgsm_set_fd (gpgsm, INPUT_FD, map_data_enc (gpgsm->input_cb.data)); + if (err) + return err; + gpgsm_clear_fd (gpgsm, OUTPUT_FD); + gpgsm_clear_fd (gpgsm, MESSAGE_FD); + gpgsm->inline_data = NULL; + } err = start (gpgsm, "IMPORT"); return err; diff --git a/src/engine.c b/src/engine.c index 87d39392..c8ff012b 100644 --- a/src/engine.c +++ b/src/engine.c @@ -620,7 +620,7 @@ _gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[], gpgme_error_t _gpgme_engine_op_export (engine_t engine, const char *pattern, - unsigned int reserved, gpgme_data_t keydata, + gpgme_export_mode_t mode, gpgme_data_t keydata, int use_armor) { if (!engine) @@ -629,7 +629,7 @@ _gpgme_engine_op_export (engine_t engine, const char *pattern, if (!engine->ops->export) return gpg_error (GPG_ERR_NOT_IMPLEMENTED); - return (*engine->ops->export) (engine->engine, pattern, reserved, + return (*engine->ops->export) (engine->engine, pattern, mode, keydata, use_armor); } @@ -667,7 +667,8 @@ _gpgme_engine_op_genkey (engine_t engine, gpgme_data_t help_data, gpgme_error_t -_gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata) +_gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata, + gpgme_key_t *keyarray) { if (!engine) return gpg_error (GPG_ERR_INV_VALUE); @@ -675,7 +676,7 @@ _gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata) if (!engine->ops->import) return gpg_error (GPG_ERR_NOT_IMPLEMENTED); - return (*engine->ops->import) (engine->engine, keydata); + return (*engine->ops->import) (engine->engine, keydata, keyarray); } diff --git a/src/engine.h b/src/engine.h index a043b3e2..ca746c8a 100644 --- a/src/engine.h +++ b/src/engine.h @@ -93,11 +93,11 @@ gpgme_error_t _gpgme_engine_op_encrypt_sign (engine_t engine, int use_armor, gpgme_ctx_t ctx /* FIXME */); gpgme_error_t _gpgme_engine_op_export (engine_t engine, const char *pattern, - unsigned int reserved, + gpgme_export_mode_t mode, gpgme_data_t keydata, int use_armor); gpgme_error_t _gpgme_engine_op_export_ext (engine_t engine, const char *pattern[], - unsigned int reserved, + gpgme_export_mode_t mode, gpgme_data_t keydata, int use_armor); gpgme_error_t _gpgme_engine_op_genkey (engine_t engine, @@ -105,7 +105,8 @@ gpgme_error_t _gpgme_engine_op_genkey (engine_t engine, int use_armor, gpgme_data_t pubkey, gpgme_data_t seckey); gpgme_error_t _gpgme_engine_op_import (engine_t engine, - gpgme_data_t keydata); + gpgme_data_t keydata, + gpgme_key_t *keyarray); gpgme_error_t _gpgme_engine_op_keylist (engine_t engine, const char *pattern, int secret_only, diff --git a/src/export.c b/src/export.c index 079a7e0e..1e294391 100644 --- a/src/export.c +++ b/src/export.c @@ -22,6 +22,8 @@ #if HAVE_CONFIG_H #include <config.h> #endif +#include <stdlib.h> +#include <string.h> #include "gpgme.h" #include "context.h" @@ -37,12 +39,24 @@ export_status_handler (void *priv, gpgme_status_code_t code, char *args) static gpgme_error_t export_start (gpgme_ctx_t ctx, int synchronous, const char *pattern, - unsigned int reserved, gpgme_data_t keydata) + gpgme_export_mode_t mode, gpgme_data_t keydata) { gpgme_error_t err; - if (!keydata) - return gpg_error (GPG_ERR_INV_VALUE); + if ((mode & ~(GPGME_EXPORT_MODE_EXTERN))) + return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE. */ + + + if ((mode & GPGME_EXPORT_MODE_EXTERN)) + { + if (keydata) + return gpg_error (GPG_ERR_INV_VALUE); + } + else + { + if (!keydata) + return gpg_error (GPG_ERR_INV_VALUE); + } err = _gpgme_op_reset (ctx, synchronous); if (err) @@ -50,26 +64,26 @@ export_start (gpgme_ctx_t ctx, int synchronous, const char *pattern, _gpgme_engine_set_status_handler (ctx->engine, export_status_handler, ctx); - return _gpgme_engine_op_export (ctx->engine, pattern, reserved, keydata, + return _gpgme_engine_op_export (ctx->engine, pattern, mode, keydata, ctx->use_armor); } -/* Export the keys listed in RECP into KEYDATA. */ +/* Export the keys listed in PATTERN into KEYDATA. */ gpgme_error_t gpgme_op_export_start (gpgme_ctx_t ctx, const char *pattern, - unsigned int reserved, gpgme_data_t keydata) + gpgme_export_mode_t mode, gpgme_data_t keydata) { - return export_start (ctx, 0, pattern, reserved, keydata); + return export_start (ctx, 0, pattern, mode, keydata); } -/* Export the keys listed in RECP into KEYDATA. */ +/* Export the keys listed in PATTERN into KEYDATA. */ gpgme_error_t -gpgme_op_export (gpgme_ctx_t ctx, const char *pattern, unsigned int reserved, - gpgme_data_t keydata) +gpgme_op_export (gpgme_ctx_t ctx, const char *pattern, + gpgme_export_mode_t mode, gpgme_data_t keydata) { - gpgme_error_t err = export_start (ctx, 1, pattern, reserved, keydata); + gpgme_error_t err = export_start (ctx, 1, pattern, mode, keydata); if (!err) err = _gpgme_wait_one (ctx); return err; @@ -78,12 +92,23 @@ gpgme_op_export (gpgme_ctx_t ctx, const char *pattern, unsigned int reserved, static gpgme_error_t export_ext_start (gpgme_ctx_t ctx, int synchronous, const char *pattern[], - unsigned int reserved, gpgme_data_t keydata) + gpgme_export_mode_t mode, gpgme_data_t keydata) { gpgme_error_t err; - if (!keydata) - return gpg_error (GPG_ERR_INV_VALUE); + if ((mode & ~(GPGME_EXPORT_MODE_EXTERN))) + return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE. */ + + if ((mode & GPGME_EXPORT_MODE_EXTERN)) + { + if (keydata) + return gpg_error (GPG_ERR_INV_VALUE); + } + else + { + if (!keydata) + return gpg_error (GPG_ERR_INV_VALUE); + } err = _gpgme_op_reset (ctx, synchronous); if (err) @@ -91,27 +116,108 @@ export_ext_start (gpgme_ctx_t ctx, int synchronous, const char *pattern[], _gpgme_engine_set_status_handler (ctx->engine, export_status_handler, ctx); - return _gpgme_engine_op_export_ext (ctx->engine, pattern, reserved, keydata, + return _gpgme_engine_op_export_ext (ctx->engine, pattern, mode, keydata, ctx->use_armor); } -/* Export the keys listed in RECP into KEYDATA. */ +/* Export the keys listed in PATTERN into KEYDATA. */ gpgme_error_t gpgme_op_export_ext_start (gpgme_ctx_t ctx, const char *pattern[], - unsigned int reserved, gpgme_data_t keydata) + gpgme_export_mode_t mode, gpgme_data_t keydata) { - return export_ext_start (ctx, 0, pattern, reserved, keydata); + return export_ext_start (ctx, 0, pattern, mode, keydata); } -/* Export the keys listed in RECP into KEYDATA. */ +/* Export the keys listed in PATTERN into KEYDATA. */ gpgme_error_t gpgme_op_export_ext (gpgme_ctx_t ctx, const char *pattern[], - unsigned int reserved, gpgme_data_t keydata) + gpgme_export_mode_t mode, gpgme_data_t keydata) +{ + gpgme_error_t err = export_ext_start (ctx, 1, pattern, mode, keydata); + if (!err) + err = _gpgme_wait_one (ctx); + return err; +} + + + + + +static gpgme_error_t +export_keys_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t keys[], + gpgme_export_mode_t mode, gpgme_data_t keydata) +{ + gpgme_error_t err; + int nkeys, idx; + char **pattern; + + if (!keys) + return gpg_error (GPG_ERR_INV_VALUE); + + /* Create a list of pattern from the keys. */ + for (idx=nkeys=0; keys[idx]; idx++) + if (keys[idx]->protocol == ctx->protocol) + nkeys++; + if (!nkeys) + return gpg_error (GPG_ERR_NO_DATA); + + pattern = calloc (nkeys+1, sizeof *pattern); + if (!pattern) + return gpg_error_from_syserror (); + + for (idx=nkeys=0; keys[idx]; idx++) + if (keys[idx]->protocol == ctx->protocol + && keys[idx]->subkeys + && keys[idx]->subkeys->fpr + && *keys[idx]->subkeys->fpr) + { + pattern[nkeys] = strdup (keys[idx]->subkeys->fpr); + if (!pattern[nkeys]) + { + err = gpg_error_from_syserror (); + goto leave; + } + nkeys++; + } + + + /* Pass on to the regular function. */ + err = export_ext_start (ctx, synchronous, (const char**)pattern, + mode, keydata); + + leave: + for (idx=0; pattern[idx]; idx++) + free (pattern[idx]); + free (pattern); + + return err; +} + + +/* Export the keys from the array KEYS into KEYDATA. Only keys of the + current protocol are exported and only those which have a + fingerprint set; that is keys received with some external search + methods are silently skipped. */ +gpgme_error_t +gpgme_op_export_keys_start (gpgme_ctx_t ctx, + gpgme_key_t keys[], + gpgme_export_mode_t mode, + gpgme_data_t keydata) { - gpgme_error_t err = export_ext_start (ctx, 1, pattern, reserved, keydata); + return export_keys_start (ctx, 0, keys, mode, keydata); +} + +gpgme_error_t +gpgme_op_export_keys (gpgme_ctx_t ctx, + gpgme_key_t keys[], + gpgme_export_mode_t mode, + gpgme_data_t keydata) +{ + gpgme_error_t err = export_keys_start (ctx, 1, keys, mode, keydata); if (!err) err = _gpgme_wait_one (ctx); return err; } + diff --git a/src/gpgme.def b/src/gpgme.def index 9bc95d00..ac0fe9a2 100644 --- a/src/gpgme.def +++ b/src/gpgme.def @@ -180,5 +180,10 @@ EXPORTS gpgme_release_ref @138 gpgme_release_unref @139 + gpgme_op_import_keys @140 + gpgme_op_import_keys_start @141 + gpgme_op_export_keys @142 + gpgme_op_export_keys_start @143 + ; END diff --git a/src/gpgme.h.in b/src/gpgme.h.in index 8e224a47..ff9bba06 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -329,6 +329,12 @@ gpgme_protocol_t; typedef unsigned int gpgme_keylist_mode_t; +/* The available export mode flags. */ +#define GPGME_EXPORT_MODE_EXTERN 2 + +typedef unsigned int gpgme_export_mode_t; + + /* Flags for the audit log functions. */ #define GPGME_AUDITLOG_HTML 1 #define GPGME_AUDITLOG_WITH_HELP 128 @@ -1497,22 +1503,39 @@ gpgme_error_t gpgme_op_import (gpgme_ctx_t ctx, gpgme_data_t keydata); gpgme_error_t gpgme_op_import_ext (gpgme_ctx_t ctx, gpgme_data_t keydata, int *nr) _GPGME_DEPRECATED; +/* Import the keys from the array KEYS into the keyring. */ +gpgme_error_t gpgme_op_import_keys_start (gpgme_ctx_t ctx, gpgme_key_t keys[]); +gpgme_error_t gpgme_op_import_keys (gpgme_ctx_t ctx, gpgme_key_t keys[]); + + /* Export the keys found by PATTERN into KEYDATA. */ gpgme_error_t gpgme_op_export_start (gpgme_ctx_t ctx, const char *pattern, - unsigned int reserved, + gpgme_export_mode_t mode, gpgme_data_t keydata); gpgme_error_t gpgme_op_export (gpgme_ctx_t ctx, const char *pattern, - unsigned int reserved, gpgme_data_t keydata); + gpgme_export_mode_t mode, + gpgme_data_t keydata); gpgme_error_t gpgme_op_export_ext_start (gpgme_ctx_t ctx, const char *pattern[], - unsigned int reserved, + gpgme_export_mode_t mode, gpgme_data_t keydata); gpgme_error_t gpgme_op_export_ext (gpgme_ctx_t ctx, const char *pattern[], - unsigned int reserved, + gpgme_export_mode_t mode, gpgme_data_t keydata); +/* Export the keys from the array KEYS into KEYDATA. */ +gpgme_error_t gpgme_op_export_keys_start (gpgme_ctx_t ctx, + gpgme_key_t keys[], + gpgme_export_mode_t mode, + gpgme_data_t keydata); +gpgme_error_t gpgme_op_export_keys (gpgme_ctx_t ctx, + gpgme_key_t keys[], + gpgme_export_mode_t mode, + gpgme_data_t keydata); + + /* Key generation. */ struct _gpgme_op_genkey_result diff --git a/src/import.c b/src/import.c index ad6b776b..8212a25e 100644 --- a/src/import.c +++ b/src/import.c @@ -238,7 +238,7 @@ _gpgme_op_import_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t keydata) _gpgme_engine_set_status_handler (ctx->engine, import_status_handler, ctx); - return _gpgme_engine_op_import (ctx->engine, keydata); + return _gpgme_engine_op_import (ctx->engine, keydata, NULL); } @@ -260,6 +260,84 @@ gpgme_op_import (gpgme_ctx_t ctx, gpgme_data_t keydata) } + +static gpgme_error_t +_gpgme_op_import_keys_start (gpgme_ctx_t ctx, int synchronous, + gpgme_key_t *keys) +{ + gpgme_error_t err; + void *hook; + op_data_t opd; + int idx, firstidx, nkeys; + + err = _gpgme_op_reset (ctx, synchronous); + if (err) + return err; + + err = _gpgme_op_data_lookup (ctx, OPDATA_IMPORT, &hook, + sizeof (*opd), release_op_data); + opd = hook; + if (err) + return err; + opd->lastp = &opd->result.imports; + + if (!keys) + return gpg_error (GPG_ERR_NO_DATA); + + for (idx=nkeys=0, firstidx=-1; keys[idx]; idx++) + { + /* We only consider keys of the current protocol. */ + if (keys[idx]->protocol != ctx->protocol) + continue; + if (firstidx == -1) + firstidx = idx; + /* If a key has been found using a different key listing mode, + we bail out. This makes the processing easier. Fixme: To + allow a mix of keys we would need to sort them by key listing + mode and start two import operations one after the other. */ + if (keys[idx]->keylist_mode != keys[firstidx]->keylist_mode) + return gpg_error (GPG_ERR_CONFLICT); + nkeys++; + } + if (!nkeys) + return gpg_error (GPG_ERR_NO_DATA); + + _gpgme_engine_set_status_handler (ctx->engine, import_status_handler, ctx); + + return _gpgme_engine_op_import (ctx->engine, NULL, keys); +} + + +/* Asynchronous version of gpgme_op_import_key. */ +gpgme_error_t +gpgme_op_import_keys_start (gpgme_ctx_t ctx, gpgme_key_t *keys) +{ + return _gpgme_op_import_keys_start (ctx, 0, keys); +} + + +/* Import the keys from the array KEYS into the keyring. This + function allows to move a key from one engine to another as long as + they are compatible. In particular it is used to actually import + keys retrieved from an external source (i.e. using + GPGME_KEYLIST_MODE_EXTERN). It replaces the old workaround of + exporting and then importing a key as used to make an X.509 key + permanent. This function automagically does the right thing. + + KEYS is a NULL terminated array of gpgme key objects. The result + is the usual import result structure. Only keys matching the + current protocol are imported; other keys are ignored. */ +gpgme_error_t +gpgme_op_import_keys (gpgme_ctx_t ctx, gpgme_key_t *keys) +{ + gpgme_error_t err = _gpgme_op_import_keys_start (ctx, 1, keys); + if (!err) + err = _gpgme_wait_one (ctx); + return err; +} + + +/* Deprecated interface. */ gpgme_error_t gpgme_op_import_ext (gpgme_ctx_t ctx, gpgme_data_t keydata, int *nr) { diff --git a/src/libgpgme.vers b/src/libgpgme.vers index 44f61760..41fa1be9 100644 --- a/src/libgpgme.vers +++ b/src/libgpgme.vers @@ -59,6 +59,11 @@ GPGME_1.1 { gpgme_result_ref; gpgme_result_unref; + + gpgme_op_import_keys; + gpgme_op_import_keys_start; + gpgme_op_export_keys; + gpgme_op_export_keys_start; }; |