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 */
657 if (!pub->version ) pub->version = string_copy(PDKIM_PUB_RECORD_VERSION);
658 else if (Ustrcmp(pub->version, PDKIM_PUB_RECORD_VERSION) != 0)
660 DEBUG(D_acl) debug_printf(" Bad v= field\n");
664 if (!pub->granularity) pub->granularity = US"*";
666 if (!pub->keytype ) pub->keytype = US"rsa";
668 if (!pub->srvtype ) pub->srvtype = US"*";
674 DEBUG(D_acl) debug_printf(" Missing p= field\n");
679 /* -------------------------------------------------------------------------- */
681 /* Update the bodyhash for one sig, with some additional data.
682 If we have to relax the data for this sig, return our copy of it. */
684 /*XXX Currently we calculate a hash for each sig. But it is possible
685 that multi-signing will be wanted using different signing algos
686 (rsa, ec) using the same hash and canonicalization. Consider in future
687 hanging the hash+cacnon from the ctx and only referencing from the sig,
688 so that it can be calculated only once - being over the body this
689 caould be meagbytes, hence expensive. */
692 pdkim_update_sig_bodyhash(pdkim_signature * sig, blob * orig_data, blob * relaxed_data)
694 blob * canon_data = orig_data;
695 /* Defaults to simple canon (no further treatment necessary) */
697 if (sig->canon_body == PDKIM_CANON_RELAXED)
699 /* Relax the line if not done already */
702 BOOL seen_wsp = FALSE;
706 /* We want to be able to free this else we allocate
707 for the entire message which could be many MB. Since
708 we don't know what allocations the SHA routines might
709 do, not safe to use store_get()/store_reset(). */
711 relaxed_data = store_malloc(sizeof(blob) + orig_data->len+1);
712 relaxed_data->data = US (relaxed_data+1);
714 for (p = orig_data->data; *p; p++)
719 if (q > 0 && relaxed_data->data[q-1] == ' ')
722 else if (c == '\t' || c == ' ')
724 c = ' '; /* Turns WSP into SP */
731 relaxed_data->data[q++] = c;
733 relaxed_data->data[q] = '\0';
734 relaxed_data->len = q;
736 canon_data = relaxed_data;
739 /* Make sure we don't exceed the to-be-signed body length */
740 if ( sig->bodylength >= 0
741 && sig->signed_body_bytes + (unsigned long)canon_data->len > sig->bodylength
743 canon_data->len = sig->bodylength - sig->signed_body_bytes;
745 if (canon_data->len > 0)
747 exim_sha_update(&sig->body_hash_ctx, CUS canon_data->data, canon_data->len);
748 sig->signed_body_bytes += canon_data->len;
749 DEBUG(D_acl) pdkim_quoteprint(canon_data->data, canon_data->len);
756 /* -------------------------------------------------------------------------- */
759 pdkim_finish_bodyhash(pdkim_ctx * ctx)
761 pdkim_signature * sig;
763 /* Traverse all signatures */
764 for (sig = ctx->sig; sig; sig = sig->next)
765 { /* Finish hashes */
768 exim_sha_finish(&sig->body_hash_ctx, &bh);
772 debug_printf("PDKIM [%s] Body bytes hashed: %lu\n"
773 "PDKIM [%s] Body %s computed: ",
774 sig->domain, sig->signed_body_bytes,
775 sig->domain, pdkim_hashes[sig->hashtype].dkim_hashname);
776 pdkim_hexprint(CUS bh.data, bh.len);
779 /* SIGNING -------------------------------------------------------------- */
780 if (ctx->flags & PDKIM_MODE_SIGN)
784 /* If bodylength limit is set, and we have received less bytes
785 than the requested amount, effectively remove the limit tag. */
786 if (sig->signed_body_bytes < sig->bodylength)
787 sig->bodylength = -1;
791 /* VERIFICATION --------------------------------------------------------- */
792 /* Be careful that the header sig included a bodyash */
794 if (sig->bodyhash.data && memcmp(bh.data, sig->bodyhash.data, bh.len) == 0)
796 DEBUG(D_acl) debug_printf("PDKIM [%s] Body hash verified OK\n", sig->domain);
802 debug_printf("PDKIM [%s] Body hash signature from headers: ", sig->domain);
803 pdkim_hexprint(sig->bodyhash.data, sig->bodyhash.len);
804 debug_printf("PDKIM [%s] Body hash did NOT verify\n", sig->domain);
806 sig->verify_status = PDKIM_VERIFY_FAIL;
807 sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
815 pdkim_body_complete(pdkim_ctx * ctx)
817 pdkim_signature * sig;
819 /* In simple body mode, if any empty lines were buffered,
820 replace with one. rfc 4871 3.4.3 */
821 /*XXX checking the signed-body-bytes is a gross hack; I think
822 it indicates that all linebreaks should be buffered, including
823 the one terminating a text line */
825 for (sig = ctx->sig; sig; sig = sig->next)
826 if ( sig->canon_body == PDKIM_CANON_SIMPLE
827 && sig->signed_body_bytes == 0
828 && sig->num_buffered_blanklines > 0
830 (void) pdkim_update_sig_bodyhash(sig, &lineending, NULL);
832 ctx->flags |= PDKIM_SEEN_EOD;
833 ctx->linebuf_offset = 0;
838 /* -------------------------------------------------------------------------- */
839 /* Call from pdkim_feed below for processing complete body lines */
842 pdkim_bodyline_complete(pdkim_ctx * ctx)
844 blob line = {.data = ctx->linebuf, .len = ctx->linebuf_offset};
845 pdkim_signature * sig;
849 /* Ignore extra data if we've seen the end-of-data marker */
850 if (ctx->flags & PDKIM_SEEN_EOD) goto all_skip;
852 /* We've always got one extra byte to stuff a zero ... */
853 ctx->linebuf[line.len] = '\0';
855 /* Terminate on EOD marker */
856 if (ctx->flags & PDKIM_DOT_TERM)
858 if (memcmp(line.data, ".\r\n", 3) == 0)
859 { pdkim_body_complete(ctx); return; }
862 if (memcmp(line.data, "..", 2) == 0)
863 { line.data++; line.len--; }
866 /* Empty lines need to be buffered until we find a non-empty line */
867 if (memcmp(line.data, "\r\n", 2) == 0)
869 for (sig = ctx->sig; sig; sig = sig->next) sig->num_buffered_blanklines++;
873 /* Process line for each sig separately */
874 for (sig = ctx->sig; sig; sig = sig->next)
876 if (sig->canon_body == PDKIM_CANON_RELAXED)
878 /* Lines with just spaces need to be buffered too */
879 uschar * cp = line.data;
884 if (c == '\r' && cp[1] == '\n') break;
885 if (c != ' ' && c != '\t') goto sig_process;
889 sig->num_buffered_blanklines++;
894 /* At this point, we have a non-empty line, so release the buffered ones. */
896 while (sig->num_buffered_blanklines)
898 rnl = pdkim_update_sig_bodyhash(sig, &lineending, rnl);
899 sig->num_buffered_blanklines--;
902 rline = pdkim_update_sig_bodyhash(sig, &line, rline);
906 if (rnl) store_free(rnl);
907 if (rline) store_free(rline);
911 ctx->linebuf_offset = 0;
916 /* -------------------------------------------------------------------------- */
917 /* Callback from pdkim_feed below for processing complete headers */
918 #define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
921 pdkim_header_complete(pdkim_ctx * ctx)
923 pdkim_signature * sig, * last_sig;
925 /* Special case: The last header can have an extra \r appended */
926 if ( (ctx->cur_header->ptr > 1) &&
927 (ctx->cur_header->s[ctx->cur_header->ptr-1] == '\r') )
928 --ctx->cur_header->ptr;
929 (void) string_from_gstring(ctx->cur_header);
931 if (++ctx->num_headers > PDKIM_MAX_HEADERS) goto BAIL;
933 /* SIGNING -------------------------------------------------------------- */
934 if (ctx->flags & PDKIM_MODE_SIGN)
935 for (sig = ctx->sig; sig; sig = sig->next) /* Traverse all signatures */
937 /* Add header to the signed headers list (in reverse order) */
938 sig->headers = pdkim_prepend_stringlist(sig->headers, ctx->cur_header->s);
940 /* VERIFICATION ----------------------------------------------------------- */
941 /* DKIM-Signature: headers are added to the verification list */
947 debug_printf("PDKIM >> raw hdr: ");
948 pdkim_quoteprint(CUS ctx->cur_header->s, ctx->cur_header->ptr);
951 if (strncasecmp(CCS ctx->cur_header->s,
952 DKIM_SIGNATURE_HEADERNAME,
953 Ustrlen(DKIM_SIGNATURE_HEADERNAME)) == 0)
955 /* Create and chain new signature block. We could error-check for all
956 required tags here, but prefer to create the internal sig and expicitly
957 fail verification of it later. */
959 DEBUG(D_acl) debug_printf(
960 "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
962 sig = pdkim_parse_sig_header(ctx, ctx->cur_header->s);
964 if (!(last_sig = ctx->sig))
968 while (last_sig->next) last_sig = last_sig->next;
969 last_sig->next = sig;
973 /* all headers are stored for signature verification */
974 ctx->headers = pdkim_prepend_stringlist(ctx->headers, ctx->cur_header->s);
978 ctx->cur_header->s[ctx->cur_header->ptr = 0] = '\0'; /* leave buffer for reuse */
984 /* -------------------------------------------------------------------------- */
985 #define HEADER_BUFFER_FRAG_SIZE 256
988 pdkim_feed(pdkim_ctx * ctx, uschar * data, int len)
992 /* Alternate EOD signal, used in non-dotstuffing mode */
994 pdkim_body_complete(ctx);
996 else for (p = 0; p<len; p++)
1000 if (ctx->flags & PDKIM_PAST_HDRS)
1002 if (c == '\n' && !(ctx->flags & PDKIM_SEEN_CR)) /* emulate the CR */
1004 ctx->linebuf[ctx->linebuf_offset++] = '\r';
1005 if (ctx->linebuf_offset == PDKIM_MAX_BODY_LINE_LEN-1)
1006 return PDKIM_ERR_LONG_LINE;
1009 /* Processing body byte */
1010 ctx->linebuf[ctx->linebuf_offset++] = c;
1012 ctx->flags |= PDKIM_SEEN_CR;
1015 ctx->flags &= ~PDKIM_SEEN_CR;
1016 pdkim_bodyline_complete(ctx);
1019 if (ctx->linebuf_offset == PDKIM_MAX_BODY_LINE_LEN-1)
1020 return PDKIM_ERR_LONG_LINE;
1024 /* Processing header byte */
1026 ctx->flags |= PDKIM_SEEN_CR;
1029 if (!(ctx->flags & PDKIM_SEEN_CR)) /* emulate the CR */
1030 ctx->cur_header = string_catn(ctx->cur_header, CUS "\r", 1);
1032 if (ctx->flags & PDKIM_SEEN_LF) /* Seen last header line */
1034 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1037 ctx->flags = (ctx->flags & ~(PDKIM_SEEN_LF|PDKIM_SEEN_CR)) | PDKIM_PAST_HDRS;
1038 DEBUG(D_acl) debug_printf(
1039 "PDKIM >> Body data for hash, canonicalized >>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1043 ctx->flags = (ctx->flags & ~PDKIM_SEEN_CR) | PDKIM_SEEN_LF;
1045 else if (ctx->flags & PDKIM_SEEN_LF)
1047 if (!(c == '\t' || c == ' ')) /* End of header */
1048 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1050 ctx->flags &= ~PDKIM_SEEN_LF;
1053 if (!ctx->cur_header || ctx->cur_header->ptr < PDKIM_MAX_HEADER_LEN)
1054 ctx->cur_header = string_catn(ctx->cur_header, CUS &data[p], 1);
1062 /* Extend a growing header with a continuation-linebreak */
1064 pdkim_hdr_cont(gstring * str, int * col)
1067 return string_catn(str, US"\r\n\t", 3);
1073 * RFC 5322 specifies that header line length SHOULD be no more than 78
1077 * returns uschar * (not nul-terminated)
1079 * col: this int holds and receives column number (octets since last '\n')
1080 * str: partial string to append to
1081 * pad: padding, split line or space after before or after eg: ";"
1082 * intro: - must join to payload eg "h=", usually the tag name
1083 * payload: eg base64 data - long data can be split arbitrarily.
1085 * this code doesn't fold the header in some of the places that RFC4871
1086 * allows: As per RFC5322(2.2.3) it only folds before or after tag-value
1087 * pairs and inside long values. it also always spaces or breaks after the
1090 * no guarantees are made for output given out-of range input. like tag
1091 * names longer than 78, or bogus col. Input is assumed to be free of line breaks.
1095 pdkim_headcat(int * col, gstring * str,
1096 const uschar * pad, const uschar * intro, const uschar * payload)
1104 str = pdkim_hdr_cont(str, col);
1105 str = string_catn(str, pad, l);
1109 l = (pad?1:0) + (intro?Ustrlen(intro):0);
1112 { /*can't fit intro - start a new line to make room.*/
1113 str = pdkim_hdr_cont(str, col);
1114 l = intro?Ustrlen(intro):0;
1117 l += payload ? Ustrlen(payload):0 ;
1120 { /* this fragment will not fit on a single line */
1123 str = string_catn(str, US" ", 1);
1125 pad = NULL; /* only want this once */
1131 size_t sl = Ustrlen(intro);
1133 str = string_catn(str, intro, sl);
1136 intro = NULL; /* only want this once */
1141 size_t sl = Ustrlen(payload);
1142 size_t chomp = *col+sl < 77 ? sl : 78-*col;
1144 str = string_catn(str, payload, chomp);
1150 /* the while precondition tells us it didn't fit. */
1151 str = pdkim_hdr_cont(str, col);
1156 str = pdkim_hdr_cont(str, col);
1162 str = string_catn(str, US" ", 1);
1169 size_t sl = Ustrlen(intro);
1171 str = string_catn(str, intro, sl);
1179 size_t sl = Ustrlen(payload);
1181 str = string_catn(str, payload, sl);
1189 /* -------------------------------------------------------------------------- */
1192 pdkim_create_header(pdkim_signature * sig, BOOL final)
1198 gstring * canon_all;
1200 canon_all = string_cat (NULL, pdkim_canons[sig->canon_headers]);
1201 canon_all = string_catn(canon_all, US"/", 1);
1202 canon_all = string_cat (canon_all, pdkim_canons[sig->canon_body]);
1203 (void) string_from_gstring(canon_all);
1205 hdr = string_cat(NULL, US"DKIM-Signature: v="PDKIM_SIGNATURE_VERSION);
1208 /* Required and static bits */
1209 hdr = pdkim_headcat(&col, hdr, US";", US"a=", dkim_sig_to_a_tag(sig));
1210 hdr = pdkim_headcat(&col, hdr, US";", US"q=", pdkim_querymethods[sig->querymethod]);
1211 hdr = pdkim_headcat(&col, hdr, US";", US"c=", canon_all->s);
1212 hdr = pdkim_headcat(&col, hdr, US";", US"d=", sig->domain);
1213 hdr = pdkim_headcat(&col, hdr, US";", US"s=", sig->selector);
1215 /* list of header names can be split between items. */
1217 uschar * n = string_copy(sig->headernames);
1218 uschar * i = US"h=";
1223 uschar * c = Ustrchr(n, ':');
1228 hdr = pdkim_headcat(&col, hdr, NULL, NULL, US":");
1230 hdr = pdkim_headcat(&col, hdr, s, i, n);
1241 base64_bh = pdkim_encode_base64(&sig->bodyhash);
1242 hdr = pdkim_headcat(&col, hdr, US";", US"bh=", base64_bh);
1246 hdr = pdkim_headcat(&col, hdr, US";", US"i=", sig->identity);
1248 if (sig->created > 0)
1252 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->created);
1253 hdr = pdkim_headcat(&col, hdr, US";", US"t=", minibuf);
1256 if (sig->expires > 0)
1260 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->expires);
1261 hdr = pdkim_headcat(&col, hdr, US";", US"x=", minibuf);
1264 if (sig->bodylength >= 0)
1268 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->bodylength);
1269 hdr = pdkim_headcat(&col, hdr, US";", US"l=", minibuf);
1272 /* Preliminary or final version? */
1275 base64_b = pdkim_encode_base64(&sig->sighash);
1276 hdr = pdkim_headcat(&col, hdr, US";", US"b=", base64_b);
1278 /* add trailing semicolon: I'm not sure if this is actually needed */
1279 hdr = pdkim_headcat(&col, hdr, NULL, US";", US"");
1283 /* To satisfy the rule "all surrounding whitespace [...] deleted"
1284 ( RFC 6376 section 3.7 ) we ensure there is no whitespace here. Otherwise
1285 the headcat routine could insert a linebreak which the relaxer would reduce
1286 to a single space preceding the terminating semicolon, resulting in an
1287 incorrect header-hash. */
1288 hdr = pdkim_headcat(&col, hdr, US";", US"b=;", US"");
1291 return string_from_gstring(hdr);
1295 /* -------------------------------------------------------------------------- */
1297 static pdkim_pubkey *
1298 pdkim_key_from_dns(pdkim_ctx * ctx, pdkim_signature * sig, ev_ctx * vctx,
1299 const uschar ** errstr)
1301 uschar * dns_txt_name, * dns_txt_reply;
1304 /* Fetch public key for signing domain, from DNS */
1306 dns_txt_name = string_sprintf("%s._domainkey.%s.", sig->selector, sig->domain);
1308 dns_txt_reply = store_get(PDKIM_DNS_TXT_MAX_RECLEN);
1309 memset(dns_txt_reply, 0, PDKIM_DNS_TXT_MAX_RECLEN);
1311 if ( ctx->dns_txt_callback(CS dns_txt_name, CS dns_txt_reply) != PDKIM_OK
1312 || dns_txt_reply[0] == '\0'
1315 sig->verify_status = PDKIM_VERIFY_INVALID;
1316 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE;
1323 "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
1327 pdkim_quoteprint(CUS dns_txt_reply, Ustrlen(dns_txt_reply));
1330 if ( !(p = pdkim_parse_pubkey_record(ctx, CUS dns_txt_reply))
1331 || (Ustrcmp(p->srvtype, "*") != 0 && Ustrcmp(p->srvtype, "email") != 0)
1334 sig->verify_status = PDKIM_VERIFY_INVALID;
1335 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD;
1340 debug_printf(" Invalid public key service type '%s'\n", p->srvtype);
1342 debug_printf(" Error while parsing public key record\n");
1344 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1349 DEBUG(D_acl) debug_printf(
1350 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1352 /* Import public key */
1353 if ((*errstr = exim_dkim_verify_init(&p->key, vctx)))
1355 DEBUG(D_acl) debug_printf("verify_init: %s\n", *errstr);
1356 sig->verify_status = PDKIM_VERIFY_INVALID;
1357 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_IMPORT;
1365 /* -------------------------------------------------------------------------- */
1368 pdkim_feed_finish(pdkim_ctx * ctx, pdkim_signature ** return_signatures,
1369 const uschar ** err)
1371 pdkim_signature * sig;
1373 /* Check if we must still flush a (partial) header. If that is the
1374 case, the message has no body, and we must compute a body hash
1375 out of '<CR><LF>' */
1376 if (ctx->cur_header && ctx->cur_header->ptr > 0)
1381 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1384 for (sig = ctx->sig; sig; sig = sig->next)
1385 rnl = pdkim_update_sig_bodyhash(sig, &lineending, rnl);
1386 if (rnl) store_free(rnl);
1389 DEBUG(D_acl) debug_printf(
1390 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1392 /* Build (and/or evaluate) body hash */
1393 pdkim_finish_bodyhash(ctx);
1395 for (sig = ctx->sig; sig; sig = sig->next)
1398 uschar * sig_hdr = US"";
1400 gstring * hdata = NULL;
1402 if (!exim_sha_init(&hhash_ctx, pdkim_hashes[sig->hashtype].exim_hashmethod))
1405 debug_printf("PDKIM: hash setup error, possibly nonhandled hashtype\n");
1409 if (ctx->flags & PDKIM_MODE_SIGN)
1410 DEBUG(D_acl) debug_printf(
1411 "PDKIM >> Headers to be signed: >>>>>>>>>>>>\n"
1415 DEBUG(D_acl) debug_printf(
1416 "PDKIM >> Header data for hash, canonicalized, in sequence >>>>>>>>>>>>\n");
1419 /* SIGNING ---------------------------------------------------------------- */
1420 /* When signing, walk through our header list and add them to the hash. As we
1421 go, construct a list of the header's names to use for the h= parameter.
1422 Then append to that list any remaining header names for which there was no
1425 if (ctx->flags & PDKIM_MODE_SIGN)
1428 pdkim_stringlist *p;
1433 sig->headernames = NULL; /* Collected signed header names */
1435 for (p = sig->headers; p; p = p->next)
1437 uschar * rh = p->value;
1439 if (header_name_match(rh, sig->sign_headers) == PDKIM_OK)
1441 /* Collect header names (Note: colon presence is guaranteed here) */
1442 g = string_append_listele_n(g, ':', rh, Ustrchr(rh, ':') - rh);
1444 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1445 rh = pdkim_relax_header(rh, TRUE); /* cook header for relaxed canon */
1447 /* Feed header to the hash algorithm */
1448 exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
1450 /* Remember headers block for signing (when the library cannot do incremental) */
1451 hdata = exim_dkim_data_append(hdata, rh);
1453 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1457 /* Any headers we wanted to sign but were not present must also be listed.
1458 Ignore elements that have been ticked-off or are marked as never-oversign. */
1460 l = sig->sign_headers;
1461 while((s = string_nextinlist(&l, &sep, NULL, 0)))
1463 if (*s == '+') /* skip oversigning marker */
1465 if (*s != '_' && *s != '=')
1466 g = string_append_listele(g, ':', s);
1468 sig->headernames = string_from_gstring(g);
1470 /* Create signature header with b= omitted */
1471 sig_hdr = pdkim_create_header(sig, FALSE);
1474 /* VERIFICATION ----------------------------------------------------------- */
1475 /* When verifying, walk through the header name list in the h= parameter and
1476 add the headers to the hash in that order. */
1479 uschar * p = sig->headernames;
1481 pdkim_stringlist * hdrs;
1486 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1492 if ((q = Ustrchr(p, ':')))
1495 /*XXX walk the list of headers in same order as received. */
1496 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1498 && strncasecmp(CCS hdrs->value, CCS p, Ustrlen(p)) == 0
1499 && (hdrs->value)[Ustrlen(p)] == ':'
1502 /* cook header for relaxed canon, or just copy it for simple */
1504 uschar * rh = sig->canon_headers == PDKIM_CANON_RELAXED
1505 ? pdkim_relax_header(hdrs->value, TRUE)
1506 : string_copy(CUS hdrs->value);
1508 /* Feed header to the hash algorithm */
1509 exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
1511 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1520 sig_hdr = string_copy(sig->rawsig_no_b_val);
1524 DEBUG(D_acl) debug_printf(
1525 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1530 "PDKIM >> Signed DKIM-Signature header, pre-canonicalized >>>>>>>>>>>>>\n");
1531 pdkim_quoteprint(CUS sig_hdr, Ustrlen(sig_hdr));
1533 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1536 /* Relax header if necessary */
1537 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1538 sig_hdr = pdkim_relax_header(sig_hdr, FALSE);
1543 "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
1544 pdkim_quoteprint(CUS sig_hdr, Ustrlen(sig_hdr));
1546 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1549 /* Finalize header hash */
1550 exim_sha_update(&hhash_ctx, CUS sig_hdr, Ustrlen(sig_hdr));
1551 exim_sha_finish(&hhash_ctx, &hhash);
1555 debug_printf("PDKIM [%s] Header %s computed: ",
1556 sig->domain, pdkim_hashes[sig->hashtype].dkim_hashname);
1557 pdkim_hexprint(hhash.data, hhash.len);
1560 /* Remember headers block for signing (when the signing library cannot do
1562 if (ctx->flags & PDKIM_MODE_SIGN)
1563 hdata = exim_dkim_data_append(hdata, US sig_hdr);
1565 /* SIGNING ---------------------------------------------------------------- */
1566 if (ctx->flags & PDKIM_MODE_SIGN)
1570 /* Import private key, including the keytype */
1571 /*XXX extend for non-RSA algos */
1572 if ((*err = exim_dkim_signing_init(US sig->privkey, &sctx)))
1574 DEBUG(D_acl) debug_printf("signing_init: %s\n", *err);
1575 return PDKIM_ERR_RSA_PRIVKEY;
1578 /* Do signing. With OpenSSL we are signing the hash of headers just
1579 calculated, with GnuTLS we have to sign an entire block of headers
1580 (due to available interfaces) and it recalculates the hash internally. */
1582 #if defined(SIGN_GNUTLS)
1583 hhash.data = hdata->s;
1584 hhash.len = hdata->ptr;
1587 /*XXX extend for non-RSA algos */
1588 if ((*err = exim_dkim_sign(&sctx,
1589 pdkim_hashes[sig->hashtype].exim_hashmethod,
1590 &hhash, &sig->sighash)))
1592 DEBUG(D_acl) debug_printf("signing: %s\n", *err);
1593 return PDKIM_ERR_RSA_SIGNING;
1598 debug_printf( "PDKIM [%s] b computed: ", sig->domain);
1599 pdkim_hexprint(sig->sighash.data, sig->sighash.len);
1602 sig->signature_header = pdkim_create_header(sig, TRUE);
1605 /* VERIFICATION ----------------------------------------------------------- */
1610 /* Make sure we have all required signature tags */
1611 if (!( sig->domain && *sig->domain
1612 && sig->selector && *sig->selector
1613 && sig->headernames && *sig->headernames
1614 && sig->bodyhash.data
1615 && sig->sighash.data
1616 && sig->keytype >= 0
1617 && sig->hashtype >= 0
1621 sig->verify_status = PDKIM_VERIFY_INVALID;
1622 sig->verify_ext_status = PDKIM_VERIFY_INVALID_SIGNATURE_ERROR;
1624 DEBUG(D_acl) debug_printf(
1625 " Error in DKIM-Signature header: tags missing or invalid\n"
1626 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1630 /* Make sure sig uses supported DKIM version (only v1) */
1631 if (sig->version != 1)
1633 sig->verify_status = PDKIM_VERIFY_INVALID;
1634 sig->verify_ext_status = PDKIM_VERIFY_INVALID_DKIM_VERSION;
1636 DEBUG(D_acl) debug_printf(
1637 " Error in DKIM-Signature header: unsupported DKIM version\n"
1638 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1644 debug_printf( "PDKIM [%s] b from mail: ", sig->domain);
1645 pdkim_hexprint(sig->sighash.data, sig->sighash.len);
1648 if (!(sig->pubkey = pdkim_key_from_dns(ctx, sig, &vctx, err)))
1651 /* If the pubkey limits to a list of specific hashes, ignore sigs that
1652 do not have the hash part of the sig algorithm matching */
1654 if (sig->pubkey->hashes)
1656 const uschar * list = sig->pubkey->hashes, * ele;
1658 while ((ele = string_nextinlist(&list, &sep, NULL, 0)))
1659 if (Ustrcmp(ele, pdkim_hashes[sig->hashtype].dkim_hashname) == 0) break;
1662 DEBUG(D_acl) debug_printf("pubkey h=%s vs. sig a=%s_%s\n",
1663 sig->pubkey->hashes,
1664 pdkim_keytypes[sig->keytype],
1665 pdkim_hashes[sig->hashtype].dkim_hashname);
1666 sig->verify_status = PDKIM_VERIFY_FAIL;
1667 sig->verify_ext_status = PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH;
1672 /* Check the signature */
1673 /*XXX needs extension for non-RSA */
1674 if ((*err = exim_dkim_verify(&vctx,
1675 pdkim_hashes[sig->hashtype].exim_hashmethod,
1676 &hhash, &sig->sighash)))
1678 DEBUG(D_acl) debug_printf("headers verify: %s\n", *err);
1679 sig->verify_status = PDKIM_VERIFY_FAIL;
1680 sig->verify_ext_status = PDKIM_VERIFY_FAIL_MESSAGE;
1685 /* We have a winner! (if bodyhash was correct earlier) */
1686 if (sig->verify_status == PDKIM_VERIFY_NONE)
1687 sig->verify_status = PDKIM_VERIFY_PASS;
1693 debug_printf("PDKIM [%s] signature status: %s",
1694 sig->domain, pdkim_verify_status_str(sig->verify_status));
1695 if (sig->verify_ext_status > 0)
1696 debug_printf(" (%s)\n",
1697 pdkim_verify_ext_status_str(sig->verify_ext_status));
1704 /* If requested, set return pointer to signature(s) */
1705 if (return_signatures)
1706 *return_signatures = ctx->sig;
1712 /* -------------------------------------------------------------------------- */
1714 DLLEXPORT pdkim_ctx *
1715 pdkim_init_verify(int(*dns_txt_callback)(char *, char *), BOOL dot_stuffing)
1719 ctx = store_get(sizeof(pdkim_ctx));
1720 memset(ctx, 0, sizeof(pdkim_ctx));
1722 if (dot_stuffing) ctx->flags = PDKIM_DOT_TERM;
1723 ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN);
1724 ctx->dns_txt_callback = dns_txt_callback;
1730 /* -------------------------------------------------------------------------- */
1732 /*XXX ? needs extension to cover non-RSA algo? */
1734 DLLEXPORT pdkim_signature *
1735 pdkim_init_sign(pdkim_ctx * ctx,
1736 uschar * domain, uschar * selector, uschar * privkey,
1737 uschar * hashname, const uschar ** errstr)
1740 pdkim_signature * sig;
1742 if (!domain || !selector || !privkey)
1745 /* Allocate & init one signature struct */
1747 sig = store_get(sizeof(pdkim_signature));
1748 memset(sig, 0, sizeof(pdkim_signature));
1750 sig->bodylength = -1;
1752 sig->domain = string_copy(US domain);
1753 sig->selector = string_copy(US selector);
1754 sig->privkey = string_copy(US privkey);
1755 /*XXX no keytype yet; comes from privkey */
1757 for (hashtype = 0; hashtype < nelem(pdkim_hashes); hashtype++)
1758 if (Ustrcmp(hashname, pdkim_hashes[hashtype].dkim_hashname) == 0)
1759 { sig->hashtype = hashtype; break; }
1760 if (hashtype >= nelem(pdkim_hashes))
1763 debug_printf("PDKIM: unrecognised hashname '%s'\n", hashname);
1767 if (!exim_sha_init(&sig->body_hash_ctx, pdkim_hashes[hashtype].exim_hashmethod))
1770 debug_printf("PDKIM: hash setup error, possibly nonhandled hashtype\n");
1776 pdkim_signature s = *sig;
1779 debug_printf("PDKIM (checking verify key)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1780 if (!pdkim_key_from_dns(ctx, &s, &vctx, errstr))
1781 debug_printf("WARNING: bad dkim key in dns\n");
1782 debug_printf("PDKIM (finished checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1788 /* -------------------------------------------------------------------------- */
1791 pdkim_set_optional(pdkim_signature * sig,
1792 char * sign_headers,
1797 unsigned long created,
1798 unsigned long expires)
1801 sig->identity = string_copy(US identity);
1803 sig->sign_headers = string_copy(sign_headers
1804 ? US sign_headers : US PDKIM_DEFAULT_SIGN_HEADERS);
1806 sig->canon_headers = canon_headers;
1807 sig->canon_body = canon_body;
1808 sig->bodylength = bodylength;
1809 sig->created = created;
1810 sig->expires = expires;
1818 pdkim_init_context(pdkim_ctx * ctx, BOOL dot_stuffed,
1819 int(*dns_txt_callback)(char *, char *))
1821 memset(ctx, 0, sizeof(pdkim_ctx));
1822 ctx->flags = dot_stuffed ? PDKIM_MODE_SIGN | PDKIM_DOT_TERM : PDKIM_MODE_SIGN;
1823 ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN);
1824 DEBUG(D_acl) ctx->dns_txt_callback = dns_txt_callback;
1836 #endif /*DISABLE_DKIM*/