From ab9152ffe9c9930a60e337926e89eb41b1088659 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 9 Feb 2016 23:27:59 +0000 Subject: [PATCH] DKIM: fix selection of header for signing/verification given several. Bug 1792 --- doc/doc-txt/ChangeLog | 5 +- src/src/pdkim/pdkim.c | 71 +++++++++---------- test/log/4503 | 32 ++++----- .../4500-Domain-Keys-Identified-Mail/4503 | 7 +- 4 files changed, 56 insertions(+), 59 deletions(-) diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 12a28dd20..8df028e4e 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -164,10 +164,13 @@ JH/38 Fix cutthrough bug with body lines having a single dot. The dot was received - but deduplicating mailstores were liable to retain only the initial truncated version. -JH/39 Bug 1781: Fix use of private-keys having trailing '=' in the base-64. +JH/39 Bug 1781: Fix use of DKIM private-keys having trailing '=' in the base-64. JH/40 Fix crash in queryprogram router when compiled with EXPERIMENTAL_SRS. +JH/41 Bug 1792: Fix selection of headers to sign for DKIM: bottom-up. While + we're in there, support oversigning also; bug 1309. + Exim version 4.86 diff --git a/src/src/pdkim/pdkim.c b/src/src/pdkim/pdkim.c index a951e6564..c5759b671 100644 --- a/src/src/pdkim/pdkim.c +++ b/src/src/pdkim/pdkim.c @@ -199,15 +199,8 @@ pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist)); if (!new_entry) return NULL; memset(new_entry, 0, sizeof(pdkim_stringlist)); if (!(new_entry->value = strdup(str))) return NULL; -if (base) - { - pdkim_stringlist *last = base; - while (last->next != NULL) { last = last->next; } - last->next = new_entry; - return base; - } -else - return new_entry; +if (base) new_entry->next = base; +return new_entry; } @@ -1152,17 +1145,15 @@ if (ctx->mode == PDKIM_MODE_SIGN) pdkim_signature *sig; for (sig = ctx->sig; sig; sig = sig->next) /* Traverse all signatures */ - if (header_name_match(ctx->cur_header->str, - sig->sign_headers) == PDKIM_OK) - { - pdkim_stringlist *list; + { + pdkim_stringlist *list; - /* Add header to the signed headers list (in reverse order) */ - if (!(list = pdkim_prepend_stringlist(sig->headers, - ctx->cur_header->str))) - return PDKIM_ERR_OOM; - sig->headers = list; - } + /* Add header to the signed headers list (in reverse order) */ + if (!(list = pdkim_prepend_stringlist(sig->headers, + ctx->cur_header->str))) + return PDKIM_ERR_OOM; + sig->headers = list; + } } /* VERIFICATION ----------------------------------------------------------- */ @@ -1594,35 +1585,36 @@ while (sig) int sep = 0; for (p = sig->headers; p; p = p->next) - { - uschar * rh; - /* Collect header names (Note: colon presence is guaranteed here) */ - uschar * q = Ustrchr(p->value, ':'); + if (header_name_match(p->value, sig->sign_headers) == PDKIM_OK) + { + uschar * rh; + /* Collect header names (Note: colon presence is guaranteed here) */ + uschar * q = Ustrchr(p->value, ':'); - if (!(pdkim_strncat(headernames, p->value, - (q - US p->value) + (p->next ? 1 : 0)))) - return PDKIM_ERR_OOM; + if (!(pdkim_strncat(headernames, p->value, + (q - US p->value) + (p->next ? 1 : 0)))) + return PDKIM_ERR_OOM; - rh = sig->canon_headers == PDKIM_CANON_RELAXED - ? US pdkim_relax_header(p->value, 1) /* cook header for relaxed canon */ - : string_copy(p->value); /* just copy it for simple canon */ - if (!rh) - return PDKIM_ERR_OOM; + rh = sig->canon_headers == PDKIM_CANON_RELAXED + ? US pdkim_relax_header(p->value, 1) /* cook header for relaxed canon */ + : string_copy(p->value); /* just copy it for simple canon */ + if (!rh) + return PDKIM_ERR_OOM; - /* Feed header to the hash algorithm */ - exim_sha_update(&hhash_ctx, rh, strlen(rh)); + /* Feed header to the hash algorithm */ + exim_sha_update(&hhash_ctx, rh, strlen(rh)); - /* Remember headers block for signing (when the library cannot do incremental) */ - (void) exim_rsa_data_append(&hdata, &hdata_alloc, rh); + /* Remember headers block for signing (when the library cannot do incremental) */ + (void) exim_rsa_data_append(&hdata, &hdata_alloc, rh); - DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh)); - } + DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh)); + } l = US sig->sign_headers; while((s = string_nextinlist(&l, &sep, NULL, 0))) if (*s != '_') - { - if (headernames->len > 0) + { /*SSS string_append_listele() */ + if (headernames->len > 0 && headernames->str[headernames->len-1] != ':') if (!(pdkim_strncat(headernames, ":", 1))) return PDKIM_ERR_OOM; if (!(pdkim_strncat(headernames, CS s, Ustrlen(s)))) @@ -1651,6 +1643,7 @@ while (sig) if ((q = Ustrchr(p, ':'))) *q = '\0'; +/*XXX walk the list of headers in same order as received. */ for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next) if ( hdrs->tag == 0 && strncasecmp(hdrs->value, CS p, Ustrlen(p)) == 0 diff --git a/test/log/4503 b/test/log/4503 index cd14c8693..53781b966 100644 --- a/test/log/4503 +++ b/test/log/4503 @@ -1,27 +1,27 @@ 1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss -1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss -1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss -1999-03-02 09:44:33 10HmaX-0005vi-00 => a@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbA-0005vi-00" +1999-03-02 09:44:33 10HmaX-0005vi-00 => a@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmaY-0005vi-00" 1999-03-02 09:44:33 10HmaX-0005vi-00 Completed -1999-03-02 09:44:33 10HmaY-0005vi-00 => b@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbB-0005vi-00" -1999-03-02 09:44:33 10HmaY-0005vi-00 Completed -1999-03-02 09:44:33 10HmaZ-0005vi-00 => c@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbC-0005vi-00" +1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss +1999-03-02 09:44:33 10HmaZ-0005vi-00 => b@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbA-0005vi-00" 1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed +1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss +1999-03-02 09:44:33 10HmbB-0005vi-00 => c@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbC-0005vi-00" +1999-03-02 09:44:33 10HmbB-0005vi-00 Completed ******** 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 10HmaY-0005vi-00 DKIM: d=test.ex s=sel c=relaxed/relaxed a=rsa-sha256 b=1024 [verification succeeded] +1999-03-02 09:44:33 10HmaY-0005vi-00 signer: test.ex bits: 1024 h=From +1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmaX-0005vi-00@myhost.test.ex +1999-03-02 09:44:33 10HmaY-0005vi-00 => :blackhole: R=server_dump +1999-03-02 09:44:33 10HmaY-0005vi-00 Completed 1999-03-02 09:44:33 10HmbA-0005vi-00 DKIM: d=test.ex s=sel c=relaxed/relaxed a=rsa-sha256 b=1024 [verification succeeded] -1999-03-02 09:44:33 10HmbA-0005vi-00 signer: test.ex bits: 1024 h=From -1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmaX-0005vi-00@myhost.test.ex -1999-03-02 09:44:33 10HmbA-0005vi-00 => :blackhole: R=server_dump +1999-03-02 09:44:33 10HmbA-0005vi-00 signer: test.ex bits: 1024 h=From:From +1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmaZ-0005vi-00@myhost.test.ex +1999-03-02 09:44:33 10HmbA-0005vi-00 => :blackhole: R=server_dump 1999-03-02 09:44:33 10HmbA-0005vi-00 Completed -1999-03-02 09:44:33 10HmbB-0005vi-00 DKIM: d=test.ex s=sel c=relaxed/relaxed a=rsa-sha256 b=1024 [verification succeeded] -1999-03-02 09:44:33 10HmbB-0005vi-00 signer: test.ex bits: 1024 h=From:From -1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmaY-0005vi-00@myhost.test.ex -1999-03-02 09:44:33 10HmbB-0005vi-00 => :blackhole: R=server_dump -1999-03-02 09:44:33 10HmbB-0005vi-00 Completed 1999-03-02 09:44:33 10HmbC-0005vi-00 DKIM: d=test.ex s=sel c=relaxed/relaxed a=rsa-sha256 b=1024 [verification succeeded] -1999-03-02 09:44:33 10HmbC-0005vi-00 signer: test.ex bits: 1024 h=From:Message-Id:Sender:Date:Reply-To:Subject:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive -1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmaZ-0005vi-00@myhost.test.ex +1999-03-02 09:44:33 10HmbC-0005vi-00 signer: test.ex bits: 1024 h=Date:Sender:Message-Id:From:Reply-To:Subject:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive +1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmbB-0005vi-00@myhost.test.ex 1999-03-02 09:44:33 10HmbC-0005vi-00 => :blackhole: R=server_dump 1999-03-02 09:44:33 10HmbC-0005vi-00 Completed diff --git a/test/scripts/4500-Domain-Keys-Identified-Mail/4503 b/test/scripts/4500-Domain-Keys-Identified-Mail/4503 index 45be7c2c6..140e6d6bf 100644 --- a/test/scripts/4500-Domain-Keys-Identified-Mail/4503 +++ b/test/scripts/4500-Domain-Keys-Identified-Mail/4503 @@ -4,21 +4,22 @@ exim -bd -DSERVER=server -oX PORT_D **** # # single header signed -exim -DOPT=From a@test.ex +exim -DOPT=From -odf a@test.ex From: nobody@example.com +From: second@example.com content **** # # single header, oversigned -exim -DOPT=From:From b@test.ex +exim -DOPT=From:From -odf b@test.ex From: nobody@example.com content **** # # default header set -exim -DHEADERS_MAXSIZE=y c@test.ex +exim -DHEADERS_MAXSIZE=y -odf c@test.ex From: nobody@example.com content -- 2.30.2