2 * PDKIM - a RFC4871 (DKIM) implementation
4 * Copyright (C) 2009 - 2016 Tom Kistner <tom@duncanthrax.net>
5 * Copyright (C) 2016 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_INVALID_PUBKEY_UNAVAILABLE: return "PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE";
136 case PDKIM_VERIFY_INVALID_BUFFER_SIZE: return "PDKIM_VERIFY_INVALID_BUFFER_SIZE";
137 case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD: return "PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD";
138 case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT: return "PDKIM_VERIFY_INVALID_PUBKEY_IMPORT";
139 case PDKIM_VERIFY_INVALID_SIGNATURE_ERROR: return "PDKIM_VERIFY_INVALID_SIGNATURE_ERROR";
140 case PDKIM_VERIFY_INVALID_DKIM_VERSION: return "PDKIM_VERIFY_INVALID_DKIM_VERSION";
141 default: return "PDKIM_VERIFY_UNKNOWN";
146 pdkim_errstr(int status)
150 case PDKIM_OK: return "OK";
151 case PDKIM_FAIL: return "FAIL";
152 case PDKIM_ERR_RSA_PRIVKEY: return "RSA_PRIVKEY";
153 case PDKIM_ERR_RSA_SIGNING: return "RSA SIGNING";
154 case PDKIM_ERR_LONG_LINE: return "RSA_LONG_LINE";
155 case PDKIM_ERR_BUFFER_TOO_SMALL: return "BUFFER_TOO_SMALL";
156 case PDKIM_SIGN_PRIVKEY_WRAP: return "PRIVKEY_WRAP";
157 case PDKIM_SIGN_PRIVKEY_B64D: return "PRIVKEY_B64D";
158 default: return "(unknown)";
163 /* -------------------------------------------------------------------------- */
164 /* Print debugging functions */
166 pdkim_quoteprint(const uschar *data, int len)
169 for (i = 0; i < len; i++)
171 const int c = data[i];
174 case ' ' : debug_printf("{SP}"); break;
175 case '\t': debug_printf("{TB}"); break;
176 case '\r': debug_printf("{CR}"); break;
177 case '\n': debug_printf("{LF}"); break;
178 case '{' : debug_printf("{BO}"); break;
179 case '}' : debug_printf("{BC}"); break;
181 if ( (c < 32) || (c > 127) )
182 debug_printf("{%02x}", c);
184 debug_printf("%c", c);
192 pdkim_hexprint(const uschar *data, int len)
195 for (i = 0 ; i < len; i++) debug_printf("%02x", data[i]);
201 static pdkim_stringlist *
202 pdkim_prepend_stringlist(pdkim_stringlist * base, const uschar * str)
204 pdkim_stringlist * new_entry = store_get(sizeof(pdkim_stringlist));
206 memset(new_entry, 0, sizeof(pdkim_stringlist));
207 new_entry->value = string_copy(str);
208 if (base) new_entry->next = base;
214 /* Trim whitespace fore & aft */
217 pdkim_strtrim(uschar * str)
221 while (*p == '\t' || *p == ' ') p++; /* skip whitespace */
222 while (*p) {*q = *p; q++; p++;} /* dump the leading whitespace */
224 while (q != str && ( (*q == '\0') || (*q == '\t') || (*q == ' ') ) )
225 { /* dump trailing whitespace */
233 /* -------------------------------------------------------------------------- */
236 pdkim_free_ctx(pdkim_ctx *ctx)
241 /* -------------------------------------------------------------------------- */
242 /* Matches the name of the passed raw "header" against
243 the passed colon-separated "tick", and invalidates
244 the entry in tick. Returns OK or fail-code */
245 /*XXX might be safer done using a pdkim_stringlist for "tick" */
248 header_name_match(const uschar * header, uschar * tick)
254 uschar * hcolon = Ustrchr(header, ':'); /* Get header name */
257 return PDKIM_FAIL; /* This isn't a header */
259 /* if we had strncmpic() we wouldn't need this copy */
260 hname = string_copyn(header, hcolon-header);
262 /* Copy tick-off list locally, so we can punch zeroes into it */
263 p = lcopy = string_copy(tick);
265 for (q = Ustrchr(p, ':'); q; q = Ustrchr(p, ':'))
268 if (strcmpic(p, hname) == 0)
274 if (strcmpic(p, hname) == 0)
280 /* Invalidate header name instance in tick-off list */
286 /* -------------------------------------------------------------------------- */
287 /* Performs "relaxed" canonicalization of a header. */
290 pdkim_relax_header(const uschar * header, int crlf)
292 BOOL past_field_name = FALSE;
293 BOOL seen_wsp = FALSE;
295 uschar * relaxed = store_get(Ustrlen(header)+3);
296 uschar * q = relaxed;
298 for (p = header; *p; p++)
302 if (c == '\r' || c == '\n')
304 if (c == '\t' || c == ' ')
308 c = ' '; /* Turns WSP into SP */
312 if (!past_field_name && c == ':')
314 if (seen_wsp) q--; /* This removes WSP before the colon */
315 seen_wsp = TRUE; /* This removes WSP after the colon */
316 past_field_name = TRUE;
321 /* Lowercase header name */
322 if (!past_field_name) c = tolower(c);
326 if (q > relaxed && q[-1] == ' ') q--; /* Squash eventual trailing SP */
328 if (crlf) { *q++ = '\r'; *q++ = '\n'; }
334 /* -------------------------------------------------------------------------- */
335 #define PDKIM_QP_ERROR_DECODE -1
338 pdkim_decode_qp_char(uschar *qp_p, int *c)
340 uschar *initial_pos = qp_p;
342 /* Advance one char */
345 /* Check for two hex digits and decode them */
346 if (isxdigit(*qp_p) && isxdigit(qp_p[1]))
348 /* Do hex conversion */
349 *c = (isdigit(*qp_p) ? *qp_p - '0' : toupper(*qp_p) - 'A' + 10) << 4;
350 *c |= isdigit(qp_p[1]) ? qp_p[1] - '0' : toupper(qp_p[1]) - 'A' + 10;
354 /* Illegal char here */
355 *c = PDKIM_QP_ERROR_DECODE;
360 /* -------------------------------------------------------------------------- */
363 pdkim_decode_qp(uschar * str)
368 uschar * n = store_get(Ustrlen(str)+1);
376 p = pdkim_decode_qp_char(p, &nchar);
392 /* -------------------------------------------------------------------------- */
395 pdkim_decode_base64(uschar *str, blob * b)
398 dlen = b64decode(str, &b->data);
399 if (dlen < 0) b->data = NULL;
404 pdkim_encode_base64(blob * b)
406 return b64encode(b->data, b->len);
410 /* -------------------------------------------------------------------------- */
411 #define PDKIM_HDR_LIMBO 0
412 #define PDKIM_HDR_TAG 1
413 #define PDKIM_HDR_VALUE 2
415 static pdkim_signature *
416 pdkim_parse_sig_header(pdkim_ctx *ctx, uschar * raw_hdr)
418 pdkim_signature *sig ;
420 uschar * cur_tag = NULL; int ts = 0, tl = 0;
421 uschar * cur_val = NULL; int vs = 0, vl = 0;
422 BOOL past_hname = FALSE;
423 BOOL in_b_val = FALSE;
424 int where = PDKIM_HDR_LIMBO;
427 sig = store_get(sizeof(pdkim_signature));
428 memset(sig, 0, sizeof(pdkim_signature));
429 sig->bodylength = -1;
431 /* Set so invalid/missing data error display is accurate */
435 q = sig->rawsig_no_b_val = store_get(Ustrlen(raw_hdr)+1);
437 for (p = raw_hdr; ; p++)
442 if (c == '\r' || c == '\n')
445 /* Fast-forward through header name */
448 if (c == ':') past_hname = TRUE;
452 if (where == PDKIM_HDR_LIMBO)
454 /* In limbo, just wait for a tag-char to appear */
455 if (!(c >= 'a' && c <= 'z'))
458 where = PDKIM_HDR_TAG;
461 if (where == PDKIM_HDR_TAG)
463 if (c >= 'a' && c <= 'z')
464 cur_tag = string_catn(cur_tag, &ts, &tl, p, 1);
469 if (Ustrcmp(cur_tag, "b") == 0)
474 where = PDKIM_HDR_VALUE;
479 if (where == PDKIM_HDR_VALUE)
481 if (c == '\r' || c == '\n' || c == ' ' || c == '\t')
484 if (c == ';' || c == '\0')
489 pdkim_strtrim(cur_val);
491 DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag, cur_val);
496 if (cur_tag[1] == 'h')
497 pdkim_decode_base64(cur_val, &sig->bodyhash);
499 pdkim_decode_base64(cur_val, &sig->sigdata);
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->sigdata.len*8);
583 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
586 exim_sha_init(&sig->body_hash, sig->algo == PDKIM_ALGO_RSA_SHA1 ? HASH_SHA1 : HASH_SHA256);
591 /* -------------------------------------------------------------------------- */
593 static pdkim_pubkey *
594 pdkim_parse_pubkey_record(pdkim_ctx *ctx, const uschar *raw_record)
598 uschar * cur_tag = NULL; int ts = 0, tl = 0;
599 uschar * cur_val = NULL; int vs = 0, vl = 0;
600 int where = PDKIM_HDR_LIMBO;
602 pub = store_get(sizeof(pdkim_pubkey));
603 memset(pub, 0, sizeof(pdkim_pubkey));
605 for (p = raw_record; ; p++)
610 if (c == '\r' || c == '\n')
613 if (where == PDKIM_HDR_LIMBO)
615 /* In limbo, just wait for a tag-char to appear */
616 if (!(c >= 'a' && c <= 'z'))
619 where = PDKIM_HDR_TAG;
622 if (where == PDKIM_HDR_TAG)
624 if (c >= 'a' && c <= 'z')
625 cur_tag = string_catn(cur_tag, &ts, &tl, p, 1);
630 where = PDKIM_HDR_VALUE;
635 if (where == PDKIM_HDR_VALUE)
637 if (c == ';' || c == '\0')
642 pdkim_strtrim(cur_val);
643 DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag, cur_val);
648 /* This tag isn't evaluated because:
649 - We only support version DKIM1.
650 - Which is the default for this value (set below)
651 - Other versions are currently not specified. */
655 pub->hashes = string_copy(cur_val); break;
657 pub->granularity = string_copy(cur_val); break;
659 pub->notes = pdkim_decode_qp(cur_val); break;
661 pdkim_decode_base64(US cur_val, &pub->key);
664 pub->srvtype = string_copy(cur_val); break;
666 if (Ustrchr(cur_val, 'y') != NULL) pub->testing = 1;
667 if (Ustrchr(cur_val, 's') != NULL) pub->no_subdomaining = 1;
670 DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
676 where = PDKIM_HDR_LIMBO;
679 cur_val = string_catn(cur_val, &vs, &vl, p, 1);
683 if (c == '\0') break;
686 /* Set fallback defaults */
687 if (!pub->version ) pub->version = string_copy(PDKIM_PUB_RECORD_VERSION);
688 if (!pub->granularity) pub->granularity = string_copy(US"*");
689 if (!pub->keytype ) pub->keytype = string_copy(US"rsa");
690 if (!pub->srvtype ) pub->srvtype = string_copy(US"*");
700 /* -------------------------------------------------------------------------- */
703 pdkim_update_bodyhash(pdkim_ctx *ctx, const char *data, int len)
705 pdkim_signature *sig = ctx->sig;
706 /* Cache relaxed version of data */
707 uschar *relaxed_data = NULL;
710 /* Traverse all signatures, updating their hashes. */
713 /* Defaults to simple canon (no further treatment necessary) */
714 const uschar *canon_data = CUS data;
717 if (sig->canon_body == PDKIM_CANON_RELAXED)
719 /* Relax the line if not done already */
722 BOOL seen_wsp = FALSE;
726 relaxed_data = store_get(len+1);
728 for (p = data; *p; p++)
733 if (q > 0 && relaxed_data[q-1] == ' ')
736 else if (c == '\t' || c == ' ')
738 c = ' '; /* Turns WSP into SP */
745 relaxed_data[q++] = c;
747 relaxed_data[q] = '\0';
750 canon_data = relaxed_data;
751 canon_len = relaxed_len;
754 /* Make sure we don't exceed the to-be-signed body length */
755 if ( sig->bodylength >= 0
756 && sig->signed_body_bytes + (unsigned long)canon_len > sig->bodylength
758 canon_len = sig->bodylength - sig->signed_body_bytes;
762 exim_sha_update(&sig->body_hash, CUS canon_data, canon_len);
763 sig->signed_body_bytes += canon_len;
764 DEBUG(D_acl) pdkim_quoteprint(canon_data, canon_len);
774 /* -------------------------------------------------------------------------- */
777 pdkim_finish_bodyhash(pdkim_ctx *ctx)
779 pdkim_signature *sig;
781 /* Traverse all signatures */
782 for (sig = ctx->sig; sig; sig = sig->next)
783 { /* Finish hashes */
786 exim_sha_finish(&sig->body_hash, &bh);
790 debug_printf("PDKIM [%s] Body bytes hashed: %lu\n"
791 "PDKIM [%s] bh computed: ",
792 sig->domain, sig->signed_body_bytes, sig->domain);
793 pdkim_hexprint(CUS bh.data, bh.len);
796 /* SIGNING -------------------------------------------------------------- */
797 if (ctx->flags & PDKIM_MODE_SIGN)
801 /* If bodylength limit is set, and we have received less bytes
802 than the requested amount, effectively remove the limit tag. */
803 if (sig->signed_body_bytes < sig->bodylength)
804 sig->bodylength = -1;
807 /* VERIFICATION --------------------------------------------------------- */
810 /* Compare bodyhash */
811 if (memcmp(bh.data, sig->bodyhash.data, bh.len) == 0)
813 DEBUG(D_acl) debug_printf("PDKIM [%s] Body hash verified OK\n", sig->domain);
819 debug_printf("PDKIM [%s] bh signature: ", sig->domain);
820 pdkim_hexprint(sig->bodyhash.data,
821 exim_sha_hashlen(&sig->body_hash));
822 debug_printf("PDKIM [%s] Body hash did NOT verify\n", sig->domain);
824 sig->verify_status = PDKIM_VERIFY_FAIL;
825 sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
834 pdkim_body_complete(pdkim_ctx * ctx)
836 pdkim_signature * sig = ctx->sig; /*XXX assumes only one sig */
838 /* In simple body mode, if any empty lines were buffered,
839 replace with one. rfc 4871 3.4.3 */
840 /*XXX checking the signed-body-bytes is a gross hack; I think
841 it indicates that all linebreaks should be buffered, including
842 the one terminating a text line */
844 if ( sig && sig->canon_body == PDKIM_CANON_SIMPLE
845 && sig->signed_body_bytes == 0
846 && ctx->num_buffered_crlf > 0
848 pdkim_update_bodyhash(ctx, "\r\n", 2);
850 ctx->flags |= PDKIM_SEEN_EOD;
851 ctx->linebuf_offset = 0;
857 /* -------------------------------------------------------------------------- */
858 /* Call from pdkim_feed below for processing complete body lines */
861 pdkim_bodyline_complete(pdkim_ctx *ctx)
863 char *p = ctx->linebuf;
864 int n = ctx->linebuf_offset;
865 pdkim_signature *sig = ctx->sig; /*XXX assumes only one sig */
867 /* Ignore extra data if we've seen the end-of-data marker */
868 if (ctx->flags & PDKIM_SEEN_EOD) goto BAIL;
870 /* We've always got one extra byte to stuff a zero ... */
871 ctx->linebuf[ctx->linebuf_offset] = '\0';
873 /* Terminate on EOD marker */
874 if (ctx->flags & PDKIM_DOT_TERM)
876 if ( memcmp(p, ".\r\n", 3) == 0)
877 return pdkim_body_complete(ctx);
880 if (memcmp(p, "..", 2) == 0)
887 /* Empty lines need to be buffered until we find a non-empty line */
888 if (memcmp(p, "\r\n", 2) == 0)
890 ctx->num_buffered_crlf++;
894 if (sig && sig->canon_body == PDKIM_CANON_RELAXED)
896 /* Lines with just spaces need to be buffered too */
898 while (memcmp(check, "\r\n", 2) != 0)
902 if (c != '\t' && c != ' ')
907 ctx->num_buffered_crlf++;
912 /* At this point, we have a non-empty line, so release the buffered ones. */
913 while (ctx->num_buffered_crlf)
915 pdkim_update_bodyhash(ctx, "\r\n", 2);
916 ctx->num_buffered_crlf--;
919 pdkim_update_bodyhash(ctx, p, n);
922 ctx->linebuf_offset = 0;
927 /* -------------------------------------------------------------------------- */
928 /* Callback from pdkim_feed below for processing complete headers */
929 #define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
932 pdkim_header_complete(pdkim_ctx *ctx)
934 /* Special case: The last header can have an extra \r appended */
935 if ( (ctx->cur_header_len > 1) &&
936 (ctx->cur_header[(ctx->cur_header_len)-1] == '\r') )
937 --ctx->cur_header_len;
938 ctx->cur_header[ctx->cur_header_len] = '\0';
941 if (ctx->num_headers > PDKIM_MAX_HEADERS) goto BAIL;
943 /* SIGNING -------------------------------------------------------------- */
944 if (ctx->flags & PDKIM_MODE_SIGN)
946 pdkim_signature *sig;
948 for (sig = ctx->sig; sig; sig = sig->next) /* Traverse all signatures */
950 /* Add header to the signed headers list (in reverse order) */
951 sig->headers = pdkim_prepend_stringlist(sig->headers,
955 /* VERIFICATION ----------------------------------------------------------- */
956 /* DKIM-Signature: headers are added to the verification list */
959 if (strncasecmp(CCS ctx->cur_header,
960 DKIM_SIGNATURE_HEADERNAME,
961 Ustrlen(DKIM_SIGNATURE_HEADERNAME)) == 0)
963 pdkim_signature *new_sig;
965 /* Create and chain new signature block */
966 DEBUG(D_acl) debug_printf(
967 "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
969 if ((new_sig = pdkim_parse_sig_header(ctx, ctx->cur_header)))
971 pdkim_signature *last_sig = ctx->sig;
976 while (last_sig->next) last_sig = last_sig->next;
977 last_sig->next = new_sig;
981 DEBUG(D_acl) debug_printf(
982 "Error while parsing signature header\n"
983 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
986 /* every other header is stored for signature verification */
988 ctx->headers = pdkim_prepend_stringlist(ctx->headers, ctx->cur_header);
992 *ctx->cur_header = '\0';
993 ctx->cur_header_len = 0; /* leave buffer for reuse */
999 /* -------------------------------------------------------------------------- */
1000 #define HEADER_BUFFER_FRAG_SIZE 256
1003 pdkim_feed(pdkim_ctx *ctx, char *data, int len)
1007 /* Alternate EOD signal, used in non-dotstuffing mode */
1009 pdkim_body_complete(ctx);
1011 for (p = 0; p<len; p++)
1015 if (ctx->flags & PDKIM_PAST_HDRS)
1017 /* Processing body byte */
1018 ctx->linebuf[ctx->linebuf_offset++] = c;
1021 int rc = pdkim_bodyline_complete(ctx); /* End of line */
1022 if (rc != PDKIM_OK) return rc;
1024 if (ctx->linebuf_offset == (PDKIM_MAX_BODY_LINE_LEN-1))
1025 return PDKIM_ERR_LONG_LINE;
1029 /* Processing header byte */
1034 if (ctx->flags & PDKIM_SEEN_LF)
1036 int rc = pdkim_header_complete(ctx); /* Seen last header line */
1037 if (rc != PDKIM_OK) return rc;
1039 ctx->flags = ctx->flags & ~PDKIM_SEEN_LF | PDKIM_PAST_HDRS;
1040 DEBUG(D_acl) debug_printf(
1041 "PDKIM >> Body data for hash, canonicalized >>>>>>>>>>>>>>>>>>>>>>\n");
1045 ctx->flags |= PDKIM_SEEN_LF;
1047 else if (ctx->flags & PDKIM_SEEN_LF)
1049 if (!(c == '\t' || c == ' '))
1051 int rc = pdkim_header_complete(ctx); /* End of header */
1052 if (rc != PDKIM_OK) return rc;
1054 ctx->flags &= ~PDKIM_SEEN_LF;
1058 if (ctx->cur_header_len < PDKIM_MAX_HEADER_LEN)
1059 ctx->cur_header = string_catn(ctx->cur_header, &ctx->cur_header_size,
1060 &ctx->cur_header_len, CUS &data[p], 1);
1068 /* Extend a grwong header with a continuation-linebreak */
1070 pdkim_hdr_cont(uschar * str, int * size, int * ptr, int * col)
1073 return string_catn(str, size, ptr, US"\r\n\t", 3);
1079 * RFC 5322 specifies that header line length SHOULD be no more than 78
1083 * returns uschar * (not nul-terminated)
1085 * col: this int holds and receives column number (octets since last '\n')
1086 * str: partial string to append to
1087 * size: current buffer size for str
1088 * ptr: current tail-pointer for str
1089 * pad: padding, split line or space after before or after eg: ";"
1090 * intro: - must join to payload eg "h=", usually the tag name
1091 * payload: eg base64 data - long data can be split arbitrarily.
1093 * this code doesn't fold the header in some of the places that RFC4871
1094 * allows: As per RFC5322(2.2.3) it only folds before or after tag-value
1095 * pairs and inside long values. it also always spaces or breaks after the
1098 * no guarantees are made for output given out-of range input. like tag
1099 * names longer than 78, or bogus col. Input is assumed to be free of line breaks.
1103 pdkim_headcat(int * col, uschar * str, int * size, int * ptr,
1104 const uschar * pad, const uschar * intro, const uschar * payload)
1112 str = pdkim_hdr_cont(str, size, ptr, col);
1113 str = string_catn(str, size, ptr, pad, l);
1117 l = (pad?1:0) + (intro?Ustrlen(intro):0);
1120 { /*can't fit intro - start a new line to make room.*/
1121 str = pdkim_hdr_cont(str, size, ptr, col);
1122 l = intro?Ustrlen(intro):0;
1125 l += payload ? Ustrlen(payload):0 ;
1128 { /* this fragment will not fit on a single line */
1131 str = string_catn(str, size, ptr, US" ", 1);
1133 pad = NULL; /* only want this once */
1139 size_t sl = Ustrlen(intro);
1141 str = string_catn(str, size, ptr, intro, sl);
1144 intro = NULL; /* only want this once */
1149 size_t sl = Ustrlen(payload);
1150 size_t chomp = *col+sl < 77 ? sl : 78-*col;
1152 str = string_catn(str, size, ptr, payload, chomp);
1158 /* the while precondition tells us it didn't fit. */
1159 str = pdkim_hdr_cont(str, size, ptr, col);
1164 str = pdkim_hdr_cont(str, size, ptr, col);
1170 str = string_catn(str, size, ptr, US" ", 1);
1177 size_t sl = Ustrlen(intro);
1179 str = string_catn(str, size, ptr, intro, sl);
1187 size_t sl = Ustrlen(payload);
1189 str = string_catn(str, size, ptr, payload, sl);
1197 /* -------------------------------------------------------------------------- */
1200 pdkim_create_header(pdkim_signature *sig, BOOL final)
1205 uschar * hdr; int hdr_size = 0, hdr_len = 0;
1206 uschar * canon_all; int can_size = 0, can_len = 0;
1208 canon_all = string_cat (NULL, &can_size, &can_len,
1209 pdkim_canons[sig->canon_headers]);
1210 canon_all = string_catn(canon_all, &can_size, &can_len, US"/", 1);
1211 canon_all = string_cat (canon_all, &can_size, &can_len,
1212 pdkim_canons[sig->canon_body]);
1213 canon_all[can_len] = '\0';
1215 hdr = string_cat(NULL, &hdr_size, &hdr_len,
1216 US"DKIM-Signature: v="PDKIM_SIGNATURE_VERSION);
1219 /* Required and static bits */
1220 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"a=",
1221 pdkim_algos[sig->algo]);
1222 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"q=",
1223 pdkim_querymethods[sig->querymethod]);
1224 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"c=",
1226 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"d=",
1228 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"s=",
1231 /* list of header names can be split between items. */
1233 uschar * n = string_copy(sig->headernames);
1234 uschar * i = US"h=";
1239 uschar * c = Ustrchr(n, ':');
1244 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, NULL, NULL, US":");
1246 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, s, i, n);
1257 base64_bh = pdkim_encode_base64(&sig->bodyhash);
1258 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"bh=", base64_bh);
1262 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"i=", sig->identity);
1264 if (sig->created > 0)
1268 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->created);
1269 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"t=", minibuf);
1272 if (sig->expires > 0)
1276 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->expires);
1277 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"x=", minibuf);
1280 if (sig->bodylength >= 0)
1284 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->bodylength);
1285 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"l=", minibuf);
1288 /* Preliminary or final version? */
1289 base64_b = final ? pdkim_encode_base64(&sig->sigdata) : US"";
1290 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"b=", base64_b);
1292 /* add trailing semicolon: I'm not sure if this is actually needed */
1293 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, NULL, US";", US"");
1295 hdr[hdr_len] = '\0';
1300 /* -------------------------------------------------------------------------- */
1303 pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatures)
1305 pdkim_signature *sig = ctx->sig;
1306 uschar * headernames = NULL; /* Collected signed header names */
1309 /* Check if we must still flush a (partial) header. If that is the
1310 case, the message has no body, and we must compute a body hash
1311 out of '<CR><LF>' */
1312 if (ctx->cur_header && ctx->cur_header_len)
1314 int rc = pdkim_header_complete(ctx);
1315 if (rc != PDKIM_OK) return rc;
1316 pdkim_update_bodyhash(ctx, "\r\n", 2);
1319 DEBUG(D_acl) debug_printf(
1320 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1322 /* Build (and/or evaluate) body hash */
1323 pdkim_finish_bodyhash(ctx);
1327 BOOL is_sha1 = sig->algo == PDKIM_ALGO_RSA_SHA1;
1332 int hdata_alloc = 0;
1337 exim_sha_init(&hhash_ctx, is_sha1 ? HASH_SHA1 : HASH_SHA256);
1339 DEBUG(D_acl) debug_printf(
1340 "PDKIM >> Hashed header data, canonicalized, in sequence >>>>>>>>>>>>>>\n");
1342 /* SIGNING ---------------------------------------------------------------- */
1343 /* When signing, walk through our header list and add them to the hash. As we
1344 go, construct a list of the header's names to use for the h= parameter.
1345 Then append to that list any remaining header names for which there was no
1348 if (ctx->flags & PDKIM_MODE_SIGN)
1350 pdkim_stringlist *p;
1355 for (p = sig->headers; p; p = p->next)
1356 if (header_name_match(p->value, sig->sign_headers) == PDKIM_OK)
1359 /* Collect header names (Note: colon presence is guaranteed here) */
1360 uschar * q = Ustrchr(p->value, ':');
1362 headernames = string_catn(headernames, &hs, &hl,
1363 p->value, (q - US p->value) + (p->next ? 1 : 0));
1365 rh = sig->canon_headers == PDKIM_CANON_RELAXED
1366 ? pdkim_relax_header(p->value, 1) /* cook header for relaxed canon */
1367 : string_copy(CUS p->value); /* just copy it for simple canon */
1369 /* Feed header to the hash algorithm */
1370 exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
1372 /* Remember headers block for signing (when the library cannot do incremental) */
1373 (void) exim_rsa_data_append(&hdata, &hdata_alloc, rh);
1375 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1378 l = sig->sign_headers;
1379 while((s = string_nextinlist(&l, &sep, NULL, 0)))
1381 { /*SSS string_append_listele() */
1382 if (hl > 0 && headernames[hl-1] != ':')
1383 headernames = string_catn(headernames, &hs, &hl, US":", 1);
1385 headernames = string_cat(headernames, &hs, &hl, s);
1387 headernames[hl] = '\0';
1389 /* Copy headernames to signature struct */
1390 sig->headernames = headernames;
1391 headernames = NULL, hs = hl = 0;
1393 /* Create signature header with b= omitted */
1394 sig_hdr = pdkim_create_header(sig, FALSE);
1397 /* VERIFICATION ----------------------------------------------------------- */
1398 /* When verifying, walk through the header name list in the h= parameter and
1399 add the headers to the hash in that order. */
1402 uschar * b = string_copy(sig->headernames);
1405 pdkim_stringlist * hdrs;
1408 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1413 if ((q = Ustrchr(p, ':')))
1416 /*XXX walk the list of headers in same order as received. */
1417 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1419 && strncasecmp(hdrs->value, CS p, Ustrlen(p)) == 0
1420 && (hdrs->value)[Ustrlen(p)] == ':'
1423 uschar * rh = sig->canon_headers == PDKIM_CANON_RELAXED
1424 ? pdkim_relax_header(hdrs->value, 1) /* cook header for relaxed canon */
1425 : string_copy(CUS hdrs->value); /* just copy it for simple canon */
1427 /* Feed header to the hash algorithm */
1428 exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
1430 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1439 sig_hdr = string_copy(sig->rawsig_no_b_val);
1442 DEBUG(D_acl) debug_printf(
1443 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1445 /* Relax header if necessary */
1446 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1447 sig_hdr = pdkim_relax_header(sig_hdr, 0);
1452 "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
1453 pdkim_quoteprint(CUS sig_hdr, Ustrlen(sig_hdr));
1455 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1458 /* Finalize header hash */
1459 exim_sha_update(&hhash_ctx, CUS sig_hdr, Ustrlen(sig_hdr));
1460 exim_sha_finish(&hhash_ctx, &hhash);
1464 debug_printf("PDKIM [%s] hh computed: ", sig->domain);
1465 pdkim_hexprint(hhash.data, hhash.len);
1468 /* Remember headers block for signing (when the library cannot do incremental) */
1469 if (ctx->flags & PDKIM_MODE_SIGN)
1470 (void) exim_rsa_data_append(&hdata, &hdata_alloc, US sig_hdr);
1472 /* SIGNING ---------------------------------------------------------------- */
1473 if (ctx->flags & PDKIM_MODE_SIGN)
1476 const uschar * errstr;
1478 /* Import private key */
1479 if ((errstr = exim_rsa_signing_init(US sig->rsa_privkey, &sctx)))
1481 DEBUG(D_acl) debug_printf("signing_init: %s\n", errstr);
1482 return PDKIM_ERR_RSA_PRIVKEY;
1485 /* Do signing. With OpenSSL we are signing the hash of headers just
1486 calculated, with GnuTLS we have to sign an entire block of headers
1487 (due to available interfaces) and it recalculates the hash internally. */
1489 #if defined(RSA_OPENSSL) || defined(RSA_GCRYPT)
1493 if ((errstr = exim_rsa_sign(&sctx, is_sha1, &hdata, &sig->sigdata)))
1495 DEBUG(D_acl) debug_printf("signing: %s\n", errstr);
1496 return PDKIM_ERR_RSA_SIGNING;
1501 debug_printf( "PDKIM [%s] b computed: ", sig->domain);
1502 pdkim_hexprint(sig->sigdata.data, sig->sigdata.len);
1505 sig->signature_header = pdkim_create_header(sig, TRUE);
1508 /* VERIFICATION ----------------------------------------------------------- */
1512 const uschar * errstr;
1514 uschar *dns_txt_name, *dns_txt_reply;
1516 /* Make sure we have all required signature tags */
1517 if (!( sig->domain && *sig->domain
1518 && sig->selector && *sig->selector
1519 && sig->headernames && *sig->headernames
1520 && sig->bodyhash.data
1521 && sig->sigdata.data
1526 sig->verify_status = PDKIM_VERIFY_INVALID;
1527 sig->verify_ext_status = PDKIM_VERIFY_INVALID_SIGNATURE_ERROR;
1529 DEBUG(D_acl) debug_printf(
1530 " Error in DKIM-Signature header: tags missing or invalid\n"
1531 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1535 /* Make sure sig uses supported DKIM version (only v1) */
1536 if (sig->version != 1)
1538 sig->verify_status = PDKIM_VERIFY_INVALID;
1539 sig->verify_ext_status = PDKIM_VERIFY_INVALID_DKIM_VERSION;
1541 DEBUG(D_acl) debug_printf(
1542 " Error in DKIM-Signature header: unsupported DKIM version\n"
1543 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1547 /* Fetch public key for signing domain, from DNS */
1549 dns_txt_name = string_sprintf("%s._domainkey.%s.",
1550 sig->selector, sig->domain);
1552 dns_txt_reply = store_get(PDKIM_DNS_TXT_MAX_RECLEN);
1553 memset(dns_txt_reply, 0, PDKIM_DNS_TXT_MAX_RECLEN);
1555 if ( ctx->dns_txt_callback(CS dns_txt_name, CS dns_txt_reply) != PDKIM_OK
1556 || dns_txt_reply[0] == '\0')
1558 sig->verify_status = PDKIM_VERIFY_INVALID;
1559 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE;
1566 "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
1568 pdkim_quoteprint(CUS dns_txt_reply, Ustrlen(dns_txt_reply));
1571 if (!(sig->pubkey = pdkim_parse_pubkey_record(ctx, CUS dns_txt_reply)))
1573 sig->verify_status = PDKIM_VERIFY_INVALID;
1574 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD;
1576 DEBUG(D_acl) debug_printf(
1577 " Error while parsing public key record\n"
1578 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1582 DEBUG(D_acl) debug_printf(
1583 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1585 /* Import public key */
1586 if ((errstr = exim_rsa_verify_init(&sig->pubkey->key, &vctx)))
1588 DEBUG(D_acl) debug_printf("verify_init: %s\n", errstr);
1589 sig->verify_status = PDKIM_VERIFY_INVALID;
1590 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_IMPORT;
1594 /* Check the signature */
1595 if ((errstr = exim_rsa_verify(&vctx, is_sha1, &hhash, &sig->sigdata)))
1597 DEBUG(D_acl) debug_printf("headers verify: %s\n", errstr);
1598 sig->verify_status = PDKIM_VERIFY_FAIL;
1599 sig->verify_ext_status = PDKIM_VERIFY_FAIL_MESSAGE;
1604 /* We have a winner! (if bodydhash was correct earlier) */
1605 if (sig->verify_status == PDKIM_VERIFY_NONE)
1606 sig->verify_status = PDKIM_VERIFY_PASS;
1612 debug_printf("PDKIM [%s] signature status: %s",
1613 sig->domain, pdkim_verify_status_str(sig->verify_status));
1614 if (sig->verify_ext_status > 0)
1615 debug_printf(" (%s)\n",
1616 pdkim_verify_ext_status_str(sig->verify_ext_status));
1625 /* If requested, set return pointer to signature(s) */
1626 if (return_signatures)
1627 *return_signatures = ctx->sig;
1633 /* -------------------------------------------------------------------------- */
1635 DLLEXPORT pdkim_ctx *
1636 pdkim_init_verify(int(*dns_txt_callback)(char *, char *), BOOL dot_stuffing)
1640 ctx = store_get(sizeof(pdkim_ctx));
1641 memset(ctx, 0, sizeof(pdkim_ctx));
1643 if (dot_stuffing) ctx->flags = PDKIM_DOT_TERM;
1644 ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN);
1645 ctx->dns_txt_callback = dns_txt_callback;
1651 /* -------------------------------------------------------------------------- */
1653 DLLEXPORT pdkim_ctx *
1654 pdkim_init_sign(char *domain, char *selector, char *rsa_privkey, int algo,
1658 pdkim_signature *sig;
1660 if (!domain || !selector || !rsa_privkey)
1663 ctx = store_get(sizeof(pdkim_ctx));
1664 memset(ctx, 0, sizeof(pdkim_ctx));
1666 ctx->flags = dot_stuffed ? PDKIM_MODE_SIGN | PDKIM_DOT_TERM : PDKIM_MODE_SIGN;
1667 ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN);
1669 sig = store_get(sizeof(pdkim_signature));
1670 memset(sig, 0, sizeof(pdkim_signature));
1672 sig->bodylength = -1;
1675 sig->domain = string_copy(US domain);
1676 sig->selector = string_copy(US selector);
1677 sig->rsa_privkey = string_copy(US rsa_privkey);
1680 exim_sha_init(&sig->body_hash, algo == PDKIM_ALGO_RSA_SHA1 ? HASH_SHA1 : HASH_SHA256);
1685 /* -------------------------------------------------------------------------- */
1688 pdkim_set_optional(pdkim_ctx *ctx,
1694 unsigned long created,
1695 unsigned long expires)
1697 pdkim_signature * sig = ctx->sig;
1700 sig->identity = string_copy(US identity);
1702 sig->sign_headers = string_copy(sign_headers
1703 ? US sign_headers : US PDKIM_DEFAULT_SIGN_HEADERS);
1705 sig->canon_headers = canon_headers;
1706 sig->canon_body = canon_body;
1707 sig->bodylength = bodylength;
1708 sig->created = created;
1709 sig->expires = expires;
1723 #endif /*DISABLE_DKIM*/