2 * PDKIM - a RFC4871 (DKIM) implementation
4 * Copyright (C) 2009 - 2016 Tom Kistner <tom@duncanthrax.net>
5 * Copyright (C) 2016 - 2017 Jeremy Harris <jgh@exim.org>
7 * http://duncanthrax.net/pdkim/
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #ifndef DISABLE_DKIM /* entire file */
30 # error Need SUPPORT_TLS for DKIM
33 #include "crypt_ver.h"
36 # include <openssl/rsa.h>
37 # include <openssl/ssl.h>
38 # include <openssl/err.h>
39 #elif defined(RSA_GNUTLS)
40 # include <gnutls/gnutls.h>
41 # include <gnutls/x509.h>
47 #define PDKIM_SIGNATURE_VERSION "1"
48 #define PDKIM_PUB_RECORD_VERSION US "DKIM1"
50 #define PDKIM_MAX_HEADER_LEN 65536
51 #define PDKIM_MAX_HEADERS 512
52 #define PDKIM_MAX_BODY_LINE_LEN 16384
53 #define PDKIM_DNS_TXT_MAX_NAMELEN 1024
54 #define PDKIM_DEFAULT_SIGN_HEADERS "From:Sender:Reply-To:Subject:Date:"\
55 "Message-ID:To:Cc:MIME-Version:Content-Type:"\
56 "Content-Transfer-Encoding:Content-ID:"\
57 "Content-Description:Resent-Date:Resent-From:"\
58 "Resent-Sender:Resent-To:Resent-Cc:"\
59 "Resent-Message-ID:In-Reply-To:References:"\
60 "List-Id:List-Help:List-Unsubscribe:"\
61 "List-Subscribe:List-Post:List-Owner:List-Archive"
63 /* -------------------------------------------------------------------------- */
64 struct pdkim_stringlist
{
70 /* -------------------------------------------------------------------------- */
71 /* A bunch of list constants */
72 const uschar
* pdkim_querymethods
[] = {
76 const uschar
* pdkim_algos
[] = {
81 const uschar
* pdkim_canons
[] = {
86 const uschar
* pdkim_hashes
[] = {
91 const uschar
* pdkim_keytypes
[] = {
96 typedef struct pdkim_combined_canon_entry
{
100 } pdkim_combined_canon_entry
;
102 pdkim_combined_canon_entry pdkim_combined_canons
[] = {
103 { US
"simple/simple", PDKIM_CANON_SIMPLE
, PDKIM_CANON_SIMPLE
},
104 { US
"simple/relaxed", PDKIM_CANON_SIMPLE
, PDKIM_CANON_RELAXED
},
105 { US
"relaxed/simple", PDKIM_CANON_RELAXED
, PDKIM_CANON_SIMPLE
},
106 { US
"relaxed/relaxed", PDKIM_CANON_RELAXED
, PDKIM_CANON_RELAXED
},
107 { US
"simple", PDKIM_CANON_SIMPLE
, PDKIM_CANON_SIMPLE
},
108 { US
"relaxed", PDKIM_CANON_RELAXED
, PDKIM_CANON_SIMPLE
},
113 /* -------------------------------------------------------------------------- */
116 pdkim_verify_status_str(int status
)
120 case PDKIM_VERIFY_NONE
: return "PDKIM_VERIFY_NONE";
121 case PDKIM_VERIFY_INVALID
: return "PDKIM_VERIFY_INVALID";
122 case PDKIM_VERIFY_FAIL
: return "PDKIM_VERIFY_FAIL";
123 case PDKIM_VERIFY_PASS
: return "PDKIM_VERIFY_PASS";
124 default: return "PDKIM_VERIFY_UNKNOWN";
129 pdkim_verify_ext_status_str(int ext_status
)
133 case PDKIM_VERIFY_FAIL_BODY
: return "PDKIM_VERIFY_FAIL_BODY";
134 case PDKIM_VERIFY_FAIL_MESSAGE
: return "PDKIM_VERIFY_FAIL_MESSAGE";
135 case PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH
: return "PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH";
136 case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE
: return "PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE";
137 case PDKIM_VERIFY_INVALID_BUFFER_SIZE
: return "PDKIM_VERIFY_INVALID_BUFFER_SIZE";
138 case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD
: return "PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD";
139 case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT
: return "PDKIM_VERIFY_INVALID_PUBKEY_IMPORT";
140 case PDKIM_VERIFY_INVALID_SIGNATURE_ERROR
: return "PDKIM_VERIFY_INVALID_SIGNATURE_ERROR";
141 case PDKIM_VERIFY_INVALID_DKIM_VERSION
: return "PDKIM_VERIFY_INVALID_DKIM_VERSION";
142 default: return "PDKIM_VERIFY_UNKNOWN";
147 pdkim_errstr(int status
)
151 case PDKIM_OK
: return US
"OK";
152 case PDKIM_FAIL
: return US
"FAIL";
153 case PDKIM_ERR_RSA_PRIVKEY
: return US
"RSA_PRIVKEY";
154 case PDKIM_ERR_RSA_SIGNING
: return US
"RSA SIGNING";
155 case PDKIM_ERR_LONG_LINE
: return US
"RSA_LONG_LINE";
156 case PDKIM_ERR_BUFFER_TOO_SMALL
: return US
"BUFFER_TOO_SMALL";
157 case PDKIM_SIGN_PRIVKEY_WRAP
: return US
"PRIVKEY_WRAP";
158 case PDKIM_SIGN_PRIVKEY_B64D
: return US
"PRIVKEY_B64D";
159 default: return US
"(unknown)";
164 /* -------------------------------------------------------------------------- */
165 /* Print debugging functions */
167 pdkim_quoteprint(const uschar
*data
, int len
)
170 for (i
= 0; i
< len
; i
++)
172 const int c
= data
[i
];
175 case ' ' : debug_printf("{SP}"); break;
176 case '\t': debug_printf("{TB}"); break;
177 case '\r': debug_printf("{CR}"); break;
178 case '\n': debug_printf("{LF}"); break;
179 case '{' : debug_printf("{BO}"); break;
180 case '}' : debug_printf("{BC}"); break;
182 if ( (c
< 32) || (c
> 127) )
183 debug_printf("{%02x}", c
);
185 debug_printf("%c", c
);
193 pdkim_hexprint(const uschar
*data
, int len
)
196 if (data
) for (i
= 0 ; i
< len
; i
++) debug_printf("%02x", data
[i
]);
197 else debug_printf("<NULL>");
203 static pdkim_stringlist
*
204 pdkim_prepend_stringlist(pdkim_stringlist
* base
, const uschar
* str
)
206 pdkim_stringlist
* new_entry
= store_get(sizeof(pdkim_stringlist
));
208 memset(new_entry
, 0, sizeof(pdkim_stringlist
));
209 new_entry
->value
= string_copy(str
);
210 if (base
) new_entry
->next
= base
;
216 /* Trim whitespace fore & aft */
219 pdkim_strtrim(uschar
* str
)
223 while (*p
== '\t' || *p
== ' ') p
++; /* skip whitespace */
224 while (*p
) {*q
= *p
; q
++; p
++;} /* dump the leading whitespace */
226 while (q
!= str
&& ( (*q
== '\0') || (*q
== '\t') || (*q
== ' ') ) )
227 { /* dump trailing whitespace */
235 /* -------------------------------------------------------------------------- */
238 pdkim_free_ctx(pdkim_ctx
*ctx
)
243 /* -------------------------------------------------------------------------- */
244 /* Matches the name of the passed raw "header" against
245 the passed colon-separated "tick", and invalidates
246 the entry in tick. Returns OK or fail-code */
247 /*XXX might be safer done using a pdkim_stringlist for "tick" */
250 header_name_match(const uschar
* header
, uschar
* tick
)
256 uschar
* hcolon
= Ustrchr(header
, ':'); /* Get header name */
259 return PDKIM_FAIL
; /* This isn't a header */
261 /* if we had strncmpic() we wouldn't need this copy */
262 hname
= string_copyn(header
, hcolon
-header
);
264 /* Copy tick-off list locally, so we can punch zeroes into it */
265 p
= lcopy
= string_copy(tick
);
267 for (q
= Ustrchr(p
, ':'); q
; q
= Ustrchr(p
, ':'))
270 if (strcmpic(p
, hname
) == 0)
276 if (strcmpic(p
, hname
) == 0)
282 /* Invalidate header name instance in tick-off list */
288 /* -------------------------------------------------------------------------- */
289 /* Performs "relaxed" canonicalization of a header. */
292 pdkim_relax_header(const uschar
* header
, BOOL append_crlf
)
294 BOOL past_field_name
= FALSE
;
295 BOOL seen_wsp
= FALSE
;
297 uschar
* relaxed
= store_get(Ustrlen(header
)+3);
298 uschar
* q
= relaxed
;
300 for (p
= header
; *p
; p
++)
304 if (c
== '\r' || c
== '\n') /* Ignore CR & LF */
306 if (c
== '\t' || c
== ' ')
310 c
= ' '; /* Turns WSP into SP */
314 if (!past_field_name
&& c
== ':')
316 if (seen_wsp
) q
--; /* This removes WSP immediately before the colon */
317 seen_wsp
= TRUE
; /* This removes WSP immediately after the colon */
318 past_field_name
= TRUE
;
323 /* Lowercase header name */
324 if (!past_field_name
) c
= tolower(c
);
328 if (q
> relaxed
&& q
[-1] == ' ') q
--; /* Squash eventual trailing SP */
330 if (append_crlf
) { *q
++ = '\r'; *q
++ = '\n'; }
336 /* -------------------------------------------------------------------------- */
337 #define PDKIM_QP_ERROR_DECODE -1
339 static const uschar
*
340 pdkim_decode_qp_char(const uschar
*qp_p
, int *c
)
342 const uschar
*initial_pos
= qp_p
;
344 /* Advance one char */
347 /* Check for two hex digits and decode them */
348 if (isxdigit(*qp_p
) && isxdigit(qp_p
[1]))
350 /* Do hex conversion */
351 *c
= (isdigit(*qp_p
) ? *qp_p
- '0' : toupper(*qp_p
) - 'A' + 10) << 4;
352 *c
|= isdigit(qp_p
[1]) ? qp_p
[1] - '0' : toupper(qp_p
[1]) - 'A' + 10;
356 /* Illegal char here */
357 *c
= PDKIM_QP_ERROR_DECODE
;
362 /* -------------------------------------------------------------------------- */
365 pdkim_decode_qp(const uschar
* str
)
369 const uschar
* p
= str
;
370 uschar
* n
= store_get(Ustrlen(str
)+1);
378 p
= pdkim_decode_qp_char(p
, &nchar
);
394 /* -------------------------------------------------------------------------- */
397 pdkim_decode_base64(const uschar
* str
, blob
* b
)
400 dlen
= b64decode(str
, &b
->data
);
401 if (dlen
< 0) b
->data
= NULL
;
406 pdkim_encode_base64(blob
* b
)
408 return b64encode(b
->data
, b
->len
);
412 /* -------------------------------------------------------------------------- */
413 #define PDKIM_HDR_LIMBO 0
414 #define PDKIM_HDR_TAG 1
415 #define PDKIM_HDR_VALUE 2
417 static pdkim_signature
*
418 pdkim_parse_sig_header(pdkim_ctx
*ctx
, uschar
* raw_hdr
)
420 pdkim_signature
* sig
;
422 uschar
* cur_tag
= NULL
; int ts
= 0, tl
= 0;
423 uschar
* cur_val
= NULL
; int vs
= 0, vl
= 0;
424 BOOL past_hname
= FALSE
;
425 BOOL in_b_val
= FALSE
;
426 int where
= PDKIM_HDR_LIMBO
;
429 sig
= store_get(sizeof(pdkim_signature
));
430 memset(sig
, 0, sizeof(pdkim_signature
));
431 sig
->bodylength
= -1;
433 /* Set so invalid/missing data error display is accurate */
437 q
= sig
->rawsig_no_b_val
= store_get(Ustrlen(raw_hdr
)+1);
439 for (p
= raw_hdr
; ; p
++)
444 if (c
== '\r' || c
== '\n')
447 /* Fast-forward through header name */
450 if (c
== ':') past_hname
= TRUE
;
454 if (where
== PDKIM_HDR_LIMBO
)
456 /* In limbo, just wait for a tag-char to appear */
457 if (!(c
>= 'a' && c
<= 'z'))
460 where
= PDKIM_HDR_TAG
;
463 if (where
== PDKIM_HDR_TAG
)
465 if (c
>= 'a' && c
<= 'z')
466 cur_tag
= string_catn(cur_tag
, &ts
, &tl
, p
, 1);
471 if (Ustrcmp(cur_tag
, "b") == 0)
476 where
= PDKIM_HDR_VALUE
;
481 if (where
== PDKIM_HDR_VALUE
)
483 if (c
== '\r' || c
== '\n' || c
== ' ' || c
== '\t')
486 if (c
== ';' || c
== '\0')
491 pdkim_strtrim(cur_val
);
493 DEBUG(D_acl
) debug_printf(" %s=%s\n", cur_tag
, cur_val
);
498 pdkim_decode_base64(cur_val
,
499 cur_tag
[1] == 'h' ? &sig
->bodyhash
: &sig
->sighash
);
502 /* We only support version 1, and that is currently the
503 only version there is. */
505 Ustrcmp(cur_val
, PDKIM_SIGNATURE_VERSION
) == 0 ? 1 : -1;
508 for (i
= 0; pdkim_algos
[i
]; i
++)
509 if (Ustrcmp(cur_val
, pdkim_algos
[i
]) == 0)
516 for (i
= 0; pdkim_combined_canons
[i
].str
; i
++)
517 if (Ustrcmp(cur_val
, pdkim_combined_canons
[i
].str
) == 0)
519 sig
->canon_headers
= pdkim_combined_canons
[i
].canon_headers
;
520 sig
->canon_body
= pdkim_combined_canons
[i
].canon_body
;
525 for (i
= 0; pdkim_querymethods
[i
]; i
++)
526 if (Ustrcmp(cur_val
, pdkim_querymethods
[i
]) == 0)
528 sig
->querymethod
= i
;
533 sig
->selector
= string_copy(cur_val
); break;
535 sig
->domain
= string_copy(cur_val
); break;
537 sig
->identity
= pdkim_decode_qp(cur_val
); break;
539 sig
->created
= strtoul(CS cur_val
, NULL
, 10); break;
541 sig
->expires
= strtoul(CS cur_val
, NULL
, 10); break;
543 sig
->bodylength
= strtol(CS cur_val
, NULL
, 10); break;
545 sig
->headernames
= string_copy(cur_val
); break;
547 sig
->copiedheaders
= pdkim_decode_qp(cur_val
); break;
549 DEBUG(D_acl
) debug_printf(" Unknown tag encountered\n");
556 where
= PDKIM_HDR_LIMBO
;
559 cur_val
= string_catn(cur_val
, &vs
, &vl
, p
, 1);
571 /* Chomp raw header. The final newline must not be added to the signature. */
572 while (--q
> sig
->rawsig_no_b_val
&& (*q
== '\r' || *q
== '\n'))
578 "PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
579 pdkim_quoteprint(US sig
->rawsig_no_b_val
, Ustrlen(sig
->rawsig_no_b_val
));
581 "PDKIM >> Sig size: %4u bits\n", (unsigned) sig
->sighash
.len
*8);
583 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
586 if (!exim_sha_init(&sig
->body_hash_ctx
,
587 sig
->algo
== PDKIM_ALGO_RSA_SHA1
? HASH_SHA1
: HASH_SHA256
))
589 DEBUG(D_acl
) debug_printf("PDKIM: hash init internal error\n");
596 /* -------------------------------------------------------------------------- */
598 static pdkim_pubkey
*
599 pdkim_parse_pubkey_record(pdkim_ctx
*ctx
, const uschar
*raw_record
)
605 pub
= store_get(sizeof(pdkim_pubkey
));
606 memset(pub
, 0, sizeof(pdkim_pubkey
));
608 while ((ele
= string_nextinlist(&raw_record
, &sep
, NULL
, 0)))
612 if ((val
= Ustrchr(ele
, '=')))
614 int taglen
= val
++ - ele
;
616 DEBUG(D_acl
) debug_printf(" %.*s=%s\n", taglen
, ele
, val
);
619 case 'v': pub
->version
= val
; break;
620 case 'h': pub
->hashes
= val
; break;
622 case 'g': pub
->granularity
= val
; break;
623 case 'n': pub
->notes
= pdkim_decode_qp(val
); break;
624 case 'p': pdkim_decode_base64(val
, &pub
->key
); break;
625 case 's': pub
->srvtype
= val
; break;
626 case 't': if (Ustrchr(val
, 'y')) pub
->testing
= 1;
627 if (Ustrchr(val
, 's')) pub
->no_subdomaining
= 1;
629 default: DEBUG(D_acl
) debug_printf(" Unknown tag encountered\n"); break;
634 /* Set fallback defaults */
635 if (!pub
->version
) pub
->version
= string_copy(PDKIM_PUB_RECORD_VERSION
);
636 else if (Ustrcmp(pub
->version
, PDKIM_PUB_RECORD_VERSION
) != 0)
638 DEBUG(D_acl
) debug_printf(" Bad v= field\n");
642 if (!pub
->granularity
) pub
->granularity
= US
"*";
644 if (!pub->keytype ) pub->keytype = US"rsa";
646 if (!pub
->srvtype
) pub
->srvtype
= US
"*";
652 DEBUG(D_acl
) debug_printf(" Missing p= field\n");
657 /* -------------------------------------------------------------------------- */
660 pdkim_update_bodyhash(pdkim_ctx
* ctx
, const char * data
, int len
)
662 pdkim_signature
* sig
;
663 uschar
* relaxed_data
= NULL
; /* Cache relaxed version of data */
666 /* Traverse all signatures, updating their hashes. */
667 for (sig
= ctx
->sig
; sig
; sig
= sig
->next
)
669 /* Defaults to simple canon (no further treatment necessary) */
670 const uschar
*canon_data
= CUS data
;
673 if (sig
->canon_body
== PDKIM_CANON_RELAXED
)
675 /* Relax the line if not done already */
678 BOOL seen_wsp
= FALSE
;
682 /* We want to be able to free this else we allocate
683 for the entire message which could be many MB. Since
684 we don't know what allocations the SHA routines might
685 do, not safe to use store_get()/store_reset(). */
687 relaxed_data
= store_malloc(len
+1);
689 for (p
= data
; *p
; p
++)
694 if (q
> 0 && relaxed_data
[q
-1] == ' ')
697 else if (c
== '\t' || c
== ' ')
699 c
= ' '; /* Turns WSP into SP */
706 relaxed_data
[q
++] = c
;
708 relaxed_data
[q
] = '\0';
711 canon_data
= relaxed_data
;
712 canon_len
= relaxed_len
;
715 /* Make sure we don't exceed the to-be-signed body length */
716 if ( sig
->bodylength
>= 0
717 && sig
->signed_body_bytes
+ (unsigned long)canon_len
> sig
->bodylength
719 canon_len
= sig
->bodylength
- sig
->signed_body_bytes
;
723 exim_sha_update(&sig
->body_hash_ctx
, CUS canon_data
, canon_len
);
724 sig
->signed_body_bytes
+= canon_len
;
725 DEBUG(D_acl
) pdkim_quoteprint(canon_data
, canon_len
);
729 if (relaxed_data
) store_free(relaxed_data
);
734 /* -------------------------------------------------------------------------- */
737 pdkim_finish_bodyhash(pdkim_ctx
*ctx
)
739 pdkim_signature
*sig
;
741 /* Traverse all signatures */
742 for (sig
= ctx
->sig
; sig
; sig
= sig
->next
)
743 { /* Finish hashes */
746 exim_sha_finish(&sig
->body_hash_ctx
, &bh
);
750 debug_printf("PDKIM [%s] Body bytes hashed: %lu\n"
751 "PDKIM [%s] Body hash computed: ",
752 sig
->domain
, sig
->signed_body_bytes
, sig
->domain
);
753 pdkim_hexprint(CUS bh
.data
, bh
.len
);
756 /* SIGNING -------------------------------------------------------------- */
757 if (ctx
->flags
& PDKIM_MODE_SIGN
)
761 /* If bodylength limit is set, and we have received less bytes
762 than the requested amount, effectively remove the limit tag. */
763 if (sig
->signed_body_bytes
< sig
->bodylength
)
764 sig
->bodylength
= -1;
768 /* VERIFICATION --------------------------------------------------------- */
769 /* Be careful that the header sig included a bodyash */
771 if (sig
->bodyhash
.data
&& memcmp(bh
.data
, sig
->bodyhash
.data
, bh
.len
) == 0)
773 DEBUG(D_acl
) debug_printf("PDKIM [%s] Body hash verified OK\n", sig
->domain
);
779 debug_printf("PDKIM [%s] Body hash signature from headers: ", sig
->domain
);
780 pdkim_hexprint(sig
->bodyhash
.data
, sig
->bodyhash
.len
);
781 debug_printf("PDKIM [%s] Body hash did NOT verify\n", sig
->domain
);
783 sig
->verify_status
= PDKIM_VERIFY_FAIL
;
784 sig
->verify_ext_status
= PDKIM_VERIFY_FAIL_BODY
;
792 pdkim_body_complete(pdkim_ctx
* ctx
)
794 pdkim_signature
* sig
= ctx
->sig
; /*XXX assumes only one sig */
796 /* In simple body mode, if any empty lines were buffered,
797 replace with one. rfc 4871 3.4.3 */
798 /*XXX checking the signed-body-bytes is a gross hack; I think
799 it indicates that all linebreaks should be buffered, including
800 the one terminating a text line */
802 if ( sig
&& sig
->canon_body
== PDKIM_CANON_SIMPLE
803 && sig
->signed_body_bytes
== 0
804 && ctx
->num_buffered_crlf
> 0
806 pdkim_update_bodyhash(ctx
, "\r\n", 2);
808 ctx
->flags
|= PDKIM_SEEN_EOD
;
809 ctx
->linebuf_offset
= 0;
815 /* -------------------------------------------------------------------------- */
816 /* Call from pdkim_feed below for processing complete body lines */
819 pdkim_bodyline_complete(pdkim_ctx
*ctx
)
821 char *p
= ctx
->linebuf
;
822 int n
= ctx
->linebuf_offset
;
823 pdkim_signature
*sig
= ctx
->sig
; /*XXX assumes only one sig */
825 /* Ignore extra data if we've seen the end-of-data marker */
826 if (ctx
->flags
& PDKIM_SEEN_EOD
) goto BAIL
;
828 /* We've always got one extra byte to stuff a zero ... */
829 ctx
->linebuf
[ctx
->linebuf_offset
] = '\0';
831 /* Terminate on EOD marker */
832 if (ctx
->flags
& PDKIM_DOT_TERM
)
834 if (memcmp(p
, ".\r\n", 3) == 0)
835 return pdkim_body_complete(ctx
);
838 if (memcmp(p
, "..", 2) == 0)
845 /* Empty lines need to be buffered until we find a non-empty line */
846 if (memcmp(p
, "\r\n", 2) == 0)
848 ctx
->num_buffered_crlf
++;
852 if (sig
&& sig
->canon_body
== PDKIM_CANON_RELAXED
)
854 /* Lines with just spaces need to be buffered too */
856 while (memcmp(check
, "\r\n", 2) != 0)
860 if (c
!= '\t' && c
!= ' ')
865 ctx
->num_buffered_crlf
++;
870 /* At this point, we have a non-empty line, so release the buffered ones. */
871 while (ctx
->num_buffered_crlf
)
873 pdkim_update_bodyhash(ctx
, "\r\n", 2);
874 ctx
->num_buffered_crlf
--;
877 pdkim_update_bodyhash(ctx
, p
, n
);
880 ctx
->linebuf_offset
= 0;
885 /* -------------------------------------------------------------------------- */
886 /* Callback from pdkim_feed below for processing complete headers */
887 #define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
890 pdkim_header_complete(pdkim_ctx
* ctx
)
892 pdkim_signature
* sig
, * last_sig
;
894 /* Special case: The last header can have an extra \r appended */
895 if ( (ctx
->cur_header_len
> 1) &&
896 (ctx
->cur_header
[(ctx
->cur_header_len
)-1] == '\r') )
897 --ctx
->cur_header_len
;
898 ctx
->cur_header
[ctx
->cur_header_len
] = '\0';
900 if (++ctx
->num_headers
> PDKIM_MAX_HEADERS
) goto BAIL
;
902 /* SIGNING -------------------------------------------------------------- */
903 if (ctx
->flags
& PDKIM_MODE_SIGN
)
904 for (sig
= ctx
->sig
; sig
; sig
= sig
->next
) /* Traverse all signatures */
906 /* Add header to the signed headers list (in reverse order) */
907 sig
->headers
= pdkim_prepend_stringlist(sig
->headers
,
910 /* VERIFICATION ----------------------------------------------------------- */
911 /* DKIM-Signature: headers are added to the verification list */
917 debug_printf("PDKIM >> raw hdr: ");
918 pdkim_quoteprint(CUS ctx
->cur_header
, ctx
->cur_header_len
);
921 if (strncasecmp(CCS ctx
->cur_header
,
922 DKIM_SIGNATURE_HEADERNAME
,
923 Ustrlen(DKIM_SIGNATURE_HEADERNAME
)) == 0)
925 /* Create and chain new signature block. We could error-check for all
926 required tags here, but prefer to create the internal sig and expicitly
927 fail verification of it later. */
929 DEBUG(D_acl
) debug_printf(
930 "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
932 sig
= pdkim_parse_sig_header(ctx
, ctx
->cur_header
);
934 if (!(last_sig
= ctx
->sig
))
938 while (last_sig
->next
) last_sig
= last_sig
->next
;
939 last_sig
->next
= sig
;
943 /* all headers are stored for signature verification */
944 ctx
->headers
= pdkim_prepend_stringlist(ctx
->headers
, ctx
->cur_header
);
948 ctx
->cur_header
[ctx
->cur_header_len
= 0] = '\0'; /* leave buffer for reuse */
954 /* -------------------------------------------------------------------------- */
955 #define HEADER_BUFFER_FRAG_SIZE 256
958 pdkim_feed(pdkim_ctx
* ctx
, uschar
* data
, int len
)
962 /* Alternate EOD signal, used in non-dotstuffing mode */
964 pdkim_body_complete(ctx
);
966 else for (p
= 0; p
<len
; p
++)
970 if (ctx
->flags
& PDKIM_PAST_HDRS
)
972 if (c
== '\n' && !(ctx
->flags
& PDKIM_SEEN_CR
)) /* emulate the CR */
974 ctx
->linebuf
[ctx
->linebuf_offset
++] = '\r';
975 if (ctx
->linebuf_offset
== PDKIM_MAX_BODY_LINE_LEN
-1)
976 return PDKIM_ERR_LONG_LINE
;
979 /* Processing body byte */
980 ctx
->linebuf
[ctx
->linebuf_offset
++] = c
;
982 ctx
->flags
|= PDKIM_SEEN_CR
;
985 ctx
->flags
&= ~PDKIM_SEEN_CR
;
986 if ((rc
= pdkim_bodyline_complete(ctx
)) != PDKIM_OK
)
990 if (ctx
->linebuf_offset
== PDKIM_MAX_BODY_LINE_LEN
-1)
991 return PDKIM_ERR_LONG_LINE
;
995 /* Processing header byte */
997 ctx
->flags
|= PDKIM_SEEN_CR
;
1000 if (!(ctx
->flags
& PDKIM_SEEN_CR
)) /* emulate the CR */
1001 ctx
->cur_header
= string_catn(ctx
->cur_header
, &ctx
->cur_header_size
,
1002 &ctx
->cur_header_len
, CUS
"\r", 1);
1004 if (ctx
->flags
& PDKIM_SEEN_LF
) /* Seen last header line */
1006 if ((rc
= pdkim_header_complete(ctx
)) != PDKIM_OK
)
1009 ctx
->flags
= (ctx
->flags
& ~(PDKIM_SEEN_LF
|PDKIM_SEEN_CR
)) | PDKIM_PAST_HDRS
;
1010 DEBUG(D_acl
) debug_printf(
1011 "PDKIM >> Body data for hash, canonicalized >>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1015 ctx
->flags
= (ctx
->flags
& ~PDKIM_SEEN_CR
) | PDKIM_SEEN_LF
;
1017 else if (ctx
->flags
& PDKIM_SEEN_LF
)
1019 if (!(c
== '\t' || c
== ' ')) /* End of header */
1020 if ((rc
= pdkim_header_complete(ctx
)) != PDKIM_OK
)
1022 ctx
->flags
&= ~PDKIM_SEEN_LF
;
1025 if (ctx
->cur_header_len
< PDKIM_MAX_HEADER_LEN
)
1026 ctx
->cur_header
= string_catn(ctx
->cur_header
, &ctx
->cur_header_size
,
1027 &ctx
->cur_header_len
, CUS
&data
[p
], 1);
1035 /* Extend a grwong header with a continuation-linebreak */
1037 pdkim_hdr_cont(uschar
* str
, int * size
, int * ptr
, int * col
)
1040 return string_catn(str
, size
, ptr
, US
"\r\n\t", 3);
1046 * RFC 5322 specifies that header line length SHOULD be no more than 78
1050 * returns uschar * (not nul-terminated)
1052 * col: this int holds and receives column number (octets since last '\n')
1053 * str: partial string to append to
1054 * size: current buffer size for str
1055 * ptr: current tail-pointer for str
1056 * pad: padding, split line or space after before or after eg: ";"
1057 * intro: - must join to payload eg "h=", usually the tag name
1058 * payload: eg base64 data - long data can be split arbitrarily.
1060 * this code doesn't fold the header in some of the places that RFC4871
1061 * allows: As per RFC5322(2.2.3) it only folds before or after tag-value
1062 * pairs and inside long values. it also always spaces or breaks after the
1065 * no guarantees are made for output given out-of range input. like tag
1066 * names longer than 78, or bogus col. Input is assumed to be free of line breaks.
1070 pdkim_headcat(int * col
, uschar
* str
, int * size
, int * ptr
,
1071 const uschar
* pad
, const uschar
* intro
, const uschar
* payload
)
1079 str
= pdkim_hdr_cont(str
, size
, ptr
, col
);
1080 str
= string_catn(str
, size
, ptr
, pad
, l
);
1084 l
= (pad
?1:0) + (intro
?Ustrlen(intro
):0);
1087 { /*can't fit intro - start a new line to make room.*/
1088 str
= pdkim_hdr_cont(str
, size
, ptr
, col
);
1089 l
= intro
?Ustrlen(intro
):0;
1092 l
+= payload
? Ustrlen(payload
):0 ;
1095 { /* this fragment will not fit on a single line */
1098 str
= string_catn(str
, size
, ptr
, US
" ", 1);
1100 pad
= NULL
; /* only want this once */
1106 size_t sl
= Ustrlen(intro
);
1108 str
= string_catn(str
, size
, ptr
, intro
, sl
);
1111 intro
= NULL
; /* only want this once */
1116 size_t sl
= Ustrlen(payload
);
1117 size_t chomp
= *col
+sl
< 77 ? sl
: 78-*col
;
1119 str
= string_catn(str
, size
, ptr
, payload
, chomp
);
1125 /* the while precondition tells us it didn't fit. */
1126 str
= pdkim_hdr_cont(str
, size
, ptr
, col
);
1131 str
= pdkim_hdr_cont(str
, size
, ptr
, col
);
1137 str
= string_catn(str
, size
, ptr
, US
" ", 1);
1144 size_t sl
= Ustrlen(intro
);
1146 str
= string_catn(str
, size
, ptr
, intro
, sl
);
1154 size_t sl
= Ustrlen(payload
);
1156 str
= string_catn(str
, size
, ptr
, payload
, sl
);
1164 /* -------------------------------------------------------------------------- */
1167 pdkim_create_header(pdkim_signature
*sig
, BOOL final
)
1172 uschar
* hdr
; int hdr_size
= 0, hdr_len
= 0;
1173 uschar
* canon_all
; int can_size
= 0, can_len
= 0;
1175 canon_all
= string_cat (NULL
, &can_size
, &can_len
,
1176 pdkim_canons
[sig
->canon_headers
]);
1177 canon_all
= string_catn(canon_all
, &can_size
, &can_len
, US
"/", 1);
1178 canon_all
= string_cat (canon_all
, &can_size
, &can_len
,
1179 pdkim_canons
[sig
->canon_body
]);
1180 canon_all
[can_len
] = '\0';
1182 hdr
= string_cat(NULL
, &hdr_size
, &hdr_len
,
1183 US
"DKIM-Signature: v="PDKIM_SIGNATURE_VERSION
);
1186 /* Required and static bits */
1187 hdr
= pdkim_headcat(&col
, hdr
, &hdr_size
, &hdr_len
, US
";", US
"a=",
1188 pdkim_algos
[sig
->algo
]);
1189 hdr
= pdkim_headcat(&col
, hdr
, &hdr_size
, &hdr_len
, US
";", US
"q=",
1190 pdkim_querymethods
[sig
->querymethod
]);
1191 hdr
= pdkim_headcat(&col
, hdr
, &hdr_size
, &hdr_len
, US
";", US
"c=",
1193 hdr
= pdkim_headcat(&col
, hdr
, &hdr_size
, &hdr_len
, US
";", US
"d=",
1195 hdr
= pdkim_headcat(&col
, hdr
, &hdr_size
, &hdr_len
, US
";", US
"s=",
1198 /* list of header names can be split between items. */
1200 uschar
* n
= string_copy(sig
->headernames
);
1201 uschar
* i
= US
"h=";
1206 uschar
* c
= Ustrchr(n
, ':');
1211 hdr
= pdkim_headcat(&col
, hdr
, &hdr_size
, &hdr_len
, NULL
, NULL
, US
":");
1213 hdr
= pdkim_headcat(&col
, hdr
, &hdr_size
, &hdr_len
, s
, i
, n
);
1224 base64_bh
= pdkim_encode_base64(&sig
->bodyhash
);
1225 hdr
= pdkim_headcat(&col
, hdr
, &hdr_size
, &hdr_len
, US
";", US
"bh=", base64_bh
);
1229 hdr
= pdkim_headcat(&col
, hdr
, &hdr_size
, &hdr_len
, US
";", US
"i=", sig
->identity
);
1231 if (sig
->created
> 0)
1235 snprintf(CS minibuf
, sizeof(minibuf
), "%lu", sig
->created
);
1236 hdr
= pdkim_headcat(&col
, hdr
, &hdr_size
, &hdr_len
, US
";", US
"t=", minibuf
);
1239 if (sig
->expires
> 0)
1243 snprintf(CS minibuf
, sizeof(minibuf
), "%lu", sig
->expires
);
1244 hdr
= pdkim_headcat(&col
, hdr
, &hdr_size
, &hdr_len
, US
";", US
"x=", minibuf
);
1247 if (sig
->bodylength
>= 0)
1251 snprintf(CS minibuf
, sizeof(minibuf
), "%lu", sig
->bodylength
);
1252 hdr
= pdkim_headcat(&col
, hdr
, &hdr_size
, &hdr_len
, US
";", US
"l=", minibuf
);
1255 /* Preliminary or final version? */
1258 base64_b
= pdkim_encode_base64(&sig
->sighash
);
1259 hdr
= pdkim_headcat(&col
, hdr
, &hdr_size
, &hdr_len
, US
";", US
"b=", base64_b
);
1261 /* add trailing semicolon: I'm not sure if this is actually needed */
1262 hdr
= pdkim_headcat(&col
, hdr
, &hdr_size
, &hdr_len
, NULL
, US
";", US
"");
1266 /* To satisfy the rule "all surrounding whitespace [...] deleted"
1267 ( RFC 6376 section 3.7 ) we ensure there is no whitespace here. Otherwise
1268 the headcat routine could insert a linebreak which the relaxer would reduce
1269 to a single space preceding the terminating semicolon, resulting in an
1270 incorrect header-hash. */
1271 hdr
= pdkim_headcat(&col
, hdr
, &hdr_size
, &hdr_len
, US
";", US
"b=;", US
"");
1274 hdr
[hdr_len
] = '\0';
1279 /* -------------------------------------------------------------------------- */
1281 static pdkim_pubkey
*
1282 pdkim_key_from_dns(pdkim_ctx
* ctx
, pdkim_signature
* sig
, ev_ctx
* vctx
,
1283 const uschar
** errstr
)
1285 uschar
* dns_txt_name
, * dns_txt_reply
;
1288 /* Fetch public key for signing domain, from DNS */
1290 dns_txt_name
= string_sprintf("%s._domainkey.%s.", sig
->selector
, sig
->domain
);
1292 dns_txt_reply
= store_get(PDKIM_DNS_TXT_MAX_RECLEN
);
1293 memset(dns_txt_reply
, 0, PDKIM_DNS_TXT_MAX_RECLEN
);
1295 if ( ctx
->dns_txt_callback(CS dns_txt_name
, CS dns_txt_reply
) != PDKIM_OK
1296 || dns_txt_reply
[0] == '\0'
1299 sig
->verify_status
= PDKIM_VERIFY_INVALID
;
1300 sig
->verify_ext_status
= PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE
;
1307 "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
1309 pdkim_quoteprint(CUS dns_txt_reply
, Ustrlen(dns_txt_reply
));
1312 if ( !(p
= pdkim_parse_pubkey_record(ctx
, CUS dns_txt_reply
))
1313 || (Ustrcmp(p
->srvtype
, "*") != 0 && Ustrcmp(p
->srvtype
, "email") != 0)
1316 sig
->verify_status
= PDKIM_VERIFY_INVALID
;
1317 sig
->verify_ext_status
= PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD
;
1322 debug_printf(" Invalid public key service type '%s'\n", p
->srvtype
);
1324 debug_printf(" Error while parsing public key record\n");
1326 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1331 DEBUG(D_acl
) debug_printf(
1332 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1334 /* Import public key */
1335 if ((*errstr
= exim_rsa_verify_init(&p
->key
, vctx
)))
1337 DEBUG(D_acl
) debug_printf("verify_init: %s\n", *errstr
);
1338 sig
->verify_status
= PDKIM_VERIFY_INVALID
;
1339 sig
->verify_ext_status
= PDKIM_VERIFY_INVALID_PUBKEY_IMPORT
;
1347 /* -------------------------------------------------------------------------- */
1350 pdkim_feed_finish(pdkim_ctx
* ctx
, pdkim_signature
** return_signatures
,
1351 const uschar
** err
)
1353 pdkim_signature
*sig
= ctx
->sig
;
1355 /* Check if we must still flush a (partial) header. If that is the
1356 case, the message has no body, and we must compute a body hash
1357 out of '<CR><LF>' */
1358 if (ctx
->cur_header
&& ctx
->cur_header_len
)
1360 int rc
= pdkim_header_complete(ctx
);
1361 if (rc
!= PDKIM_OK
) return rc
;
1362 pdkim_update_bodyhash(ctx
, "\r\n", 2);
1365 DEBUG(D_acl
) debug_printf(
1366 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1368 /* Build (and/or evaluate) body hash */
1369 pdkim_finish_bodyhash(ctx
);
1373 BOOL is_sha1
= sig
->algo
== PDKIM_ALGO_RSA_SHA1
;
1375 uschar
* sig_hdr
= US
"";
1378 int hdata_alloc
= 0;
1383 if (!exim_sha_init(&hhash_ctx
, is_sha1
? HASH_SHA1
: HASH_SHA256
))
1385 DEBUG(D_acl
) debug_printf("PDKIM: hask setup internal error\n");
1389 DEBUG(D_acl
) debug_printf(
1390 "PDKIM >> Header data for hash, canonicalized, in sequence >>>>>>>>>>>>\n");
1392 /* SIGNING ---------------------------------------------------------------- */
1393 /* When signing, walk through our header list and add them to the hash. As we
1394 go, construct a list of the header's names to use for the h= parameter.
1395 Then append to that list any remaining header names for which there was no
1398 if (ctx
->flags
& PDKIM_MODE_SIGN
)
1400 uschar
* headernames
= NULL
; /* Collected signed header names */
1402 pdkim_stringlist
*p
;
1407 for (p
= sig
->headers
; p
; p
= p
->next
)
1408 if (header_name_match(p
->value
, sig
->sign_headers
) == PDKIM_OK
)
1411 /* Collect header names (Note: colon presence is guaranteed here) */
1412 uschar
* q
= Ustrchr(p
->value
, ':');
1414 headernames
= string_catn(headernames
, &hs
, &hl
,
1415 p
->value
, (q
- US p
->value
) + (p
->next
? 1 : 0));
1417 rh
= sig
->canon_headers
== PDKIM_CANON_RELAXED
1418 ? pdkim_relax_header(p
->value
, TRUE
) /* cook header for relaxed canon */
1419 : string_copy(CUS p
->value
); /* just copy it for simple canon */
1421 /* Feed header to the hash algorithm */
1422 exim_sha_update(&hhash_ctx
, CUS rh
, Ustrlen(rh
));
1424 /* Remember headers block for signing (when the library cannot do incremental) */
1425 (void) exim_rsa_data_append(&hdata
, &hdata_alloc
, rh
);
1427 DEBUG(D_acl
) pdkim_quoteprint(rh
, Ustrlen(rh
));
1430 l
= sig
->sign_headers
;
1431 while((s
= string_nextinlist(&l
, &sep
, NULL
, 0)))
1433 { /*SSS string_append_listele() */
1434 if (hl
> 0 && headernames
[hl
-1] != ':')
1435 headernames
= string_catn(headernames
, &hs
, &hl
, US
":", 1);
1437 headernames
= string_cat(headernames
, &hs
, &hl
, s
);
1439 headernames
[hl
] = '\0';
1441 /* Copy headernames to signature struct */
1442 sig
->headernames
= headernames
;
1444 /* Create signature header with b= omitted */
1445 sig_hdr
= pdkim_create_header(sig
, FALSE
);
1448 /* VERIFICATION ----------------------------------------------------------- */
1449 /* When verifying, walk through the header name list in the h= parameter and
1450 add the headers to the hash in that order. */
1453 uschar
* p
= sig
->headernames
;
1455 pdkim_stringlist
* hdrs
;
1460 for (hdrs
= ctx
->headers
; hdrs
; hdrs
= hdrs
->next
)
1466 if ((q
= Ustrchr(p
, ':')))
1469 /*XXX walk the list of headers in same order as received. */
1470 for (hdrs
= ctx
->headers
; hdrs
; hdrs
= hdrs
->next
)
1472 && strncasecmp(CCS hdrs
->value
, CCS p
, Ustrlen(p
)) == 0
1473 && (hdrs
->value
)[Ustrlen(p
)] == ':'
1476 /* cook header for relaxed canon, or just copy it for simple */
1478 uschar
* rh
= sig
->canon_headers
== PDKIM_CANON_RELAXED
1479 ? pdkim_relax_header(hdrs
->value
, TRUE
)
1480 : string_copy(CUS hdrs
->value
);
1482 /* Feed header to the hash algorithm */
1483 exim_sha_update(&hhash_ctx
, CUS rh
, Ustrlen(rh
));
1485 DEBUG(D_acl
) pdkim_quoteprint(rh
, Ustrlen(rh
));
1494 sig_hdr
= string_copy(sig
->rawsig_no_b_val
);
1498 DEBUG(D_acl
) debug_printf(
1499 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1501 /* Relax header if necessary */
1502 if (sig
->canon_headers
== PDKIM_CANON_RELAXED
)
1503 sig_hdr
= pdkim_relax_header(sig_hdr
, FALSE
);
1508 "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
1509 pdkim_quoteprint(CUS sig_hdr
, Ustrlen(sig_hdr
));
1511 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1514 /* Finalize header hash */
1515 exim_sha_update(&hhash_ctx
, CUS sig_hdr
, Ustrlen(sig_hdr
));
1516 exim_sha_finish(&hhash_ctx
, &hhash
);
1520 debug_printf("PDKIM [%s] Header hash computed: ", sig
->domain
);
1521 pdkim_hexprint(hhash
.data
, hhash
.len
);
1524 /* Remember headers block for signing (when the library cannot do incremental) */
1525 if (ctx
->flags
& PDKIM_MODE_SIGN
)
1526 (void) exim_rsa_data_append(&hdata
, &hdata_alloc
, US sig_hdr
);
1528 /* SIGNING ---------------------------------------------------------------- */
1529 if (ctx
->flags
& PDKIM_MODE_SIGN
)
1533 /* Import private key */
1534 if ((*err
= exim_rsa_signing_init(US sig
->rsa_privkey
, &sctx
)))
1536 DEBUG(D_acl
) debug_printf("signing_init: %s\n", *err
);
1537 return PDKIM_ERR_RSA_PRIVKEY
;
1540 /* Do signing. With OpenSSL we are signing the hash of headers just
1541 calculated, with GnuTLS we have to sign an entire block of headers
1542 (due to available interfaces) and it recalculates the hash internally. */
1544 #if defined(RSA_OPENSSL) || defined(RSA_GCRYPT)
1548 if ((*err
= exim_rsa_sign(&sctx
, is_sha1
, &hdata
, &sig
->sighash
)))
1550 DEBUG(D_acl
) debug_printf("signing: %s\n", *err
);
1551 return PDKIM_ERR_RSA_SIGNING
;
1556 debug_printf( "PDKIM [%s] b computed: ", sig
->domain
);
1557 pdkim_hexprint(sig
->sighash
.data
, sig
->sighash
.len
);
1560 sig
->signature_header
= pdkim_create_header(sig
, TRUE
);
1563 /* VERIFICATION ----------------------------------------------------------- */
1568 /* Make sure we have all required signature tags */
1569 if (!( sig
->domain
&& *sig
->domain
1570 && sig
->selector
&& *sig
->selector
1571 && sig
->headernames
&& *sig
->headernames
1572 && sig
->bodyhash
.data
1573 && sig
->sighash
.data
1578 sig
->verify_status
= PDKIM_VERIFY_INVALID
;
1579 sig
->verify_ext_status
= PDKIM_VERIFY_INVALID_SIGNATURE_ERROR
;
1581 DEBUG(D_acl
) debug_printf(
1582 " Error in DKIM-Signature header: tags missing or invalid\n"
1583 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1587 /* Make sure sig uses supported DKIM version (only v1) */
1588 if (sig
->version
!= 1)
1590 sig
->verify_status
= PDKIM_VERIFY_INVALID
;
1591 sig
->verify_ext_status
= PDKIM_VERIFY_INVALID_DKIM_VERSION
;
1593 DEBUG(D_acl
) debug_printf(
1594 " Error in DKIM-Signature header: unsupported DKIM version\n"
1595 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1599 if (!(sig
->pubkey
= pdkim_key_from_dns(ctx
, sig
, &vctx
, err
)))
1602 /* If the pubkey limits to a list of specific hashes, ignore sigs that
1603 do not have the hash part of the sig algorithm matching */
1605 if (sig
->pubkey
->hashes
)
1607 const uschar
* list
= sig
->pubkey
->hashes
, * ele
;
1609 while ((ele
= string_nextinlist(&list
, &sep
, NULL
, 0)))
1610 if (Ustrcmp(ele
, pdkim_algos
[sig
->algo
] + 4) == 0) break;
1613 DEBUG(D_acl
) debug_printf("pubkey h=%s vs sig a=%s\n",
1614 sig
->pubkey
->hashes
, pdkim_algos
[sig
->algo
]);
1615 sig
->verify_status
= PDKIM_VERIFY_FAIL
;
1616 sig
->verify_ext_status
= PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH
;
1621 /* Check the signature */
1622 if ((*err
= exim_rsa_verify(&vctx
, is_sha1
, &hhash
, &sig
->sighash
)))
1624 DEBUG(D_acl
) debug_printf("headers verify: %s\n", *err
);
1625 sig
->verify_status
= PDKIM_VERIFY_FAIL
;
1626 sig
->verify_ext_status
= PDKIM_VERIFY_FAIL_MESSAGE
;
1631 /* We have a winner! (if bodyhash was correct earlier) */
1632 if (sig
->verify_status
== PDKIM_VERIFY_NONE
)
1633 sig
->verify_status
= PDKIM_VERIFY_PASS
;
1639 debug_printf("PDKIM [%s] signature status: %s",
1640 sig
->domain
, pdkim_verify_status_str(sig
->verify_status
));
1641 if (sig
->verify_ext_status
> 0)
1642 debug_printf(" (%s)\n",
1643 pdkim_verify_ext_status_str(sig
->verify_ext_status
));
1652 /* If requested, set return pointer to signature(s) */
1653 if (return_signatures
)
1654 *return_signatures
= ctx
->sig
;
1660 /* -------------------------------------------------------------------------- */
1662 DLLEXPORT pdkim_ctx
*
1663 pdkim_init_verify(int(*dns_txt_callback
)(char *, char *), BOOL dot_stuffing
)
1667 ctx
= store_get(sizeof(pdkim_ctx
));
1668 memset(ctx
, 0, sizeof(pdkim_ctx
));
1670 if (dot_stuffing
) ctx
->flags
= PDKIM_DOT_TERM
;
1671 ctx
->linebuf
= store_get(PDKIM_MAX_BODY_LINE_LEN
);
1672 ctx
->dns_txt_callback
= dns_txt_callback
;
1678 /* -------------------------------------------------------------------------- */
1680 DLLEXPORT pdkim_ctx
*
1681 pdkim_init_sign(char * domain
, char * selector
, char * rsa_privkey
, int algo
,
1682 BOOL dot_stuffed
, int(*dns_txt_callback
)(char *, char *),
1683 const uschar
** errstr
)
1686 pdkim_signature
* sig
;
1688 if (!domain
|| !selector
|| !rsa_privkey
)
1691 ctx
= store_get(sizeof(pdkim_ctx
) + PDKIM_MAX_BODY_LINE_LEN
+ sizeof(pdkim_signature
));
1692 memset(ctx
, 0, sizeof(pdkim_ctx
));
1694 ctx
->flags
= dot_stuffed
? PDKIM_MODE_SIGN
| PDKIM_DOT_TERM
: PDKIM_MODE_SIGN
;
1695 ctx
->linebuf
= CS (ctx
+1);
1697 DEBUG(D_acl
) ctx
->dns_txt_callback
= dns_txt_callback
;
1699 sig
= (pdkim_signature
*)(ctx
->linebuf
+ PDKIM_MAX_BODY_LINE_LEN
);
1700 memset(sig
, 0, sizeof(pdkim_signature
));
1702 sig
->bodylength
= -1;
1705 sig
->domain
= string_copy(US domain
);
1706 sig
->selector
= string_copy(US selector
);
1707 sig
->rsa_privkey
= string_copy(US rsa_privkey
);
1710 if (!exim_sha_init(&sig
->body_hash_ctx
,
1711 algo
== PDKIM_ALGO_RSA_SHA1
? HASH_SHA1
: HASH_SHA256
))
1713 DEBUG(D_acl
) debug_printf("PDKIM: hash setup internal error\n");
1719 pdkim_signature s
= *sig
;
1722 debug_printf("PDKIM (checking verify key)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1723 if (!pdkim_key_from_dns(ctx
, &s
, &vctx
, errstr
))
1724 debug_printf("WARNING: bad dkim key in dns\n");
1725 debug_printf("PDKIM (finished checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1731 /* -------------------------------------------------------------------------- */
1734 pdkim_set_optional(pdkim_ctx
*ctx
,
1740 unsigned long created
,
1741 unsigned long expires
)
1743 pdkim_signature
* sig
= ctx
->sig
;
1746 sig
->identity
= string_copy(US identity
);
1748 sig
->sign_headers
= string_copy(sign_headers
1749 ? US sign_headers
: US PDKIM_DEFAULT_SIGN_HEADERS
);
1751 sig
->canon_headers
= canon_headers
;
1752 sig
->canon_body
= canon_body
;
1753 sig
->bodylength
= bodylength
;
1754 sig
->created
= created
;
1755 sig
->expires
= expires
;
1769 #endif /*DISABLE_DKIM*/