From a3b63ac1dc1084beb3d4350e10033ac4af43dcf5 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 18 Mar 2009 11:18:56 +0000 Subject: [PATCH] Add server option with-ephemeral-keys. Extend SCD LEARN command. --- scd/ChangeLog | 9 ++++ scd/app-common.h | 5 ++- scd/app-dinsig.c | 4 +- scd/app-geldkarte.c | 4 +- scd/app-nks.c | 10 ++--- scd/app-openpgp.c | 4 +- scd/app-p15.c | 22 ++++++---- scd/app.c | 7 +-- scd/command.c | 104 ++++++++++++++++++++++++-------------------- sm/ChangeLog | 8 ++++ sm/gpgsm.c | 2 +- sm/gpgsm.h | 5 +-- sm/keylist.c | 2 +- sm/server.c | 5 +++ 14 files changed, 117 insertions(+), 74 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index e53c8c79f..6ae7da589 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,12 @@ +2009-03-18 Werner Koch + + * command.c (cmd_learn): Add option --keypairinfo. + * app.c (app_write_learn_status): Add arg FLAGS. + * app-common.h (struct app_ctx_s): Add arg FLAGS to LEARN_STATUS. + Change all implementors. + * app-p15.c (do_learn_status): Take care of flag bit 0. + * app-nks.c (do_learn_status, do_learn_status_core): Ditto. + 2009-03-10 Werner Koch * app-openpgp.c (send_key_attr): New. diff --git a/scd/app-common.h b/scd/app-common.h index ad899a3b6..85ac9e2b5 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -67,7 +67,7 @@ struct app_ctx_s { struct app_local_s *app_local; /* Local to the application. */ struct { void (*deinit) (app_t app); - gpg_error_t (*learn_status) (app_t app, ctrl_t ctrl); + gpg_error_t (*learn_status) (app_t app, ctrl_t ctrl, unsigned int flags); gpg_error_t (*readcert) (app_t app, const char *certid, unsigned char **cert, size_t *certlen); gpg_error_t (*readkey) (app_t app, const char *certid, @@ -145,7 +145,8 @@ char *get_supported_applications (void); void release_application (app_t app); gpg_error_t app_munge_serialno (app_t app); gpg_error_t app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp); -gpg_error_t app_write_learn_status (app_t app, ctrl_t ctrl); +gpg_error_t app_write_learn_status (app_t app, ctrl_t ctrl, + unsigned int flags); gpg_error_t app_readcert (app_t app, const char *certid, unsigned char **cert, size_t *certlen); gpg_error_t app_readkey (app_t app, const char *keyid, diff --git a/scd/app-dinsig.c b/scd/app-dinsig.c index 3b18b5e99..f0655bb2d 100644 --- a/scd/app-dinsig.c +++ b/scd/app-dinsig.c @@ -86,7 +86,7 @@ static gpg_error_t -do_learn_status (app_t app, ctrl_t ctrl) +do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags) { gpg_error_t err; char ct_buf[100], id_buf[100]; @@ -97,6 +97,8 @@ do_learn_status (app_t app, ctrl_t ctrl) ksba_cert_t cert; int fid; + (void)flags; + /* Return the certificate of the card holder. */ fid = 0xC000; len = app_help_read_length_of_cert (app->slot, fid, &certoff); diff --git a/scd/app-geldkarte.c b/scd/app-geldkarte.c index d6cbe880b..34ce08f6e 100644 --- a/scd/app-geldkarte.c +++ b/scd/app-geldkarte.c @@ -147,7 +147,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) static gpg_error_t -do_learn_status (app_t app, ctrl_t ctrl) +do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags) { static const char *names[] = { "X-KBLZ", @@ -167,6 +167,8 @@ do_learn_status (app_t app, ctrl_t ctrl) gpg_error_t err = 0; int idx; + (void)flags; + for (idx=0; names[idx] && !err; idx++) err = do_getattr (app, ctrl, names[idx]); return err; diff --git a/scd/app-nks.c b/scd/app-nks.c index 1a520bbf0..9af39184f 100644 --- a/scd/app-nks.c +++ b/scd/app-nks.c @@ -309,7 +309,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) static void -do_learn_status_core (app_t app, ctrl_t ctrl, int is_sigg) +do_learn_status_core (app_t app, ctrl_t ctrl, unsigned int flags, int is_sigg) { gpg_error_t err; char ct_buf[100], id_buf[100]; @@ -332,7 +332,7 @@ do_learn_status_core (app_t app, ctrl_t ctrl, int is_sigg) if (!!filelist[i].is_sigg != !!is_sigg) continue; - if (filelist[i].certtype) + if (filelist[i].certtype && !(flags &1)) { size_t len; @@ -377,7 +377,7 @@ do_learn_status_core (app_t app, ctrl_t ctrl, int is_sigg) static gpg_error_t -do_learn_status (app_t app, ctrl_t ctrl) +do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags) { gpg_error_t err; @@ -385,13 +385,13 @@ do_learn_status (app_t app, ctrl_t ctrl) if (err) return err; - do_learn_status_core (app, ctrl, 0); + do_learn_status_core (app, ctrl, flags, 0); err = switch_application (app, 1); if (err) return 0; /* Silently ignore if we can't switch to SigG. */ - do_learn_status_core (app, ctrl, 1); + do_learn_status_core (app, ctrl, flags, 1); return 0; } diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 4bc28d30b..ce09a51f5 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1295,8 +1295,10 @@ send_keypair_info (app_t app, ctrl_t ctrl, int keyno) /* Handle the LEARN command for OpenPGP. */ static gpg_error_t -do_learn_status (app_t app, ctrl_t ctrl) +do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags) { + (void)flags; + do_getattr (app, ctrl, "EXTCAP"); do_getattr (app, ctrl, "DISP-NAME"); do_getattr (app, ctrl, "DISP-LANG"); diff --git a/scd/app-p15.c b/scd/app-p15.c index 4ebe7b2fd..62404bef9 100644 --- a/scd/app-p15.c +++ b/scd/app-p15.c @@ -2492,17 +2492,23 @@ send_keypairinfo (app_t app, ctrl_t ctrl, prkdf_object_t keyinfo) /* This is the handler for the LEARN command. */ static gpg_error_t -do_learn_status (app_t app, ctrl_t ctrl) +do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags) { gpg_error_t err; - err = send_certinfo (app, ctrl, "100", app->app_local->certificate_info); - if (!err) - err = send_certinfo (app, ctrl, "101", - app->app_local->trusted_certificate_info); - if (!err) - err = send_certinfo (app, ctrl, "102", - app->app_local->useful_certificate_info); + if ((flags & 1)) + err = 0; + else + { + err = send_certinfo (app, ctrl, "100", app->app_local->certificate_info); + if (!err) + err = send_certinfo (app, ctrl, "101", + app->app_local->trusted_certificate_info); + if (!err) + err = send_certinfo (app, ctrl, "102", + app->app_local->useful_certificate_info); + } + if (!err) err = send_keypairinfo (app, ctrl, app->app_local->private_key_info); diff --git a/scd/app.c b/scd/app.c index d0b832843..e66c6cb7a 100644 --- a/scd/app.c +++ b/scd/app.c @@ -542,7 +542,7 @@ app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp) /* Write out the application specifig status lines for the LEARN command. */ gpg_error_t -app_write_learn_status (app_t app, ctrl_t ctrl) +app_write_learn_status (app_t app, ctrl_t ctrl, unsigned int flags) { gpg_error_t err; @@ -553,13 +553,14 @@ app_write_learn_status (app_t app, ctrl_t ctrl) if (!app->fnc.learn_status) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - if (app->apptype) + /* We do not send APPTYPE if only keypairinfo is requested. */ + if (app->apptype && !(flags & 1)) send_status_info (ctrl, "APPTYPE", app->apptype, strlen (app->apptype), NULL, 0); err = lock_reader (app->slot); if (err) return err; - err = app->fnc.learn_status (app, ctrl); + err = app->fnc.learn_status (app, ctrl, flags); unlock_reader (app->slot); return err; } diff --git a/scd/command.c b/scd/command.c index 2fa1f7c3e..242342484 100644 --- a/scd/command.c +++ b/scd/command.c @@ -1,6 +1,6 @@ /* command.c - SCdaemon command handler * Copyright (C) 2001, 2002, 2003, 2004, 2005, - * 2007, 2008 Free Software Foundation, Inc. + * 2007, 2008, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -184,7 +184,7 @@ update_card_removed (int slot, int value) -/* Check whether the option NAME appears in LINE */ +/* Check whether the option NAME appears in LINE. Returns 1 or 0. */ static int has_option (const char *line, const char *name) { @@ -528,7 +528,7 @@ cmd_serialno (assuan_context_t ctx, char *line) -/* LEARN [--force] +/* LEARN [--force] [--keypairinfo] Learn all useful information of the currently inserted card. When used without the force options, the command might do an INQUIRE @@ -538,8 +538,13 @@ cmd_serialno (assuan_context_t ctx, char *line) The client should just send an "END" if the processing should go on or a "CANCEL" to force the function to terminate with a Cancel - error message. The response of this command is a list of status - lines formatted as this: + error message. + + With the option --keypairinfo only KEYPARIINFO lstatus lines are + returned. + + The response of this command is a list of status lines formatted as + this: S APPTYPE @@ -589,13 +594,14 @@ cmd_serialno (assuan_context_t ctx, char *line) The URL to be used for locating the entire public key. - Note, that this function may be even be used on a locked card. + Note, that this function may even be used on a locked card. */ static int cmd_learn (assuan_context_t ctx, char *line) { ctrl_t ctrl = assuan_get_pointer (ctx); int rc = 0; + int only_keypairinfo = has_option (line, "--keypairinfo"); if ((rc = open_card (ctrl, NULL))) return rc; @@ -604,51 +610,53 @@ cmd_learn (assuan_context_t ctx, char *line) the card using a serial number and inquiring the client with that. The client may choose to cancel the operation if he already knows about this card */ - { - char *serial_and_stamp; - char *serial; - time_t stamp; - - rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp); - if (rc) - return rc; - rc = estream_asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp); - xfree (serial); - if (rc < 0) - return out_of_core (); - rc = 0; - assuan_write_status (ctx, "SERIALNO", serial_and_stamp); - - if (!has_option (line, "--force")) - { - char *command; - - rc = estream_asprintf (&command, "KNOWNCARDP %s", serial_and_stamp); - if (rc < 0) - { - xfree (serial_and_stamp); - return out_of_core (); - } - rc = 0; - rc = assuan_inquire (ctx, command, NULL, NULL, 0); - xfree (command); - if (rc) - { - if (gpg_err_code (rc) != GPG_ERR_ASS_CANCELED) - log_error ("inquire KNOWNCARDP failed: %s\n", - gpg_strerror (rc)); - xfree (serial_and_stamp); - return rc; - } - /* not canceled, so we have to proceeed */ - } - xfree (serial_and_stamp); - } - + if (!only_keypairinfo) + { + char *serial_and_stamp; + char *serial; + time_t stamp; + + rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp); + if (rc) + return rc; + rc = estream_asprintf (&serial_and_stamp, "%s %lu", + serial, (unsigned long)stamp); + xfree (serial); + if (rc < 0) + return out_of_core (); + rc = 0; + assuan_write_status (ctx, "SERIALNO", serial_and_stamp); + + if (!has_option (line, "--force")) + { + char *command; + + rc = estream_asprintf (&command, "KNOWNCARDP %s", serial_and_stamp); + if (rc < 0) + { + xfree (serial_and_stamp); + return out_of_core (); + } + rc = 0; + rc = assuan_inquire (ctx, command, NULL, NULL, 0); + xfree (command); + if (rc) + { + if (gpg_err_code (rc) != GPG_ERR_ASS_CANCELED) + log_error ("inquire KNOWNCARDP failed: %s\n", + gpg_strerror (rc)); + xfree (serial_and_stamp); + return rc; + } + /* Not canceled, so we have to proceeed. */ + } + xfree (serial_and_stamp); + } + /* Let the application print out its collection of useful status information. */ if (!rc) - rc = app_write_learn_status (ctrl->app_ctx, ctrl); + rc = app_write_learn_status (ctrl->app_ctx, ctrl, only_keypairinfo); TEST_CARD_REMOVAL (ctrl, rc); return rc; diff --git a/sm/ChangeLog b/sm/ChangeLog index 03fa60c98..caf96eb80 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,11 @@ +2009-03-18 Werner Koch + + * gpgsm.h (struct opt): Move field WITH_EPHEMERAL_KEYS to struct + server_control_s. + * gpgsm.c (main): Change accordingly. + * keylist.c (list_internal_keys): Ditto. + * server.c (option_handler): Add "with-ephemeral-keys". + 2009-03-12 Werner Koch * certdump.c (gpgsm_dump_time): Remove. diff --git a/sm/gpgsm.c b/sm/gpgsm.c index fe9ebf302..f49b742c2 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -1259,7 +1259,7 @@ main ( int argc, char **argv) case oWithKeyData: opt.with_key_data=1; /* fall thru */ case oWithColons: ctrl.with_colons = 1; break; case oWithValidation: ctrl.with_validation=1; break; - case oWithEphemeralKeys: opt.with_ephemeral_keys=1; break; + case oWithEphemeralKeys: ctrl.with_ephemeral_keys=1; break; case oSkipVerify: opt.skip_verify=1; break; diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 984dda135..0b16e51c2 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -82,9 +82,6 @@ struct int with_md5_fingerprint; /* Also print an MD5 fingerprint for standard key listings. */ - int with_ephemeral_keys; /* Include ephemeral flagged keys in the - keylisting. */ - int armor; /* force base64 armoring (see also ctrl.with_base64) */ int no_armor; /* don't try to figure out whether data is base64 armored*/ @@ -176,6 +173,8 @@ struct server_control_s int with_colons; /* Use column delimited output format */ int with_chain; /* Include the certifying certs in a listing */ int with_validation;/* Validate each key while listing. */ + int with_ephemeral_keys; /* Include ephemeral flagged keys in the + keylisting. */ int autodetect_encoding; /* Try to detect the input encoding */ int is_pem; /* Is in PEM format */ diff --git a/sm/keylist.c b/sm/keylist.c index 39b82c29d..8a9eaf5e7 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -1292,7 +1292,7 @@ list_internal_keys (ctrl_t ctrl, strlist_t names, estream_t fp, gpg_error_t rc = 0; const char *lastresname, *resname; int have_secret; - int want_ephemeral = opt.with_ephemeral_keys; + int want_ephemeral = ctrl->with_ephemeral_keys; hd = keydb_new (0); if (!hd) diff --git a/sm/server.c b/sm/server.c index 9b0a04f18..6b9eeb82d 100644 --- a/sm/server.c +++ b/sm/server.c @@ -296,6 +296,11 @@ option_handler (assuan_context_t ctx, const char *key, const char *value) } else if (!strcmp (key, "allow-pinentry-notify")) ctrl->server_local->allow_pinentry_notify = 1; + else if (!strcmp (key, "with-ephemeral-keys")) + { + int i = *value? atoi (value) : 0; + ctrl->with_ephemeral_keys = i; + } else return gpg_error (GPG_ERR_UNKNOWN_OPTION);