git://git.exim.org
/
exim.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
GnuTLS: fix use of SHA3 hashes
[exim.git]
/
src
/
src
/
pdkim
/
pdkim.c
diff --git
a/src/src/pdkim/pdkim.c
b/src/src/pdkim/pdkim.c
index 4309675e6d86f48bc55b297cd5388a2895ac26af..178f8f6a5a18c2c12dc6488b2c6ca634b4c7d5d6 100644
(file)
--- 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 <tom@duncanthrax.net>
* PDKIM - a RFC4871 (DKIM) implementation
*
* Copyright (C) 2009 - 2016 Tom Kistner <tom@duncanthrax.net>
- * Copyright (C) 2016 Jeremy Harris <jgh@exim.org>
+ * Copyright (C) 2016
- 2017
Jeremy Harris <jgh@exim.org>
*
* http://duncanthrax.net/pdkim/
*
*
* http://duncanthrax.net/pdkim/
*
@@
-192,7
+192,8
@@
static void
pdkim_hexprint(const uschar *data, int len)
{
int i;
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("<NULL>");
debug_printf("\n");
}
debug_printf("\n");
}
@@
-493,10
+494,8
@@
for (p = raw_hdr; ; p++)
switch (*cur_tag)
{
case 'b':
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
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 >> 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->sig
data
.len*8);
+ "PDKIM >> Sig size: %4u bits\n", (unsigned) sig->sig
hash
.len*8);
debug_printf(
"PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
}
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;
}
return sig;
}
@@
-697,15
+701,14
@@
return NULL;
/* -------------------------------------------------------------------------- */
static int
/* -------------------------------------------------------------------------- */
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. */
/* 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;
{
/* Defaults to simple canon (no further treatment necessary) */
const uschar *canon_data = CUS data;
@@
-761,12
+764,10
@@
while (sig)
if (canon_len > 0)
{
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->signed_body_bytes += canon_len;
DEBUG(D_acl) pdkim_quoteprint(canon_data, canon_len);
}
-
- sig = sig->next;
}
if (relaxed_data) store_free(relaxed_data);
}
if (relaxed_data) store_free(relaxed_data);
@@
-786,7
+787,7
@@
for (sig = ctx->sig; sig; sig = sig->next)
{ /* Finish hashes */
blob bh;
{ /* Finish hashes */
blob bh;
- exim_sha_finish(&sig->body_hash, &bh);
+ exim_sha_finish(&sig->body_hash
_ctx
, &bh);
DEBUG(D_acl)
{
DEBUG(D_acl)
{
@@
-807,11
+808,11
@@
for (sig = ctx->sig; sig; sig = sig->next)
sig->bodylength = -1;
}
sig->bodylength = -1;
}
- /* VERIFICATION --------------------------------------------------------- */
else
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);
}
{
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);
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;
}
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;
}
- }
}
}
}
}
@@
-968,32
+967,28
@@
else
DKIM_SIGNATURE_HEADERNAME,
Ustrlen(DKIM_SIGNATURE_HEADERNAME)) == 0)
{
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");
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");
}
}
- /* every other header is stored for signature verification */
- else
- ctx->headers = pdkim_prepend_stringlist(ctx->headers, ctx->cur_header);
+ /* all headers are stored for signature verification */
+ ctx->headers = pdkim_prepend_stringlist(ctx->headers, ctx->cur_header);
}
BAIL:
}
BAIL:
@@
-1010,7
+1005,7
@@
return PDKIM_OK;
DLLEXPORT int
pdkim_feed(pdkim_ctx *ctx, char *data, int len)
{
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)
/* Alternate EOD signal, used in non-dotstuffing mode */
if (!data)
@@
-1035,7
+1030,6
@@
else for (p = 0; p<len; p++)
ctx->flags |= PDKIM_SEEN_CR;
else if (c == '\n')
{
ctx->flags |= PDKIM_SEEN_CR;
else if (c == '\n')
{
- int rc;
ctx->flags &= ~PDKIM_SEEN_CR;
if ((rc = pdkim_bodyline_complete(ctx)) != PDKIM_OK)
return rc;
ctx->flags &= ~PDKIM_SEEN_CR;
if ((rc = pdkim_bodyline_complete(ctx)) != PDKIM_OK)
return rc;
@@
-1055,14
+1049,14
@@
else for (p = 0; p<len; p++)
ctx->cur_header = string_catn(ctx->cur_header, &ctx->cur_header_size,
&ctx->cur_header_len, CUS "\r", 1);
ctx->cur_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 */
{
{
- i
nt rc = pdkim_header_complete(ctx); /* Seen last header line */
-
if (rc != PDKIM_OK)
return rc;
+ i
f ((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(
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
continue;
}
else
@@
-1070,11
+1064,9
@@
else for (p = 0; p<len; p++)
}
else if (ctx->flags & PDKIM_SEEN_LF)
{
}
else if (ctx->flags & 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;
}
ctx->flags &= ~PDKIM_SEEN_LF;
}
@@
-1309,7
+1301,7
@@
if (sig->bodylength >= 0)
}
/* Preliminary or final version? */
}
/* Preliminary or final version? */
-base64_b = final ? pdkim_encode_base64(&sig->sig
data
) : US"";
+base64_b = final ? pdkim_encode_base64(&sig->sig
hash
) : 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 */
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 */
@@
-1423,7
+1415,11
@@
while (sig)
hdata.data = NULL;
hdata.len = 0;
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");
DEBUG(D_acl) debug_printf(
"PDKIM >> Header data for hash, canonicalized, in sequence >>>>>>>>>>>>>>\n");
@@
-1585,7
+1581,7
@@
while (sig)
hdata = hhash;
#endif
hdata = hhash;
#endif
- if ((errstr = exim_rsa_sign(&sctx, is_sha1, &hdata, &sig->sig
data
)))
+ if ((errstr = exim_rsa_sign(&sctx, is_sha1, &hdata, &sig->sig
hash
)))
{
DEBUG(D_acl) debug_printf("signing: %s\n", errstr);
return PDKIM_ERR_RSA_SIGNING;
{
DEBUG(D_acl) debug_printf("signing: %s\n", errstr);
return PDKIM_ERR_RSA_SIGNING;
@@
-1594,7
+1590,7
@@
while (sig)
DEBUG(D_acl)
{
debug_printf( "PDKIM [%s] b computed: ", sig->domain);
DEBUG(D_acl)
{
debug_printf( "PDKIM [%s] b computed: ", sig->domain);
- pdkim_hexprint(sig->sig
data.data, sig->sigdata
.len);
+ pdkim_hexprint(sig->sig
hash.data, sig->sighash
.len);
}
sig->signature_header = pdkim_create_header(sig, TRUE);
}
sig->signature_header = pdkim_create_header(sig, TRUE);
@@
-1612,7
+1608,7
@@
while (sig)
&& sig->selector && *sig->selector
&& sig->headernames && *sig->headernames
&& sig->bodyhash.data
&& sig->selector && *sig->selector
&& sig->headernames && *sig->headernames
&& sig->bodyhash.data
- && sig->sig
data
.data
+ && sig->sig
hash
.data
&& sig->algo > -1
&& sig->version
) )
&& sig->algo > -1
&& sig->version
) )
@@
-1642,7
+1638,7
@@
while (sig)
goto NEXT_VERIFY;
/* Check the signature */
goto NEXT_VERIFY;
/* Check the signature */
- if ((errstr = exim_rsa_verify(&vctx, is_sha1, &hhash, &sig->sig
data
)))
+ if ((errstr = exim_rsa_verify(&vctx, is_sha1, &hhash, &sig->sig
hash
)))
{
DEBUG(D_acl) debug_printf("headers verify: %s\n", errstr);
sig->verify_status = PDKIM_VERIFY_FAIL;
{
DEBUG(D_acl) debug_printf("headers verify: %s\n", errstr);
sig->verify_status = PDKIM_VERIFY_FAIL;
@@
-1729,7
+1725,12
@@
sig->selector = string_copy(US selector);
sig->rsa_privkey = string_copy(US rsa_privkey);
sig->algo = algo;
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)
{
DEBUG(D_acl)
{
@@
-1741,7
+1742,6
@@
DEBUG(D_acl)
debug_printf("WARNING: bad dkim key in dns\n");
debug_printf("PDKIM (finished checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
}
debug_printf("WARNING: bad dkim key in dns\n");
debug_printf("PDKIM (finished checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
}
-
return ctx;
}
return ctx;
}