mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
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@gnupg.org>
This commit is contained in:
parent
a209025082
commit
d30e17ac62
@ -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);
|
||||
|
@ -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;
|
||||
@ -1211,6 +1216,10 @@ send_congratulation_message (const char *mbox, const char *keyfile)
|
||||
if (err)
|
||||
goto leave;
|
||||
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");
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user