diff options
-rw-r--r-- | doc/doc-txt/ChangeLog | 3 | ||||
-rw-r--r-- | src/src/pdkim/pdkim.c | 33 | ||||
-rw-r--r-- | src/src/pdkim/pdkim.h | 15 | ||||
-rw-r--r-- | test/dnszones-src/db.test.ex | 6 | ||||
-rw-r--r-- | test/log/4500 | 3 | ||||
-rw-r--r-- | test/log/4506 | 3 | ||||
-rw-r--r-- | test/scripts/4500-DKIM/4500 | 34 | ||||
-rw-r--r-- | test/scripts/4500-DKIM/4506 | 35 | ||||
-rw-r--r-- | test/stderr/4520 | 1 |
9 files changed, 120 insertions, 13 deletions
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 0b4076c20..ecb6b33a9 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -138,6 +138,9 @@ JH/21 Bug 2151: Avoid using SIZE on the MAIL for a callout verify, on any but JH/22 Retire historical build files to an "unsupported" subdir. These are defined as "ones for which we have no current evidence of testing". +JH/23 DKIM: enforce the DNS pubkey record "h" permitted-hashes optional field, + if present. Previously it was ignored. + Exim version 4.89 ----------------- diff --git a/src/src/pdkim/pdkim.c b/src/src/pdkim/pdkim.c index d41b60f13..d289ec7a3 100644 --- a/src/src/pdkim/pdkim.c +++ b/src/src/pdkim/pdkim.c @@ -132,6 +132,7 @@ switch(ext_status) { case PDKIM_VERIFY_FAIL_BODY: return "PDKIM_VERIFY_FAIL_BODY"; case PDKIM_VERIFY_FAIL_MESSAGE: return "PDKIM_VERIFY_FAIL_MESSAGE"; + case PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH: return "PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH"; case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE: return "PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE"; case PDKIM_VERIFY_INVALID_BUFFER_SIZE: return "PDKIM_VERIFY_INVALID_BUFFER_SIZE"; case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD: return "PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD"; @@ -644,12 +645,8 @@ for (p = raw_record; ; p++) case 'v': pub->version = string_copy(cur_val); break; case 'h': + pub->hashes = string_copy(cur_val); break; case 'k': -/* This field appears to never be used. Also, unclear why -a 'k' (key-type_ would go in this field name. There is a field -"keytype", also never used. - pub->hashes = string_copy(cur_val); -*/ break; case 'g': pub->granularity = string_copy(cur_val); break; @@ -682,7 +679,11 @@ a 'k' (key-type_ would go in this field name. There is a field /* Set fallback defaults */ if (!pub->version ) pub->version = string_copy(PDKIM_PUB_RECORD_VERSION); -else if (Ustrcmp(pub->version, PDKIM_PUB_RECORD_VERSION) != 0) return NULL; +else if (Ustrcmp(pub->version, PDKIM_PUB_RECORD_VERSION) != 0) + { + DEBUG(D_acl) debug_printf(" Bad v= field\n"); + return NULL; + } if (!pub->granularity) pub->granularity = string_copy(US"*"); /* @@ -694,6 +695,7 @@ if (!pub->srvtype ) pub->srvtype = string_copy(US"*"); if (pub->key.data) return pub; +DEBUG(D_acl) debug_printf(" Missing p= field\n"); return NULL; } @@ -1631,6 +1633,25 @@ while (sig) if (!(sig->pubkey = pdkim_key_from_dns(ctx, sig, &vctx, err))) goto NEXT_VERIFY; + /* If the pubkey limits to a list of specific hashes, ignore sigs that + do not have the hash part of the sig algorithm matching */ + + if (sig->pubkey->hashes) + { + const uschar * list = sig->pubkey->hashes, * ele; + int sep = ':'; + while ((ele = string_nextinlist(&list, &sep, NULL, 0))) + if (Ustrcmp(ele, pdkim_algos[sig->algo] + 4) == 0) break; + if (!ele) + { + DEBUG(D_acl) debug_printf("pubkey h=%s vs sig a=%s\n", + sig->pubkey->hashes, pdkim_algos[sig->algo]); + sig->verify_status = PDKIM_VERIFY_FAIL; + sig->verify_ext_status = PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH; + goto NEXT_VERIFY; + } + } + /* Check the signature */ if ((*err = exim_rsa_verify(&vctx, is_sha1, &hhash, &sig->sighash))) { diff --git a/src/src/pdkim/pdkim.h b/src/src/pdkim/pdkim.h index 78e3c3c8b..9899356d5 100644 --- a/src/src/pdkim/pdkim.h +++ b/src/src/pdkim/pdkim.h @@ -51,12 +51,13 @@ #define PDKIM_VERIFY_FAIL_BODY 1 #define PDKIM_VERIFY_FAIL_MESSAGE 2 -#define PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE 3 -#define PDKIM_VERIFY_INVALID_BUFFER_SIZE 4 -#define PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD 5 -#define PDKIM_VERIFY_INVALID_PUBKEY_IMPORT 6 -#define PDKIM_VERIFY_INVALID_SIGNATURE_ERROR 7 -#define PDKIM_VERIFY_INVALID_DKIM_VERSION 8 +#define PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH 3 +#define PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE 4 +#define PDKIM_VERIFY_INVALID_BUFFER_SIZE 5 +#define PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD 6 +#define PDKIM_VERIFY_INVALID_PUBKEY_IMPORT 7 +#define PDKIM_VERIFY_INVALID_SIGNATURE_ERROR 8 +#define PDKIM_VERIFY_INVALID_DKIM_VERSION 9 /* -------------------------------------------------------------------------- */ /* Some parameter values */ @@ -100,8 +101,8 @@ typedef struct pdkim_pubkey { uschar *version; /* v= */ uschar *granularity; /* g= */ -#ifdef notdef uschar *hashes; /* h= */ +#ifdef notdef uschar *keytype; /* k= */ #endif uschar *srvtype; /* s= */ diff --git a/test/dnszones-src/db.test.ex b/test/dnszones-src/db.test.ex index f7c9e313b..73db57f9c 100644 --- a/test/dnszones-src/db.test.ex +++ b/test/dnszones-src/db.test.ex @@ -491,13 +491,19 @@ DELAY=1500 delay1500 A HOSTIPV4 ; openssl rsa -in aux-fixed/dkim/dkim.private -out /dev/stdout -pubout -outform PEM ; ; Deliberate bad version, having extra backslashes +; sha256-hash-only version.... appears to be too long, gets truncated ; ; Another, 512-bit (with a Notes field) +; 512 requiring sha1 hash +; 512 requiring sha256 hash ; sel._domainkey TXT "v=DKIM1; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXRFf+VhT+lCgFhhSkinZKcFNeRzjYdW8vT29Rbb3NadvTFwAd+cVLPFwZL8H5tUD/7JbUPqNTCPxmpgIL+V5T4tEZMorHatvvUM2qfcpQ45IfsZ+YdhbIiAslHCpy4xNxIR3zylgqRUF4+Dtsaqy3a5LhwMiKCLrnzhXk1F1hxwIDAQAB" sel_bad._domainkey TXT "v=DKIM1\; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXRFf+VhT+lCgFhhSkinZKcFNeRzjYdW8vT29Rbb3NadvTFwAd+cVLPFwZL8H5tUD/7JbUPqNTCPxmpgIL+V5T4tEZMorHatvvUM2qfcpQ45IfsZ+YdhbIiAslHCpy4xNxIR3zylgqRUF4+Dtsaqy3a5LhwMiKCLrnzhXk1F1hxwIDAQAB" +sel_sha256._domainkey TXT "v=DKIM1; h=sha256; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXRFf+VhT+lCgFhhSkinZKcFNeRzjYdW8vT29Rbb3NadvTFwAd+cVLPFwZL8H5tUD/7JbUPqNTCPxmpgIL+V5T4tEZMorHatvvUM2qfcpQ45IfsZ+YdhbIiAslHCpy4xNxIR3zylgqRUF4+Dtsaqy3a5LhwMiKCLrnzhXk1F1hxwIDAQAB" ses._domainkey TXT "v=DKIM1; n=halfkilo; p=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL6eAQxd9didJ0/+05iDwJOqT6ly826Vi8aGPecsBiYK5/tAT97fxXk+dPWMZp9kQxtknEzYjYjAydzf+HQ2yJMCAwEAAQ==" +ses_sha1._domainkey TXT "v=DKIM1; h=sha1; p=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL6eAQxd9didJ0/+05iDwJOqT6ly826Vi8aGPecsBiYK5/tAT97fxXk+dPWMZp9kQxtknEzYjYjAydzf+HQ2yJMCAwEAAQ==" +ses_sha256._domainkey TXT "v=DKIM1; h=sha256; p=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL6eAQxd9didJ0/+05iDwJOqT6ly826Vi8aGPecsBiYK5/tAT97fxXk+dPWMZp9kQxtknEzYjYjAydzf+HQ2yJMCAwEAAQ==" ; End diff --git a/test/log/4500 b/test/log/4500 index 0e0f8400d..ec8ef088e 100644 --- a/test/log/4500 +++ b/test/log/4500 @@ -10,3 +10,6 @@ 1999-03-02 09:44:33 10HmaZ-0005vi-00 DKIM: d=test.ex s=sel c=simple/simple a=rsa-sha256 b=1024 [verification succeeded] 1999-03-02 09:44:33 10HmaZ-0005vi-00 signer: test.ex bits: 1024 1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss id=qwerty1234@disco-zombie.net +1999-03-02 09:44:33 10HmbA-0005vi-00 DKIM: d=test.ex s=ses_sha1 c=simple/simple a=rsa-sha1 b=512 [verification succeeded] +1999-03-02 09:44:33 10HmbA-0005vi-00 signer: test.ex bits: 512 +1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss id=qwerty1234@disco-zombie.net diff --git a/test/log/4506 b/test/log/4506 index fb0f22567..027169df0 100644 --- a/test/log/4506 +++ b/test/log/4506 @@ -13,3 +13,6 @@ 1999-03-02 09:44:33 10HmbA-0005vi-00 DKIM: validation error: RSA_LONG_LINE 1999-03-02 09:44:33 10HmbA-0005vi-00 DKIM: Error during validation, disabling signature verification: RSA_LONG_LINE 1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss id=qwerty1234@disco-zombie.net +1999-03-02 09:44:33 10HmbB-0005vi-00 DKIM: d=test.ex s=ses_sha256 c=simple/simple a=rsa-sha1 b=512 [verification failed - unspecified reason] +1999-03-02 09:44:33 10HmbB-0005vi-00 signer: test.ex bits: 512 +1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss id=qwerty1234@disco-zombie.net diff --git a/test/scripts/4500-DKIM/4500 b/test/scripts/4500-DKIM/4500 index 6728b141d..6b3ff5fcf 100644 --- a/test/scripts/4500-DKIM/4500 +++ b/test/scripts/4500-DKIM/4500 @@ -101,6 +101,40 @@ QUIT **** # # +# This should pass. The pubkey dns decord has a additional sha1-only h= field +# +# - sha1, 512b +# Mail original in aux-fixed/4500.msg1.txt +# Sig generated by: perl aux-fixed/dkim/sign.pl --keyfile=aux-fixed/dkim/dkim512.private \ +# --method=simple/simple --selector=ses_sha1 < aux-fixed/4500.msg1.txt +client 127.0.0.1 PORT_D +??? 220 +HELO xxx +??? 250 +MAIL FROM:<CALLER@bloggs.com> +??? 250 +RCPT TO:<a@test.ex> +??? 250 +DATA +??? 354 +DKIM-Signature: v=1; a=rsa-sha1; c=simple/simple; d=test.ex; h=from:to + :date:message-id:subject; s=ses_sha1; bh=OB9dZVu7+5/ufs3TH9leIcE + pXSo=; b=hG14R3Eb/f13Pw6J0LmovHAL01KHVmVrTZ7KJrqieYTQemUaseoU2pB + 7/g8NUwG/AsYoaw3gaAK8PqxSk2lcIQ== +From: mrgus@text.ex +To: bakawolf@yahoo.com +Date: Thu, 19 Nov 2015 17:00:07 -0700 +Message-ID: <qwerty1234@disco-zombie.net> +Subject: simple test + +This is a simple test. +. +??? 250 +QUIT +??? 221 +**** +# +# killdaemon no_stdout_check no_msglog_check diff --git a/test/scripts/4500-DKIM/4506 b/test/scripts/4500-DKIM/4506 index 6eb81cc16..e8d7c41f0 100644 --- a/test/scripts/4500-DKIM/4506 +++ b/test/scripts/4500-DKIM/4506 @@ -134,6 +134,41 @@ QUIT **** # # +# This should fail as the sig on the mail uses sha1 but the dns record requires sha256 +# +# - sha256, 512b +# Mail original in aux-fixed/4500.msg1.txt +# Sig generated by: perl aux-fixed/dkim/sign.pl --keyfile=aux-fixed/dkim/dkim512.private \ +# --method=simple/simple --selector=ses_sha1 < aux-fixed/4500.msg1.txt +# and then modifying the s= manually +client 127.0.0.1 PORT_D +??? 220 +HELO xxx +??? 250 +MAIL FROM:<CALLER@bloggs.com> +??? 250 +RCPT TO:<a@test.ex> +??? 250 +DATA +??? 354 +DKIM-Signature: v=1; a=rsa-sha1; c=simple/simple; d=test.ex; h=from:to + :date:message-id:subject; s=ses_sha256; bh=OB9dZVu7+5/ufs3TH9leIcE + pXSo=; b=hG14R3Eb/f13Pw6J0LmovHAL01KHVmVrTZ7KJrqieYTQemUaseoU2pB + 7/g8NUwG/AsYoaw3gaAK8PqxSk2lcIQ== +From: mrgus@text.ex +To: bakawolf@yahoo.com +Date: Thu, 19 Nov 2015 17:00:07 -0700 +Message-ID: <qwerty1234@disco-zombie.net> +Subject: simple test + +This is a simple test. +. +??? 250 +QUIT +??? 221 +**** +# +# killdaemon no_stdout_check no_msglog_check diff --git a/test/stderr/4520 b/test/stderr/4520 index c1bafcdcc..fc64a9e93 100644 --- a/test/stderr/4520 +++ b/test/stderr/4520 @@ -28,6 +28,7 @@ PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Raw record: v=DKIM1\;{SP}p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXRFf+VhT+lCgFhhSkinZKcFNeRzjYdW8vT29Rbb3NadvTFwAd+cVLPFwZL8H5tUD/7JbUPqNTCPxmpgIL+V5T4tEZMorHatvvUM2qfcpQ45IfsZ+YdhbIiAslHCpy4xNxIR3zylgqRUF4+Dtsaqy3a5LhwMiKCLrnzhXk1F1hxwIDAQAB v=DKIM1\ p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXRFf+VhT+lCgFhhSkinZKcFNeRzjYdW8vT29Rbb3NadvTFwAd+cVLPFwZL8H5tUD/7JbUPqNTCPxmpgIL+V5T4tEZMorHatvvUM2qfcpQ45IfsZ+YdhbIiAslHCpy4xNxIR3zylgqRUF4+Dtsaqy3a5LhwMiKCLrnzhXk1F1hxwIDAQAB + Bad v= field Error while parsing public key record WARNING: bad dkim key in dns PDKIM (finished checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |