From 37f8b55404d931bd8b2103d54a0f38fbd1570767 Mon Sep 17 00:00:00 2001 From: Tom Kistner Date: Mon, 30 Apr 2012 13:37:40 +0100 Subject: [PATCH] Fix verification when DKIM Signatures are not inserted as tracking headers. Thanks to Wolfgang Breyha for the patch! (bug 1239) --- src/src/pdkim/pdkim.c | 118 ++++++++++++++++++++++++------------------ src/src/pdkim/pdkim.h | 5 +- 2 files changed, 68 insertions(+), 55 deletions(-) diff --git a/src/src/pdkim/pdkim.c b/src/src/pdkim/pdkim.c index be159b381..c0c0e3263 100644 --- a/src/src/pdkim/pdkim.c +++ b/src/src/pdkim/pdkim.c @@ -51,6 +51,7 @@ /* -------------------------------------------------------------------------- */ struct pdkim_stringlist { char *value; + int tag; void *next; }; @@ -301,7 +302,6 @@ void pdkim_free_sig(pdkim_signature *sig) { if (sig->signature_header != NULL) free(sig->signature_header); if (sig->sha1_body != NULL) free(sig->sha1_body); if (sig->sha2_body != NULL) free(sig->sha2_body); - if (sig->hnames_check != NULL) free(sig->hnames_check); if (sig->pubkey != NULL) pdkim_free_pubkey(sig->pubkey); @@ -314,6 +314,13 @@ void pdkim_free_sig(pdkim_signature *sig) { /* -------------------------------------------------------------------------- */ DLLEXPORT void pdkim_free_ctx(pdkim_ctx *ctx) { if (ctx) { + pdkim_stringlist *e = ctx->headers; + while(e != NULL) { + pdkim_stringlist *c = e; + if (e->value != NULL) free(e->value); + e = e->next; + free(c); + } pdkim_free_sig(ctx->sig); pdkim_strfree(ctx->cur_header); free(ctx); @@ -701,9 +708,6 @@ pdkim_signature *pdkim_parse_sig_header(pdkim_ctx *ctx, char *raw_hdr) { return NULL; } - /* Copy header list to 'tick-off' header list */ - sig->hnames_check = strdup(sig->headernames); - *q = '\0'; /* Chomp raw header. The final newline must not be added to the signature. */ q--; @@ -1062,65 +1066,69 @@ int pdkim_header_complete(pdkim_ctx *ctx) { ctx->num_headers++; if (ctx->num_headers > PDKIM_MAX_HEADERS) goto BAIL; - /* Traverse all signatures */ - while (sig != NULL) { - pdkim_stringlist *list; + /* SIGNING -------------------------------------------------------------- */ + if (ctx->mode == PDKIM_MODE_SIGN) { + /* Traverse all signatures */ + while (sig != NULL) { + pdkim_stringlist *list; - /* SIGNING -------------------------------------------------------------- */ - if (ctx->mode == PDKIM_MODE_SIGN) { if (header_name_match(ctx->cur_header->str, sig->sign_headers? sig->sign_headers: PDKIM_DEFAULT_SIGN_HEADERS, 0) != PDKIM_OK) goto NEXT_SIG; - } - /* VERIFICATION --------------------------------------------------------- */ - else { - /* Header is not included or all instances were already 'ticked off' */ - if (header_name_match(ctx->cur_header->str, - sig->hnames_check, 1) != PDKIM_OK) goto NEXT_SIG; - } - /* Add header to the signed headers list (in reverse order) */ - list = pdkim_prepend_stringlist(sig->headers, - ctx->cur_header->str); - if (list == NULL) return PDKIM_ERR_OOM; - sig->headers = list; - - NEXT_SIG: - sig = sig->next; + /* Add header to the signed headers list (in reverse order) */ + list = pdkim_prepend_stringlist(sig->headers, + ctx->cur_header->str); + if (list == NULL) return PDKIM_ERR_OOM; + sig->headers = list; + + NEXT_SIG: + sig = sig->next; + } } /* DKIM-Signature: headers are added to the verification list */ - if ( (ctx->mode == PDKIM_MODE_VERIFY) && - (strncasecmp(ctx->cur_header->str, + if (ctx->mode == PDKIM_MODE_VERIFY) { + if (strncasecmp(ctx->cur_header->str, DKIM_SIGNATURE_HEADERNAME, - strlen(DKIM_SIGNATURE_HEADERNAME)) == 0) ) { - pdkim_signature *new_sig; - /* Create and chain new signature block */ - #ifdef PDKIM_DEBUG - if (ctx->debug_stream) - fprintf(ctx->debug_stream, - "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); - #endif - new_sig = pdkim_parse_sig_header(ctx, ctx->cur_header->str); - if (new_sig != NULL) { - pdkim_signature *last_sig = ctx->sig; - if (last_sig == NULL) { - ctx->sig = new_sig; + strlen(DKIM_SIGNATURE_HEADERNAME)) == 0) { + pdkim_signature *new_sig; + /* Create and chain new signature block */ + #ifdef PDKIM_DEBUG + if (ctx->debug_stream) + fprintf(ctx->debug_stream, + "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); + #endif + new_sig = pdkim_parse_sig_header(ctx, ctx->cur_header->str); + if (new_sig != NULL) { + pdkim_signature *last_sig = ctx->sig; + if (last_sig == NULL) { + ctx->sig = new_sig; + } + else { + while (last_sig->next != NULL) { last_sig = last_sig->next; } + last_sig->next = new_sig; + } } else { - while (last_sig->next != NULL) { last_sig = last_sig->next; } - last_sig->next = new_sig; + #ifdef PDKIM_DEBUG + if (ctx->debug_stream) { + fprintf(ctx->debug_stream,"Error while parsing signature header\n"); + fprintf(ctx->debug_stream, + "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); + } + #endif } } + /* every other header is stored for signature verification */ else { - #ifdef PDKIM_DEBUG - if (ctx->debug_stream) { - fprintf(ctx->debug_stream,"Error while parsing signature header\n"); - fprintf(ctx->debug_stream, - "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); - } - #endif + pdkim_stringlist *list; + + list = pdkim_prepend_stringlist(ctx->headers, + ctx->cur_header->str); + if (list == NULL) return PDKIM_ERR_OOM; + ctx->headers = list; } } @@ -1377,12 +1385,20 @@ DLLEXPORT int pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatu char *q = NULL; if (b == NULL) return PDKIM_ERR_OOM; + /* clear tags */ + pdkim_stringlist *hdrs = ctx->headers; + while (hdrs != NULL) { + hdrs->tag = 0; + hdrs = hdrs->next; + } + while(1) { - pdkim_stringlist *hdrs = sig->headers; + hdrs = ctx->headers; q = strchr(p,':'); if (q != NULL) *q = '\0'; while (hdrs != NULL) { - if ( (strncasecmp(hdrs->value,p,strlen(p)) == 0) && + if ( (hdrs->tag == 0) && + (strncasecmp(hdrs->value,p,strlen(p)) == 0) && ((hdrs->value)[strlen(p)] == ':') ) { char *rh = NULL; if (sig->canon_headers == PDKIM_CANON_RELAXED) @@ -1400,7 +1416,7 @@ DLLEXPORT int pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatu pdkim_quoteprint(ctx->debug_stream, rh, strlen(rh), 1); #endif free(rh); - (hdrs->value)[0] = '_'; + hdrs->tag = 1; break; } hdrs = hdrs->next; diff --git a/src/src/pdkim/pdkim.h b/src/src/pdkim/pdkim.h index 57606ab93..2066e2734 100644 --- a/src/src/pdkim/pdkim.h +++ b/src/src/pdkim/pdkim.h @@ -237,10 +237,6 @@ typedef struct pdkim_signature { /* Signing specific ------------------------------------------------- */ char *rsa_privkey; /* Private RSA key */ char *sign_headers; /* To-be-signed header names */ - /* Verification specific -------------------------------------------- */ - char *hnames_check; /* Tick-off header list that we use to keep - track of header names that we have already - added to the signature candidates. */ char *rawsig_no_b_val; /* Original signature header w/o b= tag value. */ } pdkim_signature; @@ -274,6 +270,7 @@ typedef struct pdkim_ctx { int past_headers; int num_buffered_crlf; int num_headers; + pdkim_stringlist *headers; /* Raw headers for verification */ #ifdef PDKIM_DEBUG /* A FILE pointer. When not NULL, debug output will be generated -- 2.25.1