DKIM: fix $dkim_key_length in verify
[exim.git] / src / src / pdkim / pdkim.c
... / ...
CommitLineData
1/*
2 * PDKIM - a RFC4871 (DKIM) implementation
3 *
4 * Copyright (C) 2009 - 2016 Tom Kistner <tom@duncanthrax.net>
5 * Copyright (C) 2016 - 2018 Jeremy Harris <jgh@exim.org>
6 *
7 * http://duncanthrax.net/pdkim/
8 *
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.
13 *
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.
18 *
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.
22 */
23
24#include "../exim.h"
25
26
27#ifndef DISABLE_DKIM /* entire file */
28
29#ifdef DISABLE_TLS
30# error Must not DISABLE_TLS, for DKIM
31#endif
32
33#include "crypt_ver.h"
34
35#ifdef SIGN_OPENSSL
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>
42#endif
43
44#include "pdkim.h"
45#include "signing.h"
46
47#define PDKIM_SIGNATURE_VERSION "1"
48#define PDKIM_PUB_RECORD_VERSION US "DKIM1"
49
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
55/* -------------------------------------------------------------------------- */
56struct pdkim_stringlist {
57 uschar * value;
58 int tag;
59 void * next;
60};
61
62/* -------------------------------------------------------------------------- */
63/* A bunch of list constants */
64const uschar * pdkim_querymethods[] = {
65 US"dns/txt",
66 NULL
67};
68const uschar * pdkim_canons[] = {
69 US"simple",
70 US"relaxed",
71 NULL
72};
73
74const pdkim_hashtype pdkim_hashes[] = {
75 { US"sha1", HASH_SHA1 },
76 { US"sha256", HASH_SHA2_256 },
77 { US"sha512", HASH_SHA2_512 }
78};
79
80const uschar * pdkim_keytypes[] = {
81 [KEYTYPE_RSA] = US"rsa",
82#ifdef SIGN_HAVE_ED25519
83 [KEYTYPE_ED25519] = US"ed25519", /* Works for 3.6.0 GnuTLS, OpenSSL 1.1.1 */
84#endif
85
86#ifdef notyet_EC_dkim_extensions /* https://tools.ietf.org/html/draft-srose-dkim-ecc-00 */
87 US"eccp256",
88 US"eccp348",
89 US"ed448",
90#endif
91};
92
93typedef struct pdkim_combined_canon_entry {
94 const uschar * str;
95 int canon_headers;
96 int canon_body;
97} pdkim_combined_canon_entry;
98
99pdkim_combined_canon_entry pdkim_combined_canons[] = {
100 { US"simple/simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
101 { US"simple/relaxed", PDKIM_CANON_SIMPLE, PDKIM_CANON_RELAXED },
102 { US"relaxed/simple", PDKIM_CANON_RELAXED, PDKIM_CANON_SIMPLE },
103 { US"relaxed/relaxed", PDKIM_CANON_RELAXED, PDKIM_CANON_RELAXED },
104 { US"simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
105 { US"relaxed", PDKIM_CANON_RELAXED, PDKIM_CANON_SIMPLE },
106 { NULL, 0, 0 }
107};
108
109
110static blob lineending = {.data = US"\r\n", .len = 2};
111
112/* -------------------------------------------------------------------------- */
113uschar *
114dkim_sig_to_a_tag(const pdkim_signature * sig)
115{
116if ( sig->keytype < 0 || sig->keytype > nelem(pdkim_keytypes)
117 || sig->hashtype < 0 || sig->hashtype > nelem(pdkim_hashes))
118 return US"err";
119return string_sprintf("%s-%s",
120 pdkim_keytypes[sig->keytype], pdkim_hashes[sig->hashtype].dkim_hashname);
121}
122
123
124static int
125pdkim_keyname_to_keytype(const uschar * s)
126{
127for (int i = 0; i < nelem(pdkim_keytypes); i++)
128 if (Ustrcmp(s, pdkim_keytypes[i]) == 0) return i;
129return -1;
130}
131
132int
133pdkim_hashname_to_hashtype(const uschar * s, unsigned len)
134{
135if (!len) len = Ustrlen(s);
136for (int i = 0; i < nelem(pdkim_hashes); i++)
137 if (Ustrncmp(s, pdkim_hashes[i].dkim_hashname, len) == 0)
138 return i;
139return -1;
140}
141
142void
143pdkim_cstring_to_canons(const uschar * s, unsigned len,
144 int * canon_head, int * canon_body)
145{
146if (!len) len = Ustrlen(s);
147for (int i = 0; pdkim_combined_canons[i].str; i++)
148 if ( Ustrncmp(s, pdkim_combined_canons[i].str, len) == 0
149 && len == Ustrlen(pdkim_combined_canons[i].str))
150 {
151 *canon_head = pdkim_combined_canons[i].canon_headers;
152 *canon_body = pdkim_combined_canons[i].canon_body;
153 break;
154 }
155}
156
157
158
159const char *
160pdkim_verify_status_str(int status)
161{
162switch(status)
163 {
164 case PDKIM_VERIFY_NONE: return "PDKIM_VERIFY_NONE";
165 case PDKIM_VERIFY_INVALID: return "PDKIM_VERIFY_INVALID";
166 case PDKIM_VERIFY_FAIL: return "PDKIM_VERIFY_FAIL";
167 case PDKIM_VERIFY_PASS: return "PDKIM_VERIFY_PASS";
168 default: return "PDKIM_VERIFY_UNKNOWN";
169 }
170}
171
172const char *
173pdkim_verify_ext_status_str(int ext_status)
174{
175switch(ext_status)
176 {
177 case PDKIM_VERIFY_FAIL_BODY: return "PDKIM_VERIFY_FAIL_BODY";
178 case PDKIM_VERIFY_FAIL_MESSAGE: return "PDKIM_VERIFY_FAIL_MESSAGE";
179 case PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH: return "PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH";
180 case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE: return "PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE";
181 case PDKIM_VERIFY_INVALID_BUFFER_SIZE: return "PDKIM_VERIFY_INVALID_BUFFER_SIZE";
182 case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD: return "PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD";
183 case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT: return "PDKIM_VERIFY_INVALID_PUBKEY_IMPORT";
184 case PDKIM_VERIFY_INVALID_SIGNATURE_ERROR: return "PDKIM_VERIFY_INVALID_SIGNATURE_ERROR";
185 case PDKIM_VERIFY_INVALID_DKIM_VERSION: return "PDKIM_VERIFY_INVALID_DKIM_VERSION";
186 default: return "PDKIM_VERIFY_UNKNOWN";
187 }
188}
189
190const uschar *
191pdkim_errstr(int status)
192{
193switch(status)
194 {
195 case PDKIM_OK: return US"OK";
196 case PDKIM_FAIL: return US"FAIL";
197 case PDKIM_ERR_RSA_PRIVKEY: return US"PRIVKEY";
198 case PDKIM_ERR_RSA_SIGNING: return US"SIGNING";
199 case PDKIM_ERR_LONG_LINE: return US"LONG_LINE";
200 case PDKIM_ERR_BUFFER_TOO_SMALL: return US"BUFFER_TOO_SMALL";
201 case PDKIM_ERR_EXCESS_SIGS: return US"EXCESS_SIGS";
202 case PDKIM_SIGN_PRIVKEY_WRAP: return US"PRIVKEY_WRAP";
203 case PDKIM_SIGN_PRIVKEY_B64D: return US"PRIVKEY_B64D";
204 default: return US"(unknown)";
205 }
206}
207
208
209/* -------------------------------------------------------------------------- */
210/* Print debugging functions */
211void
212pdkim_quoteprint(const uschar *data, int len)
213{
214for (int i = 0; i < len; i++)
215 {
216 const int c = data[i];
217 switch (c)
218 {
219 case ' ' : debug_printf("{SP}"); break;
220 case '\t': debug_printf("{TB}"); break;
221 case '\r': debug_printf("{CR}"); break;
222 case '\n': debug_printf("{LF}"); break;
223 case '{' : debug_printf("{BO}"); break;
224 case '}' : debug_printf("{BC}"); break;
225 default:
226 if ( (c < 32) || (c > 127) )
227 debug_printf("{%02x}", c);
228 else
229 debug_printf("%c", c);
230 break;
231 }
232 }
233debug_printf("\n");
234}
235
236void
237pdkim_hexprint(const uschar *data, int len)
238{
239if (data) for (int i = 0 ; i < len; i++) debug_printf("%02x", data[i]);
240else debug_printf("<NULL>");
241debug_printf("\n");
242}
243
244
245
246static pdkim_stringlist *
247pdkim_prepend_stringlist(pdkim_stringlist * base, const uschar * str)
248{
249pdkim_stringlist * new_entry = store_get(sizeof(pdkim_stringlist), FALSE);
250
251memset(new_entry, 0, sizeof(pdkim_stringlist));
252new_entry->value = string_copy(str);
253if (base) new_entry->next = base;
254return new_entry;
255}
256
257
258
259/* Trim whitespace fore & aft */
260
261static void
262pdkim_strtrim(gstring * str)
263{
264uschar * p = str->s;
265uschar * q;
266
267while (*p == '\t' || *p == ' ') /* dump the leading whitespace */
268 { str->size--; str->ptr--; str->s++; }
269
270while ( str->ptr > 0
271 && ((q = str->s + str->ptr - 1), (*q == '\t' || *q == ' '))
272 )
273 str->ptr--; /* dump trailing whitespace */
274
275(void) string_from_gstring(str);
276}
277
278
279
280/* -------------------------------------------------------------------------- */
281
282DLLEXPORT void
283pdkim_free_ctx(pdkim_ctx *ctx)
284{
285}
286
287
288/* -------------------------------------------------------------------------- */
289/* Matches the name of the passed raw "header" against
290 the passed colon-separated "tick", and invalidates
291 the entry in tick. Entries can be prefixed for multi- or over-signing,
292 in which case do not invalidate.
293
294 Returns OK for a match, or fail-code
295*/
296
297static int
298header_name_match(const uschar * header, uschar * tick)
299{
300const uschar * ticklist = tick;
301int sep = ':';
302BOOL multisign;
303uschar * hname, * p, * ele;
304uschar * hcolon = Ustrchr(header, ':'); /* Get header name */
305
306if (!hcolon)
307 return PDKIM_FAIL; /* This isn't a header */
308
309/* if we had strncmpic() we wouldn't need this copy */
310hname = string_copyn(header, hcolon-header);
311
312while (p = US ticklist, ele = string_nextinlist(&ticklist, &sep, NULL, 0))
313 {
314 switch (*ele)
315 {
316 case '=': case '+': multisign = TRUE; ele++; break;
317 default: multisign = FALSE; break;
318 }
319
320 if (strcmpic(ele, hname) == 0)
321 {
322 if (!multisign)
323 *p = '_'; /* Invalidate this header name instance in tick-off list */
324 return PDKIM_OK;
325 }
326 }
327return PDKIM_FAIL;
328}
329
330
331/* -------------------------------------------------------------------------- */
332/* Performs "relaxed" canonicalization of a header. */
333
334uschar *
335pdkim_relax_header_n(const uschar * header, int len, BOOL append_crlf)
336{
337BOOL past_field_name = FALSE;
338BOOL seen_wsp = FALSE;
339uschar * relaxed = store_get(len+3, TRUE); /* tainted */
340uschar * q = relaxed;
341
342for (const uschar * p = header; p - header < len; p++)
343 {
344 uschar c = *p;
345
346 if (c == '\r' || c == '\n') /* Ignore CR & LF */
347 continue;
348 if (c == '\t' || c == ' ')
349 {
350 if (seen_wsp)
351 continue;
352 c = ' '; /* Turns WSP into SP */
353 seen_wsp = TRUE;
354 }
355 else
356 if (!past_field_name && c == ':')
357 {
358 if (seen_wsp) q--; /* This removes WSP immediately before the colon */
359 seen_wsp = TRUE; /* This removes WSP immediately after the colon */
360 past_field_name = TRUE;
361 }
362 else
363 seen_wsp = FALSE;
364
365 /* Lowercase header name */
366 if (!past_field_name) c = tolower(c);
367 *q++ = c;
368 }
369
370if (q > relaxed && q[-1] == ' ') q--; /* Squash eventual trailing SP */
371
372if (append_crlf) { *q++ = '\r'; *q++ = '\n'; }
373*q = '\0';
374return relaxed;
375}
376
377
378uschar *
379pdkim_relax_header(const uschar * header, BOOL append_crlf)
380{
381return pdkim_relax_header_n(header, Ustrlen(header), append_crlf);
382}
383
384
385/* -------------------------------------------------------------------------- */
386#define PDKIM_QP_ERROR_DECODE -1
387
388static const uschar *
389pdkim_decode_qp_char(const uschar *qp_p, int *c)
390{
391const uschar *initial_pos = qp_p;
392
393/* Advance one char */
394qp_p++;
395
396/* Check for two hex digits and decode them */
397if (isxdigit(*qp_p) && isxdigit(qp_p[1]))
398 {
399 /* Do hex conversion */
400 *c = (isdigit(*qp_p) ? *qp_p - '0' : toupper(*qp_p) - 'A' + 10) << 4;
401 *c |= isdigit(qp_p[1]) ? qp_p[1] - '0' : toupper(qp_p[1]) - 'A' + 10;
402 return qp_p + 2;
403 }
404
405/* Illegal char here */
406*c = PDKIM_QP_ERROR_DECODE;
407return initial_pos;
408}
409
410
411/* -------------------------------------------------------------------------- */
412
413static uschar *
414pdkim_decode_qp(const uschar * str)
415{
416int nchar = 0;
417uschar * q;
418const uschar * p = str;
419uschar * n = store_get(Ustrlen(str)+1, TRUE);
420
421*n = '\0';
422q = n;
423while (*p)
424 {
425 if (*p == '=')
426 {
427 p = pdkim_decode_qp_char(p, &nchar);
428 if (nchar >= 0)
429 {
430 *q++ = nchar;
431 continue;
432 }
433 }
434 else
435 *q++ = *p;
436 p++;
437 }
438*q = '\0';
439return n;
440}
441
442
443/* -------------------------------------------------------------------------- */
444
445void
446pdkim_decode_base64(const uschar * str, blob * b)
447{
448int dlen = b64decode(str, &b->data);
449if (dlen < 0) b->data = NULL;
450b->len = dlen;
451}
452
453uschar *
454pdkim_encode_base64(blob * b)
455{
456return b64encode(CUS b->data, b->len);
457}
458
459
460/* -------------------------------------------------------------------------- */
461#define PDKIM_HDR_LIMBO 0
462#define PDKIM_HDR_TAG 1
463#define PDKIM_HDR_VALUE 2
464
465static pdkim_signature *
466pdkim_parse_sig_header(pdkim_ctx * ctx, uschar * raw_hdr)
467{
468pdkim_signature * sig;
469uschar *q;
470gstring * cur_tag = NULL;
471gstring * cur_val = NULL;
472BOOL past_hname = FALSE;
473BOOL in_b_val = FALSE;
474int where = PDKIM_HDR_LIMBO;
475
476sig = store_get(sizeof(pdkim_signature), FALSE);
477memset(sig, 0, sizeof(pdkim_signature));
478sig->bodylength = -1;
479
480/* Set so invalid/missing data error display is accurate */
481sig->version = 0;
482sig->keytype = -1;
483sig->hashtype = -1;
484
485q = sig->rawsig_no_b_val = store_get(Ustrlen(raw_hdr)+1, TRUE); /* tainted */
486
487for (uschar * p = raw_hdr; ; p++)
488 {
489 char c = *p;
490
491 /* Ignore FWS */
492 if (c == '\r' || c == '\n')
493 goto NEXT_CHAR;
494
495 /* Fast-forward through header name */
496 if (!past_hname)
497 {
498 if (c == ':') past_hname = TRUE;
499 goto NEXT_CHAR;
500 }
501
502 if (where == PDKIM_HDR_LIMBO)
503 {
504 /* In limbo, just wait for a tag-char to appear */
505 if (!(c >= 'a' && c <= 'z'))
506 goto NEXT_CHAR;
507
508 where = PDKIM_HDR_TAG;
509 }
510
511 if (where == PDKIM_HDR_TAG)
512 {
513 if (c >= 'a' && c <= 'z')
514 cur_tag = string_catn(cur_tag, p, 1);
515
516 if (c == '=')
517 {
518 if (Ustrcmp(string_from_gstring(cur_tag), "b") == 0)
519 {
520 *q++ = '=';
521 in_b_val = TRUE;
522 }
523 where = PDKIM_HDR_VALUE;
524 goto NEXT_CHAR;
525 }
526 }
527
528 if (where == PDKIM_HDR_VALUE)
529 {
530 if (c == '\r' || c == '\n' || c == ' ' || c == '\t')
531 goto NEXT_CHAR;
532
533 if (c == ';' || c == '\0')
534 {
535 /* We must have both tag and value, and tags must be one char except
536 for the possibility of "bh". */
537
538 if ( cur_tag && cur_val
539 && (cur_tag->ptr == 1 || *cur_tag->s == 'b')
540 )
541 {
542 (void) string_from_gstring(cur_val);
543 pdkim_strtrim(cur_val);
544
545 DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag->s, cur_val->s);
546
547 switch (*cur_tag->s)
548 {
549 case 'b': /* sig-data or body-hash */
550 switch (cur_tag->s[1])
551 {
552 case '\0': pdkim_decode_base64(cur_val->s, &sig->sighash); break;
553 case 'h': if (cur_tag->ptr == 2)
554 pdkim_decode_base64(cur_val->s, &sig->bodyhash);
555 break;
556 default: break;
557 }
558 break;
559 case 'v': /* version */
560 /* We only support version 1, and that is currently the
561 only version there is. */
562 sig->version =
563 Ustrcmp(cur_val->s, PDKIM_SIGNATURE_VERSION) == 0 ? 1 : -1;
564 break;
565 case 'a': /* algorithm */
566 {
567 const uschar * list = cur_val->s;
568 int sep = '-';
569 uschar * elem;
570
571 if ((elem = string_nextinlist(&list, &sep, NULL, 0)))
572 sig->keytype = pdkim_keyname_to_keytype(elem);
573 if ((elem = string_nextinlist(&list, &sep, NULL, 0)))
574 for (int i = 0; i < nelem(pdkim_hashes); i++)
575 if (Ustrcmp(elem, pdkim_hashes[i].dkim_hashname) == 0)
576 { sig->hashtype = i; break; }
577 }
578
579 case 'c': /* canonicalization */
580 pdkim_cstring_to_canons(cur_val->s, 0,
581 &sig->canon_headers, &sig->canon_body);
582 break;
583 case 'q': /* Query method (for pubkey)*/
584 for (int i = 0; pdkim_querymethods[i]; i++)
585 if (Ustrcmp(cur_val->s, pdkim_querymethods[i]) == 0)
586 {
587 sig->querymethod = i; /* we never actually use this */
588 break;
589 }
590 break;
591 case 's': /* Selector */
592 sig->selector = string_copyn(cur_val->s, cur_val->ptr); break;
593 case 'd': /* SDID */
594 sig->domain = string_copyn(cur_val->s, cur_val->ptr); break;
595 case 'i': /* AUID */
596 sig->identity = pdkim_decode_qp(cur_val->s); break;
597 case 't': /* Timestamp */
598 sig->created = strtoul(CS cur_val->s, NULL, 10); break;
599 case 'x': /* Expiration */
600 sig->expires = strtoul(CS cur_val->s, NULL, 10); break;
601 case 'l': /* Body length count */
602 sig->bodylength = strtol(CS cur_val->s, NULL, 10); break;
603 case 'h': /* signed header fields */
604 sig->headernames = string_copyn(cur_val->s, cur_val->ptr); break;
605 case 'z': /* Copied headfields */
606 sig->copiedheaders = pdkim_decode_qp(cur_val->s); break;
607/*XXX draft-ietf-dcrup-dkim-crypto-05 would need 'p' tag support
608for rsafp signatures. But later discussion is dropping those. */
609 default:
610 DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
611 break;
612 }
613 }
614 cur_tag = cur_val = NULL;
615 in_b_val = FALSE;
616 where = PDKIM_HDR_LIMBO;
617 }
618 else
619 cur_val = string_catn(cur_val, p, 1);
620 }
621
622NEXT_CHAR:
623 if (c == '\0')
624 break;
625
626 if (!in_b_val)
627 *q++ = c;
628 }
629
630if (sig->keytype < 0 || sig->hashtype < 0) /* Cannot verify this signature */
631 return NULL;
632
633*q = '\0';
634/* Chomp raw header. The final newline must not be added to the signature. */
635while (--q > sig->rawsig_no_b_val && (*q == '\r' || *q == '\n'))
636 *q = '\0';
637
638DEBUG(D_acl)
639 {
640 debug_printf(
641 "DKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
642 pdkim_quoteprint(US sig->rawsig_no_b_val, Ustrlen(sig->rawsig_no_b_val));
643 debug_printf(
644 "DKIM >> Sig size: %4u bits\n", (unsigned) sig->sighash.len*8);
645 debug_printf(
646 "DKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
647 }
648
649if (!pdkim_set_sig_bodyhash(ctx, sig))
650 return NULL;
651
652return sig;
653}
654
655
656/* -------------------------------------------------------------------------- */
657
658pdkim_pubkey *
659pdkim_parse_pubkey_record(const uschar *raw_record)
660{
661const uschar * ele;
662int sep = ';';
663pdkim_pubkey * pub;
664
665pub = store_get(sizeof(pdkim_pubkey), TRUE); /* tainted */
666memset(pub, 0, sizeof(pdkim_pubkey));
667
668while ((ele = string_nextinlist(&raw_record, &sep, NULL, 0)))
669 {
670 const uschar * val;
671
672 if ((val = Ustrchr(ele, '=')))
673 {
674 int taglen = val++ - ele;
675
676 DEBUG(D_acl) debug_printf(" %.*s=%s\n", taglen, ele, val);
677 switch (ele[0])
678 {
679 case 'v': pub->version = val; break;
680 case 'h': pub->hashes = val; break;
681 case 'k': pub->keytype = val; break;
682 case 'g': pub->granularity = val; break;
683 case 'n': pub->notes = pdkim_decode_qp(val); break;
684 case 'p': pdkim_decode_base64(val, &pub->key); break;
685 case 's': pub->srvtype = val; break;
686 case 't': if (Ustrchr(val, 'y')) pub->testing = 1;
687 if (Ustrchr(val, 's')) pub->no_subdomaining = 1;
688 break;
689 default: DEBUG(D_acl) debug_printf(" Unknown tag encountered\n"); break;
690 }
691 }
692 }
693
694/* Set fallback defaults */
695if (!pub->version)
696 pub->version = string_copy(PDKIM_PUB_RECORD_VERSION);
697else if (Ustrcmp(pub->version, PDKIM_PUB_RECORD_VERSION) != 0)
698 {
699 DEBUG(D_acl) debug_printf(" Bad v= field\n");
700 return NULL;
701 }
702
703if (!pub->granularity) pub->granularity = US"*";
704if (!pub->keytype ) pub->keytype = US"rsa";
705if (!pub->srvtype ) pub->srvtype = US"*";
706
707/* p= is required */
708if (pub->key.data)
709 return pub;
710
711DEBUG(D_acl) debug_printf(" Missing p= field\n");
712return NULL;
713}
714
715
716/* -------------------------------------------------------------------------- */
717
718/* Update one bodyhash with some additional data.
719If we have to relax the data for this sig, return our copy of it. */
720
721static blob *
722pdkim_update_ctx_bodyhash(pdkim_bodyhash * b, blob * orig_data, blob * relaxed_data)
723{
724blob * canon_data = orig_data;
725/* Defaults to simple canon (no further treatment necessary) */
726
727if (b->canon_method == PDKIM_CANON_RELAXED)
728 {
729 /* Relax the line if not done already */
730 if (!relaxed_data)
731 {
732 BOOL seen_wsp = FALSE;
733 int q = 0;
734
735 /* We want to be able to free this else we allocate
736 for the entire message which could be many MB. Since
737 we don't know what allocations the SHA routines might
738 do, not safe to use store_get()/store_reset(). */
739
740 relaxed_data = store_malloc(sizeof(blob) + orig_data->len+1);
741 relaxed_data->data = US (relaxed_data+1);
742
743 for (const uschar * p = orig_data->data, * r = p + orig_data->len; p < r; p++)
744 {
745 char c = *p;
746 if (c == '\r')
747 {
748 if (q > 0 && relaxed_data->data[q-1] == ' ')
749 q--;
750 }
751 else if (c == '\t' || c == ' ')
752 {
753 c = ' '; /* Turns WSP into SP */
754 if (seen_wsp)
755 continue;
756 seen_wsp = TRUE;
757 }
758 else
759 seen_wsp = FALSE;
760 relaxed_data->data[q++] = c;
761 }
762 relaxed_data->data[q] = '\0';
763 relaxed_data->len = q;
764 }
765 canon_data = relaxed_data;
766 }
767
768/* Make sure we don't exceed the to-be-signed body length */
769if ( b->bodylength >= 0
770 && b->signed_body_bytes + (unsigned long)canon_data->len > b->bodylength
771 )
772 canon_data->len = b->bodylength - b->signed_body_bytes;
773
774if (canon_data->len > 0)
775 {
776 exim_sha_update(&b->body_hash_ctx, CUS canon_data->data, canon_data->len);
777 b->signed_body_bytes += canon_data->len;
778 DEBUG(D_acl) pdkim_quoteprint(canon_data->data, canon_data->len);
779 }
780
781return relaxed_data;
782}
783
784
785/* -------------------------------------------------------------------------- */
786
787static void
788pdkim_finish_bodyhash(pdkim_ctx * ctx)
789{
790for (pdkim_bodyhash * b = ctx->bodyhash; b; b = b->next) /* Finish hashes */
791 {
792 DEBUG(D_acl) debug_printf("DKIM: finish bodyhash %d/%d/%ld len %ld\n",
793 b->hashtype, b->canon_method, b->bodylength, b->signed_body_bytes);
794 exim_sha_finish(&b->body_hash_ctx, &b->bh);
795 }
796
797/* Traverse all signatures */
798for (pdkim_signature * sig = ctx->sig; sig; sig = sig->next)
799 {
800 pdkim_bodyhash * b = sig->calc_body_hash;
801
802 DEBUG(D_acl)
803 {
804 debug_printf("DKIM [%s] Body bytes (%s) hashed: %lu\n"
805 "DKIM [%s] Body %s computed: ",
806 sig->domain, pdkim_canons[b->canon_method], b->signed_body_bytes,
807 sig->domain, pdkim_hashes[b->hashtype].dkim_hashname);
808 pdkim_hexprint(CUS b->bh.data, b->bh.len);
809 }
810
811 /* SIGNING -------------------------------------------------------------- */
812 if (ctx->flags & PDKIM_MODE_SIGN)
813 {
814 /* If bodylength limit is set, and we have received less bytes
815 than the requested amount, effectively remove the limit tag. */
816 if (b->signed_body_bytes < sig->bodylength)
817 sig->bodylength = -1;
818 }
819
820 else
821 /* VERIFICATION --------------------------------------------------------- */
822 /* Be careful that the header sig included a bodyash */
823
824 if ( sig->bodyhash.data
825 && memcmp(b->bh.data, sig->bodyhash.data, b->bh.len) == 0)
826 {
827 DEBUG(D_acl) debug_printf("DKIM [%s] Body hash compared OK\n", sig->domain);
828 }
829 else
830 {
831 DEBUG(D_acl)
832 {
833 debug_printf("DKIM [%s] Body hash signature from headers: ", sig->domain);
834 pdkim_hexprint(sig->bodyhash.data, sig->bodyhash.len);
835 debug_printf("DKIM [%s] Body hash did NOT verify\n", sig->domain);
836 }
837 sig->verify_status = PDKIM_VERIFY_FAIL;
838 sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
839 }
840 }
841}
842
843
844
845static void
846pdkim_body_complete(pdkim_ctx * ctx)
847{
848/* In simple body mode, if any empty lines were buffered,
849replace with one. rfc 4871 3.4.3 */
850/*XXX checking the signed-body-bytes is a gross hack; I think
851it indicates that all linebreaks should be buffered, including
852the one terminating a text line */
853
854for (pdkim_bodyhash * b = ctx->bodyhash; b; b = b->next)
855 if ( b->canon_method == PDKIM_CANON_SIMPLE
856 && b->signed_body_bytes == 0
857 && b->num_buffered_blanklines > 0
858 )
859 (void) pdkim_update_ctx_bodyhash(b, &lineending, NULL);
860
861ctx->flags |= PDKIM_SEEN_EOD;
862ctx->linebuf_offset = 0;
863}
864
865
866
867/* -------------------------------------------------------------------------- */
868/* Call from pdkim_feed below for processing complete body lines */
869/* NOTE: the line is not NUL-terminated; but we have a count */
870
871static void
872pdkim_bodyline_complete(pdkim_ctx * ctx)
873{
874blob line = {.data = ctx->linebuf, .len = ctx->linebuf_offset};
875blob * rnl = NULL;
876blob * rline = NULL;
877
878/* Ignore extra data if we've seen the end-of-data marker */
879if (ctx->flags & PDKIM_SEEN_EOD) goto all_skip;
880
881/* We've always got one extra byte to stuff a zero ... */
882ctx->linebuf[line.len] = '\0';
883
884/* Terminate on EOD marker */
885if (ctx->flags & PDKIM_DOT_TERM)
886 {
887 if (memcmp(line.data, ".\r\n", 3) == 0)
888 { pdkim_body_complete(ctx); return; }
889
890 /* Unstuff dots */
891 if (memcmp(line.data, "..", 2) == 0)
892 { line.data++; line.len--; }
893 }
894
895/* Empty lines need to be buffered until we find a non-empty line */
896if (memcmp(line.data, "\r\n", 2) == 0)
897 {
898 for (pdkim_bodyhash * b = ctx->bodyhash; b; b = b->next)
899 b->num_buffered_blanklines++;
900 goto all_skip;
901 }
902
903/* Process line for each bodyhash separately */
904for (pdkim_bodyhash * b = ctx->bodyhash; b; b = b->next)
905 {
906 if (b->canon_method == PDKIM_CANON_RELAXED)
907 {
908 /* Lines with just spaces need to be buffered too */
909 uschar * cp = line.data;
910 char c;
911
912 while ((c = *cp))
913 {
914 if (c == '\r' && cp[1] == '\n') break;
915 if (c != ' ' && c != '\t') goto hash_process;
916 cp++;
917 }
918
919 b->num_buffered_blanklines++;
920 goto hash_skip;
921 }
922
923hash_process:
924 /* At this point, we have a non-empty line, so release the buffered ones. */
925
926 while (b->num_buffered_blanklines)
927 {
928 rnl = pdkim_update_ctx_bodyhash(b, &lineending, rnl);
929 b->num_buffered_blanklines--;
930 }
931
932 rline = pdkim_update_ctx_bodyhash(b, &line, rline);
933hash_skip: ;
934 }
935
936if (rnl) store_free(rnl);
937if (rline) store_free(rline);
938
939all_skip:
940
941ctx->linebuf_offset = 0;
942return;
943}
944
945
946/* -------------------------------------------------------------------------- */
947/* Callback from pdkim_feed below for processing complete headers */
948#define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
949
950static int
951pdkim_header_complete(pdkim_ctx * ctx)
952{
953if ( (ctx->cur_header->ptr > 1) &&
954 (ctx->cur_header->s[ctx->cur_header->ptr-1] == '\r') )
955 --ctx->cur_header->ptr;
956(void) string_from_gstring(ctx->cur_header);
957
958#ifdef EXPERIMENTAL_ARC
959/* Feed the header line to ARC processing */
960(void) arc_header_feed(ctx->cur_header, !(ctx->flags & PDKIM_MODE_SIGN));
961#endif
962
963if (++ctx->num_headers > PDKIM_MAX_HEADERS) goto BAIL;
964
965/* SIGNING -------------------------------------------------------------- */
966if (ctx->flags & PDKIM_MODE_SIGN)
967 for (pdkim_signature * sig = ctx->sig; sig; sig = sig->next) /* Traverse all signatures */
968
969 /* Add header to the signed headers list (in reverse order) */
970 sig->headers = pdkim_prepend_stringlist(sig->headers, ctx->cur_header->s);
971
972/* VERIFICATION ----------------------------------------------------------- */
973/* DKIM-Signature: headers are added to the verification list */
974else
975 {
976#ifdef notdef
977 DEBUG(D_acl)
978 {
979 debug_printf("DKIM >> raw hdr: ");
980 pdkim_quoteprint(CUS ctx->cur_header->s, ctx->cur_header->ptr);
981 }
982#endif
983 if (strncasecmp(CCS ctx->cur_header->s,
984 DKIM_SIGNATURE_HEADERNAME,
985 Ustrlen(DKIM_SIGNATURE_HEADERNAME)) == 0)
986 {
987 pdkim_signature * sig, * last_sig;
988 /* Create and chain new signature block. We could error-check for all
989 required tags here, but prefer to create the internal sig and expicitly
990 fail verification of it later. */
991
992 DEBUG(D_acl) debug_printf(
993 "DKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
994
995 sig = pdkim_parse_sig_header(ctx, ctx->cur_header->s);
996
997 if (!(last_sig = ctx->sig))
998 ctx->sig = sig;
999 else
1000 {
1001 while (last_sig->next) last_sig = last_sig->next;
1002 last_sig->next = sig;
1003 }
1004
1005 if (--dkim_collect_input == 0)
1006 {
1007 ctx->headers = pdkim_prepend_stringlist(ctx->headers, ctx->cur_header->s);
1008 ctx->cur_header->s[ctx->cur_header->ptr = 0] = '\0';
1009 return PDKIM_ERR_EXCESS_SIGS;
1010 }
1011 }
1012
1013 /* all headers are stored for signature verification */
1014 ctx->headers = pdkim_prepend_stringlist(ctx->headers, ctx->cur_header->s);
1015 }
1016
1017BAIL:
1018ctx->cur_header->s[ctx->cur_header->ptr = 0] = '\0'; /* leave buffer for reuse */
1019return PDKIM_OK;
1020}
1021
1022
1023
1024/* -------------------------------------------------------------------------- */
1025#define HEADER_BUFFER_FRAG_SIZE 256
1026
1027DLLEXPORT int
1028pdkim_feed(pdkim_ctx * ctx, uschar * data, int len)
1029{
1030/* Alternate EOD signal, used in non-dotstuffing mode */
1031if (!data)
1032 pdkim_body_complete(ctx);
1033
1034else for (int p = 0; p < len; p++)
1035 {
1036 uschar c = data[p];
1037 int rc;
1038
1039 if (ctx->flags & PDKIM_PAST_HDRS)
1040 {
1041 if (c == '\n' && !(ctx->flags & PDKIM_SEEN_CR)) /* emulate the CR */
1042 {
1043 ctx->linebuf[ctx->linebuf_offset++] = '\r';
1044 if (ctx->linebuf_offset == PDKIM_MAX_BODY_LINE_LEN-1)
1045 return PDKIM_ERR_LONG_LINE;
1046 }
1047
1048 /* Processing body byte */
1049 ctx->linebuf[ctx->linebuf_offset++] = c;
1050 if (c == '\r')
1051 ctx->flags |= PDKIM_SEEN_CR;
1052 else if (c == '\n')
1053 {
1054 ctx->flags &= ~PDKIM_SEEN_CR;
1055 pdkim_bodyline_complete(ctx);
1056 }
1057
1058 if (ctx->linebuf_offset == PDKIM_MAX_BODY_LINE_LEN-1)
1059 return PDKIM_ERR_LONG_LINE;
1060 }
1061 else
1062 {
1063 /* Processing header byte */
1064 if (c == '\r')
1065 ctx->flags |= PDKIM_SEEN_CR;
1066 else if (c == '\n')
1067 {
1068 if (!(ctx->flags & PDKIM_SEEN_CR)) /* emulate the CR */
1069 ctx->cur_header = string_catn(ctx->cur_header, CUS "\r", 1);
1070
1071 if (ctx->flags & PDKIM_SEEN_LF) /* Seen last header line */
1072 {
1073 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1074 return rc;
1075
1076 ctx->flags = (ctx->flags & ~(PDKIM_SEEN_LF|PDKIM_SEEN_CR)) | PDKIM_PAST_HDRS;
1077 DEBUG(D_acl) debug_printf(
1078 "DKIM >> Body data for hash, canonicalized >>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1079 continue;
1080 }
1081 else
1082 ctx->flags = (ctx->flags & ~PDKIM_SEEN_CR) | PDKIM_SEEN_LF;
1083 }
1084 else if (ctx->flags & PDKIM_SEEN_LF)
1085 {
1086 if (!(c == '\t' || c == ' ')) /* End of header */
1087 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1088 return rc;
1089 ctx->flags &= ~PDKIM_SEEN_LF;
1090 }
1091
1092 if (!ctx->cur_header || ctx->cur_header->ptr < PDKIM_MAX_HEADER_LEN)
1093 ctx->cur_header = string_catn(ctx->cur_header, CUS &data[p], 1);
1094 }
1095 }
1096return PDKIM_OK;
1097}
1098
1099
1100
1101/* Extend a growing header with a continuation-linebreak */
1102static gstring *
1103pdkim_hdr_cont(gstring * str, int * col)
1104{
1105*col = 1;
1106return string_catn(str, US"\r\n\t", 3);
1107}
1108
1109
1110
1111/*
1112 * RFC 5322 specifies that header line length SHOULD be no more than 78
1113 * lets make it so!
1114 * pdkim_headcat
1115 *
1116 * returns uschar * (not nul-terminated)
1117 *
1118 * col: this int holds and receives column number (octets since last '\n')
1119 * str: partial string to append to
1120 * pad: padding, split line or space after before or after eg: ";"
1121 * intro: - must join to payload eg "h=", usually the tag name
1122 * payload: eg base64 data - long data can be split arbitrarily.
1123 *
1124 * this code doesn't fold the header in some of the places that RFC4871
1125 * allows: As per RFC5322(2.2.3) it only folds before or after tag-value
1126 * pairs and inside long values. it also always spaces or breaks after the
1127 * "pad"
1128 *
1129 * no guarantees are made for output given out-of range input. like tag
1130 * names longer than 78, or bogus col. Input is assumed to be free of line breaks.
1131 */
1132
1133static gstring *
1134pdkim_headcat(int * col, gstring * str,
1135 const uschar * pad, const uschar * intro, const uschar * payload)
1136{
1137size_t l;
1138
1139if (pad)
1140 {
1141 l = Ustrlen(pad);
1142 if (*col + l > 78)
1143 str = pdkim_hdr_cont(str, col);
1144 str = string_catn(str, pad, l);
1145 *col += l;
1146 }
1147
1148l = (pad?1:0) + (intro?Ustrlen(intro):0);
1149
1150if (*col + l > 78)
1151 { /*can't fit intro - start a new line to make room.*/
1152 str = pdkim_hdr_cont(str, col);
1153 l = intro?Ustrlen(intro):0;
1154 }
1155
1156l += payload ? Ustrlen(payload):0 ;
1157
1158while (l>77)
1159 { /* this fragment will not fit on a single line */
1160 if (pad)
1161 {
1162 str = string_catn(str, US" ", 1);
1163 *col += 1;
1164 pad = NULL; /* only want this once */
1165 l--;
1166 }
1167
1168 if (intro)
1169 {
1170 size_t sl = Ustrlen(intro);
1171
1172 str = string_catn(str, intro, sl);
1173 *col += sl;
1174 l -= sl;
1175 intro = NULL; /* only want this once */
1176 }
1177
1178 if (payload)
1179 {
1180 size_t sl = Ustrlen(payload);
1181 size_t chomp = *col+sl < 77 ? sl : 78-*col;
1182
1183 str = string_catn(str, payload, chomp);
1184 *col += chomp;
1185 payload += chomp;
1186 l -= chomp-1;
1187 }
1188
1189 /* the while precondition tells us it didn't fit. */
1190 str = pdkim_hdr_cont(str, col);
1191 }
1192
1193if (*col + l > 78)
1194 {
1195 str = pdkim_hdr_cont(str, col);
1196 pad = NULL;
1197 }
1198
1199if (pad)
1200 {
1201 str = string_catn(str, US" ", 1);
1202 *col += 1;
1203 pad = NULL;
1204 }
1205
1206if (intro)
1207 {
1208 size_t sl = Ustrlen(intro);
1209
1210 str = string_catn(str, intro, sl);
1211 *col += sl;
1212 l -= sl;
1213 intro = NULL;
1214 }
1215
1216if (payload)
1217 {
1218 size_t sl = Ustrlen(payload);
1219
1220 str = string_catn(str, payload, sl);
1221 *col += sl;
1222 }
1223
1224return str;
1225}
1226
1227
1228/* -------------------------------------------------------------------------- */
1229
1230/* Signing: create signature header
1231*/
1232static uschar *
1233pdkim_create_header(pdkim_signature * sig, BOOL final)
1234{
1235uschar * base64_bh;
1236uschar * base64_b;
1237int col = 0;
1238gstring * hdr;
1239gstring * canon_all;
1240
1241canon_all = string_cat (NULL, pdkim_canons[sig->canon_headers]);
1242canon_all = string_catn(canon_all, US"/", 1);
1243canon_all = string_cat (canon_all, pdkim_canons[sig->canon_body]);
1244(void) string_from_gstring(canon_all);
1245
1246hdr = string_cat(NULL, US"DKIM-Signature: v="PDKIM_SIGNATURE_VERSION);
1247col = hdr->ptr;
1248
1249/* Required and static bits */
1250hdr = pdkim_headcat(&col, hdr, US";", US"a=", dkim_sig_to_a_tag(sig));
1251hdr = pdkim_headcat(&col, hdr, US";", US"q=", pdkim_querymethods[sig->querymethod]);
1252hdr = pdkim_headcat(&col, hdr, US";", US"c=", canon_all->s);
1253hdr = pdkim_headcat(&col, hdr, US";", US"d=", sig->domain);
1254hdr = pdkim_headcat(&col, hdr, US";", US"s=", sig->selector);
1255
1256/* list of header names can be split between items. */
1257 {
1258 uschar * n = string_copy(sig->headernames);
1259 uschar * i = US"h=";
1260 uschar * s = US";";
1261
1262 while (*n)
1263 {
1264 uschar * c = Ustrchr(n, ':');
1265
1266 if (c) *c ='\0';
1267
1268 if (!i)
1269 hdr = pdkim_headcat(&col, hdr, NULL, NULL, US":");
1270
1271 hdr = pdkim_headcat(&col, hdr, s, i, n);
1272
1273 if (!c)
1274 break;
1275
1276 n = c+1;
1277 s = NULL;
1278 i = NULL;
1279 }
1280 }
1281
1282base64_bh = pdkim_encode_base64(&sig->calc_body_hash->bh);
1283hdr = pdkim_headcat(&col, hdr, US";", US"bh=", base64_bh);
1284
1285/* Optional bits */
1286if (sig->identity)
1287 hdr = pdkim_headcat(&col, hdr, US";", US"i=", sig->identity);
1288
1289if (sig->created > 0)
1290 {
1291 uschar minibuf[20];
1292
1293 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->created);
1294 hdr = pdkim_headcat(&col, hdr, US";", US"t=", minibuf);
1295}
1296
1297if (sig->expires > 0)
1298 {
1299 uschar minibuf[20];
1300
1301 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->expires);
1302 hdr = pdkim_headcat(&col, hdr, US";", US"x=", minibuf);
1303 }
1304
1305if (sig->bodylength >= 0)
1306 {
1307 uschar minibuf[20];
1308
1309 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->bodylength);
1310 hdr = pdkim_headcat(&col, hdr, US";", US"l=", minibuf);
1311 }
1312
1313/* Preliminary or final version? */
1314if (final)
1315 {
1316 base64_b = pdkim_encode_base64(&sig->sighash);
1317 hdr = pdkim_headcat(&col, hdr, US";", US"b=", base64_b);
1318
1319 /* add trailing semicolon: I'm not sure if this is actually needed */
1320 hdr = pdkim_headcat(&col, hdr, NULL, US";", US"");
1321 }
1322else
1323 {
1324 /* To satisfy the rule "all surrounding whitespace [...] deleted"
1325 ( RFC 6376 section 3.7 ) we ensure there is no whitespace here. Otherwise
1326 the headcat routine could insert a linebreak which the relaxer would reduce
1327 to a single space preceding the terminating semicolon, resulting in an
1328 incorrect header-hash. */
1329 hdr = pdkim_headcat(&col, hdr, US";", US"b=;", US"");
1330 }
1331
1332return string_from_gstring(hdr);
1333}
1334
1335
1336/* -------------------------------------------------------------------------- */
1337
1338/* According to draft-ietf-dcrup-dkim-crypto-07 "keys are 256 bits" (referring
1339to DNS, hence the pubkey). Check for more than 32 bytes; if so assume the
1340alternate possible representation (still) being discussed: a
1341SubjectPublickeyInfo wrapped key - and drop all but the trailing 32-bytes (it
1342should be a DER, with exactly 12 leading bytes - but we could accept a BER also,
1343which could be any size). We still rely on the crypto library for checking for
1344undersize.
1345
1346When the RFC is published this should be re-addressed. */
1347
1348static void
1349check_bare_ed25519_pubkey(pdkim_pubkey * p)
1350{
1351int excess = p->key.len - 32;
1352if (excess > 0)
1353 {
1354 DEBUG(D_acl) debug_printf("DKIM: unexpected pubkey len %lu\n", p->key.len);
1355 p->key.data += excess; p->key.len = 32;
1356 }
1357}
1358
1359
1360static pdkim_pubkey *
1361pdkim_key_from_dns(pdkim_ctx * ctx, pdkim_signature * sig, ev_ctx * vctx,
1362 const uschar ** errstr)
1363{
1364uschar * dns_txt_name, * dns_txt_reply;
1365pdkim_pubkey * p;
1366
1367/* Fetch public key for signing domain, from DNS */
1368
1369dns_txt_name = string_sprintf("%s._domainkey.%s.", sig->selector, sig->domain);
1370
1371if ( !(dns_txt_reply = ctx->dns_txt_callback(dns_txt_name))
1372 || dns_txt_reply[0] == '\0'
1373 )
1374 {
1375 sig->verify_status = PDKIM_VERIFY_INVALID;
1376 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE;
1377 return NULL;
1378 }
1379
1380DEBUG(D_acl)
1381 {
1382 debug_printf(
1383 "DKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
1384 " %s\n"
1385 " Raw record: ",
1386 dns_txt_name);
1387 pdkim_quoteprint(CUS dns_txt_reply, Ustrlen(dns_txt_reply));
1388 }
1389
1390if ( !(p = pdkim_parse_pubkey_record(CUS dns_txt_reply))
1391 || (Ustrcmp(p->srvtype, "*") != 0 && Ustrcmp(p->srvtype, "email") != 0)
1392 )
1393 {
1394 sig->verify_status = PDKIM_VERIFY_INVALID;
1395 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD;
1396
1397 DEBUG(D_acl)
1398 {
1399 if (p)
1400 debug_printf(" Invalid public key service type '%s'\n", p->srvtype);
1401 else
1402 debug_printf(" Error while parsing public key record\n");
1403 debug_printf(
1404 "DKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1405 }
1406 return NULL;
1407 }
1408
1409DEBUG(D_acl) debug_printf(
1410 "DKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1411
1412/* Import public key */
1413
1414/* Normally we use the signature a= tag to tell us the pubkey format.
1415When signing under debug we do a test-import of the pubkey, and at that
1416time we do not have a signature so we must interpret the pubkey k= tag
1417instead. Assume writing on the sig is ok in that case. */
1418
1419if (sig->keytype < 0)
1420 if ((sig->keytype = pdkim_keyname_to_keytype(p->keytype)) < 0)
1421 {
1422 DEBUG(D_acl) debug_printf("verify_init: unhandled keytype %s\n", p->keytype);
1423 sig->verify_status = PDKIM_VERIFY_INVALID;
1424 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_IMPORT;
1425 return NULL;
1426 }
1427
1428if (sig->keytype == KEYTYPE_ED25519)
1429 check_bare_ed25519_pubkey(p);
1430
1431if ((*errstr = exim_dkim_verify_init(&p->key,
1432 sig->keytype == KEYTYPE_ED25519 ? KEYFMT_ED25519_BARE : KEYFMT_DER,
1433 vctx, &sig->keybits)))
1434 {
1435 DEBUG(D_acl) debug_printf("verify_init: %s\n", *errstr);
1436 sig->verify_status = PDKIM_VERIFY_INVALID;
1437 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_IMPORT;
1438 return NULL;
1439 }
1440
1441vctx->keytype = sig->keytype;
1442return p;
1443}
1444
1445
1446/* -------------------------------------------------------------------------- */
1447/* Sort and filter the sigs developed from the message */
1448
1449static pdkim_signature *
1450sort_sig_methods(pdkim_signature * siglist)
1451{
1452pdkim_signature * yield, ** ss;
1453const uschar * prefs;
1454uschar * ele;
1455int sep;
1456
1457if (!siglist) return NULL;
1458
1459/* first select in order of hashtypes */
1460DEBUG(D_acl) debug_printf("DKIM: dkim_verify_hashes '%s'\n", dkim_verify_hashes);
1461for (prefs = dkim_verify_hashes, sep = 0, yield = NULL, ss = &yield;
1462 ele = string_nextinlist(&prefs, &sep, NULL, 0); )
1463 {
1464 int i = pdkim_hashname_to_hashtype(CUS ele, 0);
1465 for (pdkim_signature * s = siglist, * next, ** prev = &siglist; s;
1466 s = next)
1467 {
1468 next = s->next;
1469 if (s->hashtype == i)
1470 { *prev = next; s->next = NULL; *ss = s; ss = &s->next; }
1471 else
1472 prev = &s->next;
1473 }
1474 }
1475
1476/* then in order of keytypes */
1477siglist = yield;
1478DEBUG(D_acl) debug_printf("DKIM: dkim_verify_keytypes '%s'\n", dkim_verify_keytypes);
1479for (prefs = dkim_verify_keytypes, sep = 0, yield = NULL, ss = &yield;
1480 ele = string_nextinlist(&prefs, &sep, NULL, 0); )
1481 {
1482 int i = pdkim_keyname_to_keytype(CUS ele);
1483 for (pdkim_signature * s = siglist, * next, ** prev = &siglist; s;
1484 s = next)
1485 {
1486 next = s->next;
1487 if (s->keytype == i)
1488 { *prev = next; s->next = NULL; *ss = s; ss = &s->next; }
1489 else
1490 prev = &s->next;
1491 }
1492 }
1493
1494DEBUG(D_acl) for (pdkim_signature * s = yield; s; s = s->next)
1495 debug_printf(" retain d=%s s=%s a=%s\n",
1496 s->domain, s->selector, dkim_sig_to_a_tag(s));
1497return yield;
1498}
1499
1500
1501/* -------------------------------------------------------------------------- */
1502
1503DLLEXPORT int
1504pdkim_feed_finish(pdkim_ctx * ctx, pdkim_signature ** return_signatures,
1505 const uschar ** err)
1506{
1507BOOL verify_pass = FALSE;
1508
1509/* Check if we must still flush a (partial) header. If that is the
1510 case, the message has no body, and we must compute a body hash
1511 out of '<CR><LF>' */
1512if (ctx->cur_header && ctx->cur_header->ptr > 0)
1513 {
1514 blob * rnl = NULL;
1515 int rc;
1516
1517 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1518 return rc;
1519
1520 for (pdkim_bodyhash * b = ctx->bodyhash; b; b = b->next)
1521 rnl = pdkim_update_ctx_bodyhash(b, &lineending, rnl);
1522 if (rnl) store_free(rnl);
1523 }
1524else
1525 DEBUG(D_acl) debug_printf(
1526 "DKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1527
1528/* Build (and/or evaluate) body hash. Do this even if no DKIM sigs, in case we
1529have a hash to do for ARC. */
1530
1531pdkim_finish_bodyhash(ctx);
1532
1533/* Sort and filter the recived signatures */
1534
1535if (!(ctx->flags & PDKIM_MODE_SIGN))
1536 ctx->sig = sort_sig_methods(ctx->sig);
1537
1538if (!ctx->sig)
1539 {
1540 DEBUG(D_acl) debug_printf("DKIM: no signatures\n");
1541 *return_signatures = NULL;
1542 return PDKIM_OK;
1543 }
1544
1545for (pdkim_signature * sig = ctx->sig; sig; sig = sig->next)
1546 {
1547 hctx hhash_ctx;
1548 uschar * sig_hdr = US"";
1549 blob hhash;
1550 gstring * hdata = NULL;
1551 es_ctx sctx;
1552
1553 if ( !(ctx->flags & PDKIM_MODE_SIGN)
1554 && sig->verify_status == PDKIM_VERIFY_FAIL)
1555 {
1556 DEBUG(D_acl)
1557 debug_printf("DKIM: [%s] abandoning this signature\n", sig->domain);
1558 continue;
1559 }
1560
1561 /*XXX The hash of the headers is needed for GCrypt (for which we can do RSA
1562 signing only, as it happens) and for either GnuTLS and OpenSSL when we are
1563 signing with EC (specifically, Ed25519). The former is because the GCrypt
1564 signing operation is pure (does not do its own hash) so we must hash. The
1565 latter is because we (stupidly, but this is what the IETF draft is saying)
1566 must hash with the declared hash method, then pass the result to the library
1567 hash-and-sign routine (because that's all the libraries are providing. And
1568 we're stuck with whatever that hidden hash method is, too). We may as well
1569 do this hash incrementally.
1570 We don't need the hash we're calculating here for the GnuTLS and OpenSSL
1571 cases of RSA signing, since those library routines can do hash-and-sign.
1572
1573 Some time in the future we could easily avoid doing the hash here for those
1574 cases (which will be common for a long while. We could also change from
1575 the current copy-all-the-headers-into-one-block, then call the hash-and-sign
1576 implementation - to a proper incremental one. Unfortunately, GnuTLS just
1577 cannot do incremental - either signing or verification. Unsure about GCrypt.
1578 */
1579
1580 /*XXX The header hash is also used (so far) by the verify operation */
1581
1582 if (!exim_sha_init(&hhash_ctx, pdkim_hashes[sig->hashtype].exim_hashmethod))
1583 {
1584 log_write(0, LOG_MAIN|LOG_PANIC,
1585 "DKIM: hash setup error, possibly nonhandled hashtype");
1586 break;
1587 }
1588
1589 if (ctx->flags & PDKIM_MODE_SIGN)
1590 DEBUG(D_acl) debug_printf(
1591 "DKIM >> Headers to be signed: >>>>>>>>>>>>\n"
1592 " %s\n",
1593 sig->sign_headers);
1594
1595 DEBUG(D_acl) debug_printf(
1596 "DKIM >> Header data for hash, canonicalized (%-7s), in sequence >>\n",
1597 pdkim_canons[sig->canon_headers]);
1598
1599
1600 /* SIGNING ---------------------------------------------------------------- */
1601 /* When signing, walk through our header list and add them to the hash. As we
1602 go, construct a list of the header's names to use for the h= parameter.
1603 Then append to that list any remaining header names for which there was no
1604 header to sign. */
1605
1606 if (ctx->flags & PDKIM_MODE_SIGN)
1607 {
1608 gstring * g = NULL;
1609 const uschar * l;
1610 uschar * s;
1611 int sep = 0;
1612
1613 /* Import private key, including the keytype which we need for building
1614 the signature header */
1615
1616 if ((*err = exim_dkim_signing_init(CUS sig->privkey, &sctx)))
1617 {
1618 log_write(0, LOG_MAIN|LOG_PANIC, "signing_init: %s", *err);
1619 return PDKIM_ERR_RSA_PRIVKEY;
1620 }
1621 sig->keytype = sctx.keytype;
1622
1623 sig->headernames = NULL; /* Collected signed header names */
1624 for (pdkim_stringlist * p = sig->headers; p; p = p->next)
1625 {
1626 uschar * rh = p->value;
1627
1628 if (header_name_match(rh, sig->sign_headers) == PDKIM_OK)
1629 {
1630 /* Collect header names (Note: colon presence is guaranteed here) */
1631 g = string_append_listele_n(g, ':', rh, Ustrchr(rh, ':') - rh);
1632
1633 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1634 rh = pdkim_relax_header(rh, TRUE); /* cook header for relaxed canon */
1635
1636 /* Feed header to the hash algorithm */
1637 exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
1638
1639 /* Remember headers block for signing (when the library cannot do incremental) */
1640 /*XXX we could avoid doing this for all but the GnuTLS/RSA case */
1641 hdata = exim_dkim_data_append(hdata, rh);
1642
1643 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1644 }
1645 }
1646
1647 /* Any headers we wanted to sign but were not present must also be listed.
1648 Ignore elements that have been ticked-off or are marked as never-oversign. */
1649
1650 l = sig->sign_headers;
1651 while((s = string_nextinlist(&l, &sep, NULL, 0)))
1652 {
1653 if (*s == '+') /* skip oversigning marker */
1654 s++;
1655 if (*s != '_' && *s != '=')
1656 g = string_append_listele(g, ':', s);
1657 }
1658 sig->headernames = string_from_gstring(g);
1659
1660 /* Create signature header with b= omitted */
1661 sig_hdr = pdkim_create_header(sig, FALSE);
1662 }
1663
1664 /* VERIFICATION ----------------------------------------------------------- */
1665 /* When verifying, walk through the header name list in the h= parameter and
1666 add the headers to the hash in that order. */
1667 else
1668 {
1669 uschar * p = sig->headernames;
1670 uschar * q;
1671
1672 if (p)
1673 {
1674 /* clear tags */
1675 for (pdkim_stringlist * hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1676 hdrs->tag = 0;
1677
1678 p = string_copy(p);
1679 while(1)
1680 {
1681 if ((q = Ustrchr(p, ':')))
1682 *q = '\0';
1683
1684 /*XXX walk the list of headers in same order as received. */
1685 for (pdkim_stringlist * hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1686 if ( hdrs->tag == 0
1687 && strncasecmp(CCS hdrs->value, CCS p, Ustrlen(p)) == 0
1688 && (hdrs->value)[Ustrlen(p)] == ':'
1689 )
1690 {
1691 /* cook header for relaxed canon, or just copy it for simple */
1692
1693 uschar * rh = sig->canon_headers == PDKIM_CANON_RELAXED
1694 ? pdkim_relax_header(hdrs->value, TRUE)
1695 : string_copy(CUS hdrs->value);
1696
1697 /* Feed header to the hash algorithm */
1698 exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
1699
1700 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1701 hdrs->tag = 1;
1702 break;
1703 }
1704
1705 if (!q) break;
1706 p = q+1;
1707 }
1708
1709 sig_hdr = string_copy(sig->rawsig_no_b_val);
1710 }
1711 }
1712
1713 DEBUG(D_acl) debug_printf(
1714 "DKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1715
1716 DEBUG(D_acl)
1717 {
1718 debug_printf(
1719 "DKIM >> Signed DKIM-Signature header, pre-canonicalized >>>>>>>>>>>>>\n");
1720 pdkim_quoteprint(CUS sig_hdr, Ustrlen(sig_hdr));
1721 debug_printf(
1722 "DKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1723 }
1724
1725 /* Relax header if necessary */
1726 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1727 sig_hdr = pdkim_relax_header(sig_hdr, FALSE);
1728
1729 DEBUG(D_acl)
1730 {
1731 debug_printf("DKIM >> Signed DKIM-Signature header, canonicalized (%-7s) >>>>>>>\n",
1732 pdkim_canons[sig->canon_headers]);
1733 pdkim_quoteprint(CUS sig_hdr, Ustrlen(sig_hdr));
1734 debug_printf(
1735 "DKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1736 }
1737
1738 /* Finalize header hash */
1739 exim_sha_update(&hhash_ctx, CUS sig_hdr, Ustrlen(sig_hdr));
1740 exim_sha_finish(&hhash_ctx, &hhash);
1741
1742 DEBUG(D_acl)
1743 {
1744 debug_printf("DKIM [%s] Header %s computed: ",
1745 sig->domain, pdkim_hashes[sig->hashtype].dkim_hashname);
1746 pdkim_hexprint(hhash.data, hhash.len);
1747 }
1748
1749 /* Remember headers block for signing (when the signing library cannot do
1750 incremental) */
1751 if (ctx->flags & PDKIM_MODE_SIGN)
1752 hdata = exim_dkim_data_append(hdata, US sig_hdr);
1753
1754 /* SIGNING ---------------------------------------------------------------- */
1755 if (ctx->flags & PDKIM_MODE_SIGN)
1756 {
1757 hashmethod hm = sig->keytype == KEYTYPE_ED25519
1758#if defined(SIGN_OPENSSL)
1759 ? HASH_NULL
1760#else
1761 ? HASH_SHA2_512
1762#endif
1763 : pdkim_hashes[sig->hashtype].exim_hashmethod;
1764
1765#ifdef SIGN_HAVE_ED25519
1766 /* For GCrypt, and for EC, we pass the hash-of-headers to the signing
1767 routine. For anything else we just pass the headers. */
1768
1769 if (sig->keytype != KEYTYPE_ED25519)
1770#endif
1771 {
1772 hhash.data = hdata->s;
1773 hhash.len = hdata->ptr;
1774 }
1775
1776 if ((*err = exim_dkim_sign(&sctx, hm, &hhash, &sig->sighash)))
1777 {
1778 log_write(0, LOG_MAIN|LOG_PANIC, "signing: %s", *err);
1779 return PDKIM_ERR_RSA_SIGNING;
1780 }
1781
1782 DEBUG(D_acl)
1783 {
1784 debug_printf( "DKIM [%s] b computed: ", sig->domain);
1785 pdkim_hexprint(sig->sighash.data, sig->sighash.len);
1786 }
1787
1788 sig->signature_header = pdkim_create_header(sig, TRUE);
1789 }
1790
1791 /* VERIFICATION ----------------------------------------------------------- */
1792 else
1793 {
1794 ev_ctx vctx;
1795 hashmethod hm;
1796
1797 /* Make sure we have all required signature tags */
1798 if (!( sig->domain && *sig->domain
1799 && sig->selector && *sig->selector
1800 && sig->headernames && *sig->headernames
1801 && sig->bodyhash.data
1802 && sig->sighash.data
1803 && sig->keytype >= 0
1804 && sig->hashtype >= 0
1805 && sig->version
1806 ) )
1807 {
1808 sig->verify_status = PDKIM_VERIFY_INVALID;
1809 sig->verify_ext_status = PDKIM_VERIFY_INVALID_SIGNATURE_ERROR;
1810
1811 DEBUG(D_acl) debug_printf(
1812 " Error in DKIM-Signature header: tags missing or invalid (%s)\n"
1813 "DKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
1814 !(sig->domain && *sig->domain) ? "d="
1815 : !(sig->selector && *sig->selector) ? "s="
1816 : !(sig->headernames && *sig->headernames) ? "h="
1817 : !sig->bodyhash.data ? "bh="
1818 : !sig->sighash.data ? "b="
1819 : sig->keytype < 0 || sig->hashtype < 0 ? "a="
1820 : "v="
1821 );
1822 goto NEXT_VERIFY;
1823 }
1824
1825 /* Make sure sig uses supported DKIM version (only v1) */
1826 if (sig->version != 1)
1827 {
1828 sig->verify_status = PDKIM_VERIFY_INVALID;
1829 sig->verify_ext_status = PDKIM_VERIFY_INVALID_DKIM_VERSION;
1830
1831 DEBUG(D_acl) debug_printf(
1832 " Error in DKIM-Signature header: unsupported DKIM version\n"
1833 "DKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1834 goto NEXT_VERIFY;
1835 }
1836
1837 DEBUG(D_acl)
1838 {
1839 debug_printf( "DKIM [%s] b from mail: ", sig->domain);
1840 pdkim_hexprint(sig->sighash.data, sig->sighash.len);
1841 }
1842
1843 if (!(sig->pubkey = pdkim_key_from_dns(ctx, sig, &vctx, err)))
1844 {
1845 log_write(0, LOG_MAIN, "DKIM: %s%s %s%s [failed key import]",
1846 sig->domain ? "d=" : "", sig->domain ? sig->domain : US"",
1847 sig->selector ? "s=" : "", sig->selector ? sig->selector : US"");
1848 goto NEXT_VERIFY;
1849 }
1850
1851 /* If the pubkey limits to a list of specific hashes, ignore sigs that
1852 do not have the hash part of the sig algorithm matching */
1853
1854 if (sig->pubkey->hashes)
1855 {
1856 const uschar * list = sig->pubkey->hashes, * ele;
1857 int sep = ':';
1858 while ((ele = string_nextinlist(&list, &sep, NULL, 0)))
1859 if (Ustrcmp(ele, pdkim_hashes[sig->hashtype].dkim_hashname) == 0) break;
1860 if (!ele)
1861 {
1862 DEBUG(D_acl) debug_printf("pubkey h=%s vs. sig a=%s_%s\n",
1863 sig->pubkey->hashes,
1864 pdkim_keytypes[sig->keytype],
1865 pdkim_hashes[sig->hashtype].dkim_hashname);
1866 sig->verify_status = PDKIM_VERIFY_FAIL;
1867 sig->verify_ext_status = PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH;
1868 goto NEXT_VERIFY;
1869 }
1870 }
1871
1872 hm = sig->keytype == KEYTYPE_ED25519
1873#if defined(SIGN_OPENSSL)
1874 ? HASH_NULL
1875#else
1876 ? HASH_SHA2_512
1877#endif
1878 : pdkim_hashes[sig->hashtype].exim_hashmethod;
1879
1880 /* Check the signature */
1881
1882 if ((*err = exim_dkim_verify(&vctx, hm, &hhash, &sig->sighash)))
1883 {
1884 DEBUG(D_acl) debug_printf("headers verify: %s\n", *err);
1885 sig->verify_status = PDKIM_VERIFY_FAIL;
1886 sig->verify_ext_status = PDKIM_VERIFY_FAIL_MESSAGE;
1887 goto NEXT_VERIFY;
1888 }
1889
1890
1891 /* We have a winner! (if bodyhash was correct earlier) */
1892 if (sig->verify_status == PDKIM_VERIFY_NONE)
1893 {
1894 sig->verify_status = PDKIM_VERIFY_PASS;
1895 verify_pass = TRUE;
1896 if (dkim_verify_minimal) break;
1897 }
1898
1899NEXT_VERIFY:
1900
1901 DEBUG(D_acl)
1902 {
1903 debug_printf("DKIM [%s] %s signature status: %s",
1904 sig->domain, dkim_sig_to_a_tag(sig),
1905 pdkim_verify_status_str(sig->verify_status));
1906 if (sig->verify_ext_status > 0)
1907 debug_printf(" (%s)\n",
1908 pdkim_verify_ext_status_str(sig->verify_ext_status));
1909 else
1910 debug_printf("\n");
1911 }
1912 }
1913 }
1914
1915/* If requested, set return pointer to signature(s) */
1916if (return_signatures)
1917 *return_signatures = ctx->sig;
1918
1919return ctx->flags & PDKIM_MODE_SIGN || verify_pass
1920 ? PDKIM_OK : PDKIM_FAIL;
1921}
1922
1923
1924/* -------------------------------------------------------------------------- */
1925
1926DLLEXPORT pdkim_ctx *
1927pdkim_init_verify(uschar * (*dns_txt_callback)(const uschar *), BOOL dot_stuffing)
1928{
1929pdkim_ctx * ctx;
1930
1931ctx = store_get(sizeof(pdkim_ctx), FALSE);
1932memset(ctx, 0, sizeof(pdkim_ctx));
1933
1934if (dot_stuffing) ctx->flags = PDKIM_DOT_TERM;
1935/* The line-buffer is for message data, hence tainted */
1936ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN, TRUE);
1937ctx->dns_txt_callback = dns_txt_callback;
1938
1939return ctx;
1940}
1941
1942
1943/* -------------------------------------------------------------------------- */
1944
1945DLLEXPORT pdkim_signature *
1946pdkim_init_sign(pdkim_ctx * ctx,
1947 uschar * domain, uschar * selector, uschar * privkey,
1948 uschar * hashname, const uschar ** errstr)
1949{
1950int hashtype;
1951pdkim_signature * sig;
1952
1953if (!domain || !selector || !privkey)
1954 return NULL;
1955
1956/* Allocate & init one signature struct */
1957
1958sig = store_get(sizeof(pdkim_signature), FALSE);
1959memset(sig, 0, sizeof(pdkim_signature));
1960
1961sig->bodylength = -1;
1962
1963sig->domain = string_copy(US domain);
1964sig->selector = string_copy(US selector);
1965sig->privkey = string_copy(US privkey);
1966sig->keytype = -1;
1967
1968for (hashtype = 0; hashtype < nelem(pdkim_hashes); hashtype++)
1969 if (Ustrcmp(hashname, pdkim_hashes[hashtype].dkim_hashname) == 0)
1970 { sig->hashtype = hashtype; break; }
1971if (hashtype >= nelem(pdkim_hashes))
1972 {
1973 log_write(0, LOG_MAIN|LOG_PANIC,
1974 "DKIM: unrecognised hashname '%s'", hashname);
1975 return NULL;
1976 }
1977
1978DEBUG(D_acl)
1979 {
1980 pdkim_signature s = *sig;
1981 ev_ctx vctx;
1982
1983 debug_printf("DKIM (checking verify key)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1984 if (!pdkim_key_from_dns(ctx, &s, &vctx, errstr))
1985 debug_printf("WARNING: bad dkim key in dns\n");
1986 debug_printf("DKIM (finished checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1987 }
1988return sig;
1989}
1990
1991
1992/* -------------------------------------------------------------------------- */
1993
1994DLLEXPORT void
1995pdkim_set_optional(pdkim_signature * sig,
1996 char * sign_headers,
1997 char * identity,
1998 int canon_headers,
1999 int canon_body,
2000 long bodylength,
2001 unsigned long created,
2002 unsigned long expires)
2003{
2004if (identity)
2005 sig->identity = string_copy(US identity);
2006
2007sig->sign_headers = string_copy(sign_headers
2008 ? US sign_headers : US PDKIM_DEFAULT_SIGN_HEADERS);
2009
2010sig->canon_headers = canon_headers;
2011sig->canon_body = canon_body;
2012sig->bodylength = bodylength;
2013sig->created = created;
2014sig->expires = expires;
2015
2016return;
2017}
2018
2019
2020
2021/* Set up a blob for calculating the bodyhash according to the
2022given needs. Use an existing one if possible, or create a new one.
2023
2024Return: hashblob pointer, or NULL on error
2025*/
2026pdkim_bodyhash *
2027pdkim_set_bodyhash(pdkim_ctx * ctx, int hashtype, int canon_method,
2028 long bodylength)
2029{
2030pdkim_bodyhash * b;
2031
2032if (hashtype == -1 || canon_method == -1) return NULL;
2033
2034for (b = ctx->bodyhash; b; b = b->next)
2035 if ( hashtype == b->hashtype
2036 && canon_method == b->canon_method
2037 && bodylength == b->bodylength)
2038 {
2039 DEBUG(D_receive) debug_printf("DKIM: using existing bodyhash %d/%d/%ld\n",
2040 hashtype, canon_method, bodylength);
2041 return b;
2042 }
2043
2044DEBUG(D_receive) debug_printf("DKIM: new bodyhash %d/%d/%ld\n",
2045 hashtype, canon_method, bodylength);
2046b = store_get(sizeof(pdkim_bodyhash), FALSE);
2047b->next = ctx->bodyhash;
2048b->hashtype = hashtype;
2049b->canon_method = canon_method;
2050b->bodylength = bodylength;
2051if (!exim_sha_init(&b->body_hash_ctx, /*XXX hash method: extend for sha512 */
2052 pdkim_hashes[hashtype].exim_hashmethod))
2053 {
2054 DEBUG(D_acl)
2055 debug_printf("DKIM: hash init error, possibly nonhandled hashtype\n");
2056 return NULL;
2057 }
2058b->signed_body_bytes = 0;
2059b->num_buffered_blanklines = 0;
2060ctx->bodyhash = b;
2061return b;
2062}
2063
2064
2065/* Set up a blob for calculating the bodyhash according to the
2066needs of this signature. Use an existing one if possible, or
2067create a new one.
2068
2069Return: hashblob pointer, or NULL on error (only used as a boolean).
2070*/
2071pdkim_bodyhash *
2072pdkim_set_sig_bodyhash(pdkim_ctx * ctx, pdkim_signature * sig)
2073{
2074pdkim_bodyhash * b = pdkim_set_bodyhash(ctx,
2075 sig->hashtype, sig->canon_body, sig->bodylength);
2076sig->calc_body_hash = b;
2077return b;
2078}
2079
2080
2081/* -------------------------------------------------------------------------- */
2082
2083
2084void
2085pdkim_init_context(pdkim_ctx * ctx, BOOL dot_stuffed,
2086 uschar * (*dns_txt_callback)(const uschar *))
2087{
2088memset(ctx, 0, sizeof(pdkim_ctx));
2089ctx->flags = dot_stuffed ? PDKIM_MODE_SIGN | PDKIM_DOT_TERM : PDKIM_MODE_SIGN;
2090/* The line buffer is for message data, hence tainted */
2091ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN, TRUE);
2092DEBUG(D_acl) ctx->dns_txt_callback = dns_txt_callback;
2093}
2094
2095
2096void
2097pdkim_init(void)
2098{
2099exim_dkim_init();
2100}
2101
2102
2103
2104#endif /*DISABLE_DKIM*/