X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Fpdkim%2Fpdkim.c;h=594af03c526c028b0065be196984db6878623d74;hb=13c7874e0a41d696ecf55774d62ea7d11778414f;hp=2a66909ba7181ff981f25428b5316772c1e1a1f0;hpb=d64f251592db09252ac0584adbe72a2eeb9ca122;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/pdkim/pdkim.c b/src/src/pdkim/pdkim.c index 2a66909ba..594af03c5 100644 --- a/src/src/pdkim/pdkim.c +++ b/src/src/pdkim/pdkim.c @@ -80,7 +80,7 @@ const pdkim_hashtype pdkim_hashes[] = { const uschar * pdkim_keytypes[] = { [KEYTYPE_RSA] = US"rsa", #ifdef SIGN_HAVE_ED25519 - [KEYTYPE_ED25519] = US"ed25519", /* Works for 3.6.0 GnuTLS */ + [KEYTYPE_ED25519] = US"ed25519", /* Works for 3.6.0 GnuTLS, OpenSSL 1.1.1 */ #endif #ifdef notyet_EC_dkim_extensions /* https://tools.ietf.org/html/draft-srose-dkim-ecc-00 */ @@ -192,6 +192,7 @@ switch(status) case PDKIM_ERR_RSA_SIGNING: return US"SIGNING"; case PDKIM_ERR_LONG_LINE: return US"LONG_LINE"; case PDKIM_ERR_BUFFER_TOO_SMALL: return US"BUFFER_TOO_SMALL"; + case PDKIM_ERR_EXCESS_SIGS: return US"EXCESS_SIGS"; case PDKIM_SIGN_PRIVKEY_WRAP: return US"PRIVKEY_WRAP"; case PDKIM_SIGN_PRIVKEY_B64D: return US"PRIVKEY_B64D"; default: return US"(unknown)"; @@ -561,18 +562,18 @@ for (p = raw_hdr; ; p++) break; case 'a': /* algorithm */ { - uschar * s = Ustrchr(cur_val->s, '-'); - - for(i = 0; i < nelem(pdkim_keytypes); i++) - if (Ustrncmp(cur_val->s, pdkim_keytypes[i], s - cur_val->s) == 0) - { sig->keytype = i; break; } - if (sig->keytype < 0) - log_write(0, LOG_MAIN, - "DKIM: ignoring signature due to nonhandled keytype in a=%s", - cur_val->s); - - sig->hashtype = pdkim_hashname_to_hashtype(++s, 0); - break; + const uschar * list = cur_val->s; + int sep = '-'; + uschar * elem; + + if ((elem = string_nextinlist(&list, &sep, NULL, 0))) + for(i = 0; i < nelem(pdkim_keytypes); i++) + if (Ustrcmp(elem, pdkim_keytypes[i]) == 0) + { sig->keytype = i; break; } + if ((elem = string_nextinlist(&list, &sep, NULL, 0))) + for (i = 0; i < nelem(pdkim_hashes); i++) + if (Ustrcmp(elem, pdkim_hashes[i].dkim_hashname) == 0) + { sig->hashtype = i; break; } } case 'c': /* canonicalization */ @@ -792,7 +793,7 @@ pdkim_signature * sig; for (b = ctx->bodyhash; b; b = b->next) /* Finish hashes */ { - DEBUG(D_acl) debug_printf("PDKIM: finish bodyhash %d/%d/%d len %ld\n", + DEBUG(D_acl) debug_printf("PDKIM: finish bodyhash %d/%d/%ld len %ld\n", b->hashtype, b->canon_method, b->bodylength, b->signed_body_bytes); exim_sha_finish(&b->body_hash_ctx, &b->bh); } @@ -1008,6 +1009,13 @@ else while (last_sig->next) last_sig = last_sig->next; last_sig->next = sig; } + + if (--dkim_collect_input == 0) + { + ctx->headers = pdkim_prepend_stringlist(ctx->headers, ctx->cur_header->s); + ctx->cur_header->s[ctx->cur_header->ptr = 0] = '\0'; + return PDKIM_ERR_EXCESS_SIGS; + } } /* all headers are stored for signature verification */ @@ -1033,7 +1041,7 @@ int p, rc; if (!data) pdkim_body_complete(ctx); -else for (p = 0; pkey.len - 32; +if (excess > 0) + { + DEBUG(D_acl) debug_printf("PDKIM: unexpected pubkey len %lu\n", p->key.len); + p->key.data += excess; p->key.len = 32; + } +} + + static pdkim_pubkey * pdkim_key_from_dns(pdkim_ctx * ctx, pdkim_signature * sig, ev_ctx * vctx, const uschar ** errstr) @@ -1390,6 +1420,27 @@ DEBUG(D_acl) debug_printf( /* Import public key */ +/* Normally we use the signature a= tag to tell us the pubkey format. +When signing under debug we do a test-import of the pubkey, and at that +time we do not have a signature so we must interpret the pubkey k= tag +instead. Assume writing on the sig is ok in that case. */ + +if (sig->keytype < 0) + { + int i; + for(i = 0; i < nelem(pdkim_keytypes); i++) + if (Ustrcmp(p->keytype, pdkim_keytypes[i]) == 0) + { sig->keytype = i; goto k_ok; } + DEBUG(D_acl) debug_printf("verify_init: unhandled keytype %s\n", p->keytype); + sig->verify_status = PDKIM_VERIFY_INVALID; + sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_IMPORT; + return NULL; + } +k_ok: + +if (sig->keytype == KEYTYPE_ED25519) + check_bare_ed25519_pubkey(p); + if ((*errstr = exim_dkim_verify_init(&p->key, sig->keytype == KEYTYPE_ED25519 ? KEYFMT_ED25519_BARE : KEYFMT_DER, vctx))) @@ -1662,7 +1713,12 @@ for (sig = ctx->sig; sig; sig = sig->next) if (ctx->flags & PDKIM_MODE_SIGN) { hashmethod hm = sig->keytype == KEYTYPE_ED25519 - ? HASH_SHA2_512 : pdkim_hashes[sig->hashtype].exim_hashmethod; +#if defined(SIGN_OPENSSL) + ? HASH_NULL +#else + ? HASH_SHA2_512 +#endif + : pdkim_hashes[sig->hashtype].exim_hashmethod; #ifdef SIGN_HAVE_ED25519 /* For GCrypt, and for EC, we pass the hash-of-headers to the signing @@ -1675,8 +1731,6 @@ for (sig = ctx->sig; sig; sig = sig->next) hhash.len = hdata->ptr; } -/*XXX extend for non-RSA algos */ -/*- done for GnuTLS */ if ((*err = exim_dkim_sign(&sctx, hm, &hhash, &sig->sighash))) { log_write(0, LOG_MAIN|LOG_PANIC, "signing: %s", *err); @@ -1696,6 +1750,7 @@ for (sig = ctx->sig; sig; sig = sig->next) else { ev_ctx vctx; + hashmethod hm; /* Make sure we have all required signature tags */ if (!( sig->domain && *sig->domain @@ -1772,12 +1827,17 @@ for (sig = ctx->sig; sig; sig = sig->next) } } + hm = sig->keytype == KEYTYPE_ED25519 +#if defined(SIGN_OPENSSL) + ? HASH_NULL +#else + ? HASH_SHA2_512 +#endif + : pdkim_hashes[sig->hashtype].exim_hashmethod; + /* Check the signature */ -/*XXX extend for non-RSA algos */ -/*- done for GnuTLS */ - if ((*err = exim_dkim_verify(&vctx, - pdkim_hashes[sig->hashtype].exim_hashmethod, - &hhash, &sig->sighash))) + + if ((*err = exim_dkim_verify(&vctx, hm, &hhash, &sig->sighash))) { DEBUG(D_acl) debug_printf("headers verify: %s\n", *err); sig->verify_status = PDKIM_VERIFY_FAIL;