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