summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2017-06-28 15:25:12 +0100
committerJeremy Harris <jgh146exb@wizmail.org>2017-08-09 22:23:58 +0100
commit135e949699b889c8c9088bb05f810d44adc74246 (patch)
tree1e82b43c0b5857e76cd4041ee3865fe4a191481d /src
parent0f1a8658daf8689f0ef0afbb11d0cb589447a57d (diff)
DKIM: Enforce any "h" field present in the DNS publickey record. This can be set to require specific
hash types, eg sha256, in signatues. There is an IETF draft in discussion which deprecates sha1 so this feature may start to be used.
Diffstat (limited to 'src')
-rw-r--r--src/src/pdkim/pdkim.c33
-rw-r--r--src/src/pdkim/pdkim.h15
2 files changed, 35 insertions, 13 deletions
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= */