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