po: Update Ukrainian translation
[gnupg.git] / tools / gpg-wks-client.c
index 1a53f39..c31e3a1 100644 (file)
@@ -23,6 +23,7 @@
 #include <string.h>
 
 #include "util.h"
+#include "status.h"
 #include "i18n.h"
 #include "sysutils.h"
 #include "init.h"
@@ -58,6 +59,7 @@ enum cmd_and_opt_values
     oGpgProgram,
     oSend,
     oFakeSubmissionAddr,
+    oStatusFD,
 
     oDummy
   };
@@ -86,6 +88,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_s (oGpgProgram, "gpg", "@"),
   ARGPARSE_s_n (oSend, "send", "send the mail using sendmail"),
   ARGPARSE_s_s (oOutput, "output", "|FILE|write the mail to FILE"),
+  ARGPARSE_s_i (oStatusFD, "status-fd", N_("|FD|write status info to this FD")),
 
   ARGPARSE_s_s (oFakeSubmissionAddr, "fake-submission-addr", "@"),
 
@@ -126,7 +129,7 @@ static gpg_error_t command_receive_cb (void *opaque,
 
 
 \f
-/* Print usage information and and provide strings for help. */
+/* Print usage information and provide strings for help. */
 static const char *
 my_strusage( int level )
 {
@@ -197,6 +200,9 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
         case oFakeSubmissionAddr:
           fake_submission_addr = pargs->r.ret_str;
           break;
+        case oStatusFD:
+          wks_set_status_fd (translate_sys2libc_fd_int (pargs->r.ret_int, 1));
+          break;
 
        case aSupported:
        case aCreate:
@@ -298,14 +304,21 @@ main (int argc, char **argv)
     case aCheck:
       if (argc != 1)
         wrong_args ("--check USER-ID");
-      command_check (argv[0]);
+      err = command_check (argv[0]);
       break;
 
     default:
       usage (1);
+      err = 0;
       break;
     }
 
+  if (err)
+    wks_write_status (STATUS_FAILURE, "- %u", err);
+  else if (log_get_errorcount (0))
+    wks_write_status (STATUS_FAILURE, "- %u", GPG_ERR_GENERAL);
+  else
+    wks_write_status (STATUS_SUCCESS, NULL);
   return log_get_errorcount (0)? 1:0;
 }
 
@@ -360,6 +373,7 @@ get_key (estream_t *r_key, const char *fingerprint, const char *addrspec)
       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
       goto leave;
     }
+
   /* Prefix the key with the MIME content type.  */
   es_fputs ("Content-Type: application/pgp-keys\n"
             "\n", key);
@@ -424,20 +438,38 @@ get_key (estream_t *r_key, const char *fingerprint, const char *addrspec)
 
 
 \f
+struct decrypt_stream_parm_s
+{
+  char *fpr;
+  char *mainfpr;
+  int  otrust;
+};
+
 static void
 decrypt_stream_status_cb (void *opaque, const char *keyword, char *args)
 {
-  (void)opaque;
+  struct decrypt_stream_parm_s *decinfo = opaque;
 
   if (DBG_CRYPTO)
     log_debug ("gpg status: %s %s\n", keyword, args);
-}
+  if (!strcmp (keyword, "DECRYPTION_KEY") && !decinfo->fpr)
+    {
+      char *fields[3];
 
+      if (split_fields (args, fields, DIM (fields)) >= 3)
+        {
+          decinfo->fpr = xstrdup (fields[0]);
+          decinfo->mainfpr = xstrdup (fields[1]);
+          decinfo->otrust = *fields[2];
+        }
+    }
+}
 
 /* Decrypt the INPUT stream to a new stream which is stored at success
  * at R_OUTPUT.  */
 static gpg_error_t
-decrypt_stream (estream_t *r_output, estream_t input)
+decrypt_stream (estream_t *r_output, struct decrypt_stream_parm_s *decinfo,
+                estream_t input)
 {
   gpg_error_t err;
   ccparray_t ccp;
@@ -445,6 +477,7 @@ decrypt_stream (estream_t *r_output, estream_t input)
   estream_t output;
 
   *r_output = NULL;
+  memset (decinfo, 0, sizeof *decinfo);
 
   output = es_fopenmem (0, "w+b");
   if (!output)
@@ -479,7 +512,9 @@ decrypt_stream (estream_t *r_output, estream_t input)
     }
   err = gnupg_exec_tool_stream (opt.gpg_program, argv, input,
                                 NULL, output,
-                                decrypt_stream_status_cb, NULL);
+                                decrypt_stream_status_cb, decinfo);
+  if (!err && (!decinfo->fpr || !decinfo->mainfpr || !decinfo->otrust))
+    err = gpg_error (GPG_ERR_INV_ENGINE);
   if (err)
     {
       log_error ("decryption failed: %s\n", gpg_strerror (err));
@@ -493,6 +528,12 @@ decrypt_stream (estream_t *r_output, estream_t input)
   output = NULL;
 
  leave:
+  if (err)
+    {
+      xfree (decinfo->fpr);
+      xfree (decinfo->mainfpr);
+      memset (decinfo, 0, sizeof *decinfo);
+    }
   es_fclose (output);
   xfree (argv);
   return err;
@@ -677,7 +718,16 @@ command_send (const char *fingerprint, char *userid)
   else
     err = wkd_get_submission_address (addrspec, &submission_to);
   if (err)
-    goto leave;
+    {
+      char *domain = strchr (addrspec, '@');
+      if (domain)
+        domain = domain + 1;
+      log_error (_("looking up WKS submission address for %s: %s\n"),
+                 domain ? domain : addrspec, gpg_strerror (err));
+      if (gpg_err_code (err) == GPG_ERR_NO_DATA)
+        log_error (_("this domain probably doesn't support WKS.\n"));
+      goto leave;
+    }
   log_info ("submitting request to '%s'\n", submission_to);
 
   /* Get the policy flags.  */
@@ -686,12 +736,12 @@ command_send (const char *fingerprint, char *userid)
       estream_t mbuf;
 
       err = wkd_get_policy_flags (addrspec, &mbuf);
-      if (err)
+      if (err && gpg_err_code (err) != GPG_ERR_NO_DATA)
         {
           log_error ("error reading policy flags for '%s': %s\n",
                      submission_to, gpg_strerror (err));
           goto leave;
-      }
+        }
       if (mbuf)
         {
           err = wks_parse_policy (&policy, mbuf, 1);
@@ -727,8 +777,9 @@ command_send (const char *fingerprint, char *userid)
   if (err)
     goto leave;
 
-  /* Tell server that we support draft version 3.  */
-  err = mime_maker_add_header (mime, "Wks-Draft-Version", "3");
+  /* Tell server which draft we support.  */
+  err = mime_maker_add_header (mime, "Wks-Draft-Version",
+                               STR2(WKS_DRAFT_VERSION));
   if (err)
     goto leave;
 
@@ -926,6 +977,10 @@ send_confirmation_response (const char *sender, const char *address,
   err = mime_maker_add_header (mime, "Subject", "Key publication confirmation");
   if (err)
     goto leave;
+  err = mime_maker_add_header (mime, "Wks-Draft-Version",
+                               STR2(WKS_DRAFT_VERSION));
+  if (err)
+    goto leave;
 
   if (encrypt)
     {
@@ -976,9 +1031,11 @@ send_confirmation_response (const char *sender, const char *address,
 
 
 /* Reply to a confirmation request.  The MSG has already been
- * decrypted and we only need to send the nonce back.  */
+ * decrypted and we only need to send the nonce back.  MAINFPR is
+ * either NULL or the primary key fingerprint of the key used to
+ * decrypt the request.  */
 static gpg_error_t
-process_confirmation_request (estream_t msg)
+process_confirmation_request (estream_t msg, const char *mainfpr)
 {
   gpg_error_t err;
   nvc_t nvc;
@@ -1022,8 +1079,20 @@ process_confirmation_request (estream_t msg)
     }
   fingerprint = value;
 
-  /* FIXME: Check that the fingerprint matches the key used to decrypt the
-   * message.  */
+  /* Check that the fingerprint matches the key used to decrypt the
+   * message.  In --read mode or with the old format we don't have the
+   * decryption key; thus we can't bail out.  */
+  if (!mainfpr || ascii_strcasecmp (mainfpr, fingerprint))
+    {
+      log_info ("target fingerprint: %s\n", fingerprint);
+      log_info ("but decrypted with: %s\n", mainfpr);
+      log_error ("confirmation request not decrypted with target key\n");
+      if (mainfpr)
+        {
+          err = gpg_error (GPG_ERR_INV_DATA);
+          goto leave;
+        }
+    }
 
   /* Get the address.  */
   if (!((item = nvc_lookup (nvc, "address:")) && (value = nve_value (item))
@@ -1036,10 +1105,7 @@ process_confirmation_request (estream_t msg)
     }
   address = value;
   /* FIXME: Check that the "address" matches the User ID we want to
-   * publish.  Also get the "fingerprint" and compare that to our to
-   * be published key.  Further we should make sure that we actually
-   * decrypted using that fingerprint (which is a bit problematic if
-   * --read is used). */
+   * publish.  */
 
   /* Get the sender.  */
   if (!((item = nvc_lookup (nvc, "sender:")) && (value = nve_value (item))
@@ -1108,14 +1174,24 @@ read_confirmation_request (estream_t msg)
     }
 
   if (c != '-')
-    err = process_confirmation_request (msg);
+    err = process_confirmation_request (msg, NULL);
   else
     {
-      err = decrypt_stream (&plaintext, msg);
+      struct decrypt_stream_parm_s decinfo;
+
+      err = decrypt_stream (&plaintext, &decinfo, msg);
       if (err)
         log_error ("decryption failed: %s\n", gpg_strerror (err));
+      else if (decinfo.otrust != 'u')
+        {
+          err = gpg_error (GPG_ERR_WRONG_SECKEY);
+          log_error ("key used to decrypt the confirmation request"
+                     " was not generated by us\n");
+        }
       else
-        err = process_confirmation_request (plaintext);
+        err = process_confirmation_request (plaintext, decinfo.mainfpr);
+      xfree (decinfo.fpr);
+      xfree (decinfo.mainfpr);
     }
 
   es_fclose (plaintext);