* gpgsm.c: New command --keydb-clear-some-cert-flags.
[gnupg.git] / sm / call-agent.c
index fe74096..2e8c754 100644 (file)
@@ -34,6 +34,7 @@
 #include <gcrypt.h>
 #include <assuan.h>
 #include "i18n.h"
+#include "asshelp.h"
 #include "keydb.h" /* fixme: Move this to import.c */
 #include "../common/membuf.h"
 
@@ -64,24 +65,19 @@ struct learn_parm_s {
 /* Try to connect to the agent via socket or fork it off and work by
    pipes.  Handle the server's initial greeting */
 static int
-start_agent (void)
+start_agent (ctrl_t ctrl)
 {
   int rc = 0;
   char *infostr, *p;
-  ASSUAN_CONTEXT ctx;
-  char *dft_display = NULL;
-  char *dft_ttyname = NULL;
-  char *dft_ttytype = NULL;
-  char *old_lc = NULL;
-  char *dft_lc = NULL;
+  assuan_context_t ctx;
 
   if (agent_ctx)
     return 0; /* fixme: We need a context for each thread or serialize
                  the access to the agent (which is suitable given that
-                 the agent is not MT */
+                 the agent is not MT. */
 
   infostr = force_pipe_server? NULL : getenv ("GPG_AGENT_INFO");
-  if (!infostr)
+  if (!infostr || !*infostr)
     {
       const char *pgmname;
       const char *argv[3];
@@ -90,6 +86,8 @@ start_agent (void)
 
       if (opt.verbose)
         log_info (_("no running gpg-agent - starting one\n"));
+      
+      gpgsm_status (ctrl, STATUS_PROGRESS, "starting_agent ? 0 0");
 
       if (fflush (NULL))
         {
@@ -130,7 +128,7 @@ start_agent (void)
           log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
           xfree (infostr);
           force_pipe_server = 1;
-          return start_agent ();
+          return start_agent (ctrl);
         }
       *p++ = 0;
       pid = atoi (p);
@@ -143,7 +141,7 @@ start_agent (void)
                      prot);
           xfree (infostr);
           force_pipe_server = 1;
-          return start_agent ();
+          return start_agent (ctrl);
         }
 
       rc = assuan_socket_connect (&ctx, infostr, pid);
@@ -152,7 +150,7 @@ start_agent (void)
         {
           log_error (_("can't connect to the agent - trying fall back\n"));
           force_pipe_server = 1;
-          return start_agent ();
+          return start_agent (ctrl);
         }
     }
 
@@ -170,118 +168,9 @@ start_agent (void)
   if (rc)
     return map_assuan_err (rc);
 
-  dft_display = getenv ("DISPLAY");
-  if (opt.display || dft_display)
-    {
-      char *optstr;
-      if (asprintf (&optstr, "OPTION display=%s",
-                   opt.display ? opt.display : dft_display) < 0)
-       return OUT_OF_CORE (errno);
-      rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
-                           NULL);
-      free (optstr);
-      if (rc)
-       return map_assuan_err (rc);
-    }
-  if (!opt.ttyname)
-    {
-      dft_ttyname = getenv ("GPG_TTY");
-      if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
-        dft_ttyname = ttyname (0);
-    }
-  if (opt.ttyname || dft_ttyname)
-    {
-      char *optstr;
-      if (asprintf (&optstr, "OPTION ttyname=%s",
-                   opt.ttyname ? opt.ttyname : dft_ttyname) < 0)
-       return OUT_OF_CORE (errno);
-      rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
-                           NULL);
-      free (optstr);
-      if (rc)
-       return map_assuan_err (rc);
-    }
-  dft_ttytype = getenv ("TERM");
-  if (opt.ttytype || (dft_ttyname && dft_ttytype))
-    {
-      char *optstr;
-      if (asprintf (&optstr, "OPTION ttytype=%s",
-                   opt.ttyname ? opt.ttytype : dft_ttytype) < 0)
-       return OUT_OF_CORE (errno);
-      rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
-                           NULL);
-      free (optstr);
-      if (rc)
-       return map_assuan_err (rc);
-    }
-#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
-  old_lc = setlocale (LC_CTYPE, NULL);
-  if (old_lc)
-    {
-      old_lc = strdup (old_lc);
-      if (!old_lc)
-        return OUT_OF_CORE (errno);
-    }
-  dft_lc = setlocale (LC_CTYPE, "");
-#endif
-  if (opt.lc_ctype || (dft_ttyname && dft_lc))
-    {
-      char *optstr;
-      if (asprintf (&optstr, "OPTION lc-ctype=%s",
-                   opt.lc_ctype ? opt.lc_ctype : dft_lc) < 0)
-       rc = OUT_OF_CORE (errno);
-      else
-       {
-         rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
-                               NULL);
-         free (optstr);
-         if (rc)
-           rc = map_assuan_err (rc);
-       }
-    }
-#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
-  if (old_lc)
-    {
-      setlocale (LC_CTYPE, old_lc);
-      free (old_lc);
-    }
-#endif
-  if (rc)
-    return rc;
-#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
-  old_lc = setlocale (LC_MESSAGES, NULL);
-  if (old_lc)
-    {
-      old_lc = strdup (old_lc);
-      if (!old_lc)
-        return OUT_OF_CORE (errno);
-    }
-  dft_lc = setlocale (LC_MESSAGES, "");
-#endif
-  if (opt.lc_messages || (dft_ttyname && dft_lc))
-    {
-      char *optstr;
-      if (asprintf (&optstr, "OPTION lc-messages=%s",
-                   opt.lc_messages ? opt.lc_messages : dft_lc) < 0)
-       rc = OUT_OF_CORE (errno);
-      else
-       {
-         rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
-                               NULL);
-         free (optstr);
-         if (rc)
-           rc = map_assuan_err (rc);
-       }
-    }
-#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
-  if (old_lc)
-    {
-      setlocale (LC_MESSAGES, old_lc);
-      free (old_lc);
-    }
-#endif
-
-  return rc;
+  return send_pinentry_environment (agent_ctx,
+                                    opt.display, opt.ttyname, opt.ttytype,
+                                    opt.lc_ctype, opt.lc_messages);
 }
 
 
@@ -301,7 +190,7 @@ membuf_data_cb (void *opaque, const void *buffer, size_t length)
 /* Call the agent to do a sign operation using the key identified by
    the hex string KEYGRIP. */
 int
-gpgsm_agent_pksign (const char *keygrip,
+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 )
 {
@@ -311,7 +200,7 @@ gpgsm_agent_pksign (const char *keygrip,
   size_t len;
 
   *r_buf = NULL;
-  rc = start_agent ();
+  rc = start_agent (ctrl);
   if (rc)
     return rc;
 
@@ -328,6 +217,16 @@ gpgsm_agent_pksign (const char *keygrip,
   if (rc)
     return map_assuan_err (rc);
 
+  if (desc)
+    {
+      snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
+      line[DIM(line)-1] = 0;
+      rc = assuan_transact (agent_ctx, line,
+                            NULL, NULL, NULL, NULL, NULL, NULL);
+      if (rc)
+        return map_assuan_err (rc);
+    }
+
   sprintf (line, "SETHASH %d ", digestalgo);
   p = line + strlen (line);
   for (i=0; i < digestlen ; i++, p += 2 )
@@ -376,7 +275,7 @@ inq_ciphertext_cb (void *opaque, const char *keyword)
 /* Call the agent to do a decrypt operation using the key identified by
    the hex string KEYGRIP. */
 int
-gpgsm_agent_pkdecrypt (const char *keygrip,
+gpgsm_agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
                        ksba_const_sexp_t ciphertext, 
                        char **r_buf, size_t *r_buflen )
 {
@@ -396,7 +295,7 @@ gpgsm_agent_pkdecrypt (const char *keygrip,
   if (!ciphertextlen)
     return gpg_error (GPG_ERR_INV_VALUE);
 
-  rc = start_agent ();
+  rc = start_agent (ctrl);
   if (rc)
     return rc;
 
@@ -411,6 +310,16 @@ gpgsm_agent_pkdecrypt (const char *keygrip,
   if (rc)
     return map_assuan_err (rc);
 
+  if (desc)
+    {
+      snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
+      line[DIM(line)-1] = 0;
+      rc = assuan_transact (agent_ctx, line,
+                            NULL, NULL, NULL, NULL, NULL, NULL);
+      if (rc)
+        return map_assuan_err (rc);
+    }
+
   init_membuf (&data, 1024);
   cipher_parm.ctx = agent_ctx;
   cipher_parm.ciphertext = ciphertext;
@@ -464,7 +373,8 @@ inq_genkey_parms (void *opaque, const char *keyword)
 \f
 /* Call the agent to generate a newkey */
 int
-gpgsm_agent_genkey (ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey)
+gpgsm_agent_genkey (ctrl_t ctrl,
+                    ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey)
 {
   int rc;
   struct genkey_parm_s gk_parm;
@@ -473,7 +383,7 @@ gpgsm_agent_genkey (ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey)
   char *buf;
 
   *r_pubkey = NULL;
-  rc = start_agent ();
+  rc = start_agent (ctrl);
   if (rc)
     return rc;
 
@@ -511,13 +421,13 @@ gpgsm_agent_genkey (ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey)
 /* Ask the agent whether the certificate is in the list of trusted
    keys */
 int
-gpgsm_agent_istrusted (ksba_cert_t cert)
+gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert)
 {
   int rc;
   char *fpr;
   char line[ASSUAN_LINELENGTH];
 
-  rc = start_agent ();
+  rc = start_agent (ctrl);
   if (rc)
     return rc;
 
@@ -538,13 +448,13 @@ gpgsm_agent_istrusted (ksba_cert_t cert)
 
 /* Ask the agent to mark CERT as a trusted Root-CA one */
 int
-gpgsm_agent_marktrusted (ksba_cert_t cert)
+gpgsm_agent_marktrusted (ctrl_t ctrl, ksba_cert_t cert)
 {
   int rc;
   char *fpr, *dn;
   char line[ASSUAN_LINELENGTH];
 
-  rc = start_agent ();
+  rc = start_agent (ctrl);
   if (rc)
     return rc;
 
@@ -575,12 +485,12 @@ gpgsm_agent_marktrusted (ksba_cert_t cert)
 /* Ask the agent whether the a corresponding secret key is available
    for the given keygrip */
 int
-gpgsm_agent_havekey (const char *hexkeygrip)
+gpgsm_agent_havekey (ctrl_t ctrl, const char *hexkeygrip)
 {
   int rc;
   char line[ASSUAN_LINELENGTH];
 
-  rc = start_agent ();
+  rc = start_agent (ctrl);
   if (rc)
     return rc;
 
@@ -665,14 +575,14 @@ learn_cb (void *opaque, const void *buffer, size_t length)
   
 /* Call the agent to learn about a smartcard */
 int
-gpgsm_agent_learn ()
+gpgsm_agent_learn (ctrl_t ctrl)
 {
   int rc;
   struct learn_parm_s learn_parm;
   membuf_t data;
   size_t len;
 
-  rc = start_agent ();
+  rc = start_agent (ctrl);
   if (rc)
     return rc;
 
@@ -690,20 +600,32 @@ gpgsm_agent_learn ()
 }
 
 \f
-/* Ask the agent to change the passphrase of the key identified by HEXKEYGRIP. */
+/* Ask the agent to change the passphrase of the key identified by
+   HEXKEYGRIP. If DESC is not NULL, display instead of the default
+   description message. */
 int
-gpgsm_agent_passwd (const char *hexkeygrip)
+gpgsm_agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc)
 {
   int rc;
   char line[ASSUAN_LINELENGTH];
 
-  rc = start_agent ();
+  rc = start_agent (ctrl);
   if (rc)
     return rc;
 
   if (!hexkeygrip || strlen (hexkeygrip) != 40)
     return gpg_error (GPG_ERR_INV_VALUE);
 
+  if (desc)
+    {
+      snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
+      line[DIM(line)-1] = 0;
+      rc = assuan_transact (agent_ctx, line,
+                            NULL, NULL, NULL, NULL, NULL, NULL);
+      if (rc)
+        return map_assuan_err (rc);
+    }
+
   snprintf (line, DIM(line)-1, "PASSWD %s", hexkeygrip);
   line[DIM(line)-1] = 0;