Add server option with-ephemeral-keys.
authorWerner Koch <wk@gnupg.org>
Wed, 18 Mar 2009 11:18:56 +0000 (11:18 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 18 Mar 2009 11:18:56 +0000 (11:18 +0000)
Extend SCD LEARN command.

14 files changed:
scd/ChangeLog
scd/app-common.h
scd/app-dinsig.c
scd/app-geldkarte.c
scd/app-nks.c
scd/app-openpgp.c
scd/app-p15.c
scd/app.c
scd/command.c
sm/ChangeLog
sm/gpgsm.c
sm/gpgsm.h
sm/keylist.c
sm/server.c

index e53c8c7..6ae7da5 100644 (file)
@@ -1,3 +1,12 @@
+2009-03-18  Werner Koch  <wk@g10code.com>
+
+       * 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  <wk@g10code.com>
 
        * app-openpgp.c (send_key_attr): New.
index ad899a3..85ac9e2 100644 (file)
@@ -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,
index 3b18b5e..f0655bb 100644 (file)
@@ -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); 
index d6cbe88..34ce08f 100644 (file)
@@ -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;
index 1a520bb..9af3918 100644 (file)
@@ -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;
 }
index 4bc28d3..ce09a51 100644 (file)
@@ -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");
index 4ebe7b2..62404be 100644 (file)
@@ -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);
 
index d0b8328..e66c6cb 100644 (file)
--- 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;
 }
index 2fa1f7c..2423424 100644 (file)
@@ -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 <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;
index 03fa60c..caf96eb 100644 (file)
@@ -1,3 +1,11 @@
+2009-03-18  Werner Koch  <wk@g10code.com>
+
+       * 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  <wk@g10code.com>
 
        * certdump.c (gpgsm_dump_time): Remove.
index fe9ebf3..f49b742 100644 (file)
@@ -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;
 
index 984dda1..0b16e51 100644 (file)
@@ -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 */
index 39b82c2..8a9eaf5 100644 (file)
@@ -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)
index 9b0a04f..6b9eeb8 100644 (file)
@@ -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);