[Pkg-gnupg-commit] [gnupg2] 134/166: wks: Make sure that the draft 2 request is correctly detected.

Daniel Kahn Gillmor dkg at fifthhorseman.net
Thu Mar 16 22:33:13 UTC 2017


This is an automated email from the git hooks/post-receive script.

dkg pushed a commit to branch experimental
in repository gnupg2.

commit d30e17ac62dea8913b7f353971d546b6b1a09bd5
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Feb 23 20:10:59 2017 +0100

    wks: Make sure that the draft 2 request is correctly detected.
    
    * tools/gpg-wks.h (WKS_DRAFT_VERSION): New.
    * tools/wks-receive.c (new_part): Move test wks draft version to ...
    (t2body): new callback.
    (wks_receive): Register this callback.
    * tools/gpg-wks-server.c (send_confirmation_request): Emit draft
    version header.
    (send_congratulation_message): Ditto.
    * tools/gpg-wks-client.c (decrypt_stream_parm_s): New.
    (decrypt_stream_status_cb): Check DECRYTPION_KEY status.
    (decrypt_stream): Get infor from new callback.
    (process_confirmation_request): New arg 'mainfpr'.  Check that it
    matches the decryption key.
    (read_confirmation_request): Check that the decryption key has been
    generated by us.
    (command_send): Use macro from draft version header.
    (send_confirmation_response): Emit draft version header.
    --
    
    This patch also adds a check to only send a confirmation when the
    decryption has been done by an ultimately trusted (self-generated)
    key.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>
---
 tools/gpg-wks-client.c | 88 ++++++++++++++++++++++++++++++++++++++++----------
 tools/gpg-wks-server.c | 13 ++++++--
 tools/gpg-wks.h        |  4 +++
 tools/wks-receive.c    | 49 +++++++++++++++++++---------
 4 files changed, 119 insertions(+), 35 deletions(-)

diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c
index fa19fc1..c31e3a1 100644
--- a/tools/gpg-wks-client.c
+++ b/tools/gpg-wks-client.c
@@ -373,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);
@@ -437,20 +438,38 @@ get_key (estream_t *r_key, const char *fingerprint, const char *addrspec)
 
 
 

+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;
@@ -458,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)
@@ -492,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));
@@ -506,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;
@@ -749,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;
 
@@ -948,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)
     {
@@ -998,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;
@@ -1044,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))
@@ -1058,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))
@@ -1130,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);
diff --git a/tools/gpg-wks-server.c b/tools/gpg-wks-server.c
index c17c1cf..0376cce 100644
--- a/tools/gpg-wks-server.c
+++ b/tools/gpg-wks-server.c
@@ -916,7 +916,12 @@ send_confirmation_request (server_ctx_t ctx,
   if (err)
     goto leave;
 
-  /* Help Enigmail to identify messages.  Note that this is on no way
+  err = mime_maker_add_header (mime, "Wks-Draft-Version",
+                               STR2(WKS_DRAFT_VERSION));
+  if (err)
+    goto leave;
+
+  /* Help Enigmail to identify messages.  Note that this is in no way
    * secured.  */
   err = mime_maker_add_header (mime, "WKS-Phase", "confirm");
   if (err)
@@ -1015,7 +1020,7 @@ send_confirmation_request (server_ctx_t ctx,
       if (err)
         goto leave;
 
-      mime_maker_dump_tree (mime);
+      /* mime_maker_dump_tree (mime); */
       err = mime_maker_get_part (mime, partid, &signeddata);
       if (err)
         goto leave;
@@ -1213,6 +1218,10 @@ send_congratulation_message (const char *mbox, const char *keyfile)
   err = mime_maker_add_header (mime, "Subject", "Your key has been published");
   if (err)
     goto leave;
+  err = mime_maker_add_header (mime, "Wks-Draft-Version",
+                               STR2(WKS_DRAFT_VERSION));
+  if (err)
+    goto leave;
   err = mime_maker_add_header (mime, "WKS-Phase", "done");
   if (err)
     goto leave;
diff --git a/tools/gpg-wks.h b/tools/gpg-wks.h
index 62ceb34..3b28af4 100644
--- a/tools/gpg-wks.h
+++ b/tools/gpg-wks.h
@@ -24,6 +24,10 @@
 #include "../common/strlist.h"
 #include "mime-maker.h"
 
+/* The draft version we implement.  */
+#define WKS_DRAFT_VERSION 3
+
+
 /* We keep all global options in the structure OPT.  */
 struct
 {
diff --git a/tools/wks-receive.c b/tools/wks-receive.c
index 12ec089..94f8bc6 100644
--- a/tools/wks-receive.c
+++ b/tools/wks-receive.c
@@ -255,6 +255,38 @@ collect_signature (void *cookie, const char *data)
 }
 
 
+/* The callback for the transition from header to body.  We use it to
+ * look at some header values.  */
+static gpg_error_t
+t2body (void *cookie, int level)
+{
+  receive_ctx_t ctx = cookie;
+  rfc822parse_t msg;
+  char *value;
+  size_t valueoff;
+
+  log_info ("t2body for level %d\n", level);
+  if (!level)
+    {
+      /* This is the outermost header.  */
+      msg = mime_parser_rfc822parser (ctx->parser);
+      if (msg)
+        {
+          value = rfc822parse_get_field (msg, "Wks-Draft-Version",
+                                         -1, &valueoff);
+          if (value)
+            {
+              if (atoi(value+valueoff) >= 2 )
+                ctx->draft_version_2 = 1;
+              free (value);
+            }
+        }
+    }
+
+  return 0;
+}
+
+
 static gpg_error_t
 new_part (void *cookie, const char *mediatype, const char *mediasubtype)
 {
@@ -275,22 +307,6 @@ new_part (void *cookie, const char *mediatype, const char *mediasubtype)
         }
       else
         {
-          rfc822parse_t msg = mime_parser_rfc822parser (ctx->parser);
-          if (msg)
-            {
-              char *value;
-              size_t valueoff;
-
-              value = rfc822parse_get_field (msg, "Wks-Draft-Version",
-                                             -1, &valueoff);
-              if (value)
-                {
-                  if (atoi(value+valueoff) >= 2 )
-                    ctx->draft_version_2 = 1;
-                  free (value);
-                }
-            }
-
           ctx->key_data = es_fopenmem (0, "w+b");
           if (!ctx->key_data)
             {
@@ -413,6 +429,7 @@ wks_receive (estream_t fp,
     goto leave;
   if (DBG_PARSER)
     mime_parser_set_verbose (parser, 1);
+  mime_parser_set_t2body (parser, t2body);
   mime_parser_set_new_part (parser, new_part);
   mime_parser_set_part_data (parser, part_data);
   mime_parser_set_collect_encrypted (parser, collect_encrypted);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-gnupg/gnupg2.git



More information about the Pkg-gnupg-commit mailing list