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 /*XXX hash method: extend for sha512 */
607 if (!exim_sha_init(&sig->body_hash_ctx,
608 pdkim_hashes[sig->hashtype].exim_hashmethod))
611 debug_printf("PDKIM: hash init error, possibly nonhandled hashtype\n");
618 /* -------------------------------------------------------------------------- */
620 static pdkim_pubkey *
621 pdkim_parse_pubkey_record(pdkim_ctx *ctx, const uschar *raw_record)
627 pub = store_get(sizeof(pdkim_pubkey));
628 memset(pub, 0, sizeof(pdkim_pubkey));
630 while ((ele = string_nextinlist(&raw_record, &sep, NULL, 0)))
634 if ((val = Ustrchr(ele, '=')))
636 int taglen = val++ - ele;
638 DEBUG(D_acl) debug_printf(" %.*s=%s\n", taglen, ele, val);
641 case 'v': pub->version = val; break;
642 case 'h': pub->hashes = val; break;
644 case 'g': pub->granularity = val; break;
645 case 'n': pub->notes = pdkim_decode_qp(val); break;
646 case 'p': pdkim_decode_base64(val, &pub->key); break;
647 case 's': pub->srvtype = val; break;
648 case 't': if (Ustrchr(val, 'y')) pub->testing = 1;
649 if (Ustrchr(val, 's')) pub->no_subdomaining = 1;
651 default: DEBUG(D_acl) debug_printf(" Unknown tag encountered\n"); break;
656 /* Set fallback defaults */
658 pub->version = string_copy(PDKIM_PUB_RECORD_VERSION);
659 else if (Ustrcmp(pub->version, PDKIM_PUB_RECORD_VERSION) != 0)
661 DEBUG(D_acl) debug_printf(" Bad v= field\n");
665 if (!pub->granularity) pub->granularity = US"*";
667 if (!pub->keytype ) pub->keytype = US"rsa";
669 if (!pub->srvtype ) pub->srvtype = US"*";
675 DEBUG(D_acl) debug_printf(" Missing p= field\n");
680 /* -------------------------------------------------------------------------- */
682 /* Update the bodyhash for one sig, with some additional data.
683 If we have to relax the data for this sig, return our copy of it. */
685 /*XXX Currently we calculate a hash for each sig. But it is possible
686 that multi-signing will be wanted using different signing algos
687 (rsa, ec) using the same hash and canonicalization. Consider in future
688 hanging the hash+cacnon from the ctx and only referencing from the sig,
689 so that it can be calculated only once - being over the body this
690 caould be meagbytes, hence expensive. */
693 pdkim_update_sig_bodyhash(pdkim_signature * sig, blob * orig_data, blob * relaxed_data)
695 blob * canon_data = orig_data;
696 /* Defaults to simple canon (no further treatment necessary) */
698 if (sig->canon_body == PDKIM_CANON_RELAXED)
700 /* Relax the line if not done already */
703 BOOL seen_wsp = FALSE;
707 /* We want to be able to free this else we allocate
708 for the entire message which could be many MB. Since
709 we don't know what allocations the SHA routines might
710 do, not safe to use store_get()/store_reset(). */
712 relaxed_data = store_malloc(sizeof(blob) + orig_data->len+1);
713 relaxed_data->data = US (relaxed_data+1);
715 for (p = orig_data->data; *p; p++)
720 if (q > 0 && relaxed_data->data[q-1] == ' ')
723 else if (c == '\t' || c == ' ')
725 c = ' '; /* Turns WSP into SP */
732 relaxed_data->data[q++] = c;
734 relaxed_data->data[q] = '\0';
735 relaxed_data->len = q;
737 canon_data = relaxed_data;
740 /* Make sure we don't exceed the to-be-signed body length */
741 if ( sig->bodylength >= 0
742 && sig->signed_body_bytes + (unsigned long)canon_data->len > sig->bodylength
744 canon_data->len = sig->bodylength - sig->signed_body_bytes;
746 if (canon_data->len > 0)
748 exim_sha_update(&sig->body_hash_ctx, CUS canon_data->data, canon_data->len);
749 sig->signed_body_bytes += canon_data->len;
750 DEBUG(D_acl) pdkim_quoteprint(canon_data->data, canon_data->len);
757 /* -------------------------------------------------------------------------- */
760 pdkim_finish_bodyhash(pdkim_ctx * ctx)
762 pdkim_signature * sig;
764 /* Traverse all signatures */
765 for (sig = ctx->sig; sig; sig = sig->next)
766 { /* Finish hashes */
769 exim_sha_finish(&sig->body_hash_ctx, &bh);
773 debug_printf("PDKIM [%s] Body bytes hashed: %lu\n"
774 "PDKIM [%s] Body %s computed: ",
775 sig->domain, sig->signed_body_bytes,
776 sig->domain, pdkim_hashes[sig->hashtype].dkim_hashname);
777 pdkim_hexprint(CUS bh.data, bh.len);
780 /* SIGNING -------------------------------------------------------------- */
781 if (ctx->flags & PDKIM_MODE_SIGN)
785 /* If bodylength limit is set, and we have received less bytes
786 than the requested amount, effectively remove the limit tag. */
787 if (sig->signed_body_bytes < sig->bodylength)
788 sig->bodylength = -1;
792 /* VERIFICATION --------------------------------------------------------- */
793 /* Be careful that the header sig included a bodyash */
795 if (sig->bodyhash.data && memcmp(bh.data, sig->bodyhash.data, bh.len) == 0)
797 DEBUG(D_acl) debug_printf("PDKIM [%s] Body hash verified OK\n", sig->domain);
803 debug_printf("PDKIM [%s] Body hash signature from headers: ", sig->domain);
804 pdkim_hexprint(sig->bodyhash.data, sig->bodyhash.len);
805 debug_printf("PDKIM [%s] Body hash did NOT verify\n", sig->domain);
807 sig->verify_status = PDKIM_VERIFY_FAIL;
808 sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
816 pdkim_body_complete(pdkim_ctx * ctx)
818 pdkim_signature * sig;
820 /* In simple body mode, if any empty lines were buffered,
821 replace with one. rfc 4871 3.4.3 */
822 /*XXX checking the signed-body-bytes is a gross hack; I think
823 it indicates that all linebreaks should be buffered, including
824 the one terminating a text line */
826 for (sig = ctx->sig; sig; sig = sig->next)
827 if ( sig->canon_body == PDKIM_CANON_SIMPLE
828 && sig->signed_body_bytes == 0
829 && sig->num_buffered_blanklines > 0
831 (void) pdkim_update_sig_bodyhash(sig, &lineending, NULL);
833 ctx->flags |= PDKIM_SEEN_EOD;
834 ctx->linebuf_offset = 0;
839 /* -------------------------------------------------------------------------- */
840 /* Call from pdkim_feed below for processing complete body lines */
843 pdkim_bodyline_complete(pdkim_ctx * ctx)
845 blob line = {.data = ctx->linebuf, .len = ctx->linebuf_offset};
846 pdkim_signature * sig;
850 /* Ignore extra data if we've seen the end-of-data marker */
851 if (ctx->flags & PDKIM_SEEN_EOD) goto all_skip;
853 /* We've always got one extra byte to stuff a zero ... */
854 ctx->linebuf[line.len] = '\0';
856 /* Terminate on EOD marker */
857 if (ctx->flags & PDKIM_DOT_TERM)
859 if (memcmp(line.data, ".\r\n", 3) == 0)
860 { pdkim_body_complete(ctx); return; }
863 if (memcmp(line.data, "..", 2) == 0)
864 { line.data++; line.len--; }
867 /* Empty lines need to be buffered until we find a non-empty line */
868 if (memcmp(line.data, "\r\n", 2) == 0)
870 for (sig = ctx->sig; sig; sig = sig->next) sig->num_buffered_blanklines++;
874 /* Process line for each sig separately */
875 for (sig = ctx->sig; sig; sig = sig->next)
877 if (sig->canon_body == PDKIM_CANON_RELAXED)
879 /* Lines with just spaces need to be buffered too */
880 uschar * cp = line.data;
885 if (c == '\r' && cp[1] == '\n') break;
886 if (c != ' ' && c != '\t') goto sig_process;
890 sig->num_buffered_blanklines++;
895 /* At this point, we have a non-empty line, so release the buffered ones. */
897 while (sig->num_buffered_blanklines)
899 rnl = pdkim_update_sig_bodyhash(sig, &lineending, rnl);
900 sig->num_buffered_blanklines--;
903 rline = pdkim_update_sig_bodyhash(sig, &line, rline);
907 if (rnl) store_free(rnl);
908 if (rline) store_free(rline);
912 ctx->linebuf_offset = 0;
917 /* -------------------------------------------------------------------------- */
918 /* Callback from pdkim_feed below for processing complete headers */
919 #define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
922 pdkim_header_complete(pdkim_ctx * ctx)
924 pdkim_signature * sig, * last_sig;
926 /* Special case: The last header can have an extra \r appended */
927 if ( (ctx->cur_header->ptr > 1) &&
928 (ctx->cur_header->s[ctx->cur_header->ptr-1] == '\r') )
929 --ctx->cur_header->ptr;
930 (void) string_from_gstring(ctx->cur_header);
932 if (++ctx->num_headers > PDKIM_MAX_HEADERS) goto BAIL;
934 /* SIGNING -------------------------------------------------------------- */
935 if (ctx->flags & PDKIM_MODE_SIGN)
936 for (sig = ctx->sig; sig; sig = sig->next) /* Traverse all signatures */
938 /* Add header to the signed headers list (in reverse order) */
939 sig->headers = pdkim_prepend_stringlist(sig->headers, ctx->cur_header->s);
941 /* VERIFICATION ----------------------------------------------------------- */
942 /* DKIM-Signature: headers are added to the verification list */
948 debug_printf("PDKIM >> raw hdr: ");
949 pdkim_quoteprint(CUS ctx->cur_header->s, ctx->cur_header->ptr);
952 if (strncasecmp(CCS ctx->cur_header->s,
953 DKIM_SIGNATURE_HEADERNAME,
954 Ustrlen(DKIM_SIGNATURE_HEADERNAME)) == 0)
956 /* Create and chain new signature block. We could error-check for all
957 required tags here, but prefer to create the internal sig and expicitly
958 fail verification of it later. */
960 DEBUG(D_acl) debug_printf(
961 "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
963 sig = pdkim_parse_sig_header(ctx, ctx->cur_header->s);
965 if (!(last_sig = ctx->sig))
969 while (last_sig->next) last_sig = last_sig->next;
970 last_sig->next = sig;
974 /* all headers are stored for signature verification */
975 ctx->headers = pdkim_prepend_stringlist(ctx->headers, ctx->cur_header->s);
979 ctx->cur_header->s[ctx->cur_header->ptr = 0] = '\0'; /* leave buffer for reuse */
985 /* -------------------------------------------------------------------------- */
986 #define HEADER_BUFFER_FRAG_SIZE 256
989 pdkim_feed(pdkim_ctx * ctx, uschar * data, int len)
993 /* Alternate EOD signal, used in non-dotstuffing mode */
995 pdkim_body_complete(ctx);
997 else for (p = 0; p<len; p++)
1001 if (ctx->flags & PDKIM_PAST_HDRS)
1003 if (c == '\n' && !(ctx->flags & PDKIM_SEEN_CR)) /* emulate the CR */
1005 ctx->linebuf[ctx->linebuf_offset++] = '\r';
1006 if (ctx->linebuf_offset == PDKIM_MAX_BODY_LINE_LEN-1)
1007 return PDKIM_ERR_LONG_LINE;
1010 /* Processing body byte */
1011 ctx->linebuf[ctx->linebuf_offset++] = c;
1013 ctx->flags |= PDKIM_SEEN_CR;
1016 ctx->flags &= ~PDKIM_SEEN_CR;
1017 pdkim_bodyline_complete(ctx);
1020 if (ctx->linebuf_offset == PDKIM_MAX_BODY_LINE_LEN-1)
1021 return PDKIM_ERR_LONG_LINE;
1025 /* Processing header byte */
1027 ctx->flags |= PDKIM_SEEN_CR;
1030 if (!(ctx->flags & PDKIM_SEEN_CR)) /* emulate the CR */
1031 ctx->cur_header = string_catn(ctx->cur_header, CUS "\r", 1);
1033 if (ctx->flags & PDKIM_SEEN_LF) /* Seen last header line */
1035 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1038 ctx->flags = (ctx->flags & ~(PDKIM_SEEN_LF|PDKIM_SEEN_CR)) | PDKIM_PAST_HDRS;
1039 DEBUG(D_acl) debug_printf(
1040 "PDKIM >> Body data for hash, canonicalized >>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1044 ctx->flags = (ctx->flags & ~PDKIM_SEEN_CR) | PDKIM_SEEN_LF;
1046 else if (ctx->flags & PDKIM_SEEN_LF)
1048 if (!(c == '\t' || c == ' ')) /* End of header */
1049 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1051 ctx->flags &= ~PDKIM_SEEN_LF;
1054 if (!ctx->cur_header || ctx->cur_header->ptr < PDKIM_MAX_HEADER_LEN)
1055 ctx->cur_header = string_catn(ctx->cur_header, CUS &data[p], 1);
1063 /* Extend a growing header with a continuation-linebreak */
1065 pdkim_hdr_cont(gstring * str, int * col)
1068 return string_catn(str, US"\r\n\t", 3);
1074 * RFC 5322 specifies that header line length SHOULD be no more than 78
1078 * returns uschar * (not nul-terminated)
1080 * col: this int holds and receives column number (octets since last '\n')
1081 * str: partial string to append to
1082 * pad: padding, split line or space after before or after eg: ";"
1083 * intro: - must join to payload eg "h=", usually the tag name
1084 * payload: eg base64 data - long data can be split arbitrarily.
1086 * this code doesn't fold the header in some of the places that RFC4871
1087 * allows: As per RFC5322(2.2.3) it only folds before or after tag-value
1088 * pairs and inside long values. it also always spaces or breaks after the
1091 * no guarantees are made for output given out-of range input. like tag
1092 * names longer than 78, or bogus col. Input is assumed to be free of line breaks.
1096 pdkim_headcat(int * col, gstring * str,
1097 const uschar * pad, const uschar * intro, const uschar * payload)
1105 str = pdkim_hdr_cont(str, col);
1106 str = string_catn(str, pad, l);
1110 l = (pad?1:0) + (intro?Ustrlen(intro):0);
1113 { /*can't fit intro - start a new line to make room.*/
1114 str = pdkim_hdr_cont(str, col);
1115 l = intro?Ustrlen(intro):0;
1118 l += payload ? Ustrlen(payload):0 ;
1121 { /* this fragment will not fit on a single line */
1124 str = string_catn(str, US" ", 1);
1126 pad = NULL; /* only want this once */
1132 size_t sl = Ustrlen(intro);
1134 str = string_catn(str, intro, sl);
1137 intro = NULL; /* only want this once */
1142 size_t sl = Ustrlen(payload);
1143 size_t chomp = *col+sl < 77 ? sl : 78-*col;
1145 str = string_catn(str, payload, chomp);
1151 /* the while precondition tells us it didn't fit. */
1152 str = pdkim_hdr_cont(str, col);
1157 str = pdkim_hdr_cont(str, col);
1163 str = string_catn(str, US" ", 1);
1170 size_t sl = Ustrlen(intro);
1172 str = string_catn(str, intro, sl);
1180 size_t sl = Ustrlen(payload);
1182 str = string_catn(str, payload, sl);
1190 /* -------------------------------------------------------------------------- */
1193 pdkim_create_header(pdkim_signature * sig, BOOL final)
1199 gstring * canon_all;
1201 canon_all = string_cat (NULL, pdkim_canons[sig->canon_headers]);
1202 canon_all = string_catn(canon_all, US"/", 1);
1203 canon_all = string_cat (canon_all, pdkim_canons[sig->canon_body]);
1204 (void) string_from_gstring(canon_all);
1206 hdr = string_cat(NULL, US"DKIM-Signature: v="PDKIM_SIGNATURE_VERSION);
1209 /* Required and static bits */
1210 hdr = pdkim_headcat(&col, hdr, US";", US"a=", dkim_sig_to_a_tag(sig));
1211 hdr = pdkim_headcat(&col, hdr, US";", US"q=", pdkim_querymethods[sig->querymethod]);
1212 hdr = pdkim_headcat(&col, hdr, US";", US"c=", canon_all->s);
1213 hdr = pdkim_headcat(&col, hdr, US";", US"d=", sig->domain);
1214 hdr = pdkim_headcat(&col, hdr, US";", US"s=", sig->selector);
1216 /* list of header names can be split between items. */
1218 uschar * n = string_copy(sig->headernames);
1219 uschar * i = US"h=";
1224 uschar * c = Ustrchr(n, ':');
1229 hdr = pdkim_headcat(&col, hdr, NULL, NULL, US":");
1231 hdr = pdkim_headcat(&col, hdr, s, i, n);
1242 base64_bh = pdkim_encode_base64(&sig->bodyhash);
1243 hdr = pdkim_headcat(&col, hdr, US";", US"bh=", base64_bh);
1247 hdr = pdkim_headcat(&col, hdr, US";", US"i=", sig->identity);
1249 if (sig->created > 0)
1253 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->created);
1254 hdr = pdkim_headcat(&col, hdr, US";", US"t=", minibuf);
1257 if (sig->expires > 0)
1261 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->expires);
1262 hdr = pdkim_headcat(&col, hdr, US";", US"x=", minibuf);
1265 if (sig->bodylength >= 0)
1269 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->bodylength);
1270 hdr = pdkim_headcat(&col, hdr, US";", US"l=", minibuf);
1273 /* Preliminary or final version? */
1276 base64_b = pdkim_encode_base64(&sig->sighash);
1277 hdr = pdkim_headcat(&col, hdr, US";", US"b=", base64_b);
1279 /* add trailing semicolon: I'm not sure if this is actually needed */
1280 hdr = pdkim_headcat(&col, hdr, NULL, US";", US"");
1284 /* To satisfy the rule "all surrounding whitespace [...] deleted"
1285 ( RFC 6376 section 3.7 ) we ensure there is no whitespace here. Otherwise
1286 the headcat routine could insert a linebreak which the relaxer would reduce
1287 to a single space preceding the terminating semicolon, resulting in an
1288 incorrect header-hash. */
1289 hdr = pdkim_headcat(&col, hdr, US";", US"b=;", US"");
1292 return string_from_gstring(hdr);
1296 /* -------------------------------------------------------------------------- */
1298 static pdkim_pubkey *
1299 pdkim_key_from_dns(pdkim_ctx * ctx, pdkim_signature * sig, ev_ctx * vctx,
1300 const uschar ** errstr)
1302 uschar * dns_txt_name, * dns_txt_reply;
1305 /* Fetch public key for signing domain, from DNS */
1307 dns_txt_name = string_sprintf("%s._domainkey.%s.", sig->selector, sig->domain);
1309 dns_txt_reply = store_get(PDKIM_DNS_TXT_MAX_RECLEN);
1310 memset(dns_txt_reply, 0, PDKIM_DNS_TXT_MAX_RECLEN);
1312 if ( ctx->dns_txt_callback(CS dns_txt_name, CS dns_txt_reply) != PDKIM_OK
1313 || dns_txt_reply[0] == '\0'
1316 sig->verify_status = PDKIM_VERIFY_INVALID;
1317 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE;
1324 "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
1328 pdkim_quoteprint(CUS dns_txt_reply, Ustrlen(dns_txt_reply));
1331 if ( !(p = pdkim_parse_pubkey_record(ctx, CUS dns_txt_reply))
1332 || (Ustrcmp(p->srvtype, "*") != 0 && Ustrcmp(p->srvtype, "email") != 0)
1335 sig->verify_status = PDKIM_VERIFY_INVALID;
1336 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD;
1341 debug_printf(" Invalid public key service type '%s'\n", p->srvtype);
1343 debug_printf(" Error while parsing public key record\n");
1345 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1350 DEBUG(D_acl) debug_printf(
1351 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1353 /* Import public key */
1354 if ((*errstr = exim_dkim_verify_init(&p->key, vctx)))
1356 DEBUG(D_acl) debug_printf("verify_init: %s\n", *errstr);
1357 sig->verify_status = PDKIM_VERIFY_INVALID;
1358 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_IMPORT;
1366 /* -------------------------------------------------------------------------- */
1369 pdkim_feed_finish(pdkim_ctx * ctx, pdkim_signature ** return_signatures,
1370 const uschar ** err)
1372 pdkim_signature * sig;
1374 /* Check if we must still flush a (partial) header. If that is the
1375 case, the message has no body, and we must compute a body hash
1376 out of '<CR><LF>' */
1377 if (ctx->cur_header && ctx->cur_header->ptr > 0)
1382 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1385 for (sig = ctx->sig; sig; sig = sig->next)
1386 rnl = pdkim_update_sig_bodyhash(sig, &lineending, rnl);
1387 if (rnl) store_free(rnl);
1390 DEBUG(D_acl) debug_printf(
1391 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1393 /* Build (and/or evaluate) body hash */
1394 pdkim_finish_bodyhash(ctx);
1396 for (sig = ctx->sig; sig; sig = sig->next)
1399 uschar * sig_hdr = US"";
1401 gstring * hdata = NULL;
1403 if (!exim_sha_init(&hhash_ctx, pdkim_hashes[sig->hashtype].exim_hashmethod))
1406 debug_printf("PDKIM: hash setup error, possibly nonhandled hashtype\n");
1410 if (ctx->flags & PDKIM_MODE_SIGN)
1411 DEBUG(D_acl) debug_printf(
1412 "PDKIM >> Headers to be signed: >>>>>>>>>>>>\n"
1416 DEBUG(D_acl) debug_printf(
1417 "PDKIM >> Header data for hash, canonicalized, in sequence >>>>>>>>>>>>\n");
1420 /* SIGNING ---------------------------------------------------------------- */
1421 /* When signing, walk through our header list and add them to the hash. As we
1422 go, construct a list of the header's names to use for the h= parameter.
1423 Then append to that list any remaining header names for which there was no
1426 if (ctx->flags & PDKIM_MODE_SIGN)
1429 pdkim_stringlist *p;
1434 sig->headernames = NULL; /* Collected signed header names */
1436 for (p = sig->headers; p; p = p->next)
1438 uschar * rh = p->value;
1440 if (header_name_match(rh, sig->sign_headers) == PDKIM_OK)
1442 /* Collect header names (Note: colon presence is guaranteed here) */
1443 g = string_append_listele_n(g, ':', rh, Ustrchr(rh, ':') - rh);
1445 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1446 rh = pdkim_relax_header(rh, TRUE); /* cook header for relaxed canon */
1448 /* Feed header to the hash algorithm */
1449 exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
1451 /* Remember headers block for signing (when the library cannot do incremental) */
1452 hdata = exim_dkim_data_append(hdata, rh);
1454 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1458 /* Any headers we wanted to sign but were not present must also be listed.
1459 Ignore elements that have been ticked-off or are marked as never-oversign. */
1461 l = sig->sign_headers;
1462 while((s = string_nextinlist(&l, &sep, NULL, 0)))
1464 if (*s == '+') /* skip oversigning marker */
1466 if (*s != '_' && *s != '=')
1467 g = string_append_listele(g, ':', s);
1469 sig->headernames = string_from_gstring(g);
1471 /* Create signature header with b= omitted */
1472 sig_hdr = pdkim_create_header(sig, FALSE);
1475 /* VERIFICATION ----------------------------------------------------------- */
1476 /* When verifying, walk through the header name list in the h= parameter and
1477 add the headers to the hash in that order. */
1480 uschar * p = sig->headernames;
1482 pdkim_stringlist * hdrs;
1487 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1493 if ((q = Ustrchr(p, ':')))
1496 /*XXX walk the list of headers in same order as received. */
1497 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1499 && strncasecmp(CCS hdrs->value, CCS p, Ustrlen(p)) == 0
1500 && (hdrs->value)[Ustrlen(p)] == ':'
1503 /* cook header for relaxed canon, or just copy it for simple */
1505 uschar * rh = sig->canon_headers == PDKIM_CANON_RELAXED
1506 ? pdkim_relax_header(hdrs->value, TRUE)
1507 : string_copy(CUS hdrs->value);
1509 /* Feed header to the hash algorithm */
1510 exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
1512 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1521 sig_hdr = string_copy(sig->rawsig_no_b_val);
1525 DEBUG(D_acl) debug_printf(
1526 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1531 "PDKIM >> Signed DKIM-Signature header, pre-canonicalized >>>>>>>>>>>>>\n");
1532 pdkim_quoteprint(CUS sig_hdr, Ustrlen(sig_hdr));
1534 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1537 /* Relax header if necessary */
1538 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1539 sig_hdr = pdkim_relax_header(sig_hdr, FALSE);
1544 "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
1545 pdkim_quoteprint(CUS sig_hdr, Ustrlen(sig_hdr));
1547 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1550 /* Finalize header hash */
1551 exim_sha_update(&hhash_ctx, CUS sig_hdr, Ustrlen(sig_hdr));
1552 exim_sha_finish(&hhash_ctx, &hhash);
1556 debug_printf("PDKIM [%s] Header %s computed: ",
1557 sig->domain, pdkim_hashes[sig->hashtype].dkim_hashname);
1558 pdkim_hexprint(hhash.data, hhash.len);
1561 /* Remember headers block for signing (when the signing library cannot do
1563 if (ctx->flags & PDKIM_MODE_SIGN)
1564 hdata = exim_dkim_data_append(hdata, US sig_hdr);
1566 /* SIGNING ---------------------------------------------------------------- */
1567 if (ctx->flags & PDKIM_MODE_SIGN)
1571 /* Import private key, including the keytype */
1572 /*XXX extend for non-RSA algos */
1573 if ((*err = exim_dkim_signing_init(US sig->privkey, &sctx)))
1575 DEBUG(D_acl) debug_printf("signing_init: %s\n", *err);
1576 return PDKIM_ERR_RSA_PRIVKEY;
1579 /* Do signing. With OpenSSL we are signing the hash of headers just
1580 calculated, with GnuTLS we have to sign an entire block of headers
1581 (due to available interfaces) and it recalculates the hash internally. */
1583 #if defined(SIGN_GNUTLS)
1584 hhash.data = hdata->s;
1585 hhash.len = hdata->ptr;
1588 /*XXX extend for non-RSA algos */
1589 if ((*err = exim_dkim_sign(&sctx,
1590 pdkim_hashes[sig->hashtype].exim_hashmethod,
1591 &hhash, &sig->sighash)))
1593 DEBUG(D_acl) debug_printf("signing: %s\n", *err);
1594 return PDKIM_ERR_RSA_SIGNING;
1599 debug_printf( "PDKIM [%s] b computed: ", sig->domain);
1600 pdkim_hexprint(sig->sighash.data, sig->sighash.len);
1603 sig->signature_header = pdkim_create_header(sig, TRUE);
1606 /* VERIFICATION ----------------------------------------------------------- */
1611 /* Make sure we have all required signature tags */
1612 if (!( sig->domain && *sig->domain
1613 && sig->selector && *sig->selector
1614 && sig->headernames && *sig->headernames
1615 && sig->bodyhash.data
1616 && sig->sighash.data
1617 && sig->keytype >= 0
1618 && sig->hashtype >= 0
1622 sig->verify_status = PDKIM_VERIFY_INVALID;
1623 sig->verify_ext_status = PDKIM_VERIFY_INVALID_SIGNATURE_ERROR;
1625 DEBUG(D_acl) debug_printf(
1626 " Error in DKIM-Signature header: tags missing or invalid\n"
1627 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1631 /* Make sure sig uses supported DKIM version (only v1) */
1632 if (sig->version != 1)
1634 sig->verify_status = PDKIM_VERIFY_INVALID;
1635 sig->verify_ext_status = PDKIM_VERIFY_INVALID_DKIM_VERSION;
1637 DEBUG(D_acl) debug_printf(
1638 " Error in DKIM-Signature header: unsupported DKIM version\n"
1639 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1645 debug_printf( "PDKIM [%s] b from mail: ", sig->domain);
1646 pdkim_hexprint(sig->sighash.data, sig->sighash.len);
1649 if (!(sig->pubkey = pdkim_key_from_dns(ctx, sig, &vctx, err)))
1652 /* If the pubkey limits to a list of specific hashes, ignore sigs that
1653 do not have the hash part of the sig algorithm matching */
1655 if (sig->pubkey->hashes)
1657 const uschar * list = sig->pubkey->hashes, * ele;
1659 while ((ele = string_nextinlist(&list, &sep, NULL, 0)))
1660 if (Ustrcmp(ele, pdkim_hashes[sig->hashtype].dkim_hashname) == 0) break;
1663 DEBUG(D_acl) debug_printf("pubkey h=%s vs. sig a=%s_%s\n",
1664 sig->pubkey->hashes,
1665 pdkim_keytypes[sig->keytype],
1666 pdkim_hashes[sig->hashtype].dkim_hashname);
1667 sig->verify_status = PDKIM_VERIFY_FAIL;
1668 sig->verify_ext_status = PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH;
1673 /* Check the signature */
1674 /*XXX needs extension for non-RSA */
1675 if ((*err = exim_dkim_verify(&vctx,
1676 pdkim_hashes[sig->hashtype].exim_hashmethod,
1677 &hhash, &sig->sighash)))
1679 DEBUG(D_acl) debug_printf("headers verify: %s\n", *err);
1680 sig->verify_status = PDKIM_VERIFY_FAIL;
1681 sig->verify_ext_status = PDKIM_VERIFY_FAIL_MESSAGE;
1686 /* We have a winner! (if bodyhash was correct earlier) */
1687 if (sig->verify_status == PDKIM_VERIFY_NONE)
1688 sig->verify_status = PDKIM_VERIFY_PASS;
1694 debug_printf("PDKIM [%s] signature status: %s",
1695 sig->domain, pdkim_verify_status_str(sig->verify_status));
1696 if (sig->verify_ext_status > 0)
1697 debug_printf(" (%s)\n",
1698 pdkim_verify_ext_status_str(sig->verify_ext_status));
1705 /* If requested, set return pointer to signature(s) */
1706 if (return_signatures)
1707 *return_signatures = ctx->sig;
1713 /* -------------------------------------------------------------------------- */
1715 DLLEXPORT pdkim_ctx *
1716 pdkim_init_verify(int(*dns_txt_callback)(char *, char *), BOOL dot_stuffing)
1720 ctx = store_get(sizeof(pdkim_ctx));
1721 memset(ctx, 0, sizeof(pdkim_ctx));
1723 if (dot_stuffing) ctx->flags = PDKIM_DOT_TERM;
1724 ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN);
1725 ctx->dns_txt_callback = dns_txt_callback;
1731 /* -------------------------------------------------------------------------- */
1733 /*XXX ? needs extension to cover non-RSA algo? */
1735 DLLEXPORT pdkim_signature *
1736 pdkim_init_sign(pdkim_ctx * ctx,
1737 uschar * domain, uschar * selector, uschar * privkey,
1738 uschar * hashname, const uschar ** errstr)
1741 pdkim_signature * sig;
1743 if (!domain || !selector || !privkey)
1746 /* Allocate & init one signature struct */
1748 sig = store_get(sizeof(pdkim_signature));
1749 memset(sig, 0, sizeof(pdkim_signature));
1751 sig->bodylength = -1;
1753 sig->domain = string_copy(US domain);
1754 sig->selector = string_copy(US selector);
1755 sig->privkey = string_copy(US privkey);
1756 /*XXX no keytype yet; comes from privkey */
1758 for (hashtype = 0; hashtype < nelem(pdkim_hashes); hashtype++)
1759 if (Ustrcmp(hashname, pdkim_hashes[hashtype].dkim_hashname) == 0)
1760 { sig->hashtype = hashtype; break; }
1761 if (hashtype >= nelem(pdkim_hashes))
1764 debug_printf("PDKIM: unrecognised hashname '%s'\n", hashname);
1768 if (!exim_sha_init(&sig->body_hash_ctx, pdkim_hashes[hashtype].exim_hashmethod))
1771 debug_printf("PDKIM: hash setup error, possibly nonhandled hashtype\n");
1777 pdkim_signature s = *sig;
1780 debug_printf("PDKIM (checking verify key)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1781 if (!pdkim_key_from_dns(ctx, &s, &vctx, errstr))
1782 debug_printf("WARNING: bad dkim key in dns\n");
1783 debug_printf("PDKIM (finished checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1789 /* -------------------------------------------------------------------------- */
1792 pdkim_set_optional(pdkim_signature * sig,
1793 char * sign_headers,
1798 unsigned long created,
1799 unsigned long expires)
1802 sig->identity = string_copy(US identity);
1804 sig->sign_headers = string_copy(sign_headers
1805 ? US sign_headers : US PDKIM_DEFAULT_SIGN_HEADERS);
1807 sig->canon_headers = canon_headers;
1808 sig->canon_body = canon_body;
1809 sig->bodylength = bodylength;
1810 sig->created = created;
1811 sig->expires = expires;
1819 pdkim_init_context(pdkim_ctx * ctx, BOOL dot_stuffed,
1820 int(*dns_txt_callback)(char *, char *))
1822 memset(ctx, 0, sizeof(pdkim_ctx));
1823 ctx->flags = dot_stuffed ? PDKIM_MODE_SIGN | PDKIM_DOT_TERM : PDKIM_MODE_SIGN;
1824 ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN);
1825 DEBUG(D_acl) ctx->dns_txt_callback = dns_txt_callback;
1837 #endif /*DISABLE_DKIM*/