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