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)
227 uschar * q = p + str->ptr;
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. Returns OK or fail-code */
254 /*XXX might be safer done using a pdkim_stringlist for "tick" */
257 header_name_match(const uschar * header, uschar * tick)
263 uschar * hcolon = Ustrchr(header, ':'); /* Get header name */
266 return PDKIM_FAIL; /* This isn't a header */
268 /* if we had strncmpic() we wouldn't need this copy */
269 hname = string_copyn(header, hcolon-header);
271 /* Copy tick-off list locally, so we can punch zeroes into it */
272 p = lcopy = string_copy(tick);
274 for (q = Ustrchr(p, ':'); q; q = Ustrchr(p, ':'))
277 if (strcmpic(p, hname) == 0)
283 if (strcmpic(p, hname) == 0)
289 /* Invalidate header name instance in tick-off list */
295 /* -------------------------------------------------------------------------- */
296 /* Performs "relaxed" canonicalization of a header. */
299 pdkim_relax_header(const uschar * header, BOOL append_crlf)
301 BOOL past_field_name = FALSE;
302 BOOL seen_wsp = FALSE;
304 uschar * relaxed = store_get(Ustrlen(header)+3);
305 uschar * q = relaxed;
307 for (p = header; *p; p++)
311 if (c == '\r' || c == '\n') /* Ignore CR & LF */
313 if (c == '\t' || c == ' ')
317 c = ' '; /* Turns WSP into SP */
321 if (!past_field_name && c == ':')
323 if (seen_wsp) q--; /* This removes WSP immediately before the colon */
324 seen_wsp = TRUE; /* This removes WSP immediately after the colon */
325 past_field_name = TRUE;
330 /* Lowercase header name */
331 if (!past_field_name) c = tolower(c);
335 if (q > relaxed && q[-1] == ' ') q--; /* Squash eventual trailing SP */
337 if (append_crlf) { *q++ = '\r'; *q++ = '\n'; }
343 /* -------------------------------------------------------------------------- */
344 #define PDKIM_QP_ERROR_DECODE -1
346 static const uschar *
347 pdkim_decode_qp_char(const uschar *qp_p, int *c)
349 const uschar *initial_pos = qp_p;
351 /* Advance one char */
354 /* Check for two hex digits and decode them */
355 if (isxdigit(*qp_p) && isxdigit(qp_p[1]))
357 /* Do hex conversion */
358 *c = (isdigit(*qp_p) ? *qp_p - '0' : toupper(*qp_p) - 'A' + 10) << 4;
359 *c |= isdigit(qp_p[1]) ? qp_p[1] - '0' : toupper(qp_p[1]) - 'A' + 10;
363 /* Illegal char here */
364 *c = PDKIM_QP_ERROR_DECODE;
369 /* -------------------------------------------------------------------------- */
372 pdkim_decode_qp(const uschar * str)
376 const uschar * p = str;
377 uschar * n = store_get(Ustrlen(str)+1);
385 p = pdkim_decode_qp_char(p, &nchar);
401 /* -------------------------------------------------------------------------- */
404 pdkim_decode_base64(const uschar * str, blob * b)
407 dlen = b64decode(str, &b->data);
408 if (dlen < 0) b->data = NULL;
413 pdkim_encode_base64(blob * b)
415 return b64encode(b->data, b->len);
419 /* -------------------------------------------------------------------------- */
420 #define PDKIM_HDR_LIMBO 0
421 #define PDKIM_HDR_TAG 1
422 #define PDKIM_HDR_VALUE 2
424 static pdkim_signature *
425 pdkim_parse_sig_header(pdkim_ctx * ctx, uschar * raw_hdr)
427 pdkim_signature * sig;
429 gstring * cur_tag = NULL;
430 gstring * cur_val = NULL;
431 BOOL past_hname = FALSE;
432 BOOL in_b_val = FALSE;
433 int where = PDKIM_HDR_LIMBO;
436 sig = store_get(sizeof(pdkim_signature));
437 memset(sig, 0, sizeof(pdkim_signature));
438 sig->bodylength = -1;
440 /* Set so invalid/missing data error display is accurate */
445 q = sig->rawsig_no_b_val = store_get(Ustrlen(raw_hdr)+1);
447 for (p = raw_hdr; ; p++)
452 if (c == '\r' || c == '\n')
455 /* Fast-forward through header name */
458 if (c == ':') past_hname = TRUE;
462 if (where == PDKIM_HDR_LIMBO)
464 /* In limbo, just wait for a tag-char to appear */
465 if (!(c >= 'a' && c <= 'z'))
468 where = PDKIM_HDR_TAG;
471 if (where == PDKIM_HDR_TAG)
473 if (c >= 'a' && c <= 'z')
474 cur_tag = string_catn(cur_tag, p, 1);
478 if (Ustrcmp(string_from_gstring(cur_tag), "b") == 0)
483 where = PDKIM_HDR_VALUE;
488 if (where == PDKIM_HDR_VALUE)
490 if (c == '\r' || c == '\n' || c == ' ' || c == '\t')
493 if (c == ';' || c == '\0')
495 if (cur_tag && cur_val)
497 (void) string_from_gstring(cur_val);
498 pdkim_strtrim(cur_val);
500 DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag->s, cur_val->s);
505 pdkim_decode_base64(cur_val->s,
506 cur_tag->s[1] == 'h' ? &sig->bodyhash : &sig->sighash);
509 /* We only support version 1, and that is currently the
510 only version there is. */
512 Ustrcmp(cur_val->s, PDKIM_SIGNATURE_VERSION) == 0 ? 1 : -1;
516 uschar * s = Ustrchr(cur_val->s, '-');
518 for(i = 0; i < nelem(pdkim_keytypes); i++)
519 if (Ustrncmp(cur_val->s, pdkim_keytypes[i], s - cur_val->s) == 0)
520 { sig->keytype = i; break; }
521 for (++s, i = 0; i < nelem(pdkim_hashes); i++)
522 if (Ustrcmp(s, pdkim_hashes[i].dkim_hashname) == 0)
523 { sig->hashtype = i; break; }
528 for (i = 0; pdkim_combined_canons[i].str; i++)
529 if (Ustrcmp(cur_val->s, pdkim_combined_canons[i].str) == 0)
531 sig->canon_headers = pdkim_combined_canons[i].canon_headers;
532 sig->canon_body = pdkim_combined_canons[i].canon_body;
537 for (i = 0; pdkim_querymethods[i]; i++)
538 if (Ustrcmp(cur_val->s, pdkim_querymethods[i]) == 0)
540 sig->querymethod = i;
545 sig->selector = string_copyn(cur_val->s, cur_val->ptr); break;
547 sig->domain = string_copyn(cur_val->s, cur_val->ptr); break;
549 sig->identity = pdkim_decode_qp(cur_val->s); break;
551 sig->created = strtoul(CS cur_val->s, NULL, 10); break;
553 sig->expires = strtoul(CS cur_val->s, NULL, 10); break;
555 sig->bodylength = strtol(CS cur_val->s, NULL, 10); break;
557 sig->headernames = string_copyn(cur_val->s, cur_val->ptr); break;
559 sig->copiedheaders = pdkim_decode_qp(cur_val->s); break;
561 DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
565 cur_tag = cur_val = NULL;
567 where = PDKIM_HDR_LIMBO;
570 cur_val = string_catn(cur_val, p, 1);
582 /* Chomp raw header. The final newline must not be added to the signature. */
583 while (--q > sig->rawsig_no_b_val && (*q == '\r' || *q == '\n'))
589 "PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
590 pdkim_quoteprint(US sig->rawsig_no_b_val, Ustrlen(sig->rawsig_no_b_val));
592 "PDKIM >> Sig size: %4u bits\n", (unsigned) sig->sighash.len*8);
594 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
597 /*XXX hash method: extend for sha512 */
598 if (!exim_sha_init(&sig->body_hash_ctx,
599 pdkim_hashes[sig->hashtype].exim_hashmethod))
602 debug_printf("PDKIM: hash init error, possibly nonhandled hashtype\n");
609 /* -------------------------------------------------------------------------- */
611 static pdkim_pubkey *
612 pdkim_parse_pubkey_record(pdkim_ctx *ctx, const uschar *raw_record)
618 pub = store_get(sizeof(pdkim_pubkey));
619 memset(pub, 0, sizeof(pdkim_pubkey));
621 while ((ele = string_nextinlist(&raw_record, &sep, NULL, 0)))
625 if ((val = Ustrchr(ele, '=')))
627 int taglen = val++ - ele;
629 DEBUG(D_acl) debug_printf(" %.*s=%s\n", taglen, ele, val);
632 case 'v': pub->version = val; break;
633 case 'h': pub->hashes = val; break;
635 case 'g': pub->granularity = val; break;
636 case 'n': pub->notes = pdkim_decode_qp(val); break;
637 case 'p': pdkim_decode_base64(val, &pub->key); break;
638 case 's': pub->srvtype = val; break;
639 case 't': if (Ustrchr(val, 'y')) pub->testing = 1;
640 if (Ustrchr(val, 's')) pub->no_subdomaining = 1;
642 default: DEBUG(D_acl) debug_printf(" Unknown tag encountered\n"); break;
647 /* Set fallback defaults */
648 if (!pub->version ) pub->version = string_copy(PDKIM_PUB_RECORD_VERSION);
649 else if (Ustrcmp(pub->version, PDKIM_PUB_RECORD_VERSION) != 0)
651 DEBUG(D_acl) debug_printf(" Bad v= field\n");
655 if (!pub->granularity) pub->granularity = US"*";
657 if (!pub->keytype ) pub->keytype = US"rsa";
659 if (!pub->srvtype ) pub->srvtype = US"*";
665 DEBUG(D_acl) debug_printf(" Missing p= field\n");
670 /* -------------------------------------------------------------------------- */
672 /* Update the bodyhash for one sig, with some additional data.
673 If we have to relax the data for this sig, return our copy of it. */
675 /*XXX Currently we calculate a hash for each sig. But it is possible
676 that multi-signing will be wanted using different signing algos
677 (rsa, ec) using the same hash and canonicalization. Consider in future
678 hanging the hash+cacnon from the ctx and only referencing from the sig,
679 so that it can be calculated only once - being over the body this
680 caould be meagbytes, hence expensive. */
683 pdkim_update_sig_bodyhash(pdkim_signature * sig, blob * orig_data, blob * relaxed_data)
685 blob * canon_data = orig_data;
686 /* Defaults to simple canon (no further treatment necessary) */
688 if (sig->canon_body == PDKIM_CANON_RELAXED)
690 /* Relax the line if not done already */
693 BOOL seen_wsp = FALSE;
697 /* We want to be able to free this else we allocate
698 for the entire message which could be many MB. Since
699 we don't know what allocations the SHA routines might
700 do, not safe to use store_get()/store_reset(). */
702 relaxed_data = store_malloc(sizeof(blob) + orig_data->len+1);
703 relaxed_data->data = US (relaxed_data+1);
705 for (p = orig_data->data; *p; p++)
710 if (q > 0 && relaxed_data->data[q-1] == ' ')
713 else if (c == '\t' || c == ' ')
715 c = ' '; /* Turns WSP into SP */
722 relaxed_data->data[q++] = c;
724 relaxed_data->data[q] = '\0';
725 relaxed_data->len = q;
727 canon_data = relaxed_data;
730 /* Make sure we don't exceed the to-be-signed body length */
731 if ( sig->bodylength >= 0
732 && sig->signed_body_bytes + (unsigned long)canon_data->len > sig->bodylength
734 canon_data->len = sig->bodylength - sig->signed_body_bytes;
736 if (canon_data->len > 0)
738 exim_sha_update(&sig->body_hash_ctx, CUS canon_data->data, canon_data->len);
739 sig->signed_body_bytes += canon_data->len;
740 DEBUG(D_acl) pdkim_quoteprint(canon_data->data, canon_data->len);
747 /* -------------------------------------------------------------------------- */
750 pdkim_finish_bodyhash(pdkim_ctx * ctx)
752 pdkim_signature * sig;
754 /* Traverse all signatures */
755 for (sig = ctx->sig; sig; sig = sig->next)
756 { /* Finish hashes */
759 exim_sha_finish(&sig->body_hash_ctx, &bh);
763 debug_printf("PDKIM [%s] Body bytes hashed: %lu\n"
764 "PDKIM [%s] Body %s computed: ",
765 sig->domain, sig->signed_body_bytes,
766 sig->domain, pdkim_hashes[sig->hashtype].dkim_hashname);
767 pdkim_hexprint(CUS bh.data, bh.len);
770 /* SIGNING -------------------------------------------------------------- */
771 if (ctx->flags & PDKIM_MODE_SIGN)
775 /* If bodylength limit is set, and we have received less bytes
776 than the requested amount, effectively remove the limit tag. */
777 if (sig->signed_body_bytes < sig->bodylength)
778 sig->bodylength = -1;
782 /* VERIFICATION --------------------------------------------------------- */
783 /* Be careful that the header sig included a bodyash */
785 if (sig->bodyhash.data && memcmp(bh.data, sig->bodyhash.data, bh.len) == 0)
787 DEBUG(D_acl) debug_printf("PDKIM [%s] Body hash verified OK\n", sig->domain);
793 debug_printf("PDKIM [%s] Body hash signature from headers: ", sig->domain);
794 pdkim_hexprint(sig->bodyhash.data, sig->bodyhash.len);
795 debug_printf("PDKIM [%s] Body hash did NOT verify\n", sig->domain);
797 sig->verify_status = PDKIM_VERIFY_FAIL;
798 sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
806 pdkim_body_complete(pdkim_ctx * ctx)
808 pdkim_signature * sig;
810 /* In simple body mode, if any empty lines were buffered,
811 replace with one. rfc 4871 3.4.3 */
812 /*XXX checking the signed-body-bytes is a gross hack; I think
813 it indicates that all linebreaks should be buffered, including
814 the one terminating a text line */
816 for (sig = ctx->sig; sig; sig = sig->next)
817 if ( sig->canon_body == PDKIM_CANON_SIMPLE
818 && sig->signed_body_bytes == 0
819 && sig->num_buffered_blanklines > 0
821 (void) pdkim_update_sig_bodyhash(sig, &lineending, NULL);
823 ctx->flags |= PDKIM_SEEN_EOD;
824 ctx->linebuf_offset = 0;
829 /* -------------------------------------------------------------------------- */
830 /* Call from pdkim_feed below for processing complete body lines */
833 pdkim_bodyline_complete(pdkim_ctx * ctx)
835 blob line = {.data = ctx->linebuf, .len = ctx->linebuf_offset};
836 pdkim_signature * sig;
840 /* Ignore extra data if we've seen the end-of-data marker */
841 if (ctx->flags & PDKIM_SEEN_EOD) goto all_skip;
843 /* We've always got one extra byte to stuff a zero ... */
844 ctx->linebuf[line.len] = '\0';
846 /* Terminate on EOD marker */
847 if (ctx->flags & PDKIM_DOT_TERM)
849 if (memcmp(line.data, ".\r\n", 3) == 0)
850 { pdkim_body_complete(ctx); return; }
853 if (memcmp(line.data, "..", 2) == 0)
854 { line.data++; line.len--; }
857 /* Empty lines need to be buffered until we find a non-empty line */
858 if (memcmp(line.data, "\r\n", 2) == 0)
860 for (sig = ctx->sig; sig; sig = sig->next) sig->num_buffered_blanklines++;
864 /* Process line for each sig separately */
865 for (sig = ctx->sig; sig; sig = sig->next)
867 if (sig->canon_body == PDKIM_CANON_RELAXED)
869 /* Lines with just spaces need to be buffered too */
870 uschar * cp = line.data;
875 if (c == '\r' && cp[1] == '\n') break;
876 if (c != ' ' && c != '\t') goto sig_process;
880 sig->num_buffered_blanklines++;
885 /* At this point, we have a non-empty line, so release the buffered ones. */
887 while (sig->num_buffered_blanklines)
889 rnl = pdkim_update_sig_bodyhash(sig, &lineending, rnl);
890 sig->num_buffered_blanklines--;
893 rline = pdkim_update_sig_bodyhash(sig, &line, rline);
897 if (rnl) store_free(rnl);
898 if (rline) store_free(rline);
902 ctx->linebuf_offset = 0;
907 /* -------------------------------------------------------------------------- */
908 /* Callback from pdkim_feed below for processing complete headers */
909 #define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
912 pdkim_header_complete(pdkim_ctx * ctx)
914 pdkim_signature * sig, * last_sig;
916 /* Special case: The last header can have an extra \r appended */
917 if ( (ctx->cur_header->ptr > 1) &&
918 (ctx->cur_header->s[ctx->cur_header->ptr-1] == '\r') )
919 --ctx->cur_header->ptr;
920 (void) string_from_gstring(ctx->cur_header);
922 if (++ctx->num_headers > PDKIM_MAX_HEADERS) goto BAIL;
924 /* SIGNING -------------------------------------------------------------- */
925 if (ctx->flags & PDKIM_MODE_SIGN)
926 for (sig = ctx->sig; sig; sig = sig->next) /* Traverse all signatures */
928 /* Add header to the signed headers list (in reverse order) */
929 sig->headers = pdkim_prepend_stringlist(sig->headers, ctx->cur_header->s);
931 /* VERIFICATION ----------------------------------------------------------- */
932 /* DKIM-Signature: headers are added to the verification list */
938 debug_printf("PDKIM >> raw hdr: ");
939 pdkim_quoteprint(CUS ctx->cur_header->s, ctx->cur_header->ptr);
942 if (strncasecmp(CCS ctx->cur_header->s,
943 DKIM_SIGNATURE_HEADERNAME,
944 Ustrlen(DKIM_SIGNATURE_HEADERNAME)) == 0)
946 /* Create and chain new signature block. We could error-check for all
947 required tags here, but prefer to create the internal sig and expicitly
948 fail verification of it later. */
950 DEBUG(D_acl) debug_printf(
951 "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
953 sig = pdkim_parse_sig_header(ctx, ctx->cur_header->s);
955 if (!(last_sig = ctx->sig))
959 while (last_sig->next) last_sig = last_sig->next;
960 last_sig->next = sig;
964 /* all headers are stored for signature verification */
965 ctx->headers = pdkim_prepend_stringlist(ctx->headers, ctx->cur_header->s);
969 ctx->cur_header->s[ctx->cur_header->ptr = 0] = '\0'; /* leave buffer for reuse */
975 /* -------------------------------------------------------------------------- */
976 #define HEADER_BUFFER_FRAG_SIZE 256
979 pdkim_feed(pdkim_ctx * ctx, uschar * data, int len)
983 /* Alternate EOD signal, used in non-dotstuffing mode */
985 pdkim_body_complete(ctx);
987 else for (p = 0; p<len; p++)
991 if (ctx->flags & PDKIM_PAST_HDRS)
993 if (c == '\n' && !(ctx->flags & PDKIM_SEEN_CR)) /* emulate the CR */
995 ctx->linebuf[ctx->linebuf_offset++] = '\r';
996 if (ctx->linebuf_offset == PDKIM_MAX_BODY_LINE_LEN-1)
997 return PDKIM_ERR_LONG_LINE;
1000 /* Processing body byte */
1001 ctx->linebuf[ctx->linebuf_offset++] = c;
1003 ctx->flags |= PDKIM_SEEN_CR;
1006 ctx->flags &= ~PDKIM_SEEN_CR;
1007 pdkim_bodyline_complete(ctx);
1010 if (ctx->linebuf_offset == PDKIM_MAX_BODY_LINE_LEN-1)
1011 return PDKIM_ERR_LONG_LINE;
1015 /* Processing header byte */
1017 ctx->flags |= PDKIM_SEEN_CR;
1020 if (!(ctx->flags & PDKIM_SEEN_CR)) /* emulate the CR */
1021 ctx->cur_header = string_catn(ctx->cur_header, CUS "\r", 1);
1023 if (ctx->flags & PDKIM_SEEN_LF) /* Seen last header line */
1025 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1028 ctx->flags = (ctx->flags & ~(PDKIM_SEEN_LF|PDKIM_SEEN_CR)) | PDKIM_PAST_HDRS;
1029 DEBUG(D_acl) debug_printf(
1030 "PDKIM >> Body data for hash, canonicalized >>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1034 ctx->flags = (ctx->flags & ~PDKIM_SEEN_CR) | PDKIM_SEEN_LF;
1036 else if (ctx->flags & PDKIM_SEEN_LF)
1038 if (!(c == '\t' || c == ' ')) /* End of header */
1039 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1041 ctx->flags &= ~PDKIM_SEEN_LF;
1044 if (!ctx->cur_header || ctx->cur_header->ptr < PDKIM_MAX_HEADER_LEN)
1045 ctx->cur_header = string_catn(ctx->cur_header, CUS &data[p], 1);
1053 /* Extend a growing header with a continuation-linebreak */
1055 pdkim_hdr_cont(gstring * str, int * col)
1058 return string_catn(str, US"\r\n\t", 3);
1064 * RFC 5322 specifies that header line length SHOULD be no more than 78
1068 * returns uschar * (not nul-terminated)
1070 * col: this int holds and receives column number (octets since last '\n')
1071 * str: partial string to append to
1072 * pad: padding, split line or space after before or after eg: ";"
1073 * intro: - must join to payload eg "h=", usually the tag name
1074 * payload: eg base64 data - long data can be split arbitrarily.
1076 * this code doesn't fold the header in some of the places that RFC4871
1077 * allows: As per RFC5322(2.2.3) it only folds before or after tag-value
1078 * pairs and inside long values. it also always spaces or breaks after the
1081 * no guarantees are made for output given out-of range input. like tag
1082 * names longer than 78, or bogus col. Input is assumed to be free of line breaks.
1086 pdkim_headcat(int * col, gstring * str,
1087 const uschar * pad, const uschar * intro, const uschar * payload)
1095 str = pdkim_hdr_cont(str, col);
1096 str = string_catn(str, pad, l);
1100 l = (pad?1:0) + (intro?Ustrlen(intro):0);
1103 { /*can't fit intro - start a new line to make room.*/
1104 str = pdkim_hdr_cont(str, col);
1105 l = intro?Ustrlen(intro):0;
1108 l += payload ? Ustrlen(payload):0 ;
1111 { /* this fragment will not fit on a single line */
1114 str = string_catn(str, US" ", 1);
1116 pad = NULL; /* only want this once */
1122 size_t sl = Ustrlen(intro);
1124 str = string_catn(str, intro, sl);
1127 intro = NULL; /* only want this once */
1132 size_t sl = Ustrlen(payload);
1133 size_t chomp = *col+sl < 77 ? sl : 78-*col;
1135 str = string_catn(str, payload, chomp);
1141 /* the while precondition tells us it didn't fit. */
1142 str = pdkim_hdr_cont(str, col);
1147 str = pdkim_hdr_cont(str, col);
1153 str = string_catn(str, US" ", 1);
1160 size_t sl = Ustrlen(intro);
1162 str = string_catn(str, intro, sl);
1170 size_t sl = Ustrlen(payload);
1172 str = string_catn(str, payload, sl);
1180 /* -------------------------------------------------------------------------- */
1183 pdkim_create_header(pdkim_signature * sig, BOOL final)
1189 gstring * canon_all;
1191 canon_all = string_cat (NULL, pdkim_canons[sig->canon_headers]);
1192 canon_all = string_catn(canon_all, US"/", 1);
1193 canon_all = string_cat (canon_all, pdkim_canons[sig->canon_body]);
1194 (void) string_from_gstring(canon_all);
1196 hdr = string_cat(NULL, US"DKIM-Signature: v="PDKIM_SIGNATURE_VERSION);
1199 /* Required and static bits */
1200 hdr = pdkim_headcat(&col, hdr, US";", US"a=", dkim_sig_to_a_tag(sig));
1201 hdr = pdkim_headcat(&col, hdr, US";", US"q=", pdkim_querymethods[sig->querymethod]);
1202 hdr = pdkim_headcat(&col, hdr, US";", US"c=", canon_all->s);
1203 hdr = pdkim_headcat(&col, hdr, US";", US"d=", sig->domain);
1204 hdr = pdkim_headcat(&col, hdr, US";", US"s=", sig->selector);
1206 /* list of header names can be split between items. */
1208 uschar * n = string_copy(sig->headernames);
1209 uschar * i = US"h=";
1214 uschar * c = Ustrchr(n, ':');
1219 hdr = pdkim_headcat(&col, hdr, NULL, NULL, US":");
1221 hdr = pdkim_headcat(&col, hdr, s, i, n);
1232 base64_bh = pdkim_encode_base64(&sig->bodyhash);
1233 hdr = pdkim_headcat(&col, hdr, US";", US"bh=", base64_bh);
1237 hdr = pdkim_headcat(&col, hdr, US";", US"i=", sig->identity);
1239 if (sig->created > 0)
1243 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->created);
1244 hdr = pdkim_headcat(&col, hdr, US";", US"t=", minibuf);
1247 if (sig->expires > 0)
1251 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->expires);
1252 hdr = pdkim_headcat(&col, hdr, US";", US"x=", minibuf);
1255 if (sig->bodylength >= 0)
1259 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->bodylength);
1260 hdr = pdkim_headcat(&col, hdr, US";", US"l=", minibuf);
1263 /* Preliminary or final version? */
1266 base64_b = pdkim_encode_base64(&sig->sighash);
1267 hdr = pdkim_headcat(&col, hdr, US";", US"b=", base64_b);
1269 /* add trailing semicolon: I'm not sure if this is actually needed */
1270 hdr = pdkim_headcat(&col, hdr, NULL, US";", US"");
1274 /* To satisfy the rule "all surrounding whitespace [...] deleted"
1275 ( RFC 6376 section 3.7 ) we ensure there is no whitespace here. Otherwise
1276 the headcat routine could insert a linebreak which the relaxer would reduce
1277 to a single space preceding the terminating semicolon, resulting in an
1278 incorrect header-hash. */
1279 hdr = pdkim_headcat(&col, hdr, US";", US"b=;", US"");
1282 return string_from_gstring(hdr);
1286 /* -------------------------------------------------------------------------- */
1288 static pdkim_pubkey *
1289 pdkim_key_from_dns(pdkim_ctx * ctx, pdkim_signature * sig, ev_ctx * vctx,
1290 const uschar ** errstr)
1292 uschar * dns_txt_name, * dns_txt_reply;
1295 /* Fetch public key for signing domain, from DNS */
1297 dns_txt_name = string_sprintf("%s._domainkey.%s.", sig->selector, sig->domain);
1299 dns_txt_reply = store_get(PDKIM_DNS_TXT_MAX_RECLEN);
1300 memset(dns_txt_reply, 0, PDKIM_DNS_TXT_MAX_RECLEN);
1302 if ( ctx->dns_txt_callback(CS dns_txt_name, CS dns_txt_reply) != PDKIM_OK
1303 || dns_txt_reply[0] == '\0'
1306 sig->verify_status = PDKIM_VERIFY_INVALID;
1307 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE;
1314 "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
1318 pdkim_quoteprint(CUS dns_txt_reply, Ustrlen(dns_txt_reply));
1321 if ( !(p = pdkim_parse_pubkey_record(ctx, CUS dns_txt_reply))
1322 || (Ustrcmp(p->srvtype, "*") != 0 && Ustrcmp(p->srvtype, "email") != 0)
1325 sig->verify_status = PDKIM_VERIFY_INVALID;
1326 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD;
1331 debug_printf(" Invalid public key service type '%s'\n", p->srvtype);
1333 debug_printf(" Error while parsing public key record\n");
1335 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1340 DEBUG(D_acl) debug_printf(
1341 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1343 /* Import public key */
1344 if ((*errstr = exim_dkim_verify_init(&p->key, vctx)))
1346 DEBUG(D_acl) debug_printf("verify_init: %s\n", *errstr);
1347 sig->verify_status = PDKIM_VERIFY_INVALID;
1348 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_IMPORT;
1356 /* -------------------------------------------------------------------------- */
1359 pdkim_feed_finish(pdkim_ctx * ctx, pdkim_signature ** return_signatures,
1360 const uschar ** err)
1362 pdkim_signature * sig;
1364 /* Check if we must still flush a (partial) header. If that is the
1365 case, the message has no body, and we must compute a body hash
1366 out of '<CR><LF>' */
1367 if (ctx->cur_header && ctx->cur_header->ptr > 0)
1372 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1375 for (sig = ctx->sig; sig; sig = sig->next)
1376 rnl = pdkim_update_sig_bodyhash(sig, &lineending, rnl);
1377 if (rnl) store_free(rnl);
1380 DEBUG(D_acl) debug_printf(
1381 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1383 /* Build (and/or evaluate) body hash */
1384 pdkim_finish_bodyhash(ctx);
1386 for (sig = ctx->sig; sig; sig = sig->next)
1389 uschar * sig_hdr = US"";
1391 gstring * hdata = NULL;
1393 if (!exim_sha_init(&hhash_ctx, pdkim_hashes[sig->hashtype].exim_hashmethod))
1396 debug_printf("PDKIM: hash setup error, possibly nonhandled hashtype\n");
1400 if (ctx->flags & PDKIM_MODE_SIGN)
1401 DEBUG(D_acl) debug_printf(
1402 "PDKIM >> Headers to be signed: >>>>>>>>>>>>\n"
1406 DEBUG(D_acl) debug_printf(
1407 "PDKIM >> Header data for hash, canonicalized, in sequence >>>>>>>>>>>>\n");
1410 /* SIGNING ---------------------------------------------------------------- */
1411 /* When signing, walk through our header list and add them to the hash. As we
1412 go, construct a list of the header's names to use for the h= parameter.
1413 Then append to that list any remaining header names for which there was no
1416 if (ctx->flags & PDKIM_MODE_SIGN)
1419 pdkim_stringlist *p;
1424 sig->headernames = NULL; /* Collected signed header names */
1426 for (p = sig->headers; p; p = p->next)
1428 uschar * rh = p->value;
1430 if (header_name_match(rh, sig->sign_headers) == PDKIM_OK)
1432 /* Collect header names (Note: colon presence is guaranteed here) */
1433 g = string_append_listele_n(g, ':', rh, Ustrchr(rh, ':') - rh);
1435 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1436 rh = pdkim_relax_header(rh, TRUE); /* cook header for relaxed canon */
1438 /* Feed header to the hash algorithm */
1439 exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
1441 /* Remember headers block for signing (when the library cannot do incremental) */
1442 hdata = exim_dkim_data_append(hdata, rh);
1444 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1448 /* Any headers we wanted to sign but were not present must also be listed */
1449 l = sig->sign_headers;
1450 while((s = string_nextinlist(&l, &sep, NULL, 0)))
1452 g = string_append_listele(g, ':', s);
1453 sig->headernames = string_from_gstring(g);
1455 /* Create signature header with b= omitted */
1456 sig_hdr = pdkim_create_header(sig, FALSE);
1459 /* VERIFICATION ----------------------------------------------------------- */
1460 /* When verifying, walk through the header name list in the h= parameter and
1461 add the headers to the hash in that order. */
1464 uschar * p = sig->headernames;
1466 pdkim_stringlist * hdrs;
1471 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1477 if ((q = Ustrchr(p, ':')))
1480 /*XXX walk the list of headers in same order as received. */
1481 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1483 && strncasecmp(CCS hdrs->value, CCS p, Ustrlen(p)) == 0
1484 && (hdrs->value)[Ustrlen(p)] == ':'
1487 /* cook header for relaxed canon, or just copy it for simple */
1489 uschar * rh = sig->canon_headers == PDKIM_CANON_RELAXED
1490 ? pdkim_relax_header(hdrs->value, TRUE)
1491 : string_copy(CUS hdrs->value);
1493 /* Feed header to the hash algorithm */
1494 exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
1496 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1505 sig_hdr = string_copy(sig->rawsig_no_b_val);
1509 DEBUG(D_acl) debug_printf(
1510 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1515 "PDKIM >> Signed DKIM-Signature header, pre-canonicalized >>>>>>>>>>>>>\n");
1516 pdkim_quoteprint(CUS sig_hdr, Ustrlen(sig_hdr));
1518 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1521 /* Relax header if necessary */
1522 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1523 sig_hdr = pdkim_relax_header(sig_hdr, FALSE);
1528 "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
1529 pdkim_quoteprint(CUS sig_hdr, Ustrlen(sig_hdr));
1531 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1534 /* Finalize header hash */
1535 exim_sha_update(&hhash_ctx, CUS sig_hdr, Ustrlen(sig_hdr));
1536 exim_sha_finish(&hhash_ctx, &hhash);
1540 debug_printf("PDKIM [%s] Header %s computed: ",
1541 sig->domain, pdkim_hashes[sig->hashtype].dkim_hashname);
1542 pdkim_hexprint(hhash.data, hhash.len);
1545 /* Remember headers block for signing (when the signing library cannot do
1547 if (ctx->flags & PDKIM_MODE_SIGN)
1548 hdata = exim_dkim_data_append(hdata, US sig_hdr);
1550 /* SIGNING ---------------------------------------------------------------- */
1551 if (ctx->flags & PDKIM_MODE_SIGN)
1555 /* Import private key, including the keytype */
1556 /*XXX extend for non-RSA algos */
1557 if ((*err = exim_dkim_signing_init(US sig->privkey, &sctx)))
1559 DEBUG(D_acl) debug_printf("signing_init: %s\n", *err);
1560 return PDKIM_ERR_RSA_PRIVKEY;
1563 /* Do signing. With OpenSSL we are signing the hash of headers just
1564 calculated, with GnuTLS we have to sign an entire block of headers
1565 (due to available interfaces) and it recalculates the hash internally. */
1567 #if defined(SIGN_GNUTLS)
1568 hhash.data = hdata->s;
1569 hhash.len = hdata->ptr;
1572 /*XXX extend for non-RSA algos */
1573 if ((*err = exim_dkim_sign(&sctx,
1574 pdkim_hashes[sig->hashtype].exim_hashmethod,
1575 &hhash, &sig->sighash)))
1577 DEBUG(D_acl) debug_printf("signing: %s\n", *err);
1578 return PDKIM_ERR_RSA_SIGNING;
1583 debug_printf( "PDKIM [%s] b computed: ", sig->domain);
1584 pdkim_hexprint(sig->sighash.data, sig->sighash.len);
1587 sig->signature_header = pdkim_create_header(sig, TRUE);
1590 /* VERIFICATION ----------------------------------------------------------- */
1595 /* Make sure we have all required signature tags */
1596 if (!( sig->domain && *sig->domain
1597 && sig->selector && *sig->selector
1598 && sig->headernames && *sig->headernames
1599 && sig->bodyhash.data
1600 && sig->sighash.data
1601 && sig->keytype >= 0
1602 && sig->hashtype >= 0
1606 sig->verify_status = PDKIM_VERIFY_INVALID;
1607 sig->verify_ext_status = PDKIM_VERIFY_INVALID_SIGNATURE_ERROR;
1609 DEBUG(D_acl) debug_printf(
1610 " Error in DKIM-Signature header: tags missing or invalid\n"
1611 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1615 /* Make sure sig uses supported DKIM version (only v1) */
1616 if (sig->version != 1)
1618 sig->verify_status = PDKIM_VERIFY_INVALID;
1619 sig->verify_ext_status = PDKIM_VERIFY_INVALID_DKIM_VERSION;
1621 DEBUG(D_acl) debug_printf(
1622 " Error in DKIM-Signature header: unsupported DKIM version\n"
1623 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1629 debug_printf( "PDKIM [%s] b from mail: ", sig->domain);
1630 pdkim_hexprint(sig->sighash.data, sig->sighash.len);
1633 if (!(sig->pubkey = pdkim_key_from_dns(ctx, sig, &vctx, err)))
1636 /* If the pubkey limits to a list of specific hashes, ignore sigs that
1637 do not have the hash part of the sig algorithm matching */
1639 if (sig->pubkey->hashes)
1641 const uschar * list = sig->pubkey->hashes, * ele;
1643 while ((ele = string_nextinlist(&list, &sep, NULL, 0)))
1644 if (Ustrcmp(ele, pdkim_hashes[sig->hashtype].dkim_hashname) == 0) break;
1647 DEBUG(D_acl) debug_printf("pubkey h=%s vs. sig a=%s_%s\n",
1648 sig->pubkey->hashes,
1649 pdkim_keytypes[sig->keytype],
1650 pdkim_hashes[sig->hashtype].dkim_hashname);
1651 sig->verify_status = PDKIM_VERIFY_FAIL;
1652 sig->verify_ext_status = PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH;
1657 /* Check the signature */
1658 /*XXX needs extension for non-RSA */
1659 if ((*err = exim_dkim_verify(&vctx,
1660 pdkim_hashes[sig->hashtype].exim_hashmethod,
1661 &hhash, &sig->sighash)))
1663 DEBUG(D_acl) debug_printf("headers verify: %s\n", *err);
1664 sig->verify_status = PDKIM_VERIFY_FAIL;
1665 sig->verify_ext_status = PDKIM_VERIFY_FAIL_MESSAGE;
1670 /* We have a winner! (if bodyhash was correct earlier) */
1671 if (sig->verify_status == PDKIM_VERIFY_NONE)
1672 sig->verify_status = PDKIM_VERIFY_PASS;
1678 debug_printf("PDKIM [%s] signature status: %s",
1679 sig->domain, pdkim_verify_status_str(sig->verify_status));
1680 if (sig->verify_ext_status > 0)
1681 debug_printf(" (%s)\n",
1682 pdkim_verify_ext_status_str(sig->verify_ext_status));
1689 /* If requested, set return pointer to signature(s) */
1690 if (return_signatures)
1691 *return_signatures = ctx->sig;
1697 /* -------------------------------------------------------------------------- */
1699 DLLEXPORT pdkim_ctx *
1700 pdkim_init_verify(int(*dns_txt_callback)(char *, char *), BOOL dot_stuffing)
1704 ctx = store_get(sizeof(pdkim_ctx));
1705 memset(ctx, 0, sizeof(pdkim_ctx));
1707 if (dot_stuffing) ctx->flags = PDKIM_DOT_TERM;
1708 ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN);
1709 ctx->dns_txt_callback = dns_txt_callback;
1715 /* -------------------------------------------------------------------------- */
1717 /*XXX ? needs extension to cover non-RSA algo? */
1719 DLLEXPORT pdkim_signature *
1720 pdkim_init_sign(pdkim_ctx * ctx,
1721 uschar * domain, uschar * selector, uschar * privkey,
1722 uschar * hashname, const uschar ** errstr)
1725 pdkim_signature * sig;
1727 if (!domain || !selector || !privkey)
1730 /* Allocate & init one signature struct */
1732 sig = store_get(sizeof(pdkim_signature));
1733 memset(sig, 0, sizeof(pdkim_signature));
1735 sig->bodylength = -1;
1737 sig->domain = string_copy(US domain);
1738 sig->selector = string_copy(US selector);
1739 sig->privkey = string_copy(US privkey);
1740 /*XXX no keytype yet; comes from privkey */
1742 for (hashtype = 0; hashtype < nelem(pdkim_hashes); hashtype++)
1743 if (Ustrcmp(hashname, pdkim_hashes[hashtype].dkim_hashname) == 0)
1744 { sig->hashtype = hashtype; break; }
1745 if (hashtype >= nelem(pdkim_hashes))
1748 debug_printf("PDKIM: unrecognised hashname '%s'\n", hashname);
1752 if (!exim_sha_init(&sig->body_hash_ctx, pdkim_hashes[hashtype].exim_hashmethod))
1755 debug_printf("PDKIM: hash setup error, possibly nonhandled hashtype\n");
1761 pdkim_signature s = *sig;
1764 debug_printf("PDKIM (checking verify key)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1765 if (!pdkim_key_from_dns(ctx, &s, &vctx, errstr))
1766 debug_printf("WARNING: bad dkim key in dns\n");
1767 debug_printf("PDKIM (finished checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1773 /* -------------------------------------------------------------------------- */
1776 pdkim_set_optional(pdkim_signature * sig,
1777 char * sign_headers,
1782 unsigned long created,
1783 unsigned long expires)
1786 sig->identity = string_copy(US identity);
1788 sig->sign_headers = string_copy(sign_headers
1789 ? US sign_headers : US PDKIM_DEFAULT_SIGN_HEADERS);
1791 sig->canon_headers = canon_headers;
1792 sig->canon_body = canon_body;
1793 sig->bodylength = bodylength;
1794 sig->created = created;
1795 sig->expires = expires;
1803 pdkim_init_context(pdkim_ctx * ctx, BOOL dot_stuffed,
1804 int(*dns_txt_callback)(char *, char *))
1806 memset(ctx, 0, sizeof(pdkim_ctx));
1807 ctx->flags = dot_stuffed ? PDKIM_MODE_SIGN | PDKIM_DOT_TERM : PDKIM_MODE_SIGN;
1808 ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN);
1809 DEBUG(D_acl) ctx->dns_txt_callback = dns_txt_callback;
1821 #endif /*DISABLE_DKIM*/