From b996b0540a0d78f3a3580da7814f0d86264da511 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 7 Jul 2009 14:33:10 +0000 Subject: [PATCH] Inmplement import from keys for GPGSM. Add option --cms to run-keylist test program. --- src/ChangeLog | 7 ++++ src/engine-gpg.c | 2 +- src/engine-gpgsm.c | 82 ++++++++++++++++++++++++++++++++++++++++++--- tests/ChangeLog | 2 ++ tests/run-keylist.c | 18 ++++++++-- 5 files changed, 103 insertions(+), 8 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index eca549aa..feebbdc9 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,12 @@ 2009-07-07 Werner Koch + * engine-gpgsm.c (struct engine_gpgsm): Add fields + input_helper_data and input_helper_memory. + (close_notify_handler): Release these new fields. + (gpgsm_import): Implement the keyarray feature. + + * engine-gpg.c (gpg_import): Actually return GPG_ERR_INV_VALUE. + * engine-gpgsm.c (gpgsm_import): Return an error for unknown data encodings. diff --git a/src/engine-gpg.c b/src/engine-gpg.c index a3b94677..dba49a9c 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -1914,7 +1914,7 @@ gpg_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray) gpgme_data_encoding_t dataenc; if (keydata && keyarray) - gpg_error (GPG_ERR_INV_VALUE); /* Only one is allowed. */ + return gpg_error (GPG_ERR_INV_VALUE); /* Only one is allowed. */ dataenc = gpgme_data_get_encoding (keydata); diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c index 52915d36..4067b99b 100644 --- a/src/engine-gpgsm.c +++ b/src/engine-gpgsm.c @@ -70,6 +70,8 @@ struct engine_gpgsm /* Input, output etc are from the servers perspective. */ iocb_data_t input_cb; + gpgme_data_t input_helper_data; /* Input helper data object. */ + void *input_helper_memory; /* Input helper memory block. */ iocb_data_t output_cb; @@ -141,6 +143,16 @@ close_notify_handler (int fd, void *opaque) (*gpgsm->io_cbs.remove) (gpgsm->input_cb.tag); gpgsm->input_cb.fd = -1; gpgsm->input_cb.tag = NULL; + if (gpgsm->input_helper_data) + { + gpgme_data_release (gpgsm->input_helper_data); + gpgsm->input_helper_data = NULL; + } + if (gpgsm->input_helper_memory) + { + free (gpgsm->input_helper_memory); + gpgsm->input_helper_memory = NULL; + } } else if (gpgsm->output_cb.fd == fd) { @@ -1545,18 +1557,79 @@ gpgsm_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray) engine_gpgsm_t gpgsm = engine; gpgme_error_t err; gpgme_data_encoding_t dataenc; + int idx; if (!gpgsm) return gpg_error (GPG_ERR_INV_VALUE); if (keydata && keyarray) - gpg_error (GPG_ERR_INV_VALUE); /* Only one is allowed. */ + return gpg_error (GPG_ERR_INV_VALUE); /* Only one is allowed. */ dataenc = gpgme_data_get_encoding (keydata); if (keyarray) { - return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + size_t buflen; + char *buffer, *p; + + /* Fist check whether the engine already features the + --re-import option. */ + err = gpgsm_assuan_simple_command + (gpgsm->assuan_ctx, + "GETINFO cmd_has_option IMPORT re-import", NULL, NULL); + if (err) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + /* Create an internal data object with a list of all + fingerprints. The data object and its memory (to avoid an + extra copy by gpgme_data_new_from_mem) are stored in two + variables which are released by the close_notify_handler. */ + for (idx=0, buflen=0; keyarray[idx]; idx++) + { + if (keyarray[idx]->protocol == GPGME_PROTOCOL_CMS + && keyarray[idx]->subkeys + && keyarray[idx]->subkeys->fpr + && *keyarray[idx]->subkeys->fpr) + buflen += strlen (keyarray[idx]->subkeys->fpr) + 1; + } + /* Allocate a bufer with extra space for the trailing Nul + introduced by the use of stpcpy. */ + buffer = malloc (buflen+1); + if (!buffer) + return gpg_error_from_syserror (); + for (idx=0, p = buffer; keyarray[idx]; idx++) + { + if (keyarray[idx]->protocol == GPGME_PROTOCOL_CMS + && keyarray[idx]->subkeys + && keyarray[idx]->subkeys->fpr + && *keyarray[idx]->subkeys->fpr) + p = stpcpy (stpcpy (p, keyarray[idx]->subkeys->fpr), "\n"); + } + + err = gpgme_data_new_from_mem (&gpgsm->input_helper_data, + buffer, buflen, 0); + if (err) + { + free (buffer); + return err; + } + gpgsm->input_helper_memory = buffer; + + gpgsm->input_cb.data = gpgsm->input_helper_data; + err = gpgsm_set_fd (gpgsm, INPUT_FD, map_data_enc (gpgsm->input_cb.data)); + if (err) + { + gpgme_data_release (gpgsm->input_helper_data); + gpgsm->input_helper_data = NULL; + free (gpgsm->input_helper_memory); + gpgsm->input_helper_memory = NULL; + return err; + } + gpgsm_clear_fd (gpgsm, OUTPUT_FD); + gpgsm_clear_fd (gpgsm, MESSAGE_FD); + gpgsm->inline_data = NULL; + + return start (gpgsm, "IMPORT --re-import"); } else if (dataenc == GPGME_DATA_ENCODING_URL || dataenc == GPGME_DATA_ENCODING_URL0 @@ -1573,10 +1646,9 @@ gpgsm_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray) gpgsm_clear_fd (gpgsm, OUTPUT_FD); gpgsm_clear_fd (gpgsm, MESSAGE_FD); gpgsm->inline_data = NULL; - } - err = start (gpgsm, "IMPORT"); - return err; + return start (gpgsm, "IMPORT"); + } } diff --git a/tests/ChangeLog b/tests/ChangeLog index 9e68d51d..926771ab 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,5 +1,7 @@ 2009-07-07 Werner Koch + * run-keylist.c (main): Add options --cms and --openpgp. + * gpg/pgp-keylist.c: Rename to ... * run-keylist.c: ... this. * gpg/pgp-import.c: Rename to ... diff --git a/tests/run-keylist.c b/tests/run-keylist.c index 07fc8941..8dd28b8f 100644 --- a/tests/run-keylist.c +++ b/tests/run-keylist.c @@ -43,6 +43,8 @@ show_usage (int ex) fputs ("usage: " PGM " [options] [USERID]\n\n" "Options:\n" " --verbose run in verbose mode\n" + " --openpgp use the OpenPGP protocol (default)\n" + " --cms use the CMS protocol\n" " --local use GPGME_KEYLIST_MODE_LOCAL\n" " --extern use GPGME_KEYLIST_MODE_EXTERN\n" " --sigs use GPGME_KEYLIST_MODE_SIGS\n" @@ -54,6 +56,7 @@ show_usage (int ex) exit (ex); } + int main (int argc, char **argv) { @@ -66,6 +69,7 @@ main (int argc, char **argv) int import = 0; gpgme_key_t keyarray[100]; int keyidx = 0; + gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP; if (argc) { argc--; argv++; } @@ -85,6 +89,16 @@ main (int argc, char **argv) verbose = 1; argc--; argv++; } + else if (!strcmp (*argv, "--openpgp")) + { + protocol = GPGME_PROTOCOL_OpenPGP; + argc--; argv++; + } + else if (!strcmp (*argv, "--cms")) + { + protocol = GPGME_PROTOCOL_CMS; + argc--; argv++; + } else if (!strcmp (*argv, "--local")) { mode |= GPGME_KEYLIST_MODE_LOCAL; @@ -128,11 +142,11 @@ main (int argc, char **argv) if (argc > 1) show_usage (1); - init_gpgme (GPGME_PROTOCOL_OpenPGP); + init_gpgme (protocol); err = gpgme_new (&ctx); fail_if_err (err); - gpgme_set_protocol (ctx, GPGME_PROTOCOL_OpenPGP); + gpgme_set_protocol (ctx, protocol); gpgme_set_keylist_mode (ctx, mode);