Add Kludge for RegTP sillyness.
[gnupg.git] / sm / call-agent.c
index 3ea1c45..9942672 100644 (file)
@@ -1,5 +1,5 @@
 /* call-agent.c - divert operations to the agent
- *     Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ *     Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
 #include "../common/membuf.h"
 
 
-static ASSUAN_CONTEXT agent_ctx = NULL;
+static assuan_context_t agent_ctx = NULL;
 static int force_pipe_server = 0;
 
-struct cipher_parm_s {
-  ASSUAN_CONTEXT ctx;
-  const char *ciphertext;
+struct cipher_parm_s
+{
+  assuan_context_t ctx;
+  const unsigned char *ciphertext;
   size_t ciphertextlen;
 };
 
-struct genkey_parm_s {
-  ASSUAN_CONTEXT ctx;
-  const char *sexp;
+struct genkey_parm_s
+{
+  assuan_context_t ctx;
+  const unsigned char *sexp;
   size_t sexplen;
 };
 
-struct learn_parm_s {
+struct learn_parm_s
+{
   int error;
-  ASSUAN_CONTEXT ctx;
+  assuan_context_t ctx;
   membuf_t *data;
 };
 
@@ -81,41 +84,53 @@ start_agent (ctrl_t ctrl)
     {
       const char *pgmname;
       const char *argv[3];
+      char *sockname;
       int no_close_list[3];
       int i;
 
-      if (opt.verbose)
-        log_info (_("no running gpg-agent - starting one\n"));
-      
-      gpgsm_status (ctrl, STATUS_PROGRESS, "starting_agent ? 0 0");
+      /* First check whether we can connect at the standard
+         socket.  */
+      sockname = make_filename (opt.homedir, "S.gpg-agent", NULL);
+      rc = assuan_socket_connect (&ctx, sockname, 0);
+      xfree (sockname);
 
-      if (fflush (NULL))
+      if (rc)
         {
-          gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
-          log_error ("error flushing pending output: %s\n", strerror (errno));
-          return tmperr;
+          /* With no success start a new server.  */
+          if (opt.verbose)
+            log_info (_("no running gpg-agent - starting one\n"));
+          
+          gpgsm_status (ctrl, STATUS_PROGRESS, "starting_agent ? 0 0");
+          
+          if (fflush (NULL))
+            {
+              gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
+              log_error ("error flushing pending output: %s\n",
+                         strerror (errno));
+              return tmperr;
+            }
+          
+          if (!opt.agent_program || !*opt.agent_program)
+            opt.agent_program = GNUPG_DEFAULT_AGENT;
+          if ( !(pgmname = strrchr (opt.agent_program, '/')))
+            pgmname = opt.agent_program;
+          else
+            pgmname++;
+
+          argv[0] = pgmname;
+          argv[1] = "--server";
+          argv[2] = NULL;
+
+          i=0;
+          if (log_get_fd () != -1)
+            no_close_list[i++] = log_get_fd ();
+          no_close_list[i++] = fileno (stderr);
+          no_close_list[i] = -1;
+
+          /* Connect to the agent and perform initial handshaking. */
+          rc = assuan_pipe_connect (&ctx, opt.agent_program, (char**)argv,
+                                    no_close_list);
         }
-
-      if (!opt.agent_program || !*opt.agent_program)
-        opt.agent_program = GNUPG_DEFAULT_AGENT;
-      if ( !(pgmname = strrchr (opt.agent_program, '/')))
-        pgmname = opt.agent_program;
-      else
-        pgmname++;
-
-      argv[0] = pgmname;
-      argv[1] = "--server";
-      argv[2] = NULL;
-
-      i=0;
-      if (log_get_fd () != -1)
-        no_close_list[i++] = log_get_fd ();
-      no_close_list[i++] = fileno (stderr);
-      no_close_list[i] = -1;
-
-      /* Connect to the agent and perform initial handshaking. */
-      rc = assuan_pipe_connect (&ctx, opt.agent_program, (char**)argv,
-                                no_close_list);
     }
   else
     {
@@ -123,7 +138,7 @@ start_agent (ctrl_t ctrl)
       int pid;
 
       infostr = xstrdup (infostr);
-      if ( !(p = strchr (infostr, ':')) || p == infostr)
+      if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
         {
           log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
           xfree (infostr);
@@ -132,7 +147,7 @@ start_agent (ctrl_t ctrl)
         }
       *p++ = 0;
       pid = atoi (p);
-      while (*p && *p != ':')
+      while (*p && *p != PATHSEP_C)
         p++;
       prot = *p? atoi (p+1) : 0;
       if (prot != 1)
@@ -168,7 +183,7 @@ start_agent (ctrl_t ctrl)
   if (rc)
     return map_assuan_err (rc);
 
-  return send_pinentry_environment (agent_ctx,
+  return send_pinentry_environment (agent_ctx, GPG_ERR_SOURCE_DEFAULT,
                                     opt.display, opt.ttyname, opt.ttytype,
                                     opt.lc_ctype, opt.lc_messages);
 }
@@ -192,7 +207,7 @@ membuf_data_cb (void *opaque, const void *buffer, size_t length)
 int
 gpgsm_agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc,
                     unsigned char *digest, size_t digestlen, int digestalgo,
-                    char **r_buf, size_t *r_buflen )
+                    unsigned char **r_buf, size_t *r_buflen )
 {
   int rc, i;
   char *p, line[ASSUAN_LINELENGTH];
@@ -380,7 +395,7 @@ gpgsm_agent_genkey (ctrl_t ctrl,
   struct genkey_parm_s gk_parm;
   membuf_t data;
   size_t len;
-  char *buf;
+  unsigned char *buf;
 
   *r_pubkey = NULL;
   rc = start_agent (ctrl);
@@ -418,6 +433,51 @@ gpgsm_agent_genkey (ctrl_t ctrl,
 }
 
 \f
+/* Call the agent to read the public key part for a given keygrip.  */
+int
+gpgsm_agent_readkey (ctrl_t ctrl, const char *hexkeygrip,
+                     ksba_sexp_t *r_pubkey)
+{
+  int rc;
+  membuf_t data;
+  size_t len;
+  unsigned char *buf;
+  char line[ASSUAN_LINELENGTH];
+
+  *r_pubkey = NULL;
+  rc = start_agent (ctrl);
+  if (rc)
+    return rc;
+
+  rc = assuan_transact (agent_ctx, "RESET",NULL, NULL, NULL, NULL, NULL, NULL);
+  if (rc)
+    return map_assuan_err (rc);
+
+  snprintf (line, DIM(line)-1, "READKEY %s", hexkeygrip);
+  line[DIM(line)-1] = 0;
+
+  init_membuf (&data, 1024);
+  rc = assuan_transact (agent_ctx, line,
+                        membuf_data_cb, &data, 
+                        NULL, NULL, NULL, NULL);
+  if (rc)
+    {
+      xfree (get_membuf (&data, &len));
+      return map_assuan_err (rc);
+    }
+  buf = get_membuf (&data, &len);
+  if (!buf)
+    return gpg_error (GPG_ERR_ENOMEM);
+  if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
+    {
+      xfree (buf);
+      return gpg_error (GPG_ERR_INV_SEXP);
+    }
+  *r_pubkey = buf;
+  return 0;
+}
+
+\f
 /* Ask the agent whether the certificate is in the list of trusted
    keys */
 int
@@ -633,3 +693,23 @@ gpgsm_agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc)
   return map_assuan_err (rc);
 }
 
+
+\f
+/* Ask the agent to pop up a confirmation dialog with the text DESC
+   and an okay and cancel button.  */
+gpg_error_t
+gpgsm_agent_get_confirmation (ctrl_t ctrl, const char *desc)
+{
+  int rc;
+  char line[ASSUAN_LINELENGTH];
+
+  rc = start_agent (ctrl);
+  if (rc)
+    return rc;
+
+  snprintf (line, DIM(line)-1, "GET_CONFIRMATION %s", desc);
+  line[DIM(line)-1] = 0;
+
+  rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
+  return map_assuan_err (rc);
+}