From 6a11a9e618a72b8d96aecb2ad9aa300b98f8d991 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Sun, 29 Nov 2015 01:12:38 +0000 Subject: [PATCH] DKIM: relaxed body canonicalisation should ignore whitespace at EOL and empty lines at EOM. Bug 1721 --- src/src/dkim.c | 1 - src/src/pdkim/pdkim.c | 31 +++++-- test/aux-fixed/4500.msg1.txt | 7 ++ test/aux-fixed/4501.msg1.txt | 11 +++ test/aux-fixed/4502.msg1.txt | 22 +++++ test/aux-fixed/dkim/dkim.private | 15 ++++ test/aux-fixed/dkim/sign.pl | 38 +++++++++ test/confs/4500 | 21 +++++ test/confs/4501 | 1 + test/confs/4502 | 1 + test/dnszones-src/db.test.ex | 8 ++ test/log/4500 | 5 ++ test/log/4501 | 7 ++ test/log/4502 | 5 ++ .../4500-Domain-Keys-Identified-Mail/4500 | 39 +++++++++ .../4500-Domain-Keys-Identified-Mail/4501 | 80 +++++++++++++++++++ .../4500-Domain-Keys-Identified-Mail/4502 | 55 +++++++++++++ 17 files changed, 339 insertions(+), 8 deletions(-) create mode 100644 test/aux-fixed/4500.msg1.txt create mode 100644 test/aux-fixed/4501.msg1.txt create mode 100644 test/aux-fixed/4502.msg1.txt create mode 100644 test/aux-fixed/dkim/dkim.private create mode 100644 test/aux-fixed/dkim/sign.pl create mode 100644 test/confs/4500 create mode 120000 test/confs/4501 create mode 120000 test/confs/4502 create mode 100644 test/log/4500 create mode 100644 test/log/4501 create mode 100644 test/log/4502 create mode 100644 test/scripts/4500-Domain-Keys-Identified-Mail/4500 create mode 100644 test/scripts/4500-Domain-Keys-Identified-Mail/4501 create mode 100644 test/scripts/4500-Domain-Keys-Identified-Mail/4502 diff --git a/src/src/dkim.c b/src/src/dkim.c index 504595815..6bae64174 100644 --- a/src/src/dkim.c +++ b/src/src/dkim.c @@ -231,7 +231,6 @@ dkim_exim_acl_setup(uschar * id) pdkim_signature * sig; uschar * cmp_val; - dkim_cur_sig = NULL; dkim_cur_signer = id; diff --git a/src/src/pdkim/pdkim.c b/src/src/pdkim/pdkim.c index cd7952174..de774a265 100644 --- a/src/src/pdkim/pdkim.c +++ b/src/src/pdkim/pdkim.c @@ -596,7 +596,7 @@ pdkim_signature *pdkim_parse_sig_header(pdkim_ctx *ctx, char *raw_hdr) { pdkim_strtrim(cur_val); #ifdef PDKIM_DEBUG if (ctx->debug_stream) - fprintf(ctx->debug_stream, "%s=%s\n", cur_tag->str, cur_val->str); + fprintf(ctx->debug_stream, " %s=%s\n", cur_tag->str, cur_val->str); #endif switch (cur_tag->str[0]) { case 'b': @@ -674,7 +674,7 @@ pdkim_signature *pdkim_parse_sig_header(pdkim_ctx *ctx, char *raw_hdr) { default: #ifdef PDKIM_DEBUG if (ctx->debug_stream) - fprintf(ctx->debug_stream, "Unknown tag encountered\n"); + fprintf(ctx->debug_stream, " Unknown tag encountered\n"); #endif break; } @@ -799,7 +799,7 @@ pdkim_pubkey *pdkim_parse_pubkey_record(pdkim_ctx *ctx, char *raw_record) { pdkim_strtrim(cur_val); #ifdef PDKIM_DEBUG if (ctx->debug_stream) - fprintf(ctx->debug_stream, "%s=%s\n", cur_tag->str, cur_val->str); + fprintf(ctx->debug_stream, " %s=%s\n", cur_tag->str, cur_val->str); #endif switch (cur_tag->str[0]) { case 'v': @@ -833,7 +833,7 @@ pdkim_pubkey *pdkim_parse_pubkey_record(pdkim_ctx *ctx, char *raw_record) { default: #ifdef PDKIM_DEBUG if (ctx->debug_stream) - fprintf(ctx->debug_stream, "Unknown tag encountered\n"); + fprintf(ctx->debug_stream, " Unknown tag encountered\n"); #endif break; } @@ -925,7 +925,7 @@ int pdkim_update_bodyhash(pdkim_ctx *ctx, const char *data, int len) { sig->signed_body_bytes += canon_len; #ifdef PDKIM_DEBUG if (ctx->debug_stream!=NULL) - pdkim_quoteprint(ctx->debug_stream,canon_data,canon_len,0); + pdkim_quoteprint(ctx->debug_stream,canon_data,canon_len,1); #endif } @@ -1037,6 +1037,23 @@ int pdkim_bodyline_complete(pdkim_ctx *ctx) { goto BAIL; } + if ( ctx->sig + && ctx->sig->canon_body == PDKIM_CANON_RELAXED) { + /* Lines with just spaces need to be buffered too */ + char *check = p; + while(memcmp(check,"\r\n",2) != 0) { + char c = *check; + + if (c != '\t' && c != ' ') + goto PROCESS; + check++; + } + + ctx->num_buffered_crlf++; + goto BAIL; + } + + PROCESS: /* At this point, we have a non-empty line, so release the buffered ones. */ while (ctx->num_buffered_crlf) { pdkim_update_bodyhash(ctx,"\r\n",2); @@ -1699,7 +1716,7 @@ DLLEXPORT int pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatu if (ctx->debug_stream) { fprintf(ctx->debug_stream, "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); - fprintf(ctx->debug_stream,"Raw record: "); + fprintf(ctx->debug_stream," Raw record: "); pdkim_quoteprint(ctx->debug_stream, dns_txt_reply, strlen(dns_txt_reply), 1); } #endif @@ -1710,7 +1727,7 @@ DLLEXPORT int pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatu sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_PARSING; #ifdef PDKIM_DEBUG if (ctx->debug_stream) { - fprintf(ctx->debug_stream,"Error while parsing public key record\n"); + fprintf(ctx->debug_stream," Error while parsing public key record\n"); fprintf(ctx->debug_stream, "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); } diff --git a/test/aux-fixed/4500.msg1.txt b/test/aux-fixed/4500.msg1.txt new file mode 100644 index 000000000..957ef430b --- /dev/null +++ b/test/aux-fixed/4500.msg1.txt @@ -0,0 +1,7 @@ +From: mrgus@text.ex +To: bakawolf@yahoo.com +Date: Thu, 19 Nov 2015 17:00:07 -0700 +Message-ID: +Subject: simple test + +This is a simple test. diff --git a/test/aux-fixed/4501.msg1.txt b/test/aux-fixed/4501.msg1.txt new file mode 100644 index 000000000..93311ee81 --- /dev/null +++ b/test/aux-fixed/4501.msg1.txt @@ -0,0 +1,11 @@ +From: mrgus@test.ex +To: bakawolf@yahoo.com +Date: Thu, 19 Nov 2015 17:00:07 -0700 +Message-ID: +Subject: simple space test + +This is a test of simple with spaces. + + + +End of content (spaced line two lines down). diff --git a/test/aux-fixed/4502.msg1.txt b/test/aux-fixed/4502.msg1.txt new file mode 100644 index 000000000..6b45a4009 --- /dev/null +++ b/test/aux-fixed/4502.msg1.txt @@ -0,0 +1,22 @@ +Message-ID: <564CFC9B.1040905@yahoo.com> +Date: Wed, 18 Nov 2015 14:32:59 -0800 +From: Joaquin Lopez +User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:24.0) Gecko/20100101 Thunderbird/24.0 +MIME-Version: 1.0 +To: bakawolf@yahoo.com +Subject: test +Content-Type: text/plain; charset=ISO-8859-1; format=flowed +Content-Transfer-Encoding: 7bit +Content-Length: 13 + + + +test + + + + + + + + diff --git a/test/aux-fixed/dkim/dkim.private b/test/aux-fixed/dkim/dkim.private new file mode 100644 index 000000000..e509ee027 --- /dev/null +++ b/test/aux-fixed/dkim/dkim.private @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDXRFf+VhT+lCgFhhSkinZKcFNeRzjYdW8vT29Rbb3NadvTFwAd ++cVLPFwZL8H5tUD/7JbUPqNTCPxmpgIL+V5T4tEZMorHatvvUM2qfcpQ45IfsZ+Y +dhbIiAslHCpy4xNxIR3zylgqRUF4+Dtsaqy3a5LhwMiKCLrnzhXk1F1hxwIDAQAB +AoGAZPokJKQQmRK6a0zn5f8lWemy0airG66KhzDF0Pafb/nWKgDCB02gpJgdw5rJ +bO7/HI3IeqsfRdYTP7tjfmZtPiPo1mnF7D1rSRspZjOF2yXY/ky7t7c5xChRcSxf ++69CknwjrfteY9Aj0j6o7N+2w2uvHO+AAq8BHDgXKmPo0SECQQDzQ/glyhNH9tlO +x+3TTMwwyZUf2mYYosN3Q9NIl3Umz/3+13K5b6Ed6fZvS/XwU55Qf5IBUVj2Fujk +Rv2lbGPpAkEA4okpnzYz5nm1X5WjpJPQPyo8nGEU1A5QfoDbkAvWYvVoYrpWPOx5 +HFpOAHkvSk1Y1vhCUa+zHwiQRBC8OMp6LwJBAOAUK/AjQ792UpWO9DM++pe2F/dP +ZdwrkYG6qFSlrvQhgwXLz5GgkfjMGoRKpDDL1XixCfzMwfVtBPnBqsNGJIECQGYX +SIGu7L7edMXJ60C9OKluwHf9LGTQuqf4LHsDSq+4Rz3PGhREwePsMqD1/EDxEKt4 +oHKtyvyeYF28aQbzARMCQQCRtJlR6vlKhxYL8+xoPrCu3MijKgVruRUcNstXkDZK +fKQax6vhiMq+0qIiEwLA1wavyLVKZ7Mfag+/4NTcDUVC +-----END RSA PRIVATE KEY----- diff --git a/test/aux-fixed/dkim/sign.pl b/test/aux-fixed/dkim/sign.pl new file mode 100644 index 000000000..1c2a87280 --- /dev/null +++ b/test/aux-fixed/dkim/sign.pl @@ -0,0 +1,38 @@ +use Mail::DKIM::Signer; +use Mail::DKIM::TextWrap; #recommended +use Getopt::Long; + +my $method = "simple/simple"; + +GetOptions( + "method=s" => \$method, +); + +# create a signer object +my $dkim = Mail::DKIM::Signer->new( + Algorithm => "rsa-sha1", + Method => $method, + Domain => "test.ex", + Selector => "sel", + KeyFile => "aux-fixed/dkim/dkim.private", + ); + +# read an email and pass it into the signer, one line at a time +while () +{ + # remove local line terminators + chomp; + s/\015$//; + + # use SMTP line terminators + $dkim->PRINT("$_\015\012"); +} +$dkim->CLOSE; + +# what is the signature result? +my $signature = $dkim->signature; +print $signature->as_string; +print "\n"; + +#print $dkim->headers; +#print "\n"; diff --git a/test/confs/4500 b/test/confs/4500 new file mode 100644 index 000000000..e452bc091 --- /dev/null +++ b/test/confs/4500 @@ -0,0 +1,21 @@ +# Exim test configuration 4500 + +SERVER= + +exim_path = EXIM_PATH +host_lookup_order = bydns +primary_hostname = myhost.test.ex +spool_directory = DIR/spool +log_file_path = DIR/spool/log/SERVER%slog +gecos_pattern = "" +gecos_name = CALLER_NAME +tls_advertise_hosts = + +# ----- Main settings ----- + +acl_smtp_rcpt = accept + +queue_only +queue_run_in_order + +# End diff --git a/test/confs/4501 b/test/confs/4501 new file mode 120000 index 000000000..c4f73bacd --- /dev/null +++ b/test/confs/4501 @@ -0,0 +1 @@ +4500 \ No newline at end of file diff --git a/test/confs/4502 b/test/confs/4502 new file mode 120000 index 000000000..c4f73bacd --- /dev/null +++ b/test/confs/4502 @@ -0,0 +1 @@ +4500 \ No newline at end of file diff --git a/test/dnszones-src/db.test.ex b/test/dnszones-src/db.test.ex index 61f274eb0..6b8a531af 100644 --- a/test/dnszones-src/db.test.ex +++ b/test/dnszones-src/db.test.ex @@ -454,5 +454,13 @@ DNSSEC dane.no.2 A 127.0.0.1 DELAY=500 delay500 A HOSTIPV4 DELAY=1500 delay1500 A HOSTIPV4 +; ------- DKIM --------- + +; public key, base64 - matches private key in aux-fixed/dkim/dkim/private +; openssl genrsa -out aux-fixed/dkim/dkim.private 1024 +; openssl rsa -in aux-fixed/dkim/dkim.private -out /dev/stdout -pubout -outform PEM +; +sel._domainkey TXT "v=DKIM1; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXRFf+VhT+lCgFhhSkinZKcFNeRzjYdW8vT29Rbb3NadvTFwAd+cVLPFwZL8H5tUD/7JbUPqNTCPxmpgIL+V5T4tEZMorHatvvUM2qfcpQ45IfsZ+YdhbIiAslHCpy4xNxIR3zylgqRUF4+Dtsaqy3a5LhwMiKCLrnzhXk1F1hxwIDAQAB" + ; End diff --git a/test/log/4500 b/test/log/4500 new file mode 100644 index 000000000..5ab02f31d --- /dev/null +++ b/test/log/4500 @@ -0,0 +1,5 @@ + +******** SERVER ******** +1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 +1999-03-02 09:44:33 10HmaX-0005vi-00 DKIM: d=test.ex s=sel c=simple/simple a=rsa-sha1 [verification succeeded] +1999-03-02 09:44:33 10HmaX-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/4501 b/test/log/4501 new file mode 100644 index 000000000..223417674 --- /dev/null +++ b/test/log/4501 @@ -0,0 +1,7 @@ + +******** SERVER ******** +1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 +1999-03-02 09:44:33 10HmaX-0005vi-00 DKIM: d=test.ex s=sel c=simple/simple a=rsa-sha1 [verification succeeded] +1999-03-02 09:44:33 10HmaX-0005vi-00 <= pass@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss id=qwerty1234@disco-zombie.net +1999-03-02 09:44:33 10HmaY-0005vi-00 DKIM: d=test.ex s=sel c=simple/simple a=rsa-sha1 [verification failed - body hash mismatch (body probably modified in transit)] +1999-03-02 09:44:33 10HmaY-0005vi-00 <= fail@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss id=qwerty1234@disco-zombie.net diff --git a/test/log/4502 b/test/log/4502 new file mode 100644 index 000000000..1e6be43f0 --- /dev/null +++ b/test/log/4502 @@ -0,0 +1,5 @@ + +******** SERVER ******** +1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 +1999-03-02 09:44:33 10HmaX-0005vi-00 DKIM: d=test.ex s=sel c=relaxed/relaxed a=rsa-sha1 [verification succeeded] +1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss id=564CFC9B.1040905@yahoo.com diff --git a/test/scripts/4500-Domain-Keys-Identified-Mail/4500 b/test/scripts/4500-Domain-Keys-Identified-Mail/4500 new file mode 100644 index 000000000..1dea02245 --- /dev/null +++ b/test/scripts/4500-Domain-Keys-Identified-Mail/4500 @@ -0,0 +1,39 @@ +# DKIM simple canonicalisation +# +exim -DSERVER=server -bd -oX PORT_D +**** +# +# This should pass. +# Mail original in aux-fixed/4500.msg1.txt +# Sig generatd by: perl aux-fixed/dkim/sign.pl --method=simple/simple < aux-fixed/4500.msg1.txt +client 127.0.0.1 PORT_D +??? 220 +HELO xxx +??? 250 +MAIL FROM: +??? 250 +RCPT TO: +??? 250 +DATA +??? 354 +DKIM-Signature: v=1; a=rsa-sha1; c=simple/simple; d=test.ex; h=from:to + :date:message-id:subject; s=sel; bh=OB9dZVu7+5/ufs3TH9leIcEpXSo=; b= + PeUA8iBGfStWv+9/BBKkvCEYj/AVMl4e9k+AqWOXKyuEUfHxqAnV+sPnOejpmvT8 + 41kuM4u0bICvK371YvB/yO61vtliRhyqU76Y2e55p2uvMADb3UyDhLyzpco4+yBo + 1w0AuIxu0VU4TK8UmOLyCw/1hxrh1DcEInbEMEKJ7kI= +From: mrgus@text.ex +To: bakawolf@yahoo.com +Date: Thu, 19 Nov 2015 17:00:07 -0700 +Message-ID: +Subject: simple test + +This is a simple test. +. +??? 250 +QUIT +??? 221 +**** +# +killdaemon +no_stdout_check +no_msglog_check diff --git a/test/scripts/4500-Domain-Keys-Identified-Mail/4501 b/test/scripts/4500-Domain-Keys-Identified-Mail/4501 new file mode 100644 index 000000000..5a4bf2be6 --- /dev/null +++ b/test/scripts/4500-Domain-Keys-Identified-Mail/4501 @@ -0,0 +1,80 @@ +# DKIM simple canonicalisation, with spaces +# +exim -DSERVER=server -bd -oX PORT_D +**** +# +# this should pass verification +# Mail original in aux-fixed/4501.msg1.txt +# Sig generated by: perl aux-fixed/dkim/sign.pl --method=simple/simple < aux-fixed/4501.msg1.txt +client 127.0.0.1 PORT_D +??? 220 +HELO xxx +??? 250 +MAIL FROM: +??? 250 +RCPT TO: +??? 250 +DATA +??? 354 +DKIM-Signature: v=1; a=rsa-sha1; c=simple/simple; d=test.ex; h=from:to + :date:message-id:subject; s=sel; bh=pdsXC6mnKSmAYjraebHb2Tt2xqw=; b= + bE9pnPdz5eDwz58PFMAsiFqpcsel33p5+pnvhwY5D6B6suGFbvku+LC1pi77z3lq + 45mFRxT4Dr4rW4612jYi5WpNk8ed28BkNMowUCgkM2TDoktiRClFpXTUX00hCico + KWcgcvORf6L8txhtICsHsl94ERKXxgptXHQk8XwMEuU= +From: mrgus@test.ex +To: bakawolf@yahoo.com +Date: Thu, 19 Nov 2015 17:00:07 -0700 +Message-ID: +Subject: simple space test + +This is a test of simple with spaces. + + + +End of content (spaced line two lines down). +. +??? 250 +QUIT +??? 221 +**** +# +# this should fail verification +# Same message and sig as above, but body extended with (emptyline) (line with only spaces) (emptyline) +client 127.0.0.1 PORT_D +??? 220 +HELO xxx +??? 250 +MAIL FROM: +??? 250 +RCPT TO: +??? 250 +DATA +??? 354 +DKIM-Signature: v=1; a=rsa-sha1; c=simple/simple; d=test.ex; h=from:to + :date:message-id:subject; s=sel; bh=pdsXC6mnKSmAYjraebHb2Tt2xqw=; b= + bE9pnPdz5eDwz58PFMAsiFqpcsel33p5+pnvhwY5D6B6suGFbvku+LC1pi77z3lq + 45mFRxT4Dr4rW4612jYi5WpNk8ed28BkNMowUCgkM2TDoktiRClFpXTUX00hCico + KWcgcvORf6L8txhtICsHsl94ERKXxgptXHQk8XwMEuU= +From: mrgus@test.ex +To: bakawolf@yahoo.com +Date: Thu, 19 Nov 2015 17:00:07 -0700 +Message-ID: +Subject: simple space test + +This is a test of simple with spaces. + + + +End of content (spaced line two lines down). + + + +. +??? 250 +QUIT +??? 221 +**** +# +killdaemon +no_stdout_check +no_msglog_check diff --git a/test/scripts/4500-Domain-Keys-Identified-Mail/4502 b/test/scripts/4500-Domain-Keys-Identified-Mail/4502 new file mode 100644 index 000000000..9f6d62fcd --- /dev/null +++ b/test/scripts/4500-Domain-Keys-Identified-Mail/4502 @@ -0,0 +1,55 @@ +# DKIM relaxed canonicalisation +# +exim -DSERVER=server -bd -oX PORT_D +**** +# +# This should pass. +# Mail original in aux-fixed/4502.msg1.txt +# Sig generated by: perl aux-fixed/dkim/sign.pl --method=relaxed/relaxed < aux_fixed/4502.msg1.txt +client 127.0.0.1 PORT_D +??? 220 +HELO xxx +??? 250 +MAIL FROM: +??? 250 +RCPT TO: +??? 250 +DATA +??? 354 +DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=test.ex; h= + message-id:date:from:mime-version:to:subject:content-type + :content-transfer-encoding; s=sel; bh=rn0kk3aPKyhYbxzfi3WG8dAxhN + M=; b=Tsi3kJtTNmIP0LAkEXR201R/alr7FwaWRAP+V9qQZf7MzAFrkfKAhkT3UQ + zPTJsZowOZaM1UoeeDQCvfvHG5YG8YCFwU3tuLgdDvbCmYJvR+jPNntN27BXcrVH + fyQLstR8eQPUopT7vmdYwsMlXz0Jv7iLM1MyxsWn6z1LTlvYA= +Message-ID: <564CFC9B.1040905@yahoo.com> +Date: Wed, 18 Nov 2015 14:32:59 -0800 +From: Joaquin Lopez +User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:24.0) Gecko/20100101 Thunderbird/24.0 +MIME-Version: 1.0 +To: bakawolf@yahoo.com +Subject: test +Content-Type: text/plain; charset=ISO-8859-1; format=flowed +Content-Transfer-Encoding: 7bit +Content-Length: 13 + + + +test + + + + + + + + +. +??? 250 +QUIT +??? 221 +**** +# +killdaemon +no_stdout_check +no_msglog_check -- 2.25.1