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(SIGN_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
55 /* -------------------------------------------------------------------------- */
56 struct pdkim_stringlist {
62 /* -------------------------------------------------------------------------- */
63 /* A bunch of list constants */
64 const uschar * pdkim_querymethods[] = {
68 const uschar * pdkim_canons[] = {
75 const uschar * dkim_hashname;
76 hashmethod exim_hashmethod;
78 static const pdkim_hashtype pdkim_hashes[] = {
79 { US"sha1", HASH_SHA1 },
80 { US"sha256", HASH_SHA2_256 },
81 { US"sha512", HASH_SHA2_512 }
84 const uschar * pdkim_keytypes[] = {
88 typedef struct pdkim_combined_canon_entry {
92 } pdkim_combined_canon_entry;
94 pdkim_combined_canon_entry pdkim_combined_canons[] = {
95 { US"simple/simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
96 { US"simple/relaxed", PDKIM_CANON_SIMPLE, PDKIM_CANON_RELAXED },
97 { US"relaxed/simple", PDKIM_CANON_RELAXED, PDKIM_CANON_SIMPLE },
98 { US"relaxed/relaxed", PDKIM_CANON_RELAXED, PDKIM_CANON_RELAXED },
99 { US"simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
100 { US"relaxed", PDKIM_CANON_RELAXED, PDKIM_CANON_SIMPLE },
105 static blob lineending = {.data = US"\r\n", .len = 2};
107 /* -------------------------------------------------------------------------- */
109 dkim_sig_to_a_tag(const pdkim_signature * sig)
111 if ( sig->keytype < 0 || sig->keytype > nelem(pdkim_keytypes)
112 || sig->hashtype < 0 || sig->hashtype > nelem(pdkim_hashes))
114 return string_sprintf("%s-%s",
115 pdkim_keytypes[sig->keytype], pdkim_hashes[sig->hashtype].dkim_hashname);
121 pdkim_verify_status_str(int status)
125 case PDKIM_VERIFY_NONE: return "PDKIM_VERIFY_NONE";
126 case PDKIM_VERIFY_INVALID: return "PDKIM_VERIFY_INVALID";
127 case PDKIM_VERIFY_FAIL: return "PDKIM_VERIFY_FAIL";
128 case PDKIM_VERIFY_PASS: return "PDKIM_VERIFY_PASS";
129 default: return "PDKIM_VERIFY_UNKNOWN";
134 pdkim_verify_ext_status_str(int ext_status)
138 case PDKIM_VERIFY_FAIL_BODY: return "PDKIM_VERIFY_FAIL_BODY";
139 case PDKIM_VERIFY_FAIL_MESSAGE: return "PDKIM_VERIFY_FAIL_MESSAGE";
140 case PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH: return "PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH";
141 case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE: return "PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE";
142 case PDKIM_VERIFY_INVALID_BUFFER_SIZE: return "PDKIM_VERIFY_INVALID_BUFFER_SIZE";
143 case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD: return "PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD";
144 case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT: return "PDKIM_VERIFY_INVALID_PUBKEY_IMPORT";
145 case PDKIM_VERIFY_INVALID_SIGNATURE_ERROR: return "PDKIM_VERIFY_INVALID_SIGNATURE_ERROR";
146 case PDKIM_VERIFY_INVALID_DKIM_VERSION: return "PDKIM_VERIFY_INVALID_DKIM_VERSION";
147 default: return "PDKIM_VERIFY_UNKNOWN";
152 pdkim_errstr(int status)
156 case PDKIM_OK: return US"OK";
157 case PDKIM_FAIL: return US"FAIL";
158 case PDKIM_ERR_RSA_PRIVKEY: return US"RSA_PRIVKEY";
159 case PDKIM_ERR_RSA_SIGNING: return US"RSA SIGNING";
160 case PDKIM_ERR_LONG_LINE: return US"RSA_LONG_LINE";
161 case PDKIM_ERR_BUFFER_TOO_SMALL: return US"BUFFER_TOO_SMALL";
162 case PDKIM_SIGN_PRIVKEY_WRAP: return US"PRIVKEY_WRAP";
163 case PDKIM_SIGN_PRIVKEY_B64D: return US"PRIVKEY_B64D";
164 default: return US"(unknown)";
169 /* -------------------------------------------------------------------------- */
170 /* Print debugging functions */
172 pdkim_quoteprint(const uschar *data, int len)
175 for (i = 0; i < len; i++)
177 const int c = data[i];
180 case ' ' : debug_printf("{SP}"); break;
181 case '\t': debug_printf("{TB}"); break;
182 case '\r': debug_printf("{CR}"); break;
183 case '\n': debug_printf("{LF}"); break;
184 case '{' : debug_printf("{BO}"); break;
185 case '}' : debug_printf("{BC}"); break;
187 if ( (c < 32) || (c > 127) )
188 debug_printf("{%02x}", c);
190 debug_printf("%c", c);
198 pdkim_hexprint(const uschar *data, int len)
201 if (data) for (i = 0 ; i < len; i++) debug_printf("%02x", data[i]);
202 else debug_printf("<NULL>");
208 static pdkim_stringlist *
209 pdkim_prepend_stringlist(pdkim_stringlist * base, const uschar * str)
211 pdkim_stringlist * new_entry = store_get(sizeof(pdkim_stringlist));
213 memset(new_entry, 0, sizeof(pdkim_stringlist));
214 new_entry->value = string_copy(str);
215 if (base) new_entry->next = base;
221 /* Trim whitespace fore & aft */
224 pdkim_strtrim(gstring * str)
229 while (*p == '\t' || *p == ' ') /* dump the leading whitespace */
230 { str->size--; str->ptr--; str->s++; }
233 && ((q = str->s + str->ptr - 1), (*q == '\t' || *q == ' '))
235 str->ptr--; /* dump trailing whitespace */
237 (void) string_from_gstring(str);
242 /* -------------------------------------------------------------------------- */
245 pdkim_free_ctx(pdkim_ctx *ctx)
250 /* -------------------------------------------------------------------------- */
251 /* Matches the name of the passed raw "header" against
252 the passed colon-separated "tick", and invalidates
253 the entry in tick. Entries can be prefixed for multi- or over-signing,
254 in which case do not invalidate.
256 Returns OK for a match, or fail-code
260 header_name_match(const uschar * header, uschar * tick)
262 const uschar * ticklist = tick;
265 uschar * hname, * p, * ele;
266 uschar * hcolon = Ustrchr(header, ':'); /* Get header name */
269 return PDKIM_FAIL; /* This isn't a header */
271 /* if we had strncmpic() we wouldn't need this copy */
272 hname = string_copyn(header, hcolon-header);
274 while (p = US ticklist, ele = string_nextinlist(&ticklist, &sep, NULL, 0))
278 case '=': case '+': multisign = TRUE; ele++; break;
279 default: multisign = FALSE; break;
282 if (strcmpic(ele, hname) == 0)
285 *p = '_'; /* Invalidate this header name instance in tick-off list */
293 /* -------------------------------------------------------------------------- */
294 /* Performs "relaxed" canonicalization of a header. */
297 pdkim_relax_header(const uschar * header, BOOL append_crlf)
299 BOOL past_field_name = FALSE;
300 BOOL seen_wsp = FALSE;
302 uschar * relaxed = store_get(Ustrlen(header)+3);
303 uschar * q = relaxed;
305 for (p = header; *p; p++)
309 if (c == '\r' || c == '\n') /* Ignore CR & LF */
311 if (c == '\t' || c == ' ')
315 c = ' '; /* Turns WSP into SP */
319 if (!past_field_name && c == ':')
321 if (seen_wsp) q--; /* This removes WSP immediately before the colon */
322 seen_wsp = TRUE; /* This removes WSP immediately after the colon */
323 past_field_name = TRUE;
328 /* Lowercase header name */
329 if (!past_field_name) c = tolower(c);
333 if (q > relaxed && q[-1] == ' ') q--; /* Squash eventual trailing SP */
335 if (append_crlf) { *q++ = '\r'; *q++ = '\n'; }
341 /* -------------------------------------------------------------------------- */
342 #define PDKIM_QP_ERROR_DECODE -1
344 static const uschar *
345 pdkim_decode_qp_char(const uschar *qp_p, int *c)
347 const uschar *initial_pos = qp_p;
349 /* Advance one char */
352 /* Check for two hex digits and decode them */
353 if (isxdigit(*qp_p) && isxdigit(qp_p[1]))
355 /* Do hex conversion */
356 *c = (isdigit(*qp_p) ? *qp_p - '0' : toupper(*qp_p) - 'A' + 10) << 4;
357 *c |= isdigit(qp_p[1]) ? qp_p[1] - '0' : toupper(qp_p[1]) - 'A' + 10;
361 /* Illegal char here */
362 *c = PDKIM_QP_ERROR_DECODE;
367 /* -------------------------------------------------------------------------- */
370 pdkim_decode_qp(const uschar * str)
374 const uschar * p = str;
375 uschar * n = store_get(Ustrlen(str)+1);
383 p = pdkim_decode_qp_char(p, &nchar);
399 /* -------------------------------------------------------------------------- */
402 pdkim_decode_base64(const uschar * str, blob * b)
405 dlen = b64decode(str, &b->data);
406 if (dlen < 0) b->data = NULL;
411 pdkim_encode_base64(blob * b)
413 return b64encode(b->data, b->len);
417 /* -------------------------------------------------------------------------- */
418 #define PDKIM_HDR_LIMBO 0
419 #define PDKIM_HDR_TAG 1
420 #define PDKIM_HDR_VALUE 2
422 static pdkim_signature *
423 pdkim_parse_sig_header(pdkim_ctx * ctx, uschar * raw_hdr)
425 pdkim_signature * sig;
427 gstring * cur_tag = NULL;
428 gstring * cur_val = NULL;
429 BOOL past_hname = FALSE;
430 BOOL in_b_val = FALSE;
431 int where = PDKIM_HDR_LIMBO;
434 sig = store_get(sizeof(pdkim_signature));
435 memset(sig, 0, sizeof(pdkim_signature));
436 sig->bodylength = -1;
438 /* Set so invalid/missing data error display is accurate */
443 q = sig->rawsig_no_b_val = store_get(Ustrlen(raw_hdr)+1);
445 for (p = raw_hdr; ; p++)
450 if (c == '\r' || c == '\n')
453 /* Fast-forward through header name */
456 if (c == ':') past_hname = TRUE;
460 if (where == PDKIM_HDR_LIMBO)
462 /* In limbo, just wait for a tag-char to appear */
463 if (!(c >= 'a' && c <= 'z'))
466 where = PDKIM_HDR_TAG;
469 if (where == PDKIM_HDR_TAG)
471 if (c >= 'a' && c <= 'z')
472 cur_tag = string_catn(cur_tag, p, 1);
476 if (Ustrcmp(string_from_gstring(cur_tag), "b") == 0)
481 where = PDKIM_HDR_VALUE;
486 if (where == PDKIM_HDR_VALUE)
488 if (c == '\r' || c == '\n' || c == ' ' || c == '\t')
491 if (c == ';' || c == '\0')
493 /* We must have both tag and value, and tags must be one char except
494 for the possibility of "bh". */
496 if ( cur_tag && cur_val
497 && (cur_tag->ptr == 1 || *cur_tag->s == 'b')
500 (void) string_from_gstring(cur_val);
501 pdkim_strtrim(cur_val);
503 DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag->s, cur_val->s);
508 switch (cur_tag->s[1])
510 case '\0': pdkim_decode_base64(cur_val->s, &sig->sighash); break;
511 case 'h': if (cur_tag->ptr == 2)
512 pdkim_decode_base64(cur_val->s, &sig->bodyhash);
518 /* We only support version 1, and that is currently the
519 only version there is. */
521 Ustrcmp(cur_val->s, PDKIM_SIGNATURE_VERSION) == 0 ? 1 : -1;
525 uschar * s = Ustrchr(cur_val->s, '-');
527 for(i = 0; i < nelem(pdkim_keytypes); i++)
528 if (Ustrncmp(cur_val->s, pdkim_keytypes[i], s - cur_val->s) == 0)
529 { sig->keytype = i; break; }
530 for (++s, i = 0; i < nelem(pdkim_hashes); i++)
531 if (Ustrcmp(s, pdkim_hashes[i].dkim_hashname) == 0)
532 { sig->hashtype = i; break; }
537 for (i = 0; pdkim_combined_canons[i].str; i++)
538 if (Ustrcmp(cur_val->s, pdkim_combined_canons[i].str) == 0)
540 sig->canon_headers = pdkim_combined_canons[i].canon_headers;
541 sig->canon_body = pdkim_combined_canons[i].canon_body;
546 for (i = 0; pdkim_querymethods[i]; i++)
547 if (Ustrcmp(cur_val->s, pdkim_querymethods[i]) == 0)
549 sig->querymethod = i;
554 sig->selector = string_copyn(cur_val->s, cur_val->ptr); break;
556 sig->domain = string_copyn(cur_val->s, cur_val->ptr); break;
558 sig->identity = pdkim_decode_qp(cur_val->s); break;
560 sig->created = strtoul(CS cur_val->s, NULL, 10); break;
562 sig->expires = strtoul(CS cur_val->s, NULL, 10); break;
564 sig->bodylength = strtol(CS cur_val->s, NULL, 10); break;
566 sig->headernames = string_copyn(cur_val->s, cur_val->ptr); break;
568 sig->copiedheaders = pdkim_decode_qp(cur_val->s); break;
570 DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
574 cur_tag = cur_val = NULL;
576 where = PDKIM_HDR_LIMBO;
579 cur_val = string_catn(cur_val, p, 1);
591 /* Chomp raw header. The final newline must not be added to the signature. */
592 while (--q > sig->rawsig_no_b_val && (*q == '\r' || *q == '\n'))
598 "PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
599 pdkim_quoteprint(US sig->rawsig_no_b_val, Ustrlen(sig->rawsig_no_b_val));
601 "PDKIM >> Sig size: %4u bits\n", (unsigned) sig->sighash.len*8);
603 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
606 if (!pdkim_set_bodyhash(ctx, sig))
613 /* -------------------------------------------------------------------------- */
615 static pdkim_pubkey *
616 pdkim_parse_pubkey_record(pdkim_ctx *ctx, const uschar *raw_record)
622 pub = store_get(sizeof(pdkim_pubkey));
623 memset(pub, 0, sizeof(pdkim_pubkey));
625 while ((ele = string_nextinlist(&raw_record, &sep, NULL, 0)))
629 if ((val = Ustrchr(ele, '=')))
631 int taglen = val++ - ele;
633 DEBUG(D_acl) debug_printf(" %.*s=%s\n", taglen, ele, val);
636 case 'v': pub->version = val; break;
637 case 'h': pub->hashes = val; break;
639 case 'g': pub->granularity = val; break;
640 case 'n': pub->notes = pdkim_decode_qp(val); break;
641 case 'p': pdkim_decode_base64(val, &pub->key); break;
642 case 's': pub->srvtype = val; break;
643 case 't': if (Ustrchr(val, 'y')) pub->testing = 1;
644 if (Ustrchr(val, 's')) pub->no_subdomaining = 1;
646 default: DEBUG(D_acl) debug_printf(" Unknown tag encountered\n"); break;
651 /* Set fallback defaults */
653 pub->version = string_copy(PDKIM_PUB_RECORD_VERSION);
654 else if (Ustrcmp(pub->version, PDKIM_PUB_RECORD_VERSION) != 0)
656 DEBUG(D_acl) debug_printf(" Bad v= field\n");
660 if (!pub->granularity) pub->granularity = US"*";
662 if (!pub->keytype ) pub->keytype = US"rsa";
664 if (!pub->srvtype ) pub->srvtype = US"*";
670 DEBUG(D_acl) debug_printf(" Missing p= field\n");
675 /* -------------------------------------------------------------------------- */
677 /* Update one bodyhash with some additional data.
678 If we have to relax the data for this sig, return our copy of it. */
681 pdkim_update_ctx_bodyhash(pdkim_bodyhash * b, blob * orig_data, blob * relaxed_data)
683 blob * canon_data = orig_data;
684 /* Defaults to simple canon (no further treatment necessary) */
686 if (b->canon_method == PDKIM_CANON_RELAXED)
688 /* Relax the line if not done already */
691 BOOL seen_wsp = FALSE;
695 /* We want to be able to free this else we allocate
696 for the entire message which could be many MB. Since
697 we don't know what allocations the SHA routines might
698 do, not safe to use store_get()/store_reset(). */
700 relaxed_data = store_malloc(sizeof(blob) + orig_data->len+1);
701 relaxed_data->data = US (relaxed_data+1);
703 for (p = orig_data->data; *p; p++)
708 if (q > 0 && relaxed_data->data[q-1] == ' ')
711 else if (c == '\t' || c == ' ')
713 c = ' '; /* Turns WSP into SP */
720 relaxed_data->data[q++] = c;
722 relaxed_data->data[q] = '\0';
723 relaxed_data->len = q;
725 canon_data = relaxed_data;
728 /* Make sure we don't exceed the to-be-signed body length */
729 if ( b->bodylength >= 0
730 && b->signed_body_bytes + (unsigned long)canon_data->len > b->bodylength
732 canon_data->len = b->bodylength - b->signed_body_bytes;
734 if (canon_data->len > 0)
736 exim_sha_update(&b->body_hash_ctx, CUS canon_data->data, canon_data->len);
737 b->signed_body_bytes += canon_data->len;
738 DEBUG(D_acl) pdkim_quoteprint(canon_data->data, canon_data->len);
745 /* -------------------------------------------------------------------------- */
748 pdkim_finish_bodyhash(pdkim_ctx * ctx)
751 pdkim_signature * sig;
753 for (b = ctx->bodyhash; b; b = b->next) /* Finish hashes */
754 exim_sha_finish(&b->body_hash_ctx, &b->bh);
756 /* Traverse all signatures */
757 for (sig = ctx->sig; sig; sig = sig->next)
759 b = sig->calc_body_hash;
763 debug_printf("PDKIM [%s] Body bytes hashed: %lu\n"
764 "PDKIM [%s] Body %s computed: ",
765 sig->domain, b->signed_body_bytes,
766 sig->domain, pdkim_hashes[sig->hashtype].dkim_hashname);
767 pdkim_hexprint(CUS b->bh.data, b->bh.len);
770 /* SIGNING -------------------------------------------------------------- */
771 if (ctx->flags & PDKIM_MODE_SIGN)
773 /* If bodylength limit is set, and we have received less bytes
774 than the requested amount, effectively remove the limit tag. */
775 if (b->signed_body_bytes < sig->bodylength)
776 sig->bodylength = -1;
780 /* VERIFICATION --------------------------------------------------------- */
781 /* Be careful that the header sig included a bodyash */
783 if ( sig->bodyhash.data
784 && memcmp(b->bh.data, sig->bodyhash.data, b->bh.len) == 0)
786 DEBUG(D_acl) debug_printf("PDKIM [%s] Body hash verified OK\n", sig->domain);
792 debug_printf("PDKIM [%s] Body hash signature from headers: ", sig->domain);
793 pdkim_hexprint(sig->bodyhash.data, sig->bodyhash.len);
794 debug_printf("PDKIM [%s] Body hash did NOT verify\n", sig->domain);
796 sig->verify_status = PDKIM_VERIFY_FAIL;
797 sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
805 pdkim_body_complete(pdkim_ctx * ctx)
809 /* In simple body mode, if any empty lines were buffered,
810 replace with one. rfc 4871 3.4.3 */
811 /*XXX checking the signed-body-bytes is a gross hack; I think
812 it indicates that all linebreaks should be buffered, including
813 the one terminating a text line */
815 for (b = ctx->bodyhash; b; b = b->next)
816 if ( b->canon_method == PDKIM_CANON_SIMPLE
817 && b->signed_body_bytes == 0
818 && b->num_buffered_blanklines > 0
820 (void) pdkim_update_ctx_bodyhash(b, &lineending, NULL);
822 ctx->flags |= PDKIM_SEEN_EOD;
823 ctx->linebuf_offset = 0;
828 /* -------------------------------------------------------------------------- */
829 /* Call from pdkim_feed below for processing complete body lines */
832 pdkim_bodyline_complete(pdkim_ctx * ctx)
834 blob line = {.data = ctx->linebuf, .len = ctx->linebuf_offset};
839 /* Ignore extra data if we've seen the end-of-data marker */
840 if (ctx->flags & PDKIM_SEEN_EOD) goto all_skip;
842 /* We've always got one extra byte to stuff a zero ... */
843 ctx->linebuf[line.len] = '\0';
845 /* Terminate on EOD marker */
846 if (ctx->flags & PDKIM_DOT_TERM)
848 if (memcmp(line.data, ".\r\n", 3) == 0)
849 { pdkim_body_complete(ctx); return; }
852 if (memcmp(line.data, "..", 2) == 0)
853 { line.data++; line.len--; }
856 /* Empty lines need to be buffered until we find a non-empty line */
857 if (memcmp(line.data, "\r\n", 2) == 0)
859 for (b = ctx->bodyhash; b; b = b->next) b->num_buffered_blanklines++;
863 /* Process line for each bodyhash separately */
864 for (b = ctx->bodyhash; b; b = b->next)
866 if (b->canon_method == PDKIM_CANON_RELAXED)
868 /* Lines with just spaces need to be buffered too */
869 uschar * cp = line.data;
874 if (c == '\r' && cp[1] == '\n') break;
875 if (c != ' ' && c != '\t') goto hash_process;
879 b->num_buffered_blanklines++;
884 /* At this point, we have a non-empty line, so release the buffered ones. */
886 while (b->num_buffered_blanklines)
888 rnl = pdkim_update_ctx_bodyhash(b, &lineending, rnl);
889 b->num_buffered_blanklines--;
892 rline = pdkim_update_ctx_bodyhash(b, &line, rline);
896 if (rnl) store_free(rnl);
897 if (rline) store_free(rline);
901 ctx->linebuf_offset = 0;
906 /* -------------------------------------------------------------------------- */
907 /* Callback from pdkim_feed below for processing complete headers */
908 #define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
911 pdkim_header_complete(pdkim_ctx * ctx)
913 pdkim_signature * sig, * last_sig;
915 /* Special case: The last header can have an extra \r appended */
916 if ( (ctx->cur_header->ptr > 1) &&
917 (ctx->cur_header->s[ctx->cur_header->ptr-1] == '\r') )
918 --ctx->cur_header->ptr;
919 (void) string_from_gstring(ctx->cur_header);
921 if (++ctx->num_headers > PDKIM_MAX_HEADERS) goto BAIL;
923 /* SIGNING -------------------------------------------------------------- */
924 if (ctx->flags & PDKIM_MODE_SIGN)
925 for (sig = ctx->sig; sig; sig = sig->next) /* Traverse all signatures */
927 /* Add header to the signed headers list (in reverse order) */
928 sig->headers = pdkim_prepend_stringlist(sig->headers, ctx->cur_header->s);
930 /* VERIFICATION ----------------------------------------------------------- */
931 /* DKIM-Signature: headers are added to the verification list */
937 debug_printf("PDKIM >> raw hdr: ");
938 pdkim_quoteprint(CUS ctx->cur_header->s, ctx->cur_header->ptr);
941 if (strncasecmp(CCS ctx->cur_header->s,
942 DKIM_SIGNATURE_HEADERNAME,
943 Ustrlen(DKIM_SIGNATURE_HEADERNAME)) == 0)
945 /* Create and chain new signature block. We could error-check for all
946 required tags here, but prefer to create the internal sig and expicitly
947 fail verification of it later. */
949 DEBUG(D_acl) debug_printf(
950 "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
952 sig = pdkim_parse_sig_header(ctx, ctx->cur_header->s);
954 if (!(last_sig = ctx->sig))
958 while (last_sig->next) last_sig = last_sig->next;
959 last_sig->next = sig;
963 /* all headers are stored for signature verification */
964 ctx->headers = pdkim_prepend_stringlist(ctx->headers, ctx->cur_header->s);
968 ctx->cur_header->s[ctx->cur_header->ptr = 0] = '\0'; /* leave buffer for reuse */
974 /* -------------------------------------------------------------------------- */
975 #define HEADER_BUFFER_FRAG_SIZE 256
978 pdkim_feed(pdkim_ctx * ctx, uschar * data, int len)
982 /* Alternate EOD signal, used in non-dotstuffing mode */
984 pdkim_body_complete(ctx);
986 else for (p = 0; p<len; p++)
990 if (ctx->flags & PDKIM_PAST_HDRS)
992 if (c == '\n' && !(ctx->flags & PDKIM_SEEN_CR)) /* emulate the CR */
994 ctx->linebuf[ctx->linebuf_offset++] = '\r';
995 if (ctx->linebuf_offset == PDKIM_MAX_BODY_LINE_LEN-1)
996 return PDKIM_ERR_LONG_LINE;
999 /* Processing body byte */
1000 ctx->linebuf[ctx->linebuf_offset++] = c;
1002 ctx->flags |= PDKIM_SEEN_CR;
1005 ctx->flags &= ~PDKIM_SEEN_CR;
1006 pdkim_bodyline_complete(ctx);
1009 if (ctx->linebuf_offset == PDKIM_MAX_BODY_LINE_LEN-1)
1010 return PDKIM_ERR_LONG_LINE;
1014 /* Processing header byte */
1016 ctx->flags |= PDKIM_SEEN_CR;
1019 if (!(ctx->flags & PDKIM_SEEN_CR)) /* emulate the CR */
1020 ctx->cur_header = string_catn(ctx->cur_header, CUS "\r", 1);
1022 if (ctx->flags & PDKIM_SEEN_LF) /* Seen last header line */
1024 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1027 ctx->flags = (ctx->flags & ~(PDKIM_SEEN_LF|PDKIM_SEEN_CR)) | PDKIM_PAST_HDRS;
1028 DEBUG(D_acl) debug_printf(
1029 "PDKIM >> Body data for hash, canonicalized >>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1033 ctx->flags = (ctx->flags & ~PDKIM_SEEN_CR) | PDKIM_SEEN_LF;
1035 else if (ctx->flags & PDKIM_SEEN_LF)
1037 if (!(c == '\t' || c == ' ')) /* End of header */
1038 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1040 ctx->flags &= ~PDKIM_SEEN_LF;
1043 if (!ctx->cur_header || ctx->cur_header->ptr < PDKIM_MAX_HEADER_LEN)
1044 ctx->cur_header = string_catn(ctx->cur_header, CUS &data[p], 1);
1052 /* Extend a growing header with a continuation-linebreak */
1054 pdkim_hdr_cont(gstring * str, int * col)
1057 return string_catn(str, US"\r\n\t", 3);
1063 * RFC 5322 specifies that header line length SHOULD be no more than 78
1067 * returns uschar * (not nul-terminated)
1069 * col: this int holds and receives column number (octets since last '\n')
1070 * str: partial string to append to
1071 * pad: padding, split line or space after before or after eg: ";"
1072 * intro: - must join to payload eg "h=", usually the tag name
1073 * payload: eg base64 data - long data can be split arbitrarily.
1075 * this code doesn't fold the header in some of the places that RFC4871
1076 * allows: As per RFC5322(2.2.3) it only folds before or after tag-value
1077 * pairs and inside long values. it also always spaces or breaks after the
1080 * no guarantees are made for output given out-of range input. like tag
1081 * names longer than 78, or bogus col. Input is assumed to be free of line breaks.
1085 pdkim_headcat(int * col, gstring * str,
1086 const uschar * pad, const uschar * intro, const uschar * payload)
1094 str = pdkim_hdr_cont(str, col);
1095 str = string_catn(str, pad, l);
1099 l = (pad?1:0) + (intro?Ustrlen(intro):0);
1102 { /*can't fit intro - start a new line to make room.*/
1103 str = pdkim_hdr_cont(str, col);
1104 l = intro?Ustrlen(intro):0;
1107 l += payload ? Ustrlen(payload):0 ;
1110 { /* this fragment will not fit on a single line */
1113 str = string_catn(str, US" ", 1);
1115 pad = NULL; /* only want this once */
1121 size_t sl = Ustrlen(intro);
1123 str = string_catn(str, intro, sl);
1126 intro = NULL; /* only want this once */
1131 size_t sl = Ustrlen(payload);
1132 size_t chomp = *col+sl < 77 ? sl : 78-*col;
1134 str = string_catn(str, payload, chomp);
1140 /* the while precondition tells us it didn't fit. */
1141 str = pdkim_hdr_cont(str, col);
1146 str = pdkim_hdr_cont(str, col);
1152 str = string_catn(str, US" ", 1);
1159 size_t sl = Ustrlen(intro);
1161 str = string_catn(str, intro, sl);
1169 size_t sl = Ustrlen(payload);
1171 str = string_catn(str, payload, sl);
1179 /* -------------------------------------------------------------------------- */
1181 /* Signing: create signature header
1184 pdkim_create_header(pdkim_signature * sig, BOOL final)
1190 gstring * canon_all;
1192 canon_all = string_cat (NULL, pdkim_canons[sig->canon_headers]);
1193 canon_all = string_catn(canon_all, US"/", 1);
1194 canon_all = string_cat (canon_all, pdkim_canons[sig->canon_body]);
1195 (void) string_from_gstring(canon_all);
1197 hdr = string_cat(NULL, US"DKIM-Signature: v="PDKIM_SIGNATURE_VERSION);
1200 /* Required and static bits */
1201 hdr = pdkim_headcat(&col, hdr, US";", US"a=", dkim_sig_to_a_tag(sig));
1202 hdr = pdkim_headcat(&col, hdr, US";", US"q=", pdkim_querymethods[sig->querymethod]);
1203 hdr = pdkim_headcat(&col, hdr, US";", US"c=", canon_all->s);
1204 hdr = pdkim_headcat(&col, hdr, US";", US"d=", sig->domain);
1205 hdr = pdkim_headcat(&col, hdr, US";", US"s=", sig->selector);
1207 /* list of header names can be split between items. */
1209 uschar * n = string_copy(sig->headernames);
1210 uschar * i = US"h=";
1215 uschar * c = Ustrchr(n, ':');
1220 hdr = pdkim_headcat(&col, hdr, NULL, NULL, US":");
1222 hdr = pdkim_headcat(&col, hdr, s, i, n);
1233 base64_bh = pdkim_encode_base64(&sig->calc_body_hash->bh);
1234 hdr = pdkim_headcat(&col, hdr, US";", US"bh=", base64_bh);
1238 hdr = pdkim_headcat(&col, hdr, US";", US"i=", sig->identity);
1240 if (sig->created > 0)
1244 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->created);
1245 hdr = pdkim_headcat(&col, hdr, US";", US"t=", minibuf);
1248 if (sig->expires > 0)
1252 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->expires);
1253 hdr = pdkim_headcat(&col, hdr, US";", US"x=", minibuf);
1256 if (sig->bodylength >= 0)
1260 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->bodylength);
1261 hdr = pdkim_headcat(&col, hdr, US";", US"l=", minibuf);
1264 /* Preliminary or final version? */
1267 base64_b = pdkim_encode_base64(&sig->sighash);
1268 hdr = pdkim_headcat(&col, hdr, US";", US"b=", base64_b);
1270 /* add trailing semicolon: I'm not sure if this is actually needed */
1271 hdr = pdkim_headcat(&col, hdr, NULL, US";", US"");
1275 /* To satisfy the rule "all surrounding whitespace [...] deleted"
1276 ( RFC 6376 section 3.7 ) we ensure there is no whitespace here. Otherwise
1277 the headcat routine could insert a linebreak which the relaxer would reduce
1278 to a single space preceding the terminating semicolon, resulting in an
1279 incorrect header-hash. */
1280 hdr = pdkim_headcat(&col, hdr, US";", US"b=;", US"");
1283 return string_from_gstring(hdr);
1287 /* -------------------------------------------------------------------------- */
1289 static pdkim_pubkey *
1290 pdkim_key_from_dns(pdkim_ctx * ctx, pdkim_signature * sig, ev_ctx * vctx,
1291 const uschar ** errstr)
1293 uschar * dns_txt_name, * dns_txt_reply;
1296 /* Fetch public key for signing domain, from DNS */
1298 dns_txt_name = string_sprintf("%s._domainkey.%s.", sig->selector, sig->domain);
1300 if ( !(dns_txt_reply = ctx->dns_txt_callback(CS dns_txt_name))
1301 || dns_txt_reply[0] == '\0'
1304 sig->verify_status = PDKIM_VERIFY_INVALID;
1305 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE;
1312 "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
1316 pdkim_quoteprint(CUS dns_txt_reply, Ustrlen(dns_txt_reply));
1319 if ( !(p = pdkim_parse_pubkey_record(ctx, CUS dns_txt_reply))
1320 || (Ustrcmp(p->srvtype, "*") != 0 && Ustrcmp(p->srvtype, "email") != 0)
1323 sig->verify_status = PDKIM_VERIFY_INVALID;
1324 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD;
1329 debug_printf(" Invalid public key service type '%s'\n", p->srvtype);
1331 debug_printf(" Error while parsing public key record\n");
1333 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1338 DEBUG(D_acl) debug_printf(
1339 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1341 /* Import public key */
1342 if ((*errstr = exim_dkim_verify_init(&p->key, vctx)))
1344 DEBUG(D_acl) debug_printf("verify_init: %s\n", *errstr);
1345 sig->verify_status = PDKIM_VERIFY_INVALID;
1346 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_IMPORT;
1354 /* -------------------------------------------------------------------------- */
1357 pdkim_feed_finish(pdkim_ctx * ctx, pdkim_signature ** return_signatures,
1358 const uschar ** err)
1361 pdkim_signature * sig;
1363 /* Check if we must still flush a (partial) header. If that is the
1364 case, the message has no body, and we must compute a body hash
1365 out of '<CR><LF>' */
1366 if (ctx->cur_header && ctx->cur_header->ptr > 0)
1371 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1374 for (b = ctx->bodyhash; b; b = b->next)
1375 rnl = pdkim_update_ctx_bodyhash(b, &lineending, rnl);
1376 if (rnl) store_free(rnl);
1379 DEBUG(D_acl) debug_printf(
1380 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1382 /* Build (and/or evaluate) body hash */
1383 pdkim_finish_bodyhash(ctx);
1385 for (sig = ctx->sig; sig; sig = sig->next)
1388 uschar * sig_hdr = US"";
1390 gstring * hdata = NULL;
1392 if (!exim_sha_init(&hhash_ctx, pdkim_hashes[sig->hashtype].exim_hashmethod))
1395 debug_printf("PDKIM: hash setup error, possibly nonhandled hashtype\n");
1399 if (ctx->flags & PDKIM_MODE_SIGN)
1400 DEBUG(D_acl) debug_printf(
1401 "PDKIM >> Headers to be signed: >>>>>>>>>>>>\n"
1405 DEBUG(D_acl) debug_printf(
1406 "PDKIM >> Header data for hash, canonicalized, in sequence >>>>>>>>>>>>\n");
1409 /* SIGNING ---------------------------------------------------------------- */
1410 /* When signing, walk through our header list and add them to the hash. As we
1411 go, construct a list of the header's names to use for the h= parameter.
1412 Then append to that list any remaining header names for which there was no
1415 if (ctx->flags & PDKIM_MODE_SIGN)
1418 pdkim_stringlist *p;
1423 sig->headernames = NULL; /* Collected signed header names */
1425 for (p = sig->headers; p; p = p->next)
1427 uschar * rh = p->value;
1429 if (header_name_match(rh, sig->sign_headers) == PDKIM_OK)
1431 /* Collect header names (Note: colon presence is guaranteed here) */
1432 g = string_append_listele_n(g, ':', rh, Ustrchr(rh, ':') - rh);
1434 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1435 rh = pdkim_relax_header(rh, TRUE); /* cook header for relaxed canon */
1437 /* Feed header to the hash algorithm */
1438 exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
1440 /* Remember headers block for signing (when the library cannot do incremental) */
1441 hdata = exim_dkim_data_append(hdata, rh);
1443 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1447 /* Any headers we wanted to sign but were not present must also be listed.
1448 Ignore elements that have been ticked-off or are marked as never-oversign. */
1450 l = sig->sign_headers;
1451 while((s = string_nextinlist(&l, &sep, NULL, 0)))
1453 if (*s == '+') /* skip oversigning marker */
1455 if (*s != '_' && *s != '=')
1456 g = string_append_listele(g, ':', s);
1458 sig->headernames = string_from_gstring(g);
1460 /* Create signature header with b= omitted */
1461 sig_hdr = pdkim_create_header(sig, FALSE);
1464 /* VERIFICATION ----------------------------------------------------------- */
1465 /* When verifying, walk through the header name list in the h= parameter and
1466 add the headers to the hash in that order. */
1469 uschar * p = sig->headernames;
1471 pdkim_stringlist * hdrs;
1476 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1482 if ((q = Ustrchr(p, ':')))
1485 /*XXX walk the list of headers in same order as received. */
1486 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1488 && strncasecmp(CCS hdrs->value, CCS p, Ustrlen(p)) == 0
1489 && (hdrs->value)[Ustrlen(p)] == ':'
1492 /* cook header for relaxed canon, or just copy it for simple */
1494 uschar * rh = sig->canon_headers == PDKIM_CANON_RELAXED
1495 ? pdkim_relax_header(hdrs->value, TRUE)
1496 : string_copy(CUS hdrs->value);
1498 /* Feed header to the hash algorithm */
1499 exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
1501 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1510 sig_hdr = string_copy(sig->rawsig_no_b_val);
1514 DEBUG(D_acl) debug_printf(
1515 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1520 "PDKIM >> Signed DKIM-Signature header, pre-canonicalized >>>>>>>>>>>>>\n");
1521 pdkim_quoteprint(CUS sig_hdr, Ustrlen(sig_hdr));
1523 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1526 /* Relax header if necessary */
1527 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1528 sig_hdr = pdkim_relax_header(sig_hdr, FALSE);
1533 "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
1534 pdkim_quoteprint(CUS sig_hdr, Ustrlen(sig_hdr));
1536 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1539 /* Finalize header hash */
1540 exim_sha_update(&hhash_ctx, CUS sig_hdr, Ustrlen(sig_hdr));
1541 exim_sha_finish(&hhash_ctx, &hhash);
1545 debug_printf("PDKIM [%s] Header %s computed: ",
1546 sig->domain, pdkim_hashes[sig->hashtype].dkim_hashname);
1547 pdkim_hexprint(hhash.data, hhash.len);
1550 /* Remember headers block for signing (when the signing library cannot do
1552 if (ctx->flags & PDKIM_MODE_SIGN)
1553 hdata = exim_dkim_data_append(hdata, US sig_hdr);
1555 /* SIGNING ---------------------------------------------------------------- */
1556 if (ctx->flags & PDKIM_MODE_SIGN)
1560 /* Import private key, including the keytype */
1561 /*XXX extend for non-RSA algos */
1562 if ((*err = exim_dkim_signing_init(US sig->privkey, &sctx)))
1564 DEBUG(D_acl) debug_printf("signing_init: %s\n", *err);
1565 return PDKIM_ERR_RSA_PRIVKEY;
1568 /* Do signing. With OpenSSL we are signing the hash of headers just
1569 calculated, with GnuTLS we have to sign an entire block of headers
1570 (due to available interfaces) and it recalculates the hash internally. */
1572 #if defined(SIGN_GNUTLS)
1573 hhash.data = hdata->s;
1574 hhash.len = hdata->ptr;
1577 /*XXX extend for non-RSA algos */
1578 if ((*err = exim_dkim_sign(&sctx,
1579 pdkim_hashes[sig->hashtype].exim_hashmethod,
1580 &hhash, &sig->sighash)))
1582 DEBUG(D_acl) debug_printf("signing: %s\n", *err);
1583 return PDKIM_ERR_RSA_SIGNING;
1588 debug_printf( "PDKIM [%s] b computed: ", sig->domain);
1589 pdkim_hexprint(sig->sighash.data, sig->sighash.len);
1592 sig->signature_header = pdkim_create_header(sig, TRUE);
1595 /* VERIFICATION ----------------------------------------------------------- */
1600 /* Make sure we have all required signature tags */
1601 if (!( sig->domain && *sig->domain
1602 && sig->selector && *sig->selector
1603 && sig->headernames && *sig->headernames
1604 && sig->bodyhash.data
1605 && sig->sighash.data
1606 && sig->keytype >= 0
1607 && sig->hashtype >= 0
1611 sig->verify_status = PDKIM_VERIFY_INVALID;
1612 sig->verify_ext_status = PDKIM_VERIFY_INVALID_SIGNATURE_ERROR;
1614 DEBUG(D_acl) debug_printf(
1615 " Error in DKIM-Signature header: tags missing or invalid\n"
1616 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1620 /* Make sure sig uses supported DKIM version (only v1) */
1621 if (sig->version != 1)
1623 sig->verify_status = PDKIM_VERIFY_INVALID;
1624 sig->verify_ext_status = PDKIM_VERIFY_INVALID_DKIM_VERSION;
1626 DEBUG(D_acl) debug_printf(
1627 " Error in DKIM-Signature header: unsupported DKIM version\n"
1628 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1634 debug_printf( "PDKIM [%s] b from mail: ", sig->domain);
1635 pdkim_hexprint(sig->sighash.data, sig->sighash.len);
1638 if (!(sig->pubkey = pdkim_key_from_dns(ctx, sig, &vctx, err)))
1641 /* If the pubkey limits to a list of specific hashes, ignore sigs that
1642 do not have the hash part of the sig algorithm matching */
1644 if (sig->pubkey->hashes)
1646 const uschar * list = sig->pubkey->hashes, * ele;
1648 while ((ele = string_nextinlist(&list, &sep, NULL, 0)))
1649 if (Ustrcmp(ele, pdkim_hashes[sig->hashtype].dkim_hashname) == 0) break;
1652 DEBUG(D_acl) debug_printf("pubkey h=%s vs. sig a=%s_%s\n",
1653 sig->pubkey->hashes,
1654 pdkim_keytypes[sig->keytype],
1655 pdkim_hashes[sig->hashtype].dkim_hashname);
1656 sig->verify_status = PDKIM_VERIFY_FAIL;
1657 sig->verify_ext_status = PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH;
1662 /* Check the signature */
1663 /*XXX needs extension for non-RSA */
1664 if ((*err = exim_dkim_verify(&vctx,
1665 pdkim_hashes[sig->hashtype].exim_hashmethod,
1666 &hhash, &sig->sighash)))
1668 DEBUG(D_acl) debug_printf("headers verify: %s\n", *err);
1669 sig->verify_status = PDKIM_VERIFY_FAIL;
1670 sig->verify_ext_status = PDKIM_VERIFY_FAIL_MESSAGE;
1675 /* We have a winner! (if bodyhash was correct earlier) */
1676 if (sig->verify_status == PDKIM_VERIFY_NONE)
1677 sig->verify_status = PDKIM_VERIFY_PASS;
1683 debug_printf("PDKIM [%s] signature status: %s",
1684 sig->domain, pdkim_verify_status_str(sig->verify_status));
1685 if (sig->verify_ext_status > 0)
1686 debug_printf(" (%s)\n",
1687 pdkim_verify_ext_status_str(sig->verify_ext_status));
1694 /* If requested, set return pointer to signature(s) */
1695 if (return_signatures)
1696 *return_signatures = ctx->sig;
1702 /* -------------------------------------------------------------------------- */
1704 DLLEXPORT pdkim_ctx *
1705 pdkim_init_verify(uschar * (*dns_txt_callback)(char *), BOOL dot_stuffing)
1709 ctx = store_get(sizeof(pdkim_ctx));
1710 memset(ctx, 0, sizeof(pdkim_ctx));
1712 if (dot_stuffing) ctx->flags = PDKIM_DOT_TERM;
1713 ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN);
1714 ctx->dns_txt_callback = dns_txt_callback;
1720 /* -------------------------------------------------------------------------- */
1722 /*XXX ? needs extension to cover non-RSA algo? */
1724 DLLEXPORT pdkim_signature *
1725 pdkim_init_sign(pdkim_ctx * ctx,
1726 uschar * domain, uschar * selector, uschar * privkey,
1727 uschar * hashname, const uschar ** errstr)
1730 pdkim_signature * sig;
1732 if (!domain || !selector || !privkey)
1735 /* Allocate & init one signature struct */
1737 sig = store_get(sizeof(pdkim_signature));
1738 memset(sig, 0, sizeof(pdkim_signature));
1740 sig->bodylength = -1;
1742 sig->domain = string_copy(US domain);
1743 sig->selector = string_copy(US selector);
1744 sig->privkey = string_copy(US privkey);
1745 /*XXX no keytype yet; comes from privkey */
1747 for (hashtype = 0; hashtype < nelem(pdkim_hashes); hashtype++)
1748 if (Ustrcmp(hashname, pdkim_hashes[hashtype].dkim_hashname) == 0)
1749 { sig->hashtype = hashtype; break; }
1750 if (hashtype >= nelem(pdkim_hashes))
1753 debug_printf("PDKIM: unrecognised hashname '%s'\n", hashname);
1759 pdkim_signature s = *sig;
1762 debug_printf("PDKIM (checking verify key)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1763 if (!pdkim_key_from_dns(ctx, &s, &vctx, errstr))
1764 debug_printf("WARNING: bad dkim key in dns\n");
1765 debug_printf("PDKIM (finished checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1771 /* -------------------------------------------------------------------------- */
1774 pdkim_set_optional(pdkim_signature * sig,
1775 char * sign_headers,
1780 unsigned long created,
1781 unsigned long expires)
1784 sig->identity = string_copy(US identity);
1786 sig->sign_headers = string_copy(sign_headers
1787 ? US sign_headers : US PDKIM_DEFAULT_SIGN_HEADERS);
1789 sig->canon_headers = canon_headers;
1790 sig->canon_body = canon_body;
1791 sig->bodylength = bodylength;
1792 sig->created = created;
1793 sig->expires = expires;
1800 /* Set up a blob for calculating the bodyhash according to the
1801 needs of this signature. Use an existing one if possible, or
1804 Return: hashblob pointer, or NULL on error (only used as a boolean).
1807 pdkim_set_bodyhash(pdkim_ctx * ctx, pdkim_signature * sig)
1811 for (b = ctx->bodyhash; b; b = b->next)
1812 if ( sig->hashtype == b->hashtype
1813 && sig->canon_body == b->canon_method
1814 && sig->bodylength == b->bodylength)
1817 b = store_get(sizeof(pdkim_bodyhash));
1818 b->next = ctx->bodyhash;
1819 b->hashtype = sig->hashtype;
1820 b->canon_method = sig->canon_body;
1821 b->bodylength = sig->bodylength;
1822 if (!exim_sha_init(&b->body_hash_ctx, /*XXX hash method: extend for sha512 */
1823 pdkim_hashes[sig->hashtype].exim_hashmethod))
1826 debug_printf("PDKIM: hash init error, possibly nonhandled hashtype\n");
1829 b->signed_body_bytes = 0;
1830 b->num_buffered_blanklines = 0;
1834 sig->calc_body_hash = b;
1839 /* -------------------------------------------------------------------------- */
1843 pdkim_init_context(pdkim_ctx * ctx, BOOL dot_stuffed,
1844 uschar * (*dns_txt_callback)(char *))
1846 memset(ctx, 0, sizeof(pdkim_ctx));
1847 ctx->flags = dot_stuffed ? PDKIM_MODE_SIGN | PDKIM_DOT_TERM : PDKIM_MODE_SIGN;
1848 ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN);
1849 DEBUG(D_acl) ctx->dns_txt_callback = dns_txt_callback;
1861 #endif /*DISABLE_DKIM*/