1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

wks: Partly implement draft-koch-openpgp-webkey-service-02.

* tools/gpg-wks.h (WKS_RECEIVE_DRAFT2): New.
* tools/wks-receive.c: Include rfc822parse.h.
(struct receive_ctx_s): Add fields PARSER, DRAFT_VERSION_2, and
MULTIPART_MIXED_SEEN.
(decrypt_data): Add --no-options.
(verify_signature): Ditto.
(new_part): Check for Wks-Draft-Version header.  Take care of text
parts.
(wks_receive): Set Parser and pass a flag value to RESULT_CB.
* tools/gpg-wks-client.c (read_confirmation_request): New.
(main) <aRead>: Call read_confirmation_request instead of
process_confirmation_request.
(command_receive_cb): Ditto.  Add arg FLAGS..
(decrypt_stream_status_cb, decrypt_stream): New.
(command_send): Set header Wks-Draft-Version.
* tools/gpg-wks-server.c (struct server_ctx_s): Add field
DRAFT_VERSION_2.
(sign_stream_status_cb, sign_stream): New.
(command_receive_cb): Set draft flag.
(send_confirmation_request): Rework to implement protocol draft
version 2.

* tools/gpg-wks.h (DBG_MIME_VALUE, DBG_PARSER_VALUE): New.
(DBG_MIME, DBG_PARSER, DBG_CRYPTO): New.  Use instead of a plain
opt.debug where useful.
* tools/gpg-wks-client.c (debug_flags): Add "mime" and "parser".
* tools/gpg-wks-server.c (debug_flags): Ditto.
--

If a client supporting the version 2 of the protocol is used, it will
tell this the server using a mail header.  An old server will ignore
that but a recent server will use the new protocol.  Next task is to
actually write draft-02.

There are still a lot of FIXMEs - take care.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2016-09-29 17:55:32 +02:00
parent c738f92c19
commit 33800280da
No known key found for this signature in database
GPG key ID: E3FDFF218E45B72B
4 changed files with 417 additions and 57 deletions

View file

@ -91,6 +91,8 @@ static ARGPARSE_OPTS opts[] = {
/* The list of supported debug flags. */
static struct debug_flags_s debug_flags [] =
{
{ DBG_MIME_VALUE , "mime" },
{ DBG_PARSER_VALUE , "parser" },
{ DBG_CRYPTO_VALUE , "crypto" },
{ DBG_MEMORY_VALUE , "memory" },
{ DBG_MEMSTAT_VALUE, "memstat" },
@ -103,9 +105,10 @@ static struct debug_flags_s debug_flags [] =
static void wrong_args (const char *text) GPGRT_ATTR_NORETURN;
static gpg_error_t command_supported (char *userid);
static gpg_error_t command_send (const char *fingerprint, char *userid);
static gpg_error_t process_confirmation_request (estream_t msg);
static gpg_error_t read_confirmation_request (estream_t msg);
static gpg_error_t command_receive_cb (void *opaque,
const char *mediatype, estream_t fp);
const char *mediatype, estream_t fp,
unsigned int flags);
@ -269,7 +272,7 @@ main (int argc, char **argv)
case aRead:
if (argc)
wrong_args ("--read < WKS-DATA");
err = process_confirmation_request (es_stdin);
err = read_confirmation_request (es_stdin);
if (err)
log_error ("processing mail failed: %s\n", gpg_strerror (err));
break;
@ -393,6 +396,83 @@ get_key (estream_t *r_key, const char *fingerprint, const char *addrspec)
}
static void
decrypt_stream_status_cb (void *opaque, const char *keyword, char *args)
{
(void)opaque;
if (DBG_CRYPTO)
log_debug ("gpg status: %s %s\n", keyword, args);
}
/* 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)
{
gpg_error_t err;
ccparray_t ccp;
const char **argv;
estream_t output;
*r_output = NULL;
output = es_fopenmem (0, "w+b");
if (!output)
{
err = gpg_error_from_syserror ();
log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
return err;
}
ccparray_init (&ccp, 0);
ccparray_put (&ccp, "--no-options");
/* We limit the output to 64 KiB to avoid DoS using compression
* tricks. A regular client will anyway only send a minimal key;
* that is one w/o key signatures and attribute packets. */
ccparray_put (&ccp, "--max-output=0x10000");
if (!opt.verbose)
ccparray_put (&ccp, "--quiet");
else if (opt.verbose > 1)
ccparray_put (&ccp, "--verbose");
ccparray_put (&ccp, "--batch");
ccparray_put (&ccp, "--status-fd=2");
ccparray_put (&ccp, "--decrypt");
ccparray_put (&ccp, "--");
ccparray_put (&ccp, NULL);
argv = ccparray_get (&ccp, NULL);
if (!argv)
{
err = gpg_error_from_syserror ();
goto leave;
}
err = gnupg_exec_tool_stream (opt.gpg_program, argv, input,
NULL, output,
decrypt_stream_status_cb, NULL);
if (err)
{
log_error ("decryption failed: %s\n", gpg_strerror (err));
goto leave;
}
else if (opt.verbose)
log_info ("decryption succeeded\n");
es_rewind (output);
*r_output = output;
output = NULL;
leave:
es_fclose (output);
xfree (argv);
return err;
}
/* Check whether the provider supports the WKS protocol. */
static gpg_error_t
@ -517,6 +597,11 @@ 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");
if (err)
goto leave;
err = mime_maker_add_stream (mime, &key);
if (err)
goto leave;
@ -539,8 +624,8 @@ encrypt_response_status_cb (void *opaque, const char *keyword, char *args)
gpg_error_t *failure = opaque;
char *fields[2];
if (opt.debug)
log_debug ("%s: %s\n", keyword, args);
if (DBG_CRYPTO)
log_debug ("gpg status: %s %s\n", keyword, args);
if (!strcmp (keyword, "FAILURE"))
{
@ -747,7 +832,7 @@ process_confirmation_request (estream_t msg)
goto leave;
}
if (opt.debug)
if (DBG_MIME)
{
log_debug ("request follows:\n");
nvc_write (nvc, log_get_stream ());
@ -822,16 +907,62 @@ process_confirmation_request (estream_t msg)
}
/* Read a confirmation request and decrypt it if needed. This
* function may not be used with a mail or MIME message but only with
* the actual encrypted or plaintext WKS data. */
static gpg_error_t
read_confirmation_request (estream_t msg)
{
gpg_error_t err;
int c;
estream_t plaintext = NULL;
/* We take a really simple approach to check whether MSG is
* encrypted: We know that an encrypted message is always armored
* and thus starts with a few dashes. It is even sufficient to
* check for a single dash, because that can never be a proper first
* WKS data octet. We need to skip leading spaces, though. */
while ((c = es_fgetc (msg)) == ' ' || c == '\t' || c == '\r' || c == '\n')
;
if (c == EOF)
{
log_error ("can't process an empty message\n");
return gpg_error (GPG_ERR_INV_DATA);
}
if (es_ungetc (c, msg) != c)
{
log_error ("error ungetting octet from message\n");
return gpg_error (GPG_ERR_INTERNAL);
}
if (c != '-')
err = process_confirmation_request (msg);
else
{
err = decrypt_stream (&plaintext, msg);
if (err)
log_error ("decryption failed: %s\n", gpg_strerror (err));
else
err = process_confirmation_request (plaintext);
}
es_fclose (plaintext);
return err;
}
/* Called from the MIME receiver to process the plain text data in MSG. */
static gpg_error_t
command_receive_cb (void *opaque, const char *mediatype, estream_t msg)
command_receive_cb (void *opaque, const char *mediatype,
estream_t msg, unsigned int flags)
{
gpg_error_t err;
(void)opaque;
(void)flags;
if (!strcmp (mediatype, "application/vnd.gnupg.wks"))
err = process_confirmation_request (msg);
err = read_confirmation_request (msg);
else
{
log_info ("ignoring unexpected message of type '%s'\n", mediatype);