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
54 #define PDKIM_DEFAULT_SIGN_HEADERS "From:Sender:Reply-To:Subject:Date:"\
55 "Message-ID:To:Cc:MIME-Version:Content-Type:"\
56 "Content-Transfer-Encoding:Content-ID:"\
57 "Content-Description:Resent-Date:Resent-From:"\
58 "Resent-Sender:Resent-To:Resent-Cc:"\
59 "Resent-Message-ID:In-Reply-To:References:"\
60 "List-Id:List-Help:List-Unsubscribe:"\
61 "List-Subscribe:List-Post:List-Owner:List-Archive"
63 /* -------------------------------------------------------------------------- */
64 struct pdkim_stringlist {
70 /* -------------------------------------------------------------------------- */
71 /* A bunch of list constants */
72 const uschar * pdkim_querymethods[] = {
76 const uschar * pdkim_canons[] = {
83 const uschar * dkim_hashname;
84 hashmethod exim_hashmethod;
86 static const pdkim_hashtype pdkim_hashes[] = {
87 { US"sha1", HASH_SHA1 },
88 { US"sha256", HASH_SHA2_256 },
89 { US"sha512", HASH_SHA2_512 }
92 const uschar * pdkim_keytypes[] = {
96 typedef struct pdkim_combined_canon_entry {
100 } pdkim_combined_canon_entry;
102 pdkim_combined_canon_entry pdkim_combined_canons[] = {
103 { US"simple/simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
104 { US"simple/relaxed", PDKIM_CANON_SIMPLE, PDKIM_CANON_RELAXED },
105 { US"relaxed/simple", PDKIM_CANON_RELAXED, PDKIM_CANON_SIMPLE },
106 { US"relaxed/relaxed", PDKIM_CANON_RELAXED, PDKIM_CANON_RELAXED },
107 { US"simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
108 { US"relaxed", PDKIM_CANON_RELAXED, PDKIM_CANON_SIMPLE },
113 static blob lineending = {.data = US"\r\n", .len = 2};
115 /* -------------------------------------------------------------------------- */
117 dkim_sig_to_a_tag(const pdkim_signature * sig)
119 if ( sig->keytype < 0 || sig->keytype > nelem(pdkim_keytypes)
120 || sig->hashtype < 0 || sig->hashtype > nelem(pdkim_hashes))
122 return string_sprintf("%s-%s",
123 pdkim_keytypes[sig->keytype], pdkim_hashes[sig->hashtype].dkim_hashname);
129 pdkim_verify_status_str(int status)
133 case PDKIM_VERIFY_NONE: return "PDKIM_VERIFY_NONE";
134 case PDKIM_VERIFY_INVALID: return "PDKIM_VERIFY_INVALID";
135 case PDKIM_VERIFY_FAIL: return "PDKIM_VERIFY_FAIL";
136 case PDKIM_VERIFY_PASS: return "PDKIM_VERIFY_PASS";
137 default: return "PDKIM_VERIFY_UNKNOWN";
142 pdkim_verify_ext_status_str(int ext_status)
146 case PDKIM_VERIFY_FAIL_BODY: return "PDKIM_VERIFY_FAIL_BODY";
147 case PDKIM_VERIFY_FAIL_MESSAGE: return "PDKIM_VERIFY_FAIL_MESSAGE";
148 case PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH: return "PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH";
149 case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE: return "PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE";
150 case PDKIM_VERIFY_INVALID_BUFFER_SIZE: return "PDKIM_VERIFY_INVALID_BUFFER_SIZE";
151 case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD: return "PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD";
152 case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT: return "PDKIM_VERIFY_INVALID_PUBKEY_IMPORT";
153 case PDKIM_VERIFY_INVALID_SIGNATURE_ERROR: return "PDKIM_VERIFY_INVALID_SIGNATURE_ERROR";
154 case PDKIM_VERIFY_INVALID_DKIM_VERSION: return "PDKIM_VERIFY_INVALID_DKIM_VERSION";
155 default: return "PDKIM_VERIFY_UNKNOWN";
160 pdkim_errstr(int status)
164 case PDKIM_OK: return US"OK";
165 case PDKIM_FAIL: return US"FAIL";
166 case PDKIM_ERR_RSA_PRIVKEY: return US"RSA_PRIVKEY";
167 case PDKIM_ERR_RSA_SIGNING: return US"RSA SIGNING";
168 case PDKIM_ERR_LONG_LINE: return US"RSA_LONG_LINE";
169 case PDKIM_ERR_BUFFER_TOO_SMALL: return US"BUFFER_TOO_SMALL";
170 case PDKIM_SIGN_PRIVKEY_WRAP: return US"PRIVKEY_WRAP";
171 case PDKIM_SIGN_PRIVKEY_B64D: return US"PRIVKEY_B64D";
172 default: return US"(unknown)";
177 /* -------------------------------------------------------------------------- */
178 /* Print debugging functions */
180 pdkim_quoteprint(const uschar *data, int len)
183 for (i = 0; i < len; i++)
185 const int c = data[i];
188 case ' ' : debug_printf("{SP}"); break;
189 case '\t': debug_printf("{TB}"); break;
190 case '\r': debug_printf("{CR}"); break;
191 case '\n': debug_printf("{LF}"); break;
192 case '{' : debug_printf("{BO}"); break;
193 case '}' : debug_printf("{BC}"); break;
195 if ( (c < 32) || (c > 127) )
196 debug_printf("{%02x}", c);
198 debug_printf("%c", c);
206 pdkim_hexprint(const uschar *data, int len)
209 if (data) for (i = 0 ; i < len; i++) debug_printf("%02x", data[i]);
210 else debug_printf("<NULL>");
216 static pdkim_stringlist *
217 pdkim_prepend_stringlist(pdkim_stringlist * base, const uschar * str)
219 pdkim_stringlist * new_entry = store_get(sizeof(pdkim_stringlist));
221 memset(new_entry, 0, sizeof(pdkim_stringlist));
222 new_entry->value = string_copy(str);
223 if (base) new_entry->next = base;
229 /* Trim whitespace fore & aft */
232 pdkim_strtrim(uschar * str)
236 while (*p == '\t' || *p == ' ') p++; /* skip whitespace */
237 while (*p) {*q = *p; q++; p++;} /* dump the leading whitespace */
239 while (q != str && ( (*q == '\0') || (*q == '\t') || (*q == ' ') ) )
240 { /* dump trailing whitespace */
248 /* -------------------------------------------------------------------------- */
251 pdkim_free_ctx(pdkim_ctx *ctx)
256 /* -------------------------------------------------------------------------- */
257 /* Matches the name of the passed raw "header" against
258 the passed colon-separated "tick", and invalidates
259 the entry in tick. Returns OK or fail-code */
260 /*XXX might be safer done using a pdkim_stringlist for "tick" */
263 header_name_match(const uschar * header, uschar * tick)
269 uschar * hcolon = Ustrchr(header, ':'); /* Get header name */
272 return PDKIM_FAIL; /* This isn't a header */
274 /* if we had strncmpic() we wouldn't need this copy */
275 hname = string_copyn(header, hcolon-header);
277 /* Copy tick-off list locally, so we can punch zeroes into it */
278 p = lcopy = string_copy(tick);
280 for (q = Ustrchr(p, ':'); q; q = Ustrchr(p, ':'))
283 if (strcmpic(p, hname) == 0)
289 if (strcmpic(p, hname) == 0)
295 /* Invalidate header name instance in tick-off list */
301 /* -------------------------------------------------------------------------- */
302 /* Performs "relaxed" canonicalization of a header. */
305 pdkim_relax_header(const uschar * header, BOOL append_crlf)
307 BOOL past_field_name = FALSE;
308 BOOL seen_wsp = FALSE;
310 uschar * relaxed = store_get(Ustrlen(header)+3);
311 uschar * q = relaxed;
313 for (p = header; *p; p++)
317 if (c == '\r' || c == '\n') /* Ignore CR & LF */
319 if (c == '\t' || c == ' ')
323 c = ' '; /* Turns WSP into SP */
327 if (!past_field_name && c == ':')
329 if (seen_wsp) q--; /* This removes WSP immediately before the colon */
330 seen_wsp = TRUE; /* This removes WSP immediately after the colon */
331 past_field_name = TRUE;
336 /* Lowercase header name */
337 if (!past_field_name) c = tolower(c);
341 if (q > relaxed && q[-1] == ' ') q--; /* Squash eventual trailing SP */
343 if (append_crlf) { *q++ = '\r'; *q++ = '\n'; }
349 /* -------------------------------------------------------------------------- */
350 #define PDKIM_QP_ERROR_DECODE -1
352 static const uschar *
353 pdkim_decode_qp_char(const uschar *qp_p, int *c)
355 const uschar *initial_pos = qp_p;
357 /* Advance one char */
360 /* Check for two hex digits and decode them */
361 if (isxdigit(*qp_p) && isxdigit(qp_p[1]))
363 /* Do hex conversion */
364 *c = (isdigit(*qp_p) ? *qp_p - '0' : toupper(*qp_p) - 'A' + 10) << 4;
365 *c |= isdigit(qp_p[1]) ? qp_p[1] - '0' : toupper(qp_p[1]) - 'A' + 10;
369 /* Illegal char here */
370 *c = PDKIM_QP_ERROR_DECODE;
375 /* -------------------------------------------------------------------------- */
378 pdkim_decode_qp(const uschar * str)
382 const uschar * p = str;
383 uschar * n = store_get(Ustrlen(str)+1);
391 p = pdkim_decode_qp_char(p, &nchar);
407 /* -------------------------------------------------------------------------- */
410 pdkim_decode_base64(const uschar * str, blob * b)
413 dlen = b64decode(str, &b->data);
414 if (dlen < 0) b->data = NULL;
419 pdkim_encode_base64(blob * b)
421 return b64encode(b->data, b->len);
425 /* -------------------------------------------------------------------------- */
426 #define PDKIM_HDR_LIMBO 0
427 #define PDKIM_HDR_TAG 1
428 #define PDKIM_HDR_VALUE 2
430 static pdkim_signature *
431 pdkim_parse_sig_header(pdkim_ctx * ctx, uschar * raw_hdr)
433 pdkim_signature * sig;
435 uschar * cur_tag = NULL; int ts = 0, tl = 0;
436 uschar * cur_val = NULL; int vs = 0, vl = 0;
437 BOOL past_hname = FALSE;
438 BOOL in_b_val = FALSE;
439 int where = PDKIM_HDR_LIMBO;
442 sig = store_get(sizeof(pdkim_signature));
443 memset(sig, 0, sizeof(pdkim_signature));
444 sig->bodylength = -1;
446 /* Set so invalid/missing data error display is accurate */
451 q = sig->rawsig_no_b_val = store_get(Ustrlen(raw_hdr)+1);
453 for (p = raw_hdr; ; p++)
458 if (c == '\r' || c == '\n')
461 /* Fast-forward through header name */
464 if (c == ':') past_hname = TRUE;
468 if (where == PDKIM_HDR_LIMBO)
470 /* In limbo, just wait for a tag-char to appear */
471 if (!(c >= 'a' && c <= 'z'))
474 where = PDKIM_HDR_TAG;
477 if (where == PDKIM_HDR_TAG)
479 if (c >= 'a' && c <= 'z')
480 cur_tag = string_catn(cur_tag, &ts, &tl, p, 1);
485 if (Ustrcmp(cur_tag, "b") == 0)
490 where = PDKIM_HDR_VALUE;
495 if (where == PDKIM_HDR_VALUE)
497 if (c == '\r' || c == '\n' || c == ' ' || c == '\t')
500 if (c == ';' || c == '\0')
505 pdkim_strtrim(cur_val);
507 DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag, cur_val);
512 pdkim_decode_base64(cur_val,
513 cur_tag[1] == 'h' ? &sig->bodyhash : &sig->sighash);
516 /* We only support version 1, and that is currently the
517 only version there is. */
519 Ustrcmp(cur_val, PDKIM_SIGNATURE_VERSION) == 0 ? 1 : -1;
523 uschar * s = Ustrchr(cur_val, '-');
525 for(i = 0; i < nelem(pdkim_keytypes); i++)
526 if (Ustrncmp(cur_val, pdkim_keytypes[i], s - cur_val) == 0)
527 { sig->keytype = i; break; }
528 for (++s, i = 0; i < nelem(pdkim_hashes); i++)
529 if (Ustrcmp(s, pdkim_hashes[i].dkim_hashname) == 0)
530 { sig->hashtype = i; break; }
535 for (i = 0; pdkim_combined_canons[i].str; i++)
536 if (Ustrcmp(cur_val, pdkim_combined_canons[i].str) == 0)
538 sig->canon_headers = pdkim_combined_canons[i].canon_headers;
539 sig->canon_body = pdkim_combined_canons[i].canon_body;
544 for (i = 0; pdkim_querymethods[i]; i++)
545 if (Ustrcmp(cur_val, pdkim_querymethods[i]) == 0)
547 sig->querymethod = i;
552 sig->selector = string_copy(cur_val); break;
554 sig->domain = string_copy(cur_val); break;
556 sig->identity = pdkim_decode_qp(cur_val); break;
558 sig->created = strtoul(CS cur_val, NULL, 10); break;
560 sig->expires = strtoul(CS cur_val, NULL, 10); break;
562 sig->bodylength = strtol(CS cur_val, NULL, 10); break;
564 sig->headernames = string_copy(cur_val); break;
566 sig->copiedheaders = pdkim_decode_qp(cur_val); break;
568 DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
575 where = PDKIM_HDR_LIMBO;
578 cur_val = string_catn(cur_val, &vs, &vl, p, 1);
590 /* Chomp raw header. The final newline must not be added to the signature. */
591 while (--q > sig->rawsig_no_b_val && (*q == '\r' || *q == '\n'))
597 "PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
598 pdkim_quoteprint(US sig->rawsig_no_b_val, Ustrlen(sig->rawsig_no_b_val));
600 "PDKIM >> Sig size: %4u bits\n", (unsigned) sig->sighash.len*8);
602 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
605 /*XXX hash method: extend for sha512 */
606 if (!exim_sha_init(&sig->body_hash_ctx,
607 pdkim_hashes[sig->hashtype].exim_hashmethod))
610 debug_printf("PDKIM: hash init error, possibly nonhandled hashtype\n");
617 /* -------------------------------------------------------------------------- */
619 static pdkim_pubkey *
620 pdkim_parse_pubkey_record(pdkim_ctx *ctx, const uschar *raw_record)
626 pub = store_get(sizeof(pdkim_pubkey));
627 memset(pub, 0, sizeof(pdkim_pubkey));
629 while ((ele = string_nextinlist(&raw_record, &sep, NULL, 0)))
633 if ((val = Ustrchr(ele, '=')))
635 int taglen = val++ - ele;
637 DEBUG(D_acl) debug_printf(" %.*s=%s\n", taglen, ele, val);
640 case 'v': pub->version = val; break;
641 case 'h': pub->hashes = val; break;
643 case 'g': pub->granularity = val; break;
644 case 'n': pub->notes = pdkim_decode_qp(val); break;
645 case 'p': pdkim_decode_base64(val, &pub->key); break;
646 case 's': pub->srvtype = val; break;
647 case 't': if (Ustrchr(val, 'y')) pub->testing = 1;
648 if (Ustrchr(val, 's')) pub->no_subdomaining = 1;
650 default: DEBUG(D_acl) debug_printf(" Unknown tag encountered\n"); break;
655 /* Set fallback defaults */
656 if (!pub->version ) pub->version = string_copy(PDKIM_PUB_RECORD_VERSION);
657 else if (Ustrcmp(pub->version, PDKIM_PUB_RECORD_VERSION) != 0)
659 DEBUG(D_acl) debug_printf(" Bad v= field\n");
663 if (!pub->granularity) pub->granularity = US"*";
665 if (!pub->keytype ) pub->keytype = US"rsa";
667 if (!pub->srvtype ) pub->srvtype = US"*";
673 DEBUG(D_acl) debug_printf(" Missing p= field\n");
678 /* -------------------------------------------------------------------------- */
680 /* Update the bodyhash for one sig, with some additional data.
681 If we have to relax the data for this sig, return our copy of it. */
683 /*XXX Currently we calculate a hash for each sig. But it is possible
684 that multi-signing will be wanted using different signing algos
685 (rsa, ec) using the same hash and canonicalization. Consider in future
686 hanging the hash+cacnon from the ctx and only referencing from the sig,
687 so that it can be calculated only once - being over the body this
688 caould be meagbytes, hence expensive. */
691 pdkim_update_sig_bodyhash(pdkim_signature * sig, blob * orig_data, blob * relaxed_data)
693 blob * canon_data = orig_data;
694 /* Defaults to simple canon (no further treatment necessary) */
696 if (sig->canon_body == PDKIM_CANON_RELAXED)
698 /* Relax the line if not done already */
701 BOOL seen_wsp = FALSE;
705 /* We want to be able to free this else we allocate
706 for the entire message which could be many MB. Since
707 we don't know what allocations the SHA routines might
708 do, not safe to use store_get()/store_reset(). */
710 relaxed_data = store_malloc(sizeof(blob) + orig_data->len+1);
711 relaxed_data->data = US (relaxed_data+1);
713 for (p = orig_data->data; *p; p++)
718 if (q > 0 && relaxed_data->data[q-1] == ' ')
721 else if (c == '\t' || c == ' ')
723 c = ' '; /* Turns WSP into SP */
730 relaxed_data->data[q++] = c;
732 relaxed_data->data[q] = '\0';
733 relaxed_data->len = q;
735 canon_data = relaxed_data;
738 /* Make sure we don't exceed the to-be-signed body length */
739 if ( sig->bodylength >= 0
740 && sig->signed_body_bytes + (unsigned long)canon_data->len > sig->bodylength
742 canon_data->len = sig->bodylength - sig->signed_body_bytes;
744 if (canon_data->len > 0)
746 exim_sha_update(&sig->body_hash_ctx, CUS canon_data->data, canon_data->len);
747 sig->signed_body_bytes += canon_data->len;
748 DEBUG(D_acl) pdkim_quoteprint(canon_data->data, canon_data->len);
755 /* -------------------------------------------------------------------------- */
758 pdkim_finish_bodyhash(pdkim_ctx * ctx)
760 pdkim_signature * sig;
762 /* Traverse all signatures */
763 for (sig = ctx->sig; sig; sig = sig->next)
764 { /* Finish hashes */
767 exim_sha_finish(&sig->body_hash_ctx, &bh);
771 debug_printf("PDKIM [%s] Body bytes hashed: %lu\n"
772 "PDKIM [%s] Body %s computed: ",
773 sig->domain, sig->signed_body_bytes,
774 sig->domain, pdkim_hashes[sig->hashtype].dkim_hashname);
775 pdkim_hexprint(CUS bh.data, bh.len);
778 /* SIGNING -------------------------------------------------------------- */
779 if (ctx->flags & PDKIM_MODE_SIGN)
783 /* If bodylength limit is set, and we have received less bytes
784 than the requested amount, effectively remove the limit tag. */
785 if (sig->signed_body_bytes < sig->bodylength)
786 sig->bodylength = -1;
790 /* VERIFICATION --------------------------------------------------------- */
791 /* Be careful that the header sig included a bodyash */
793 if (sig->bodyhash.data && memcmp(bh.data, sig->bodyhash.data, bh.len) == 0)
795 DEBUG(D_acl) debug_printf("PDKIM [%s] Body hash verified OK\n", sig->domain);
801 debug_printf("PDKIM [%s] Body hash signature from headers: ", sig->domain);
802 pdkim_hexprint(sig->bodyhash.data, sig->bodyhash.len);
803 debug_printf("PDKIM [%s] Body hash did NOT verify\n", sig->domain);
805 sig->verify_status = PDKIM_VERIFY_FAIL;
806 sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
814 pdkim_body_complete(pdkim_ctx * ctx)
816 pdkim_signature * sig;
818 /* In simple body mode, if any empty lines were buffered,
819 replace with one. rfc 4871 3.4.3 */
820 /*XXX checking the signed-body-bytes is a gross hack; I think
821 it indicates that all linebreaks should be buffered, including
822 the one terminating a text line */
824 for (sig = ctx->sig; sig; sig = sig->next)
825 if ( sig->canon_body == PDKIM_CANON_SIMPLE
826 && sig->signed_body_bytes == 0
827 && sig->num_buffered_blanklines > 0
829 (void) pdkim_update_sig_bodyhash(sig, &lineending, NULL);
831 ctx->flags |= PDKIM_SEEN_EOD;
832 ctx->linebuf_offset = 0;
837 /* -------------------------------------------------------------------------- */
838 /* Call from pdkim_feed below for processing complete body lines */
841 pdkim_bodyline_complete(pdkim_ctx * ctx)
843 blob line = {.data = ctx->linebuf, .len = ctx->linebuf_offset};
844 pdkim_signature * sig;
848 /* Ignore extra data if we've seen the end-of-data marker */
849 if (ctx->flags & PDKIM_SEEN_EOD) goto all_skip;
851 /* We've always got one extra byte to stuff a zero ... */
852 ctx->linebuf[line.len] = '\0';
854 /* Terminate on EOD marker */
855 if (ctx->flags & PDKIM_DOT_TERM)
857 if (memcmp(line.data, ".\r\n", 3) == 0)
858 { pdkim_body_complete(ctx); return; }
861 if (memcmp(line.data, "..", 2) == 0)
862 { line.data++; line.len--; }
865 /* Empty lines need to be buffered until we find a non-empty line */
866 if (memcmp(line.data, "\r\n", 2) == 0)
868 for (sig = ctx->sig; sig; sig = sig->next) sig->num_buffered_blanklines++;
872 /* Process line for each sig separately */
873 for (sig = ctx->sig; sig; sig = sig->next)
875 if (sig->canon_body == PDKIM_CANON_RELAXED)
877 /* Lines with just spaces need to be buffered too */
878 uschar * cp = line.data;
883 if (c == '\r' && cp[1] == '\n') break;
884 if (c != ' ' && c != '\t') goto sig_process;
888 sig->num_buffered_blanklines++;
893 /* At this point, we have a non-empty line, so release the buffered ones. */
895 while (sig->num_buffered_blanklines)
897 rnl = pdkim_update_sig_bodyhash(sig, &lineending, rnl);
898 sig->num_buffered_blanklines--;
901 rline = pdkim_update_sig_bodyhash(sig, &line, rline);
905 if (rnl) store_free(rnl);
906 if (rline) store_free(rline);
910 ctx->linebuf_offset = 0;
915 /* -------------------------------------------------------------------------- */
916 /* Callback from pdkim_feed below for processing complete headers */
917 #define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
920 pdkim_header_complete(pdkim_ctx * ctx)
922 pdkim_signature * sig, * last_sig;
924 /* Special case: The last header can have an extra \r appended */
925 if ( (ctx->cur_header_len > 1) &&
926 (ctx->cur_header[(ctx->cur_header_len)-1] == '\r') )
927 --ctx->cur_header_len;
928 ctx->cur_header[ctx->cur_header_len] = '\0';
930 if (++ctx->num_headers > PDKIM_MAX_HEADERS) goto BAIL;
932 /* SIGNING -------------------------------------------------------------- */
933 if (ctx->flags & PDKIM_MODE_SIGN)
934 for (sig = ctx->sig; sig; sig = sig->next) /* Traverse all signatures */
936 /* Add header to the signed headers list (in reverse order) */
937 sig->headers = pdkim_prepend_stringlist(sig->headers,
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, ctx->cur_header_len);
951 if (strncasecmp(CCS ctx->cur_header,
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);
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);
978 ctx->cur_header[ctx->cur_header_len = 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, &ctx->cur_header_size,
1031 &ctx->cur_header_len, 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_len < PDKIM_MAX_HEADER_LEN)
1055 ctx->cur_header = string_catn(ctx->cur_header, &ctx->cur_header_size,
1056 &ctx->cur_header_len, CUS &data[p], 1);
1064 /* Extend a grwong header with a continuation-linebreak */
1066 pdkim_hdr_cont(uschar * str, int * size, int * ptr, int * col)
1069 return string_catn(str, size, ptr, US"\r\n\t", 3);
1075 * RFC 5322 specifies that header line length SHOULD be no more than 78
1079 * returns uschar * (not nul-terminated)
1081 * col: this int holds and receives column number (octets since last '\n')
1082 * str: partial string to append to
1083 * size: current buffer size for str
1084 * ptr: current tail-pointer for str
1085 * pad: padding, split line or space after before or after eg: ";"
1086 * intro: - must join to payload eg "h=", usually the tag name
1087 * payload: eg base64 data - long data can be split arbitrarily.
1089 * this code doesn't fold the header in some of the places that RFC4871
1090 * allows: As per RFC5322(2.2.3) it only folds before or after tag-value
1091 * pairs and inside long values. it also always spaces or breaks after the
1094 * no guarantees are made for output given out-of range input. like tag
1095 * names longer than 78, or bogus col. Input is assumed to be free of line breaks.
1099 pdkim_headcat(int * col, uschar * str, int * size, int * ptr,
1100 const uschar * pad, const uschar * intro, const uschar * payload)
1108 str = pdkim_hdr_cont(str, size, ptr, col);
1109 str = string_catn(str, size, ptr, pad, l);
1113 l = (pad?1:0) + (intro?Ustrlen(intro):0);
1116 { /*can't fit intro - start a new line to make room.*/
1117 str = pdkim_hdr_cont(str, size, ptr, col);
1118 l = intro?Ustrlen(intro):0;
1121 l += payload ? Ustrlen(payload):0 ;
1124 { /* this fragment will not fit on a single line */
1127 str = string_catn(str, size, ptr, US" ", 1);
1129 pad = NULL; /* only want this once */
1135 size_t sl = Ustrlen(intro);
1137 str = string_catn(str, size, ptr, intro, sl);
1140 intro = NULL; /* only want this once */
1145 size_t sl = Ustrlen(payload);
1146 size_t chomp = *col+sl < 77 ? sl : 78-*col;
1148 str = string_catn(str, size, ptr, payload, chomp);
1154 /* the while precondition tells us it didn't fit. */
1155 str = pdkim_hdr_cont(str, size, ptr, col);
1160 str = pdkim_hdr_cont(str, size, ptr, col);
1166 str = string_catn(str, size, ptr, US" ", 1);
1173 size_t sl = Ustrlen(intro);
1175 str = string_catn(str, size, ptr, intro, sl);
1183 size_t sl = Ustrlen(payload);
1185 str = string_catn(str, size, ptr, payload, sl);
1193 /* -------------------------------------------------------------------------- */
1196 pdkim_create_header(pdkim_signature * sig, BOOL final)
1201 uschar * hdr; int hdr_size = 0, hdr_len = 0;
1202 uschar * canon_all; int can_size = 0, can_len = 0;
1204 canon_all = string_cat (NULL, &can_size, &can_len,
1205 pdkim_canons[sig->canon_headers]);
1206 canon_all = string_catn(canon_all, &can_size, &can_len, US"/", 1);
1207 canon_all = string_cat (canon_all, &can_size, &can_len,
1208 pdkim_canons[sig->canon_body]);
1209 canon_all[can_len] = '\0';
1211 hdr = string_cat(NULL, &hdr_size, &hdr_len,
1212 US"DKIM-Signature: v="PDKIM_SIGNATURE_VERSION);
1215 /* Required and static bits */
1216 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"a=",
1217 dkim_sig_to_a_tag(sig));
1218 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"q=",
1219 pdkim_querymethods[sig->querymethod]);
1220 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"c=",
1222 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"d=",
1224 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"s=",
1227 /* list of header names can be split between items. */
1229 uschar * n = string_copy(sig->headernames);
1230 uschar * i = US"h=";
1235 uschar * c = Ustrchr(n, ':');
1240 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, NULL, NULL, US":");
1242 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, s, i, n);
1253 base64_bh = pdkim_encode_base64(&sig->bodyhash);
1254 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"bh=", base64_bh);
1258 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"i=", sig->identity);
1260 if (sig->created > 0)
1264 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->created);
1265 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"t=", minibuf);
1268 if (sig->expires > 0)
1272 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->expires);
1273 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"x=", minibuf);
1276 if (sig->bodylength >= 0)
1280 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->bodylength);
1281 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"l=", minibuf);
1284 /* Preliminary or final version? */
1287 base64_b = pdkim_encode_base64(&sig->sighash);
1288 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"b=", base64_b);
1290 /* add trailing semicolon: I'm not sure if this is actually needed */
1291 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, NULL, US";", US"");
1295 /* To satisfy the rule "all surrounding whitespace [...] deleted"
1296 ( RFC 6376 section 3.7 ) we ensure there is no whitespace here. Otherwise
1297 the headcat routine could insert a linebreak which the relaxer would reduce
1298 to a single space preceding the terminating semicolon, resulting in an
1299 incorrect header-hash. */
1300 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"b=;", US"");
1303 hdr[hdr_len] = '\0';
1308 /* -------------------------------------------------------------------------- */
1310 static pdkim_pubkey *
1311 pdkim_key_from_dns(pdkim_ctx * ctx, pdkim_signature * sig, ev_ctx * vctx,
1312 const uschar ** errstr)
1314 uschar * dns_txt_name, * dns_txt_reply;
1317 /* Fetch public key for signing domain, from DNS */
1319 dns_txt_name = string_sprintf("%s._domainkey.%s.", sig->selector, sig->domain);
1321 dns_txt_reply = store_get(PDKIM_DNS_TXT_MAX_RECLEN);
1322 memset(dns_txt_reply, 0, PDKIM_DNS_TXT_MAX_RECLEN);
1324 if ( ctx->dns_txt_callback(CS dns_txt_name, CS dns_txt_reply) != PDKIM_OK
1325 || dns_txt_reply[0] == '\0'
1328 sig->verify_status = PDKIM_VERIFY_INVALID;
1329 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE;
1336 "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
1340 pdkim_quoteprint(CUS dns_txt_reply, Ustrlen(dns_txt_reply));
1343 if ( !(p = pdkim_parse_pubkey_record(ctx, CUS dns_txt_reply))
1344 || (Ustrcmp(p->srvtype, "*") != 0 && Ustrcmp(p->srvtype, "email") != 0)
1347 sig->verify_status = PDKIM_VERIFY_INVALID;
1348 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD;
1353 debug_printf(" Invalid public key service type '%s'\n", p->srvtype);
1355 debug_printf(" Error while parsing public key record\n");
1357 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1362 DEBUG(D_acl) debug_printf(
1363 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1365 /* Import public key */
1366 if ((*errstr = exim_dkim_verify_init(&p->key, vctx)))
1368 DEBUG(D_acl) debug_printf("verify_init: %s\n", *errstr);
1369 sig->verify_status = PDKIM_VERIFY_INVALID;
1370 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_IMPORT;
1378 /* -------------------------------------------------------------------------- */
1381 pdkim_feed_finish(pdkim_ctx * ctx, pdkim_signature ** return_signatures,
1382 const uschar ** err)
1384 pdkim_signature * sig;
1386 /* Check if we must still flush a (partial) header. If that is the
1387 case, the message has no body, and we must compute a body hash
1388 out of '<CR><LF>' */
1389 if (ctx->cur_header && ctx->cur_header_len)
1394 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1397 for (sig = ctx->sig; sig; sig = sig->next)
1398 rnl = pdkim_update_sig_bodyhash(sig, &lineending, rnl);
1399 if (rnl) store_free(rnl);
1402 DEBUG(D_acl) debug_printf(
1403 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1405 /* Build (and/or evaluate) body hash */
1406 pdkim_finish_bodyhash(ctx);
1408 for (sig = ctx->sig; sig; sig = sig->next)
1411 uschar * sig_hdr = US"";
1414 int hdata_alloc = 0;
1419 if (!exim_sha_init(&hhash_ctx, pdkim_hashes[sig->hashtype].exim_hashmethod))
1422 debug_printf("PDKIM: hash setup error, possibly nonhandled hashtype\n");
1426 if (ctx->flags & PDKIM_MODE_SIGN)
1427 DEBUG(D_acl) debug_printf(
1428 "PDKIM >> Headers to be signed: >>>>>>>>>>>>\n"
1432 DEBUG(D_acl) debug_printf(
1433 "PDKIM >> Header data for hash, canonicalized, in sequence >>>>>>>>>>>>\n");
1436 /* SIGNING ---------------------------------------------------------------- */
1437 /* When signing, walk through our header list and add them to the hash. As we
1438 go, construct a list of the header's names to use for the h= parameter.
1439 Then append to that list any remaining header names for which there was no
1442 if (ctx->flags & PDKIM_MODE_SIGN)
1445 pdkim_stringlist *p;
1450 sig->headernames = NULL; /* Collected signed header names */
1452 for (p = sig->headers; p; p = p->next)
1454 uschar * rh = p->value;
1456 if (header_name_match(rh, sig->sign_headers) == PDKIM_OK)
1458 /* Collect header names (Note: colon presence is guaranteed here) */
1459 sig->headernames = string_append_listele_n(sig->headernames, &hs, &hl,
1460 ':', rh, Ustrchr(rh, ':') - rh);
1462 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1463 rh = pdkim_relax_header(rh, TRUE); /* cook header for relaxed canon */
1465 /* Feed header to the hash algorithm */
1466 exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
1468 /* Remember headers block for signing (when the library cannot do incremental) */
1469 (void) exim_dkim_data_append(&hdata, &hdata_alloc, rh);
1471 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1475 /* Any headers we wanted to sign but were not present must also be listed */
1476 l = sig->sign_headers;
1477 while((s = string_nextinlist(&l, &sep, NULL, 0)))
1479 sig->headernames = string_append_listele(sig->headernames, &hs, &hl, ':', s);
1480 sig->headernames[hl] = '\0';
1482 /* Create signature header with b= omitted */
1483 sig_hdr = pdkim_create_header(sig, FALSE);
1486 /* VERIFICATION ----------------------------------------------------------- */
1487 /* When verifying, walk through the header name list in the h= parameter and
1488 add the headers to the hash in that order. */
1491 uschar * p = sig->headernames;
1493 pdkim_stringlist * hdrs;
1498 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1504 if ((q = Ustrchr(p, ':')))
1507 /*XXX walk the list of headers in same order as received. */
1508 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1510 && strncasecmp(CCS hdrs->value, CCS p, Ustrlen(p)) == 0
1511 && (hdrs->value)[Ustrlen(p)] == ':'
1514 /* cook header for relaxed canon, or just copy it for simple */
1516 uschar * rh = sig->canon_headers == PDKIM_CANON_RELAXED
1517 ? pdkim_relax_header(hdrs->value, TRUE)
1518 : string_copy(CUS hdrs->value);
1520 /* Feed header to the hash algorithm */
1521 exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
1523 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1532 sig_hdr = string_copy(sig->rawsig_no_b_val);
1536 DEBUG(D_acl) debug_printf(
1537 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1542 "PDKIM >> Signed DKIM-Signature header, pre-canonicalized >>>>>>>>>>>>>\n");
1543 pdkim_quoteprint(CUS sig_hdr, Ustrlen(sig_hdr));
1545 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1548 /* Relax header if necessary */
1549 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1550 sig_hdr = pdkim_relax_header(sig_hdr, FALSE);
1555 "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
1556 pdkim_quoteprint(CUS sig_hdr, Ustrlen(sig_hdr));
1558 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1561 /* Finalize header hash */
1562 exim_sha_update(&hhash_ctx, CUS sig_hdr, Ustrlen(sig_hdr));
1563 exim_sha_finish(&hhash_ctx, &hhash);
1567 debug_printf("PDKIM [%s] Header %s computed: ",
1568 sig->domain, pdkim_hashes[sig->hashtype].dkim_hashname);
1569 pdkim_hexprint(hhash.data, hhash.len);
1572 /* Remember headers block for signing (when the signing library cannot do
1574 if (ctx->flags & PDKIM_MODE_SIGN)
1575 (void) exim_dkim_data_append(&hdata, &hdata_alloc, US sig_hdr);
1577 /* SIGNING ---------------------------------------------------------------- */
1578 if (ctx->flags & PDKIM_MODE_SIGN)
1582 /* Import private key, including the keytype */
1583 /*XXX extend for non-RSA algos */
1584 if ((*err = exim_dkim_signing_init(US sig->privkey, &sctx)))
1586 DEBUG(D_acl) debug_printf("signing_init: %s\n", *err);
1587 return PDKIM_ERR_RSA_PRIVKEY;
1590 /* Do signing. With OpenSSL we are signing the hash of headers just
1591 calculated, with GnuTLS we have to sign an entire block of headers
1592 (due to available interfaces) and it recalculates the hash internally. */
1594 #if defined(SIGN_OPENSSL) || defined(SIGN_GCRYPT)
1598 /*XXX extend for non-RSA algos */
1599 if ((*err = exim_dkim_sign(&sctx,
1600 pdkim_hashes[sig->hashtype].exim_hashmethod,
1601 &hdata, &sig->sighash)))
1603 DEBUG(D_acl) debug_printf("signing: %s\n", *err);
1604 return PDKIM_ERR_RSA_SIGNING;
1609 debug_printf( "PDKIM [%s] b computed: ", sig->domain);
1610 pdkim_hexprint(sig->sighash.data, sig->sighash.len);
1613 sig->signature_header = pdkim_create_header(sig, TRUE);
1616 /* VERIFICATION ----------------------------------------------------------- */
1621 /* Make sure we have all required signature tags */
1622 if (!( sig->domain && *sig->domain
1623 && sig->selector && *sig->selector
1624 && sig->headernames && *sig->headernames
1625 && sig->bodyhash.data
1626 && sig->sighash.data
1627 && sig->keytype >= 0
1628 && sig->hashtype >= 0
1632 sig->verify_status = PDKIM_VERIFY_INVALID;
1633 sig->verify_ext_status = PDKIM_VERIFY_INVALID_SIGNATURE_ERROR;
1635 DEBUG(D_acl) debug_printf(
1636 " Error in DKIM-Signature header: tags missing or invalid\n"
1637 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1641 /* Make sure sig uses supported DKIM version (only v1) */
1642 if (sig->version != 1)
1644 sig->verify_status = PDKIM_VERIFY_INVALID;
1645 sig->verify_ext_status = PDKIM_VERIFY_INVALID_DKIM_VERSION;
1647 DEBUG(D_acl) debug_printf(
1648 " Error in DKIM-Signature header: unsupported DKIM version\n"
1649 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1655 debug_printf( "PDKIM [%s] b from mail: ", sig->domain);
1656 pdkim_hexprint(sig->sighash.data, sig->sighash.len);
1659 if (!(sig->pubkey = pdkim_key_from_dns(ctx, sig, &vctx, err)))
1662 /* If the pubkey limits to a list of specific hashes, ignore sigs that
1663 do not have the hash part of the sig algorithm matching */
1665 if (sig->pubkey->hashes)
1667 const uschar * list = sig->pubkey->hashes, * ele;
1669 while ((ele = string_nextinlist(&list, &sep, NULL, 0)))
1670 if (Ustrcmp(ele, pdkim_hashes[sig->hashtype].dkim_hashname) == 0) break;
1673 DEBUG(D_acl) debug_printf("pubkey h=%s vs. sig a=%s_%s\n",
1674 sig->pubkey->hashes,
1675 pdkim_keytypes[sig->keytype],
1676 pdkim_hashes[sig->hashtype].dkim_hashname);
1677 sig->verify_status = PDKIM_VERIFY_FAIL;
1678 sig->verify_ext_status = PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH;
1683 /* Check the signature */
1684 /*XXX needs extension for non-RSA */
1685 if ((*err = exim_dkim_verify(&vctx,
1686 pdkim_hashes[sig->hashtype].exim_hashmethod,
1687 &hhash, &sig->sighash)))
1689 DEBUG(D_acl) debug_printf("headers verify: %s\n", *err);
1690 sig->verify_status = PDKIM_VERIFY_FAIL;
1691 sig->verify_ext_status = PDKIM_VERIFY_FAIL_MESSAGE;
1696 /* We have a winner! (if bodyhash was correct earlier) */
1697 if (sig->verify_status == PDKIM_VERIFY_NONE)
1698 sig->verify_status = PDKIM_VERIFY_PASS;
1704 debug_printf("PDKIM [%s] signature status: %s",
1705 sig->domain, pdkim_verify_status_str(sig->verify_status));
1706 if (sig->verify_ext_status > 0)
1707 debug_printf(" (%s)\n",
1708 pdkim_verify_ext_status_str(sig->verify_ext_status));
1715 /* If requested, set return pointer to signature(s) */
1716 if (return_signatures)
1717 *return_signatures = ctx->sig;
1723 /* -------------------------------------------------------------------------- */
1725 DLLEXPORT pdkim_ctx *
1726 pdkim_init_verify(int(*dns_txt_callback)(char *, char *), BOOL dot_stuffing)
1730 ctx = store_get(sizeof(pdkim_ctx));
1731 memset(ctx, 0, sizeof(pdkim_ctx));
1733 if (dot_stuffing) ctx->flags = PDKIM_DOT_TERM;
1734 ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN);
1735 ctx->dns_txt_callback = dns_txt_callback;
1741 /* -------------------------------------------------------------------------- */
1743 /*XXX ? needs extension to cover non-RSA algo? */
1745 DLLEXPORT pdkim_signature *
1746 pdkim_init_sign(pdkim_ctx * ctx,
1747 uschar * domain, uschar * selector, uschar * privkey,
1748 uschar * hashname, const uschar ** errstr)
1751 pdkim_signature * sig;
1753 if (!domain || !selector || !privkey)
1756 /* Allocate & init one signature struct */
1758 sig = store_get(sizeof(pdkim_signature));
1759 memset(sig, 0, sizeof(pdkim_signature));
1761 sig->bodylength = -1;
1763 sig->domain = string_copy(US domain);
1764 sig->selector = string_copy(US selector);
1765 sig->privkey = string_copy(US privkey);
1766 /*XXX no keytype yet; comes from privkey */
1768 for (hashtype = 0; hashtype < nelem(pdkim_hashes); hashtype++)
1769 if (Ustrcmp(hashname, pdkim_hashes[hashtype].dkim_hashname) == 0)
1770 { sig->hashtype = hashtype; break; }
1771 if (hashtype >= nelem(pdkim_hashes))
1774 debug_printf("PDKIM: unrecognised hashname '%s'\n", hashname);
1778 if (!exim_sha_init(&sig->body_hash_ctx, pdkim_hashes[hashtype].exim_hashmethod))
1781 debug_printf("PDKIM: hash setup error, possibly nonhandled hashtype\n");
1787 pdkim_signature s = *sig;
1790 debug_printf("PDKIM (checking verify key)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1791 if (!pdkim_key_from_dns(ctx, &s, &vctx, errstr))
1792 debug_printf("WARNING: bad dkim key in dns\n");
1793 debug_printf("PDKIM (finished checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1799 /* -------------------------------------------------------------------------- */
1802 pdkim_set_optional(pdkim_signature * sig,
1803 char * sign_headers,
1808 unsigned long created,
1809 unsigned long expires)
1812 sig->identity = string_copy(US identity);
1814 sig->sign_headers = string_copy(sign_headers
1815 ? US sign_headers : US PDKIM_DEFAULT_SIGN_HEADERS);
1817 sig->canon_headers = canon_headers;
1818 sig->canon_body = canon_body;
1819 sig->bodylength = bodylength;
1820 sig->created = created;
1821 sig->expires = expires;
1829 pdkim_init_context(pdkim_ctx * ctx, BOOL dot_stuffed,
1830 int(*dns_txt_callback)(char *, char *))
1832 memset(ctx, 0, sizeof(pdkim_ctx));
1833 ctx->flags = dot_stuffed ? PDKIM_MODE_SIGN | PDKIM_DOT_TERM : PDKIM_MODE_SIGN;
1834 ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN);
1835 DEBUG(D_acl) ctx->dns_txt_callback = dns_txt_callback;
1847 #endif /*DISABLE_DKIM*/