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