[svn] GnuPG - r5467 - in trunk: agent common g10 po sm

svn author wk cvs at cvs.gnupg.org
Tue Oct 26 11:10:32 CEST 2010


Author: wk
Date: 2010-10-26 11:10:29 +0200 (Tue, 26 Oct 2010)
New Revision: 5467

Modified:
   trunk/agent/ChangeLog
   trunk/agent/agent.h
   trunk/agent/cache.c
   trunk/agent/command.c
   trunk/agent/findkey.c
   trunk/agent/genkey.c
   trunk/common/ChangeLog
   trunk/common/logging.c
   trunk/common/logging.h
   trunk/g10/ChangeLog
   trunk/g10/call-agent.c
   trunk/g10/call-agent.h
   trunk/g10/gpg.c
   trunk/g10/keyedit.c
   trunk/g10/main.h
   trunk/g10/passphrase.c
   trunk/po/de.po
   trunk/sm/server.c
Log:
Re-implemented GPG's --passwd command and improved it.


Modified: trunk/agent/ChangeLog
===================================================================
--- trunk/agent/ChangeLog	2010-10-22 07:35:30 UTC (rev 5466)
+++ trunk/agent/ChangeLog	2010-10-26 09:10:29 UTC (rev 5467)
@@ -1,3 +1,20 @@
+2010-10-26  Werner Koch  <wk at g10code.com>
+
+	* cache.c (agent_put_cache): Allow deletion even if TTL is passwd
+	as 0.
+
+	* genkey.c (agent_protect_and_store): Add arg PASSPHRASE_ADDR.
+	* command.c (cmd_passwd): Add option --passwd-nonce.
+	(struct server_local_s): Add LAST_CACHE_NONCE and LAST_PASSWD_NONCE.
+	(clear_nonce_cache): New.
+	(reset_notify): Clear the nonce cache.
+	(start_command_handler): Ditto.
+
+2010-10-25  Werner Koch  <wk at g10code.com>
+
+	* command.c (cmd_export_key): Free CACHE_NONCE.
+	(cmd_passwd): Add option --cache-nonce.
+
 2010-10-18  Werner Koch  <wk at g10code.com>
 
 	* call-pinentry.c (start_pinentry): Print name of pinentry on

Modified: trunk/common/ChangeLog
===================================================================
--- trunk/common/ChangeLog	2010-10-22 07:35:30 UTC (rev 5466)
+++ trunk/common/ChangeLog	2010-10-26 09:10:29 UTC (rev 5467)
@@ -1,3 +1,7 @@
+2010-10-25  Werner Koch  <wk at g10code.com>
+
+	* logging.c (do_log): Rename to log_log and make global.
+
 2010-10-20  Werner Koch  <wk at g10code.com>
 
 	* i18n.c (i18n_init) [USE_SIMPLE_GETTEXT]: Call textdomain.

Modified: trunk/g10/ChangeLog
===================================================================
--- trunk/g10/ChangeLog	2010-10-22 07:35:30 UTC (rev 5466)
+++ trunk/g10/ChangeLog	2010-10-26 09:10:29 UTC (rev 5467)
@@ -1,5 +1,24 @@
+2010-10-26  Werner Koch  <wk at g10code.com>
+
+	* keyedit.c (change_passphrase): Handle the passwd_nonce.
+	* call-agent.c (cache_nonce_parm_s): New.
+	(cache_nonce_status_cb): Use that new struct.
+	(agent_genkey, agent_import_key, agent_export_key, agent_passwd):
+	Adjust for that change.
+
+2010-10-25  Werner Koch  <wk at g10code.com>
+
+	* passphrase.c (gpg_format_keydesc): Fix printing of main keyid.
+
+	* keyedit.c (JNLIB_NEED_LOG_LOGV): Define.
+	* call-agent.c (agent_passwd): New.
+
 2010-10-21  Werner Koch  <wk at g10code.com>
 
+	* keyedit.c (keyedit_passwd): Simplify.
+	(change_passphrase): Return an error code and not the change
+	flag.  Remove editing of the keyring.
+
 	* seckey-cert.c: Remove.
 	* Makefile.am (gpg2_SOURCES): Remove seckey-cert.c
 

Modified: trunk/agent/agent.h
===================================================================
--- trunk/agent/agent.h	2010-10-22 07:35:30 UTC (rev 5466)
+++ trunk/agent/agent.h	2010-10-26 09:10:29 UTC (rev 5467)
@@ -295,7 +295,8 @@
 int agent_genkey (ctrl_t ctrl, const char *cache_nonce,
                   const char *keyparam, size_t keyparmlen,
                   int no_protection, membuf_t *outbuf);
-int agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey);
+gpg_error_t agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey,
+                                     char **passphrase_addr);
 
 /*-- protect.c --*/
 unsigned long get_standard_s2k_count (void);

Modified: trunk/agent/cache.c
===================================================================
--- trunk/agent/cache.c	2010-10-22 07:35:30 UTC (rev 5466)
+++ trunk/agent/cache.c	2010-10-26 09:10:29 UTC (rev 5467)
@@ -284,7 +284,7 @@
         default: ttl = opt.def_cache_ttl; break;
         }
     }
-  if (!ttl || cache_mode == CACHE_MODE_IGNORE)
+  if ((!ttl && data) || cache_mode == CACHE_MODE_IGNORE)
     return 0;
 
   for (r=thecache; r; r = r->next)

Modified: trunk/agent/command.c
===================================================================
--- trunk/agent/command.c	2010-10-22 07:35:30 UTC (rev 5466)
+++ trunk/agent/command.c	2010-10-26 09:10:29 UTC (rev 5467)
@@ -72,6 +72,8 @@
   void *import_key;  /* Malloced KEK for the import_key command.  */
   void *export_key;  /* Malloced KEK for the export_key command.  */
   int allow_fully_canceled; /* Client is aware of GPG_ERR_FULLY_CANCELED.  */
+  char *last_cache_nonce;   /* Last CACHE_NOCNE sent as status (malloced).  */
+  char *last_passwd_nonce;  /* Last PASSWD_NOCNE sent as status (malloced). */
 };
 
 
@@ -153,6 +155,26 @@
 }
 
 
+static void
+clear_nonce_cache (ctrl_t ctrl)
+{
+  if (ctrl->server_local->last_cache_nonce)
+    {
+      agent_put_cache (ctrl->server_local->last_cache_nonce,
+                       CACHE_MODE_NONCE, NULL, 0);
+      xfree (ctrl->server_local->last_cache_nonce);
+      ctrl->server_local->last_cache_nonce = NULL;
+    }
+  if (ctrl->server_local->last_passwd_nonce)
+    {
+      agent_put_cache (ctrl->server_local->last_passwd_nonce,
+                       CACHE_MODE_NONCE, NULL, 0);
+      xfree (ctrl->server_local->last_passwd_nonce);
+      ctrl->server_local->last_passwd_nonce = NULL;
+    }
+}
+
+
 static gpg_error_t
 reset_notify (assuan_context_t ctx, char *line)
 {
@@ -166,6 +188,9 @@
 
   xfree (ctrl->server_local->keydesc);
   ctrl->server_local->keydesc = NULL;
+
+  clear_nonce_cache (ctrl);
+
   return 0;
 }
 
@@ -1331,44 +1356,135 @@
 
 
 static const char hlp_passwd[] = 
-  "PASSWD <hexstring_with_keygrip>\n"
+  "PASSWD [--cache-nonce=<c>] [--passwd-nonce=<s>] <hexstring_with_keygrip>\n"
   "\n"
   "Change the passphrase/PIN for the key identified by keygrip in LINE.";
 static gpg_error_t
 cmd_passwd (assuan_context_t ctx, char *line)
 {
   ctrl_t ctrl = assuan_get_pointer (ctx);
-  int rc;
+  gpg_error_t err;
+  int c;
+  char *cache_nonce = NULL;
+  char *passwd_nonce = NULL;
   unsigned char grip[20];
   gcry_sexp_t s_skey = NULL;
   unsigned char *shadow_info = NULL;
+  char *passphrase = NULL;
+  char *pend;
 
-  rc = parse_keygrip (ctx, line, grip);
-  if (rc)
+  cache_nonce = option_value (line, "--cache-nonce");
+  if (cache_nonce)
+    {
+      for (pend = cache_nonce; *pend && !spacep (pend); pend++)
+        ;
+      c = *pend;
+      *pend = '\0';
+      cache_nonce = xtrystrdup (cache_nonce);
+      *pend = c;
+      if (!cache_nonce)
+        {
+          err = gpg_error_from_syserror ();
+          goto leave;
+        }
+    }
+
+  passwd_nonce = option_value (line, "--passwd-nonce");
+  if (passwd_nonce)
+    {
+      for (pend = passwd_nonce; *pend && !spacep (pend); pend++)
+        ;
+      c = *pend;
+      *pend = '\0';
+      passwd_nonce = xtrystrdup (passwd_nonce);
+      *pend = c;
+      if (!passwd_nonce)
+        {
+          err = gpg_error_from_syserror ();
+          goto leave;
+        }
+    }
+
+  line = skip_options (line);
+
+  err = parse_keygrip (ctx, line, grip);
+  if (err)
     goto leave;
 
   ctrl->in_passwd++;
-  rc = agent_key_from_file (ctrl, NULL, ctrl->server_local->keydesc,
-                            grip, &shadow_info, CACHE_MODE_IGNORE, NULL, 
-                            &s_skey, NULL);
-  if (rc)
+  err = agent_key_from_file (ctrl, cache_nonce, ctrl->server_local->keydesc,
+                             grip, &shadow_info, CACHE_MODE_IGNORE, NULL, 
+                             &s_skey, &passphrase);
+  if (err)
     ;
   else if (!s_skey)
     {
       log_error ("changing a smartcard PIN is not yet supported\n");
-      rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+      err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
     }
   else
-    rc = agent_protect_and_store (ctrl, s_skey);
+    {
+      char *newpass = NULL;
+
+      if (passwd_nonce)
+        newpass = agent_get_cache (passwd_nonce, CACHE_MODE_NONCE);
+      err = agent_protect_and_store (ctrl, s_skey, &newpass);
+      if (!err && passphrase)
+        {
+          /* A passphrase existed on the old key and the change was
+             successful.  Return a nonce for that old passphrase to
+             let the caller try to unprotect the other subkeys with
+             the same key.  */
+          if (!cache_nonce)
+            {
+              char buf[12];
+              gcry_create_nonce (buf, 12);
+              cache_nonce = bin2hex (buf, 12, NULL);
+            }
+          if (cache_nonce 
+              && !agent_put_cache (cache_nonce, CACHE_MODE_NONCE,
+                                   passphrase, 120 /*seconds*/))
+            {
+              assuan_write_status (ctx, "CACHE_NONCE", cache_nonce);
+              xfree (ctrl->server_local->last_cache_nonce);
+              ctrl->server_local->last_cache_nonce = cache_nonce;
+              cache_nonce = NULL;
+            }
+          if (newpass)
+            {
+              /* If we have a new passphrase (which might be empty) we
+                 store it under a passwd nonce so that the caller may
+                 send that nonce again to use it for another key. */
+              if (!passwd_nonce)
+                {
+                  char buf[12];
+                  gcry_create_nonce (buf, 12);
+                  passwd_nonce = bin2hex (buf, 12, NULL);
+                }
+              if (passwd_nonce 
+                  && !agent_put_cache (passwd_nonce, CACHE_MODE_NONCE,
+                                       newpass, 120 /*seconds*/))
+                {
+                  assuan_write_status (ctx, "PASSWD_NONCE", passwd_nonce);
+                  xfree (ctrl->server_local->last_passwd_nonce);
+                  ctrl->server_local->last_passwd_nonce = passwd_nonce;
+                  passwd_nonce = NULL;
+                }
+            }
+        }
+      xfree (newpass);
+    }
   ctrl->in_passwd--;
 
   xfree (ctrl->server_local->keydesc);
   ctrl->server_local->keydesc = NULL;
 
  leave:
+  xfree (passphrase);
   gcry_sexp_release (s_skey);
   xfree (shadow_info);
-  return leave_cmd (ctx, rc);
+  xfree (cache_nonce);
+  return leave_cmd (ctx, err);
 }
 
 
@@ -1812,6 +1928,7 @@
   
 
  leave:
+  xfree (cache_nonce);
   xfree (passphrase);
   xfree (wrappedkey);
   gcry_cipher_close (cipherhd);
@@ -2448,6 +2565,9 @@
         }
     }
 
+  /* Reset the nonce caches.  */
+  clear_nonce_cache (ctrl);
+
   /* Reset the SCD if needed. */
   agent_reset_scd (ctrl);
 

Modified: trunk/agent/findkey.c
===================================================================
--- trunk/agent/findkey.c	2010-10-22 07:35:30 UTC (rev 5466)
+++ trunk/agent/findkey.c	2010-10-26 09:10:29 UTC (rev 5467)
@@ -405,7 +405,7 @@
               xfree (pi);
               return rc;
             }
-          rc = agent_protect_and_store (ctrl, s_skey);
+          rc = agent_protect_and_store (ctrl, s_skey, NULL);
           gcry_sexp_release (s_skey);
           if (rc)
             {

Modified: trunk/agent/genkey.c
===================================================================
--- trunk/agent/genkey.c	2010-10-22 07:35:30 UTC (rev 5466)
+++ trunk/agent/genkey.c	2010-10-26 09:10:29 UTC (rev 5467)
@@ -468,20 +468,40 @@
 
 
 
-/* Apply a new passphrase to the key S_SKEY and store it. */
-int
-agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey) 
+/* Apply a new passphrase to the key S_SKEY and store it.  If
+   PASSPHRASE_ADDR and *PASSPHRASE_ADDR are not NULL, use that
+   passphrase.  If PASSPHRASE_ADDR is not NULL store a newly entered
+   passphrase at that address. */
+gpg_error_t
+agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey,
+                         char **passphrase_addr) 
 {
-  int rc;
-  char *passphrase;
+  gpg_error_t err;
 
-  rc = agent_ask_new_passphrase (ctrl, 
-                                 _("Please enter the new passphrase"),
-                                 &passphrase);
-  if (!rc)
+  if (passphrase_addr && *passphrase_addr)
     {
-      rc = store_key (s_skey, passphrase, 1);
-      xfree (passphrase);
+      /* Take an empty string as request not to protect the key.  */
+      err = store_key (s_skey, **passphrase_addr? *passphrase_addr:NULL, 1);
     }
-  return rc;
+  else
+    {
+      char *pass = NULL;
+
+      if (passphrase_addr)
+        {
+          xfree (*passphrase_addr);
+          *passphrase_addr = NULL;
+        }
+      err = agent_ask_new_passphrase (ctrl, 
+                                      _("Please enter the new passphrase"),
+                                      &pass);
+      if (!err)
+        err = store_key (s_skey, pass, 1);
+      if (!err && passphrase_addr)
+        *passphrase_addr = pass;
+      else
+        xfree (pass);
+    }
+  
+  return err;
 }

Modified: trunk/common/logging.c
===================================================================
--- trunk/common/logging.c	2010-10-22 07:35:30 UTC (rev 5466)
+++ trunk/common/logging.c	2010-10-26 09:10:29 UTC (rev 5467)
@@ -670,8 +670,8 @@
 }
 
 
-static void
-do_log (int level, const char *fmt, ...)
+void
+log_log (int level, const char *fmt, ...)
 {
   va_list arg_ptr ;
   
@@ -812,14 +812,14 @@
 void
 bug_at( const char *file, int line, const char *func )
 {
-  do_log (JNLIB_LOG_BUG, ("... this is a bug (%s:%d:%s)\n"), file, line, func);
+  log_log (JNLIB_LOG_BUG, ("... this is a bug (%s:%d:%s)\n"), file, line, func);
   abort (); /* Never called; just to make the compiler happy.  */
 }
 #else
 void
 bug_at( const char *file, int line )
 {
-  do_log (JNLIB_LOG_BUG, _("you found a bug ... (%s:%d)\n"), file, line);
+  log_log (JNLIB_LOG_BUG, _("you found a bug ... (%s:%d)\n"), file, line);
   abort (); /* Never called; just to make the compiler happy.  */
 }
 #endif

Modified: trunk/common/logging.h
===================================================================
--- trunk/common/logging.h	2010-10-22 07:35:30 UTC (rev 5466)
+++ trunk/common/logging.h	2010-10-26 09:10:29 UTC (rev 5467)
@@ -65,6 +65,7 @@
     JNLIB_LOG_BUG,
     JNLIB_LOG_DEBUG
 };
+void log_log (int level, const char *fmt, ...) JNLIB_GCC_A_PRINTF(2,3);
 void log_logv (int level, const char *fmt, va_list arg_ptr);
 void log_string (int level, const char *string);
 #endif /*JNLIB_NEED_LOG_LOGV*/

Modified: trunk/g10/call-agent.c
===================================================================
--- trunk/g10/call-agent.c	2010-10-22 07:35:30 UTC (rev 5466)
+++ trunk/g10/call-agent.c	2010-10-26 09:10:29 UTC (rev 5467)
@@ -86,6 +86,13 @@
 };
 
 
+struct cache_nonce_parm_s
+{
+  char **cache_nonce_addr;
+  char **passwd_nonce_addr;
+};
+
+
 static gpg_error_t learn_status_cb (void *opaque, const char *line);
 
 
@@ -1470,7 +1477,7 @@
 static gpg_error_t
 cache_nonce_status_cb (void *opaque, const char *line)
 {
-  char **cache_nonce = opaque;
+  struct cache_nonce_parm_s *parm = opaque;
   const char *keyword = line;
   int keywordlen;
 
@@ -1481,12 +1488,20 @@
 
   if (keywordlen == 11 && !memcmp (keyword, "CACHE_NONCE", keywordlen))
     {
-      if (cache_nonce)
+      if (parm->cache_nonce_addr)
         {
-          xfree (*cache_nonce);
-          *cache_nonce = xtrystrdup (line);
+          xfree (*parm->cache_nonce_addr);
+          *parm->cache_nonce_addr = xtrystrdup (line);
         }
     }
+  else if (keywordlen == 12 && !memcmp (keyword, "PASSWD_NONCE", keywordlen))
+    {
+      if (parm->passwd_nonce_addr)
+        {
+          xfree (*parm->passwd_nonce_addr);
+          *parm->passwd_nonce_addr = xtrystrdup (line);
+        }
+    }
 
   return 0;
 }
@@ -1523,6 +1538,7 @@
 {
   gpg_error_t err;
   struct genkey_parm_s gk_parm;
+  struct cache_nonce_parm_s cn_parm;
   membuf_t data;
   size_t len;
   unsigned char *buf;
@@ -1546,10 +1562,12 @@
             no_protection? " --no-protection":"",
             cache_nonce_addr && *cache_nonce_addr? " ":"",
             cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"");
+  cn_parm.cache_nonce_addr = cache_nonce_addr;
+  cn_parm.passwd_nonce_addr = NULL;
   err = assuan_transact (agent_ctx, line,
                          membuf_data_cb, &data, 
                          inq_genkey_parms, &gk_parm, 
-                         cache_nonce_status_cb, cache_nonce_addr);
+                         cache_nonce_status_cb, &cn_parm);
   if (err)
     {
       xfree (get_membuf (&data, &len));
@@ -1625,7 +1643,7 @@
    displayed if the agent needs to ask for the PIN.  DIGEST and
    DIGESTLEN is the hash value to sign and DIGESTALGO the algorithm id
    used to compute the digest.  If CACHE_NONCE is used the agent is
-   advised to firts try a passphrase associated with that nonce. */
+   advised to first try a passphrase associated with that nonce. */
 gpg_error_t
 agent_pksign (ctrl_t ctrl, const char *cache_nonce,
               const char *keygrip, const char *desc,
@@ -1890,6 +1908,7 @@
 {
   gpg_error_t err;
   struct import_key_parm_s parm;
+  struct cache_nonce_parm_s cn_parm;
   char line[ASSUAN_LINELENGTH];
 
   err = start_agent (ctrl, 0);
@@ -1914,9 +1933,11 @@
   snprintf (line, sizeof line, "IMPORT_KEY%s%s",
             cache_nonce_addr && *cache_nonce_addr? " ":"",
             cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"");
+  cn_parm.cache_nonce_addr = cache_nonce_addr;
+  cn_parm.passwd_nonce_addr = NULL;
   err = assuan_transact (agent_ctx, line,
                          NULL, NULL, inq_import_key_parms, &parm,
-                         cache_nonce_status_cb, cache_nonce_addr);
+                         cache_nonce_status_cb, &cn_parm);
   return err;
 }
 
@@ -1932,6 +1953,7 @@
                   unsigned char **r_result, size_t *r_resultlen)
 {
   gpg_error_t err;
+  struct cache_nonce_parm_s cn_parm;
   membuf_t data;
   size_t len;
   unsigned char *buf;
@@ -1958,10 +1980,12 @@
             hexkeygrip);
 
   init_membuf_secure (&data, 1024);
+  cn_parm.cache_nonce_addr = cache_nonce_addr;
+  cn_parm.passwd_nonce_addr = NULL;
   err = assuan_transact (agent_ctx, line,
                          membuf_data_cb, &data, 
                          default_inq_cb, ctrl,
-                         cache_nonce_status_cb, cache_nonce_addr);
+                         cache_nonce_status_cb, &cn_parm);
   if (err)
     {
       xfree (get_membuf (&data, &len));
@@ -1974,3 +1998,49 @@
   *r_resultlen = len;
   return 0;
 }
+
+
+
+/* Ask the agent to change the passphrase of the key identified by
+   HEXKEYGRIP.  If DESC is not NULL, display DESC instead of the
+   default description message.  If CACHE_NONCE_ADDR is not NULL the
+   agent is advised to first try a passphrase associated with that
+   nonce.  If PASSWD_NONCE_ADDR is not NULL the agent will try to use
+   the passphrase associated with that nonce.  */
+gpg_error_t
+agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
+              char **cache_nonce_addr, char **passwd_nonce_addr)
+{
+  gpg_error_t err;
+  struct cache_nonce_parm_s cn_parm;
+  char line[ASSUAN_LINELENGTH];
+
+  err = start_agent (ctrl, 0);
+  if (err)
+    return err;
+
+  if (!hexkeygrip || strlen (hexkeygrip) != 40)
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  if (desc)
+    {
+      snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
+      err = assuan_transact (agent_ctx, line,
+                             NULL, NULL, NULL, NULL, NULL, NULL);
+      if (err)
+        return err;
+    }
+
+  snprintf (line, DIM(line)-1, "PASSWD %s%s %s%s %s",
+            cache_nonce_addr && *cache_nonce_addr? "--cache-nonce=":"",
+            cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"",
+            passwd_nonce_addr && *passwd_nonce_addr? "--passwd-nonce=":"",
+            passwd_nonce_addr && *passwd_nonce_addr? *passwd_nonce_addr:"",
+            hexkeygrip);
+  cn_parm.cache_nonce_addr = cache_nonce_addr;
+  cn_parm.passwd_nonce_addr = passwd_nonce_addr;
+  err = assuan_transact (agent_ctx, line, NULL, NULL,
+                         default_inq_cb, ctrl,
+                         cache_nonce_status_cb, &cn_parm);
+  return err;
+}

Modified: trunk/g10/call-agent.h
===================================================================
--- trunk/g10/call-agent.h	2010-10-22 07:35:30 UTC (rev 5466)
+++ trunk/g10/call-agent.h	2010-10-26 09:10:29 UTC (rev 5467)
@@ -184,6 +184,9 @@
                               const char *desc, char **cache_nonce_addr,
                               unsigned char **r_result, size_t *r_resultlen);
 
+/* Change the passphrase of a key.  */
+gpg_error_t agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
+                          char **cache_nonce_addr, char **passwd_nonce_addr);
 
+
 #endif /*GNUPG_G10_CALL_AGENT_H*/
-

Modified: trunk/g10/gpg.c
===================================================================
--- trunk/g10/gpg.c	2010-10-22 07:35:30 UTC (rev 5466)
+++ trunk/g10/gpg.c	2010-10-26 09:10:29 UTC (rev 5467)
@@ -3657,7 +3657,7 @@
         else
           {
             username = make_username (fname);
-            keyedit_passwd (username);
+            keyedit_passwd (ctrl, username);
             xfree (username);
           }
         break;

Modified: trunk/g10/keyedit.c
===================================================================
--- trunk/g10/keyedit.c	2010-10-22 07:35:30 UTC (rev 5466)
+++ trunk/g10/keyedit.c	2010-10-26 09:10:29 UTC (rev 5467)
@@ -30,6 +30,7 @@
 # include <readline/readline.h>
 #endif
 
+#define JNLIB_NEED_LOG_LOGV
 #include "gpg.h"
 #include "options.h"
 #include "packet.h"
@@ -1124,44 +1125,63 @@
 
 
 /*
- * Change the passphrase of the primary and all secondary keys.
- * We use only one passphrase for all keys.
+ * Change the passphrase of the primary and all secondary keys.  Note
+ * that it is common to use only one passphrase for the primary and
+ * all subkeys.  However, this is now (since GnuPG 2.1) all up to the
+ * gpg-agent.  Returns 0 on success or an error code.
  */
-static int
-change_passphrase (KBNODE keyblock, int *r_err)
+static gpg_error_t
+change_passphrase (ctrl_t ctrl, kbnode_t keyblock)
 {
-  int rc = 0;
-  int changed = 0;
-  KBNODE node;
-  PKT_public_key *pksk;
-  char *passphrase = NULL;
-  int no_primary_secrets = 0;
+  gpg_error_t err;
+  kbnode_t node;
+  PKT_public_key *pk;
   int any;
+  u32 keyid[2], subid[2];
+  char *hexgrip = NULL;
+  char *cache_nonce = NULL;
+  char *passwd_nonce = NULL;
 
   node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
   if (!node)
     {
       log_error ("Oops; public key missing!\n");
+      err = gpg_error (GPG_ERR_INTERNAL);
       goto leave;
     }
-  pksk = node->pkt->pkt.public_key;
+  pk = node->pkt->pkt.public_key;
+  keyid_from_pk (pk, keyid);
 
+  /* Check whether it is likely that we will be able to change the
+     passphrase for any subkey.  */
   for (any = 0, node = keyblock; node; node = node->next)
     {
       if (node->pkt->pkttype == PKT_PUBLIC_KEY
 	  || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
 	{
-          log_debug ("FIXME\n");
-	  /* PKT_public_key *tmpsk = node->pkt->pkt.public_key; */
-	  /* if (!(tmpsk->is_protected */
-	  /*       && (tmpsk->protect.s2k.mode == 1001 */
-	  /*           || tmpsk->protect.s2k.mode == 1002))) */
-	  /*   { */
-	  /*     any = 1; */
-	  /*     break; */
-	  /*   } */
+          char *serialno;
+
+          pk = node->pkt->pkt.public_key;
+          keyid_from_pk (pk, subid);
+          
+          xfree (hexgrip);
+          err = hexkeygrip_from_pk (pk, &hexgrip);
+          if (err)
+            goto leave;
+          err = agent_get_keyinfo (ctrl, hexgrip, &serialno);
+          if (!err && serialno)
+            ; /* Key on card.  */
+          else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
+            ; /* Maybe stub key. */
+          else if (!err)
+            any = 1; /* Key is known.  */
+          else
+            log_error ("key %s: error getting keyinfo from agent: %s\n",
+                       keystr_with_sub (keyid, subid), gpg_strerror (err));
+          xfree (serialno);
 	}
     }
+  err = 0;
   if (!any)
     {
       tty_printf (_("Key has only stub or on-card key items - "
@@ -1169,162 +1189,43 @@
       goto leave;
     }
 
-          log_debug ("FIXME\n");
-  /* See how to handle this key.  */
-  /* switch (is_secret_key_protected (pksk)) */
-  /*   { */
-  /*   case -1: */
-  /*     rc = G10ERR_PUBKEY_ALGO; */
-  /*     break; */
-  /*   case 0: */
-  /*     tty_printf (_("This key is not protected.\n")); */
-  /*     break; */
-  /*   default: */
-  /*     if (sk->protect.s2k.mode == 1001) */
-  /*       { */
-  /*         tty_printf (_("Secret parts of key are not available.\n")); */
-  /*         no_primary_secrets = 1; */
-  /*       } */
-  /*     else if (sk->protect.s2k.mode == 1002) */
-  /*       { */
-  /*         tty_printf (_("Secret parts of key are stored on-card.\n")); */
-  /*         no_primary_secrets = 1; */
-  /*       } */
-  /*     else */
-  /*       { */
-  /*         u32 keyid[2]; */
-
-  /*         tty_printf (_("Key is protected.\n")); */
-
-  /*         /\* Clear the passphrase cache so that the user is required */
-  /*            to enter the old passphrase.  *\/ */
-  /*         keyid_from_pk (pksk, keyid); */
-  /*         passphrase_clear_cache (keyid, NULL, 0); */
-
-  /*         /\* rc = check_secret_key( sk, 0 ); *\/ */
-  /*         /\* if( !rc ) *\/ */
-  /*         /\*     passphrase = get_last_passphrase(); *\/ */
-  /*       } */
-  /*     break; */
-  /*   } */
-
-  /* Unprotect all subkeys (use the supplied passphrase or ask) */
-  for (node = keyblock; !rc && node; node = node->next)
+  /* Change the passphrase for all keys.  */
+  for (any = 0, node = keyblock; node; node = node->next)
     {
-      if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
-	{
-          log_debug ("FIXME\n");
-	  /* PKT_pubic_key *subsk = node->pkt->pkt.public_key; */
-	  /* if (!(subsk->is_protected */
-	  /*       && (subsk->protect.s2k.mode == 1001 */
-	  /*           || subsk->protect.s2k.mode == 1002))) */
-	  /*   { */
-	  /*     set_next_passphrase (passphrase); */
-	  /*     /\* rc = check_secret_key( subsk, 0 ); *\/ */
-	  /*     /\* if( !rc && !passphrase ) *\/ */
-	  /*     /\*     passphrase = get_last_passphrase(); *\/ */
-	  /*   } */
-	}
-    }
+      if (node->pkt->pkttype == PKT_PUBLIC_KEY
+	  || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
+        { 
+          char *desc;
 
-  if (rc)
-    tty_printf (_("Can't edit this key: %s\n"), g10_errstr (rc));
-  else
-    {
-      DEK *dek = NULL;
-      STRING2KEY *s2k = xmalloc_secure (sizeof *s2k);
-      const char *errtext = NULL;
+          pk = node->pkt->pkt.public_key;
+          keyid_from_pk (pk, subid);
 
-      tty_printf (_("Enter the new passphrase for this secret key.\n\n"));
-
-      set_next_passphrase (NULL);
-      for (;;)
-	{
-	  int canceled;
-
-	  s2k->mode = opt.s2k_mode;
-	  s2k->hash_algo = S2K_DIGEST_ALGO;
-	  dek = passphrase_to_dek (NULL, 0, opt.s2k_cipher_algo,
-				   s2k, 2, errtext, &canceled);
-	  if (!dek && canceled)
-	    {
-	      rc = GPG_ERR_CANCELED;
-	      break;
-	    }
-	  else if (!dek)
-	    {
-	      errtext = N_("passphrase not correctly repeated; try again");
-	      tty_printf ("%s.\n", _(errtext));
-	    }
-	  else if (!dek->keylen)
-	    {
-	      rc = 0;
-	      tty_printf (_("You don't want a passphrase -"
-			    " this is probably a *bad* idea!\n\n"));
-	      if (cpr_get_answer_is_yes 
-                  ("change_passwd.empty.okay",
-                   _("Do you really want to do this? (y/N) ")))
-		{
-		  changed++;
-		  break;
-		}
-	    }
-	  else
-	    {			/* okay */
-	      rc = 0;
-	      if (!no_primary_secrets)
-		{
-		  /* sk->protect.algo = dek->algo; */
-		  /* sk->protect.s2k = *s2k; */
-		  rc = 0;
-		  /* rc = protect_secret_key( sk, dek ); */
-		}
-	      for (node = keyblock; !rc && node; node = node->next)
-		{
-		  if (node->pkt->pkttype == PKT_SECRET_SUBKEY)
-		    {
-                      log_debug ("FIXME\n");
-/* 		      PKT_secret_key *subsk = node->pkt->pkt.secret_key; */
-/* 		      if (!(subsk->is_protected */
-/* 			    && (subsk->protect.s2k.mode == 1001 */
-/* 				|| subsk->protect.s2k.mode == 1002))) */
-/* 			{ */
-/* 			  subsk->protect.algo = dek->algo; */
-/* 			  subsk->protect.s2k = *s2k; */
-/* #warning fixme */
-/* 			  rc = 0; */
-/* 			  /\* rc = protect_secret_key( subsk, dek ); *\/ */
-/* 			} */
-		    }
-		}
-	      if (rc)
-		log_error ("protect_secret_key failed: %s\n",
-			   g10_errstr (rc));
-	      else
-		{
-		  u32 keyid[2];
-
-		  /* Clear the cahce again so that the user is
-		     required to enter the new passphrase at the
-		     next operation.  */
-		  /* FIXME keyid_from_sk (sk, keyid); */
-		  passphrase_clear_cache (keyid, NULL, 0);
-
-		  changed++;
-		}
-	      break;
-	    }
-	}
-      xfree (s2k);
-      xfree (dek);
+          xfree (hexgrip);
+          err = hexkeygrip_from_pk (pk, &hexgrip);
+          if (err)
+            goto leave;
+          
+          desc = gpg_format_keydesc (pk, 0, 1);
+          err = agent_passwd (ctrl, hexgrip, desc, &cache_nonce, &passwd_nonce);
+          xfree (desc);
+        
+          if (err)
+            log_log ((gpg_err_code (err) == GPG_ERR_CANCELED
+                      || gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
+                     ? JNLIB_LOG_INFO : JNLIB_LOG_ERROR,
+                     _("key %s: error changing passphrase: %s\n"),
+                       keystr_with_sub (keyid, subid),
+                       gpg_strerror (err));
+          if (gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
+            break;
+        }
     }
 
-leave:
-  xfree (passphrase);
-  set_next_passphrase (NULL);
-  if (r_err)
-    *r_err = rc;
-  return changed && !rc;
+ leave:
+  xfree (hexgrip);
+  xfree (cache_nonce);
+  xfree (passwd_nonce);
+  return err;
 }
 
 
@@ -2184,7 +2085,7 @@
 	  break;
 
 	case cmdPASSWD:
-	  change_passphrase (keyblock, NULL);
+	  change_passphrase (ctrl, keyblock);
 	  break;
 
 	case cmdTRUST:
@@ -2361,13 +2262,10 @@
 
 /* Change the passphrase of the secret key identified by USERNAME.  */
 void
-keyedit_passwd (const char *username)
+keyedit_passwd (ctrl_t ctrl, const char *username)
 {
   gpg_error_t err;
   PKT_public_key *pk;
-  unsigned char fpr[MAX_FINGERPRINT_LEN];
-  size_t fprlen;
-  KEYDB_HANDLE kdh = NULL;
   kbnode_t keyblock = NULL;
 
   pk = xtrycalloc (1, sizeof *pk);
@@ -2376,44 +2274,16 @@
       err = gpg_error_from_syserror ();
       goto leave;
     }
-  err = getkey_byname (NULL, pk, username, 1, NULL);
+  err = getkey_byname (NULL, pk, username, 1, &keyblock);
   if (err)
     goto leave;
-  fingerprint_from_pk (pk, fpr, &fprlen);
-  while (fprlen < MAX_FINGERPRINT_LEN)
-    fpr[fprlen++] = 0;
 
-  /* FIXME: Call an agent function instead.  */
+  err = change_passphrase (ctrl, keyblock);
 
-  kdh = NULL /*keydb_new (1)*/;
-   if (!kdh)
-    {
-      err = gpg_error (GPG_ERR_GENERAL);
-      goto leave;
-    }
-
-  err = keydb_search_fpr (kdh, fpr);
-  if (err == -1 || gpg_err_code (err) == GPG_ERR_EOF)
-    err = gpg_error (GPG_ERR_NO_SECKEY);
-  if (err)
-    goto leave;
-
-  err = keydb_get_keyblock (kdh, &keyblock);
-  if (err)
-    goto leave;
-
-  if (!change_passphrase (keyblock, &err))
-    goto leave;
-
-  err = keydb_update_keyblock (kdh, keyblock);
-  if (err)
-    log_error (_("update secret failed: %s\n"), gpg_strerror (err));
-
 leave:
   release_kbnode (keyblock);
   if (pk)
     free_public_key (pk);
-  keydb_release (kdh);
   if (err)
     {
       log_info ("error changing the passphrase for `%s': %s\n",

Modified: trunk/g10/main.h
===================================================================
--- trunk/g10/main.h	2010-10-22 07:35:30 UTC (rev 5466)
+++ trunk/g10/main.h	2010-10-26 09:10:29 UTC (rev 5467)
@@ -224,7 +224,7 @@
 /*-- keyedit.c --*/
 void keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
 		   strlist_t commands, int quiet, int seckey_check );
-void keyedit_passwd (const char *username);
+void keyedit_passwd (ctrl_t ctrl, const char *username);
 void show_basic_key_info (KBNODE keyblock);
 
 /*-- keygen.c --*/

Modified: trunk/g10/passphrase.c
===================================================================
--- trunk/g10/passphrase.c	2010-10-22 07:35:30 UTC (rev 5466)
+++ trunk/g10/passphrase.c	2010-10-26 09:10:29 UTC (rev 5467)
@@ -675,7 +675,7 @@
 }
 
 
-/* Return an allocated utf-8 string describing the key PK.  IF ESCAPED
+/* Return an allocated utf-8 string describing the key PK.  If ESCAPED
    is true spaces and control characters are percent or plus escaped.
    MODE 0 is for the common prompt, MODE 1 for the import prompt. */
 char *
@@ -696,9 +696,9 @@
 
   orig_codeset = i18n_switchto_utf8 ();
 
-  if (pk->main_keyid[2] && pk->main_keyid[3]
-      && pk->keyid[0] != pk->main_keyid[2] 
-      && pk->keyid[1] != pk->main_keyid[3])
+  if (pk->main_keyid[0] && pk->main_keyid[1]
+      && pk->keyid[0] != pk->main_keyid[0] 
+      && pk->keyid[1] != pk->main_keyid[1])
     maink = xtryasprintf (_(" (main key ID %s)"), keystr (pk->main_keyid));
   else
     maink = NULL;

Modified: trunk/po/de.po  [not shown]
Modified: trunk/sm/server.c
===================================================================
--- trunk/sm/server.c	2010-10-22 07:35:30 UTC (rev 5466)
+++ trunk/sm/server.c	2010-10-26 09:10:29 UTC (rev 5467)
@@ -163,7 +163,9 @@
 {
   if (ctrl->server_local->message_fd != -1)
     {
+#ifdef HAVE_W32CE_SYSTEM
 #warning Is this correct for W32/W32CE?
+#endif
       close (ctrl->server_local->message_fd);
       ctrl->server_local->message_fd = -1;
     }





More information about the Gnupg-commits mailing list