X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Fpdkim%2Fpdkim.c;h=6e76b8e9fa2555e0a8e422b618d87a0bf424940d;hb=f6ee24a2b56b9365b948dd9e501c0e4627e6fa4f;hp=a77dd5792322a96ccece9b5c326dd6d1c8c64e4e;hpb=eea190173538a3e71a87f174baa190cb22e0e8fb;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/pdkim/pdkim.c b/src/src/pdkim/pdkim.c index a77dd5792..6e76b8e9f 100644 --- a/src/src/pdkim/pdkim.c +++ b/src/src/pdkim/pdkim.c @@ -2,7 +2,7 @@ * PDKIM - a RFC4871 (DKIM) implementation * * Copyright (C) 2009 - 2016 Tom Kistner - * Copyright (C) 2016 Jeremy Harris + * Copyright (C) 2016 - 2017 Jeremy Harris * * http://duncanthrax.net/pdkim/ * @@ -192,7 +192,8 @@ static void pdkim_hexprint(const uschar *data, int len) { int i; -for (i = 0 ; i < len; i++) debug_printf("%02x", data[i]); +if (data) for (i = 0 ; i < len; i++) debug_printf("%02x", data[i]); +else debug_printf(""); debug_printf("\n"); } @@ -493,10 +494,8 @@ for (p = raw_hdr; ; p++) switch (*cur_tag) { case 'b': - if (cur_tag[1] == 'h') - pdkim_decode_base64(cur_val, &sig->bodyhash); - else - pdkim_decode_base64(cur_val, &sig->sigdata); + pdkim_decode_base64(cur_val, + cur_tag[1] == 'h' ? &sig->bodyhash : &sig->sighash); break; case 'v': /* We only support version 1, and that is currently the @@ -578,12 +577,17 @@ DEBUG(D_acl) "PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); pdkim_quoteprint(US sig->rawsig_no_b_val, Ustrlen(sig->rawsig_no_b_val)); debug_printf( - "PDKIM >> Sig size: %4u bits\n", (unsigned) sig->sigdata.len*8); + "PDKIM >> Sig size: %4u bits\n", (unsigned) sig->sighash.len*8); debug_printf( "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); } -exim_sha_init(&sig->body_hash, sig->algo == PDKIM_ALGO_RSA_SHA1 ? HASH_SHA1 : HASH_SHA256); +if (!exim_sha_init(&sig->body_hash_ctx, + sig->algo == PDKIM_ALGO_RSA_SHA1 ? HASH_SHA1 : HASH_SHA256)) + { + DEBUG(D_acl) debug_printf("PDKIM: hash init internal error\n"); + return NULL; + } return sig; } @@ -697,15 +701,14 @@ return NULL; /* -------------------------------------------------------------------------- */ static int -pdkim_update_bodyhash(pdkim_ctx *ctx, const char *data, int len) +pdkim_update_bodyhash(pdkim_ctx * ctx, const char * data, int len) { -pdkim_signature *sig = ctx->sig; -/* Cache relaxed version of data */ -uschar *relaxed_data = NULL; -int relaxed_len = 0; +pdkim_signature * sig; +uschar * relaxed_data = NULL; /* Cache relaxed version of data */ +int relaxed_len = 0; /* Traverse all signatures, updating their hashes. */ -while (sig) +for (sig = ctx->sig; sig; sig = sig->next) { /* Defaults to simple canon (no further treatment necessary) */ const uschar *canon_data = CUS data; @@ -761,12 +764,10 @@ while (sig) if (canon_len > 0) { - exim_sha_update(&sig->body_hash, CUS canon_data, canon_len); + exim_sha_update(&sig->body_hash_ctx, CUS canon_data, canon_len); sig->signed_body_bytes += canon_len; DEBUG(D_acl) pdkim_quoteprint(canon_data, canon_len); } - - sig = sig->next; } if (relaxed_data) store_free(relaxed_data); @@ -786,7 +787,7 @@ for (sig = ctx->sig; sig; sig = sig->next) { /* Finish hashes */ blob bh; - exim_sha_finish(&sig->body_hash, &bh); + exim_sha_finish(&sig->body_hash_ctx, &bh); DEBUG(D_acl) { @@ -807,11 +808,11 @@ for (sig = ctx->sig; sig; sig = sig->next) sig->bodylength = -1; } - /* VERIFICATION --------------------------------------------------------- */ else - { - /* Compare bodyhash */ - if (memcmp(bh.data, sig->bodyhash.data, bh.len) == 0) + /* VERIFICATION --------------------------------------------------------- */ + /* Be careful that the header sig included a bodyash */ + + if (sig->bodyhash.data && memcmp(bh.data, sig->bodyhash.data, bh.len) == 0) { DEBUG(D_acl) debug_printf("PDKIM [%s] Body hash verified OK\n", sig->domain); } @@ -820,14 +821,12 @@ for (sig = ctx->sig; sig; sig = sig->next) DEBUG(D_acl) { debug_printf("PDKIM [%s] Body hash signature from headers: ", sig->domain); - pdkim_hexprint(sig->bodyhash.data, - exim_sha_hashlen(&sig->body_hash)); + pdkim_hexprint(sig->bodyhash.data, sig->bodyhash.len); debug_printf("PDKIM [%s] Body hash did NOT verify\n", sig->domain); } sig->verify_status = PDKIM_VERIFY_FAIL; sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY; } - } } } @@ -959,36 +958,35 @@ if (ctx->flags & PDKIM_MODE_SIGN) /* DKIM-Signature: headers are added to the verification list */ else { +#ifdef notdef DEBUG(D_acl) { debug_printf("PDKIM >> raw hdr: "); pdkim_quoteprint(CUS ctx->cur_header, Ustrlen(ctx->cur_header)); } +#endif if (strncasecmp(CCS ctx->cur_header, DKIM_SIGNATURE_HEADERNAME, Ustrlen(DKIM_SIGNATURE_HEADERNAME)) == 0) { - pdkim_signature *new_sig; + pdkim_signature * new_sig, * last_sig; + + /* Create and chain new signature block. We could error-check for all + required tags here, but prefer to create the internal sig and expicitly + fail verification of it later. */ - /* Create and chain new signature block */ DEBUG(D_acl) debug_printf( "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); - if ((new_sig = pdkim_parse_sig_header(ctx, ctx->cur_header))) + new_sig = pdkim_parse_sig_header(ctx, ctx->cur_header); + + if (!(last_sig = ctx->sig)) + ctx->sig = new_sig; + else { - pdkim_signature *last_sig = ctx->sig; - if (!last_sig) - ctx->sig = new_sig; - else - { - while (last_sig->next) last_sig = last_sig->next; - last_sig->next = new_sig; - } + while (last_sig->next) last_sig = last_sig->next; + last_sig->next = new_sig; } - else - DEBUG(D_acl) debug_printf( - "Error while parsing signature header\n" - "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); } /* all headers are stored for signature verification */ @@ -1009,7 +1007,7 @@ return PDKIM_OK; DLLEXPORT int pdkim_feed(pdkim_ctx *ctx, char *data, int len) { -int p; +int p, rc; /* Alternate EOD signal, used in non-dotstuffing mode */ if (!data) @@ -1034,7 +1032,6 @@ else for (p = 0; pflags |= PDKIM_SEEN_CR; else if (c == '\n') { - int rc; ctx->flags &= ~PDKIM_SEEN_CR; if ((rc = pdkim_bodyline_complete(ctx)) != PDKIM_OK) return rc; @@ -1054,14 +1051,14 @@ else for (p = 0; pcur_header = string_catn(ctx->cur_header, &ctx->cur_header_size, &ctx->cur_header_len, CUS "\r", 1); - if (ctx->flags & PDKIM_SEEN_LF) + if (ctx->flags & PDKIM_SEEN_LF) /* Seen last header line */ { - int rc = pdkim_header_complete(ctx); /* Seen last header line */ - if (rc != PDKIM_OK) return rc; + if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK) + return rc; ctx->flags = ctx->flags & ~(PDKIM_SEEN_LF|PDKIM_SEEN_CR) | PDKIM_PAST_HDRS; DEBUG(D_acl) debug_printf( - "PDKIM >> Body data for hash, canonicalized >>>>>>>>>>>>>>>>>>>>>>\n"); + "PDKIM >> Body data for hash, canonicalized >>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); continue; } else @@ -1069,11 +1066,9 @@ else for (p = 0; pflags & PDKIM_SEEN_LF) { - if (!(c == '\t' || c == ' ')) - { - int rc = pdkim_header_complete(ctx); /* End of header */ - if (rc != PDKIM_OK) return rc; - } + if (!(c == '\t' || c == ' ')) /* End of header */ + if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK) + return rc; ctx->flags &= ~PDKIM_SEEN_LF; } @@ -1308,7 +1303,7 @@ if (sig->bodylength >= 0) } /* Preliminary or final version? */ -base64_b = final ? pdkim_encode_base64(&sig->sigdata) : US""; +base64_b = final ? pdkim_encode_base64(&sig->sighash) : US""; hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"b=", base64_b); /* add trailing semicolon: I'm not sure if this is actually needed */ @@ -1422,7 +1417,11 @@ while (sig) hdata.data = NULL; hdata.len = 0; - exim_sha_init(&hhash_ctx, is_sha1 ? HASH_SHA1 : HASH_SHA256); + if (!exim_sha_init(&hhash_ctx, is_sha1 ? HASH_SHA1 : HASH_SHA256)) + { + DEBUG(D_acl) debug_printf("PDKIM: hask setup internal error\n"); + break; + } DEBUG(D_acl) debug_printf( "PDKIM >> Header data for hash, canonicalized, in sequence >>>>>>>>>>>>>>\n"); @@ -1584,7 +1583,7 @@ while (sig) hdata = hhash; #endif - if ((errstr = exim_rsa_sign(&sctx, is_sha1, &hdata, &sig->sigdata))) + if ((errstr = exim_rsa_sign(&sctx, is_sha1, &hdata, &sig->sighash))) { DEBUG(D_acl) debug_printf("signing: %s\n", errstr); return PDKIM_ERR_RSA_SIGNING; @@ -1593,7 +1592,7 @@ while (sig) DEBUG(D_acl) { debug_printf( "PDKIM [%s] b computed: ", sig->domain); - pdkim_hexprint(sig->sigdata.data, sig->sigdata.len); + pdkim_hexprint(sig->sighash.data, sig->sighash.len); } sig->signature_header = pdkim_create_header(sig, TRUE); @@ -1611,7 +1610,7 @@ while (sig) && sig->selector && *sig->selector && sig->headernames && *sig->headernames && sig->bodyhash.data - && sig->sigdata.data + && sig->sighash.data && sig->algo > -1 && sig->version ) ) @@ -1641,7 +1640,7 @@ while (sig) goto NEXT_VERIFY; /* Check the signature */ - if ((errstr = exim_rsa_verify(&vctx, is_sha1, &hhash, &sig->sigdata))) + if ((errstr = exim_rsa_verify(&vctx, is_sha1, &hhash, &sig->sighash))) { DEBUG(D_acl) debug_printf("headers verify: %s\n", errstr); sig->verify_status = PDKIM_VERIFY_FAIL; @@ -1728,7 +1727,12 @@ sig->selector = string_copy(US selector); sig->rsa_privkey = string_copy(US rsa_privkey); sig->algo = algo; -exim_sha_init(&sig->body_hash, algo == PDKIM_ALGO_RSA_SHA1 ? HASH_SHA1 : HASH_SHA256); +if (!exim_sha_init(&sig->body_hash_ctx, + algo == PDKIM_ALGO_RSA_SHA1 ? HASH_SHA1 : HASH_SHA256)) + { + DEBUG(D_acl) debug_printf("PDKIM: hash setup internal error\n"); + return NULL; + } DEBUG(D_acl) { @@ -1740,7 +1744,6 @@ DEBUG(D_acl) debug_printf("WARNING: bad dkim key in dns\n"); debug_printf("PDKIM (finished checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); } - return ctx; }