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

@ -102,6 +102,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" },
@ -116,6 +118,7 @@ struct server_ctx_s
{
char *fpr;
strlist_t mboxes; /* List of addr-specs taken from the UIDs. */
unsigned int draft_version_2:1; /* Client supports the draft 2. */
};
typedef struct server_ctx_s *server_ctx_t;
@ -123,7 +126,8 @@ typedef struct server_ctx_s *server_ctx_t;
static gpg_error_t get_domain_list (strlist_t *r_list);
static gpg_error_t command_receive_cb (void *opaque,
const char *mediatype, estream_t fp);
const char *mediatype, estream_t fp,
unsigned int flags);
static gpg_error_t command_list_domains (void);
static gpg_error_t command_cron (void);
@ -350,8 +354,8 @@ list_key_status_cb (void *opaque, const char *keyword, char *args)
{
server_ctx_t ctx = opaque;
(void)ctx;
if (opt.debug)
log_debug ("%s: %s\n", keyword, args);
if (DBG_CRYPTO)
log_debug ("gpg status: %s %s\n", keyword, args);
}
@ -629,8 +633,8 @@ encrypt_stream_status_cb (void *opaque, const char *keyword, char *args)
{
(void)opaque;
if (opt.debug)
log_debug ("%s: %s\n", keyword, args);
if (DBG_CRYPTO)
log_debug ("gpg status: %s %s\n", keyword, args);
}
@ -698,6 +702,78 @@ encrypt_stream (estream_t *r_output, estream_t input, const char *keyfile)
}
static void
sign_stream_status_cb (void *opaque, const char *keyword, char *args)
{
(void)opaque;
if (DBG_CRYPTO)
log_debug ("gpg status: %s %s\n", keyword, args);
}
/* Sign the INPUT stream to a new stream which is stored at success at
* R_OUTPUT. A detached signature is created using the key specified
* by USERID. */
static gpg_error_t
sign_stream (estream_t *r_output, estream_t input, const char *userid)
{
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");
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, "--armor");
ccparray_put (&ccp, "--local-user");
ccparray_put (&ccp, userid);
ccparray_put (&ccp, "--detach-sign");
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,
sign_stream_status_cb, NULL);
if (err)
{
log_error ("signing failed: %s\n", gpg_strerror (err));
goto leave;
}
es_rewind (output);
*r_output = output;
output = NULL;
leave:
es_fclose (output);
xfree (argv);
return err;
}
/* Get the submission address for address MBOX. Caller must free the
* value. If no address can be found NULL is returned. */
static char *
@ -933,6 +1009,8 @@ send_confirmation_request (server_ctx_t ctx,
gpg_error_t err;
estream_t body = NULL;
estream_t bodyenc = NULL;
estream_t signeddata = NULL;
estream_t signature = NULL;
mime_maker_t mime = NULL;
char *from_buffer = NULL;
const char *from;
@ -958,12 +1036,16 @@ send_confirmation_request (server_ctx_t ctx,
log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
goto leave;
}
/* It is fine to use 8 bit encoding because that is encrypted and
* only our client will see it. */
es_fputs ("Content-Type: application/vnd.gnupg.wks\n"
"Content-Transfer-Encoding: 8bit\n"
"\n",
body);
if (!ctx->draft_version_2)
{
/* It is fine to use 8 bit encoding because that is encrypted and
* only our client will see it. */
es_fputs ("Content-Type: application/vnd.gnupg.wks\n"
"Content-Transfer-Encoding: 8bit\n"
"\n",
body);
}
es_fprintf (body, ("type: confirmation-request\n"
"sender: %s\n"
@ -1002,35 +1084,117 @@ send_confirmation_request (server_ctx_t ctx,
goto leave;
}
err = mime_maker_add_header (mime, "Content-Type",
"multipart/encrypted; "
"protocol=\"application/pgp-encrypted\"");
if (err)
goto leave;
err = mime_maker_add_container (mime);
if (err)
goto leave;
if (!ctx->draft_version_2)
{
err = mime_maker_add_header (mime, "Content-Type",
"multipart/encrypted; "
"protocol=\"application/pgp-encrypted\"");
if (err)
goto leave;
err = mime_maker_add_container (mime);
if (err)
goto leave;
err = mime_maker_add_header (mime, "Content-Type",
"application/pgp-encrypted");
if (err)
goto leave;
err = mime_maker_add_body (mime, "Version: 1\n");
if (err)
goto leave;
err = mime_maker_add_header (mime, "Content-Type",
"application/octet-stream");
if (err)
goto leave;
err = mime_maker_add_header (mime, "Content-Type",
"application/pgp-encrypted");
if (err)
goto leave;
err = mime_maker_add_body (mime, "Version: 1\n");
if (err)
goto leave;
err = mime_maker_add_header (mime, "Content-Type",
"application/octet-stream");
if (err)
goto leave;
err = mime_maker_add_stream (mime, &bodyenc);
if (err)
goto leave;
err = mime_maker_add_stream (mime, &bodyenc);
if (err)
goto leave;
}
else
{
unsigned int partid;
/* FIXME: Add micalg. */
err = mime_maker_add_header (mime, "Content-Type",
"multipart/signed; "
"protocol=\"application/pgp-signature\"");
if (err)
goto leave;
err = mime_maker_add_container (mime);
if (err)
goto leave;
err = mime_maker_add_header (mime, "Content-Type", "multipart/mixed");
if (err)
goto leave;
err = mime_maker_add_container (mime);
if (err)
goto leave;
partid = mime_maker_get_partid (mime);
err = mime_maker_add_header (mime, "Content-Type", "text/plain");
if (err)
goto leave;
err = mime_maker_add_body
(mime,
"This message has been send to confirm your request\n"
"to publish your key. If you did not request a key\n"
"publication, simply ignore this message.\n"
"\n"
"Most mail software can handle this kind of message\n"
"automatically and thus you would not have seen this\n"
"message. It seems that your client does not fully\n"
"support this service. The web page\n"
"\n"
" https://gnupg.org/faq/wkd.html\n"
"\n"
"explains how you can process this message anyway in\n"
"a few manual steps.\n");
if (err)
goto leave;
err = mime_maker_add_header (mime, "Content-Type",
"application/vnd.gnupg.wks");
if (err)
goto leave;
err = mime_maker_add_stream (mime, &bodyenc);
if (err)
goto leave;
err = mime_maker_end_container (mime);
if (err)
goto leave;
mime_maker_dump_tree (mime);
err = mime_maker_get_part (mime, partid, &signeddata);
if (err)
goto leave;
err = sign_stream (&signature, signeddata, from);
if (err)
goto leave;
err = mime_maker_add_header (mime, "Content-Type",
"application/pgp-signature");
if (err)
goto leave;
err = mime_maker_add_stream (mime, &signature);
if (err)
goto leave;
}
err = wks_send_mime (mime);
leave:
mime_maker_release (mime);
es_fclose (signature);
es_fclose (signeddata);
es_fclose (bodyenc);
es_fclose (body);
xfree (from_buffer);
@ -1478,15 +1642,18 @@ process_confirmation_response (server_ctx_t ctx, estream_t msg)
/* 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;
struct server_ctx_s ctx;
memset (&ctx, 0, sizeof ctx);
(void)opaque;
memset (&ctx, 0, sizeof ctx);
if ((flags & WKS_RECEIVE_DRAFT2))
ctx.draft_version_2 = 1;
if (!strcmp (mediatype, "application/pgp-keys"))
err = process_new_key (&ctx, msg);
else if (!strcmp (mediatype, "application/vnd.gnupg.wks"))