Enhanced last patch.
authorWerner Koch <wk@gnupg.org>
Tue, 17 Mar 2009 17:59:36 +0000 (17:59 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 17 Mar 2009 17:59:36 +0000 (17:59 +0000)
agent/ChangeLog
agent/command.c
g10/ChangeLog
g10/call-agent.c

index 635259d..25aa478 100644 (file)
@@ -1,6 +1,9 @@
 2009-03-17  Werner Koch  <wk@g10code.com>
 
        * command.c (cmd_get_passphrase): Break repeat loop on error.
+       Show error message.
+       (cmd_getinfo): Add subcommand "cmd_has_option".
+       (command_has_option): New.
 
 2009-03-17  Daiki Ueno  <ueno@unixuser.org>
 
index 9451f27..1f8febc 100644 (file)
@@ -105,6 +105,10 @@ struct
 } eventcounter;
 
 
+\f
+/*  Local prototypes.  */
+static int command_has_option (const char *cmd, const char *cmdopt);
+
 
 
 \f
@@ -1046,6 +1050,7 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
   char *p;
   void *cache_marker;
   int opt_data, opt_check, opt_no_ask, opt_repeat = 0;
+  char *repeat_errtext = NULL;
 
   opt_data = has_option (line, "--data");
   opt_check = has_option (line, "--check");
@@ -1125,7 +1130,10 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
         plus_to_blank (desc);
 
     next_try:
-      rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext);
+      rc = agent_get_passphrase (ctrl, &response, desc, prompt, 
+                                 repeat_errtext? repeat_errtext:errtext);
+      xfree (repeat_errtext);
+      repeat_errtext = NULL;
       if (!rc)
         {
           int i;
@@ -1147,6 +1155,13 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
                 {
                   xfree (response2);
                   xfree (response);
+                  repeat_errtext = try_percent_escape 
+                    (_("does not match - try again"), NULL);
+                  if (!repeat_errtext)
+                    {
+                      rc = gpg_error_from_syserror ();
+                      break;
+                    }
                   goto next_try;
                 }
               xfree (response2);
@@ -1599,6 +1614,9 @@ cmd_reloadagent (assuan_context_t ctx, char *line)
      socket_name - Return the name of the socket.
      ssh_socket_name - Return the name of the ssh socket.
      scd_running - Return OK if the SCdaemon is already running.
+
+     cmd_has_option CMD OPT
+                 - Returns OK if the command CMD implements the option OPT.
  */
 static int
 cmd_getinfo (assuan_context_t ctx, char *line)
@@ -1639,6 +1657,38 @@ cmd_getinfo (assuan_context_t ctx, char *line)
     {
       rc = agent_scd_check_running ()? 0 : gpg_error (GPG_ERR_GENERAL);
     }
+  else if (!strncmp (line, "cmd_has_option", 14)
+           && (line[14] == ' ' || line[14] == '\t' || !line[14]))
+    {
+      char *cmd, *cmdopt;
+      line += 14;
+      while (*line == ' ' || *line == '\t')
+        line++;
+      if (!*line)
+        rc = gpg_error (GPG_ERR_MISSING_VALUE);
+      else
+        {
+          cmd = line;
+          while (*line && (*line != ' ' && *line != '\t'))
+            line++;
+          if (!*line)
+            rc = gpg_error (GPG_ERR_MISSING_VALUE);
+          else
+            {
+              *line++ = 0;
+              while (*line == ' ' || *line == '\t')
+                line++;
+              if (!*line)
+                rc = gpg_error (GPG_ERR_MISSING_VALUE);
+              else
+                {
+                  cmdopt = line;
+                  if (!command_has_option (cmd, cmdopt))
+                    rc = gpg_error (GPG_ERR_GENERAL);
+                }
+            }
+        }
+    }
   else
     rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
   return rc;
@@ -1765,6 +1815,20 @@ io_monitor (assuan_context_t ctx, int direction,
 }
 
 
+/* Return true if the commznd CMD implements the option OPT.  */
+static int
+command_has_option (const char *cmd, const char *cmdopt)
+{
+  if (!strcmp (cmd, "GET_PASSPHRASE"))
+    {
+      if (!strcmp (cmdopt, "repeat"))
+          return 1;
+    }
+      
+  return 0;
+}
+
+
 /* Tell the assuan library about our commands */
 static int
 register_commands (assuan_context_t ctx)
index 3bb5bf9..959655f 100644 (file)
@@ -1,3 +1,8 @@
+2009-03-17  Werner Koch  <wk@g10code.com>
+
+       * call-agent.c (my_percent_plus_escape): Remove.
+       (agent_get_passphrase): Rewrite using percent_plus_escape.
+
 2009-03-17  Daiki Ueno  <ueno@unixuser.org>
 
        * passphrase.c (passphrase_get): Add extra arg REPEAT and adjust
index fb66602..b6c61aa 100644 (file)
@@ -144,29 +144,6 @@ unescape_status_string (const unsigned char *s)
   return buffer;
 }
 
-/* Copy the text ATEXT into the buffer P and do plus '+' and percent
-   escaping.  Note that the provided buffer needs to be 3 times the
-   size of ATEXT plus 1.  Returns a pointer to the leading Nul in P. */
-static char *
-my_percent_plus_escape (char *p, const char *atext)
-{
-  const unsigned char *s;
-
-  for (s=atext; *s; s++)
-    {
-      if (*s < ' ' || *s == '+' || *s == '%')
-        {
-          snprintf (p, 4, "%%%02X", *s);
-          p += 3;
-        }
-      else if (*s == ' ')
-        *p++ = '+';
-      else
-        *p++ = *s;
-    }
-  *p = 0;
-  return p;
-}
 
 /* Take a 20 byte hexencoded string and put it into the the provided
    20 byte buffer FPR in binary format. */
@@ -878,8 +855,11 @@ agent_get_passphrase (const char *cache_id,
                       char **r_passphrase)
 {
   int rc;
-  char *line, *p;
-  char cmd[] = "GET_PASSPHRASE --data --repeat=%d -- ";
+  char line[ASSUAN_LINELENGTH];
+  char *arg1 = NULL;
+  char *arg2 = NULL;  
+  char *arg3 = NULL; 
+  char *arg4 = NULL;
   membuf_t data;
 
   *r_passphrase = NULL;
@@ -888,41 +868,37 @@ agent_get_passphrase (const char *cache_id,
   if (rc)
     return rc;
 
-  /* We allocate 3 times the needed space for the texts so that
-     there is enough space for escaping. */
-  line = xtrymalloc ( strlen (cmd) + sizeof(repeat) + 1
-                      + (cache_id? 3*strlen (cache_id): 1) + 1
-                      + (err_msg?  3*strlen (err_msg): 1) + 1
-                      + (prompt?   3*strlen (prompt): 1) + 1
-                      + (desc_msg? 3*strlen (desc_msg): 1) + 1
-                      + 1);
-  if (!line)
-    return gpg_error_from_syserror ();
-
-  p = line + sprintf (line, cmd, repeat);
-  if (cache_id && *cache_id)
-    p = my_percent_plus_escape (p, cache_id);
-  else
-    *p++ = 'X';
-  *p++ = ' ';
+  /* Check that the gpg-agent understands the repeat option.  */
+  if (assuan_transact (agent_ctx, 
+                       "GETINFO cmd_has_option GET_PASSPHRASE repeat",
+                       NULL, NULL, NULL, NULL, NULL, NULL))
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
 
+  if (cache_id && *cache_id)
+    if (!(arg1 = percent_plus_escape (cache_id)))
+      goto no_mem;
   if (err_msg && *err_msg)
-    p = my_percent_plus_escape (p, err_msg);
-  else
-    *p++ = 'X';
-  *p++ = ' ';
-
+    if (!(arg2 = percent_plus_escape (err_msg)))
+      goto no_mem;
   if (prompt && *prompt)
-    p = my_percent_plus_escape (p, prompt);
-  else
-    *p++ = 'X'; 
-  *p++ = ' ';
-
+    if (!(arg3 = percent_plus_escape (prompt)))
+      goto no_mem;
   if (desc_msg && *desc_msg)
-    p = my_percent_plus_escape (p, desc_msg);
-  else
-    *p++ = 'X';
-  *p = 0;
+    if (!(arg4 = percent_plus_escape (desc_msg)))
+      goto no_mem;
+
+  snprintf (line, DIM(line)-1, 
+            "GET_PASSPHRASE --data --repeat=%d -- %s %s %s %s", 
+            repeat, 
+            arg1? arg1:"X",
+            arg2? arg2:"X",
+            arg3? arg3:"X",
+            arg4? arg4:"X");
+  line[DIM(line)-1] = 0;
+  xfree (arg1);
+  xfree (arg2);
+  xfree (arg3);
+  xfree (arg4);
 
   init_membuf_secure (&data, 64);
   rc = assuan_transact (agent_ctx, line, 
@@ -938,7 +914,13 @@ agent_get_passphrase (const char *cache_id,
       if (!*r_passphrase)
         rc = gpg_error_from_syserror ();
     }
-  xfree (line);
+  return rc;
+ no_mem:
+  rc = gpg_error_from_syserror ();
+  xfree (arg1);
+  xfree (arg2);
+  xfree (arg3);
+  xfree (arg4);
   return rc;
 }