diff options
author | Werner Koch <[email protected]> | 2016-09-29 15:55:32 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2016-09-29 15:59:41 +0000 |
commit | 33800280da55a859e08dfa57f29144c89dd1bead (patch) | |
tree | 5c36328d866ad1bd0a49fef51a4ac7935d4009c7 /tools/gpg-wks-server.c | |
parent | tools: Convey signeddata also to the part_data callback in mime-parser. (diff) | |
download | gnupg-33800280da55a859e08dfa57f29144c89dd1bead.tar.gz gnupg-33800280da55a859e08dfa57f29144c89dd1bead.zip |
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 <[email protected]>
Diffstat (limited to 'tools/gpg-wks-server.c')
-rw-r--r-- | tools/gpg-wks-server.c | 239 |
1 files changed, 203 insertions, 36 deletions
diff --git a/tools/gpg-wks-server.c b/tools/gpg-wks-server.c index 96e5e05a5..408e3f549 100644 --- a/tools/gpg-wks-server.c +++ b/tools/gpg-wks-server.c @@ -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")) |