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);

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"))

View File

@ -39,12 +39,18 @@ struct
} opt;
/* Debug values and macros. */
#define DBG_MIME_VALUE 1 /* Debug the MIME structure. */
#define DBG_PARSER_VALUE 2 /* Debug the Mail parser. */
#define DBG_CRYPTO_VALUE 4 /* Debug low level crypto. */
#define DBG_MEMORY_VALUE 32 /* Debug memory allocation stuff. */
#define DBG_MEMSTAT_VALUE 128 /* Show memory statistics. */
#define DBG_IPC_VALUE 1024 /* Debug assuan communication. */
#define DBG_EXTPROG_VALUE 16384 /* debug external program calls */
#define DBG_MIME (opt.debug & DBG_MIME_VALUE)
#define DBG_PARSER (opt.debug & DBG_PARSER_VALUE)
#define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE)
/* The parsed policy flags. */
struct policy_flags_s
@ -64,10 +70,15 @@ gpg_error_t wks_parse_policy (policy_flags_t flags, estream_t stream,
int ignore_unknown);
/*-- wks-receive.c --*/
/* Flag values for the receive callback. */
#define WKS_RECEIVE_DRAFT2 1
gpg_error_t wks_receive (estream_t fp,
gpg_error_t (*result_cb)(void *opaque,
const char *mediatype,
estream_t data),
estream_t data,
unsigned int flags),
void *cb_data);

View File

@ -26,6 +26,7 @@
#include "ccparray.h"
#include "exectool.h"
#include "gpg-wks.h"
#include "rfc822parse.h"
#include "mime-parser.h"
@ -41,6 +42,7 @@
/* Data for a received object. */
struct receive_ctx_s
{
mime_parser_t parser;
estream_t encrypted;
estream_t plaintext;
estream_t signeddata;
@ -49,6 +51,8 @@ struct receive_ctx_s
estream_t wkd_data;
unsigned int collect_key_data:1;
unsigned int collect_wkd_data:1;
unsigned int draft_version_2:1; /* This is a draft version 2 request. */
unsigned int multipart_mixed_seen:1;
};
typedef struct receive_ctx_s *receive_ctx_t;
@ -59,7 +63,8 @@ decrypt_data_status_cb (void *opaque, const char *keyword, char *args)
{
receive_ctx_t ctx = opaque;
(void)ctx;
log_debug ("%s: %s\n", keyword, args);
if (DBG_CRYPTO)
log_debug ("gpg status: %s %s\n", keyword, args);
}
@ -86,6 +91,7 @@ decrypt_data (receive_ctx_t ctx)
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. */
@ -113,7 +119,7 @@ decrypt_data (receive_ctx_t ctx)
goto leave;
}
if (opt.debug)
if (DBG_CRYPTO)
{
es_rewind (ctx->plaintext);
log_debug ("plaintext: '");
@ -133,7 +139,8 @@ verify_signature_status_cb (void *opaque, const char *keyword, char *args)
{
receive_ctx_t ctx = opaque;
(void)ctx;
log_debug ("%s: %s\n", keyword, args);
if (DBG_CRYPTO)
log_debug ("gpg status: %s %s\n", keyword, args);
}
/* Verify the signed data. */
@ -151,6 +158,7 @@ verify_signature (receive_ctx_t ctx)
ccparray_init (&ccp, 0);
ccparray_put (&ccp, "--no-options");
ccparray_put (&ccp, "--batch");
if (opt.verbose)
ccparray_put (&ccp, "--verbose");
@ -177,6 +185,8 @@ verify_signature (receive_ctx_t ctx)
goto leave;
}
log_debug ("Fixme: Verification result is not used\n");
leave:
xfree (argv);
}
@ -264,6 +274,22 @@ 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)
{
@ -303,6 +329,19 @@ new_part (void *cookie, const char *mediatype, const char *mediasubtype)
}
}
}
else if (!strcmp (mediatype, "multipart")
&& !strcmp (mediasubtype, "mixed"))
{
ctx->multipart_mixed_seen = 1;
}
else if (!strcmp (mediatype, "text"))
{
/* Check that we receive a text part only after a
* application/mixed. This is actually a too simple test and we
* should eventually employ a strict MIME structure check. */
if (!ctx->multipart_mixed_seen)
err = gpg_error (GPG_ERR_UNEXPECTED_MSG);
}
else
{
log_error ("unexpected '%s/%s' message part\n", mediatype, mediasubtype);
@ -320,7 +359,7 @@ part_data (void *cookie, const void *data, size_t datalen)
if (data)
{
if (opt.debug)
if (DBG_MIME)
log_debug ("part_data: '%.*s'\n", (int)datalen, (const char*)data);
if (ctx->collect_key_data)
{
@ -337,7 +376,7 @@ part_data (void *cookie, const void *data, size_t datalen)
}
else
{
if (opt.debug)
if (DBG_MIME)
log_debug ("part_data: finished\n");
ctx->collect_key_data = 0;
ctx->collect_wkd_data = 0;
@ -353,7 +392,8 @@ gpg_error_t
wks_receive (estream_t fp,
gpg_error_t (*result_cb)(void *opaque,
const char *mediatype,
estream_t data),
estream_t data,
unsigned int flags),
void *cb_data)
{
gpg_error_t err;
@ -361,6 +401,7 @@ wks_receive (estream_t fp,
mime_parser_t parser;
estream_t plaintext = NULL;
int c;
unsigned int flags = 0;
ctx = xtrycalloc (1, sizeof *ctx);
if (!ctx)
@ -369,14 +410,16 @@ wks_receive (estream_t fp,
err = mime_parser_new (&parser, ctx);
if (err)
goto leave;
if (opt.verbose > 1 || opt.debug)
mime_parser_set_verbose (parser, opt.debug? 10: 1);
if (DBG_PARSER)
mime_parser_set_verbose (parser, 1);
mime_parser_set_new_part (parser, new_part);
mime_parser_set_part_data (parser, part_data);
mime_parser_set_collect_encrypted (parser, collect_encrypted);
mime_parser_set_collect_signeddata (parser, collect_signeddata);
mime_parser_set_collect_signature (parser, collect_signature);
ctx->parser = parser;
err = mime_parser_parse (parser, fp);
if (err)
goto leave;
@ -385,6 +428,11 @@ wks_receive (estream_t fp,
log_info ("key data found\n");
if (ctx->wkd_data)
log_info ("wkd data found\n");
if (ctx->draft_version_2)
{
log_info ("draft version 2 requested\n");
flags |= WKS_RECEIVE_DRAFT2;
}
if (ctx->plaintext)
{
@ -412,7 +460,7 @@ wks_receive (estream_t fp,
if (ctx->key_data)
{
if (opt.debug)
if (DBG_MIME)
{
es_rewind (ctx->key_data);
log_debug ("Key: '");
@ -424,14 +472,15 @@ wks_receive (estream_t fp,
if (result_cb)
{
es_rewind (ctx->key_data);
err = result_cb (cb_data, "application/pgp-keys", ctx->key_data);
err = result_cb (cb_data, "application/pgp-keys",
ctx->key_data, flags);
if (err)
goto leave;
}
}
if (ctx->wkd_data)
{
if (opt.debug)
if (DBG_MIME)
{
es_rewind (ctx->wkd_data);
log_debug ("WKD: '");
@ -443,7 +492,8 @@ wks_receive (estream_t fp,
if (result_cb)
{
es_rewind (ctx->wkd_data);
err = result_cb (cb_data, "application/vnd.gnupg.wks", ctx->wkd_data);
err = result_cb (cb_data, "application/vnd.gnupg.wks",
ctx->wkd_data, flags);
if (err)
goto leave;
}
@ -453,6 +503,7 @@ wks_receive (estream_t fp,
leave:
es_fclose (plaintext);
mime_parser_release (parser);
ctx->parser = NULL;
es_fclose (ctx->encrypted);
es_fclose (ctx->plaintext);
es_fclose (ctx->signeddata);