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