365234f4e82d44308d7e81f9be4a081b43fa5eaf
[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;
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 /* We must have both tag and value, and tags must be one char except
494 for the possibility of "bh". */
495
496 if ( cur_tag && cur_val
497 && (cur_tag->ptr == 1 || *cur_tag->s == 'b')
498 )
499 {
500 (void) string_from_gstring(cur_val);
501 pdkim_strtrim(cur_val);
502
503 DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag->s, cur_val->s);
504
505 switch (*cur_tag->s)
506 {
507 case 'b':
508 switch (cur_tag->s[1])
509 {
510 case '\0': pdkim_decode_base64(cur_val->s, &sig->sighash); break;
511 case 'h': if (cur_tag->ptr == 2)
512 pdkim_decode_base64(cur_val->s, &sig->bodyhash);
513 break;
514 default: break;
515 }
516 break;
517 case 'v':
518 /* We only support version 1, and that is currently the
519 only version there is. */
520 sig->version =
521 Ustrcmp(cur_val->s, PDKIM_SIGNATURE_VERSION) == 0 ? 1 : -1;
522 break;
523 case 'a':
524 {
525 uschar * s = Ustrchr(cur_val->s, '-');
526
527 for(i = 0; i < nelem(pdkim_keytypes); i++)
528 if (Ustrncmp(cur_val->s, pdkim_keytypes[i], s - cur_val->s) == 0)
529 { sig->keytype = i; break; }
530 for (++s, i = 0; i < nelem(pdkim_hashes); i++)
531 if (Ustrcmp(s, pdkim_hashes[i].dkim_hashname) == 0)
532 { sig->hashtype = i; break; }
533 break;
534 }
535
536 case 'c':
537 for (i = 0; pdkim_combined_canons[i].str; i++)
538 if (Ustrcmp(cur_val->s, pdkim_combined_canons[i].str) == 0)
539 {
540 sig->canon_headers = pdkim_combined_canons[i].canon_headers;
541 sig->canon_body = pdkim_combined_canons[i].canon_body;
542 break;
543 }
544 break;
545 case 'q':
546 for (i = 0; pdkim_querymethods[i]; i++)
547 if (Ustrcmp(cur_val->s, pdkim_querymethods[i]) == 0)
548 {
549 sig->querymethod = i;
550 break;
551 }
552 break;
553 case 's':
554 sig->selector = string_copyn(cur_val->s, cur_val->ptr); break;
555 case 'd':
556 sig->domain = string_copyn(cur_val->s, cur_val->ptr); break;
557 case 'i':
558 sig->identity = pdkim_decode_qp(cur_val->s); break;
559 case 't':
560 sig->created = strtoul(CS cur_val->s, NULL, 10); break;
561 case 'x':
562 sig->expires = strtoul(CS cur_val->s, NULL, 10); break;
563 case 'l':
564 sig->bodylength = strtol(CS cur_val->s, NULL, 10); break;
565 case 'h':
566 sig->headernames = string_copyn(cur_val->s, cur_val->ptr); break;
567 case 'z':
568 sig->copiedheaders = pdkim_decode_qp(cur_val->s); break;
569 default:
570 DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
571 break;
572 }
573 }
574 cur_tag = cur_val = NULL;
575 in_b_val = FALSE;
576 where = PDKIM_HDR_LIMBO;
577 }
578 else
579 cur_val = string_catn(cur_val, p, 1);
580 }
581
582 NEXT_CHAR:
583 if (c == '\0')
584 break;
585
586 if (!in_b_val)
587 *q++ = c;
588 }
589
590 *q = '\0';
591 /* Chomp raw header. The final newline must not be added to the signature. */
592 while (--q > sig->rawsig_no_b_val && (*q == '\r' || *q == '\n'))
593 *q = '\0';
594
595 DEBUG(D_acl)
596 {
597 debug_printf(
598 "PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
599 pdkim_quoteprint(US sig->rawsig_no_b_val, Ustrlen(sig->rawsig_no_b_val));
600 debug_printf(
601 "PDKIM >> Sig size: %4u bits\n", (unsigned) sig->sighash.len*8);
602 debug_printf(
603 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
604 }
605
606 if (!pdkim_set_bodyhash(ctx, sig))
607 return NULL;
608
609 return sig;
610 }
611
612
613 /* -------------------------------------------------------------------------- */
614
615 static pdkim_pubkey *
616 pdkim_parse_pubkey_record(pdkim_ctx *ctx, const uschar *raw_record)
617 {
618 const uschar * ele;
619 int sep = ';';
620 pdkim_pubkey * pub;
621
622 pub = store_get(sizeof(pdkim_pubkey));
623 memset(pub, 0, sizeof(pdkim_pubkey));
624
625 while ((ele = string_nextinlist(&raw_record, &sep, NULL, 0)))
626 {
627 const uschar * val;
628
629 if ((val = Ustrchr(ele, '=')))
630 {
631 int taglen = val++ - ele;
632
633 DEBUG(D_acl) debug_printf(" %.*s=%s\n", taglen, ele, val);
634 switch (ele[0])
635 {
636 case 'v': pub->version = val; break;
637 case 'h': pub->hashes = val; break;
638 case 'k': break;
639 case 'g': pub->granularity = val; break;
640 case 'n': pub->notes = pdkim_decode_qp(val); break;
641 case 'p': pdkim_decode_base64(val, &pub->key); break;
642 case 's': pub->srvtype = val; break;
643 case 't': if (Ustrchr(val, 'y')) pub->testing = 1;
644 if (Ustrchr(val, 's')) pub->no_subdomaining = 1;
645 break;
646 default: DEBUG(D_acl) debug_printf(" Unknown tag encountered\n"); break;
647 }
648 }
649 }
650
651 /* Set fallback defaults */
652 if (!pub->version)
653 pub->version = string_copy(PDKIM_PUB_RECORD_VERSION);
654 else if (Ustrcmp(pub->version, PDKIM_PUB_RECORD_VERSION) != 0)
655 {
656 DEBUG(D_acl) debug_printf(" Bad v= field\n");
657 return NULL;
658 }
659
660 if (!pub->granularity) pub->granularity = US"*";
661 /*
662 if (!pub->keytype ) pub->keytype = US"rsa";
663 */
664 if (!pub->srvtype ) pub->srvtype = US"*";
665
666 /* p= is required */
667 if (pub->key.data)
668 return pub;
669
670 DEBUG(D_acl) debug_printf(" Missing p= field\n");
671 return NULL;
672 }
673
674
675 /* -------------------------------------------------------------------------- */
676
677 /* Update one bodyhash with some additional data.
678 If we have to relax the data for this sig, return our copy of it. */
679
680 static blob *
681 pdkim_update_ctx_bodyhash(pdkim_bodyhash * b, 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 (b->canon_method == 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 ( b->bodylength >= 0
730 && b->signed_body_bytes + (unsigned long)canon_data->len > b->bodylength
731 )
732 canon_data->len = b->bodylength - b->signed_body_bytes;
733
734 if (canon_data->len > 0)
735 {
736 exim_sha_update(&b->body_hash_ctx, CUS canon_data->data, canon_data->len);
737 b->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_bodyhash * b;
751 pdkim_signature * sig;
752
753 for (b = ctx->bodyhash; b; b = b->next) /* Finish hashes */
754 exim_sha_finish(&b->body_hash_ctx, &b->bh);
755
756 /* Traverse all signatures */
757 for (sig = ctx->sig; sig; sig = sig->next)
758 {
759 b = sig->calc_body_hash;
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, b->signed_body_bytes,
766 sig->domain, pdkim_hashes[sig->hashtype].dkim_hashname);
767 pdkim_hexprint(CUS b->bh.data, b->bh.len);
768 }
769
770 /* SIGNING -------------------------------------------------------------- */
771 if (ctx->flags & PDKIM_MODE_SIGN)
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 (b->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
784 && memcmp(b->bh.data, sig->bodyhash.data, b->bh.len) == 0)
785 {
786 DEBUG(D_acl) debug_printf("PDKIM [%s] Body hash verified OK\n", sig->domain);
787 }
788 else
789 {
790 DEBUG(D_acl)
791 {
792 debug_printf("PDKIM [%s] Body hash signature from headers: ", sig->domain);
793 pdkim_hexprint(sig->bodyhash.data, sig->bodyhash.len);
794 debug_printf("PDKIM [%s] Body hash did NOT verify\n", sig->domain);
795 }
796 sig->verify_status = PDKIM_VERIFY_FAIL;
797 sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
798 }
799 }
800 }
801
802
803
804 static void
805 pdkim_body_complete(pdkim_ctx * ctx)
806 {
807 pdkim_bodyhash * b;
808
809 /* In simple body mode, if any empty lines were buffered,
810 replace with one. rfc 4871 3.4.3 */
811 /*XXX checking the signed-body-bytes is a gross hack; I think
812 it indicates that all linebreaks should be buffered, including
813 the one terminating a text line */
814
815 for (b = ctx->bodyhash; b; b = b->next)
816 if ( b->canon_method == PDKIM_CANON_SIMPLE
817 && b->signed_body_bytes == 0
818 && b->num_buffered_blanklines > 0
819 )
820 (void) pdkim_update_ctx_bodyhash(b, &lineending, NULL);
821
822 ctx->flags |= PDKIM_SEEN_EOD;
823 ctx->linebuf_offset = 0;
824 }
825
826
827
828 /* -------------------------------------------------------------------------- */
829 /* Call from pdkim_feed below for processing complete body lines */
830
831 static void
832 pdkim_bodyline_complete(pdkim_ctx * ctx)
833 {
834 blob line = {.data = ctx->linebuf, .len = ctx->linebuf_offset};
835 pdkim_bodyhash * b;
836 blob * rnl = NULL;
837 blob * rline = NULL;
838
839 /* Ignore extra data if we've seen the end-of-data marker */
840 if (ctx->flags & PDKIM_SEEN_EOD) goto all_skip;
841
842 /* We've always got one extra byte to stuff a zero ... */
843 ctx->linebuf[line.len] = '\0';
844
845 /* Terminate on EOD marker */
846 if (ctx->flags & PDKIM_DOT_TERM)
847 {
848 if (memcmp(line.data, ".\r\n", 3) == 0)
849 { pdkim_body_complete(ctx); return; }
850
851 /* Unstuff dots */
852 if (memcmp(line.data, "..", 2) == 0)
853 { line.data++; line.len--; }
854 }
855
856 /* Empty lines need to be buffered until we find a non-empty line */
857 if (memcmp(line.data, "\r\n", 2) == 0)
858 {
859 for (b = ctx->bodyhash; b; b = b->next) b->num_buffered_blanklines++;
860 goto all_skip;
861 }
862
863 /* Process line for each bodyhash separately */
864 for (b = ctx->bodyhash; b; b = b->next)
865 {
866 if (b->canon_method == PDKIM_CANON_RELAXED)
867 {
868 /* Lines with just spaces need to be buffered too */
869 uschar * cp = line.data;
870 char c;
871
872 while ((c = *cp))
873 {
874 if (c == '\r' && cp[1] == '\n') break;
875 if (c != ' ' && c != '\t') goto hash_process;
876 cp++;
877 }
878
879 b->num_buffered_blanklines++;
880 goto hash_skip;
881 }
882
883 hash_process:
884 /* At this point, we have a non-empty line, so release the buffered ones. */
885
886 while (b->num_buffered_blanklines)
887 {
888 rnl = pdkim_update_ctx_bodyhash(b, &lineending, rnl);
889 b->num_buffered_blanklines--;
890 }
891
892 rline = pdkim_update_ctx_bodyhash(b, &line, rline);
893 hash_skip: ;
894 }
895
896 if (rnl) store_free(rnl);
897 if (rline) store_free(rline);
898
899 all_skip:
900
901 ctx->linebuf_offset = 0;
902 return;
903 }
904
905
906 /* -------------------------------------------------------------------------- */
907 /* Callback from pdkim_feed below for processing complete headers */
908 #define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
909
910 static int
911 pdkim_header_complete(pdkim_ctx * ctx)
912 {
913 pdkim_signature * sig, * last_sig;
914
915 /* Special case: The last header can have an extra \r appended */
916 if ( (ctx->cur_header->ptr > 1) &&
917 (ctx->cur_header->s[ctx->cur_header->ptr-1] == '\r') )
918 --ctx->cur_header->ptr;
919 (void) string_from_gstring(ctx->cur_header);
920
921 if (++ctx->num_headers > PDKIM_MAX_HEADERS) goto BAIL;
922
923 /* SIGNING -------------------------------------------------------------- */
924 if (ctx->flags & PDKIM_MODE_SIGN)
925 for (sig = ctx->sig; sig; sig = sig->next) /* Traverse all signatures */
926
927 /* Add header to the signed headers list (in reverse order) */
928 sig->headers = pdkim_prepend_stringlist(sig->headers, ctx->cur_header->s);
929
930 /* VERIFICATION ----------------------------------------------------------- */
931 /* DKIM-Signature: headers are added to the verification list */
932 else
933 {
934 #ifdef notdef
935 DEBUG(D_acl)
936 {
937 debug_printf("PDKIM >> raw hdr: ");
938 pdkim_quoteprint(CUS ctx->cur_header->s, ctx->cur_header->ptr);
939 }
940 #endif
941 if (strncasecmp(CCS ctx->cur_header->s,
942 DKIM_SIGNATURE_HEADERNAME,
943 Ustrlen(DKIM_SIGNATURE_HEADERNAME)) == 0)
944 {
945 /* Create and chain new signature block. We could error-check for all
946 required tags here, but prefer to create the internal sig and expicitly
947 fail verification of it later. */
948
949 DEBUG(D_acl) debug_printf(
950 "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
951
952 sig = pdkim_parse_sig_header(ctx, ctx->cur_header->s);
953
954 if (!(last_sig = ctx->sig))
955 ctx->sig = sig;
956 else
957 {
958 while (last_sig->next) last_sig = last_sig->next;
959 last_sig->next = sig;
960 }
961 }
962
963 /* all headers are stored for signature verification */
964 ctx->headers = pdkim_prepend_stringlist(ctx->headers, ctx->cur_header->s);
965 }
966
967 BAIL:
968 ctx->cur_header->s[ctx->cur_header->ptr = 0] = '\0'; /* leave buffer for reuse */
969 return PDKIM_OK;
970 }
971
972
973
974 /* -------------------------------------------------------------------------- */
975 #define HEADER_BUFFER_FRAG_SIZE 256
976
977 DLLEXPORT int
978 pdkim_feed(pdkim_ctx * ctx, uschar * data, int len)
979 {
980 int p, rc;
981
982 /* Alternate EOD signal, used in non-dotstuffing mode */
983 if (!data)
984 pdkim_body_complete(ctx);
985
986 else for (p = 0; p<len; p++)
987 {
988 uschar c = data[p];
989
990 if (ctx->flags & PDKIM_PAST_HDRS)
991 {
992 if (c == '\n' && !(ctx->flags & PDKIM_SEEN_CR)) /* emulate the CR */
993 {
994 ctx->linebuf[ctx->linebuf_offset++] = '\r';
995 if (ctx->linebuf_offset == PDKIM_MAX_BODY_LINE_LEN-1)
996 return PDKIM_ERR_LONG_LINE;
997 }
998
999 /* Processing body byte */
1000 ctx->linebuf[ctx->linebuf_offset++] = c;
1001 if (c == '\r')
1002 ctx->flags |= PDKIM_SEEN_CR;
1003 else if (c == '\n')
1004 {
1005 ctx->flags &= ~PDKIM_SEEN_CR;
1006 pdkim_bodyline_complete(ctx);
1007 }
1008
1009 if (ctx->linebuf_offset == PDKIM_MAX_BODY_LINE_LEN-1)
1010 return PDKIM_ERR_LONG_LINE;
1011 }
1012 else
1013 {
1014 /* Processing header byte */
1015 if (c == '\r')
1016 ctx->flags |= PDKIM_SEEN_CR;
1017 else if (c == '\n')
1018 {
1019 if (!(ctx->flags & PDKIM_SEEN_CR)) /* emulate the CR */
1020 ctx->cur_header = string_catn(ctx->cur_header, CUS "\r", 1);
1021
1022 if (ctx->flags & PDKIM_SEEN_LF) /* Seen last header line */
1023 {
1024 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1025 return rc;
1026
1027 ctx->flags = (ctx->flags & ~(PDKIM_SEEN_LF|PDKIM_SEEN_CR)) | PDKIM_PAST_HDRS;
1028 DEBUG(D_acl) debug_printf(
1029 "PDKIM >> Body data for hash, canonicalized >>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1030 continue;
1031 }
1032 else
1033 ctx->flags = (ctx->flags & ~PDKIM_SEEN_CR) | PDKIM_SEEN_LF;
1034 }
1035 else if (ctx->flags & PDKIM_SEEN_LF)
1036 {
1037 if (!(c == '\t' || c == ' ')) /* End of header */
1038 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1039 return rc;
1040 ctx->flags &= ~PDKIM_SEEN_LF;
1041 }
1042
1043 if (!ctx->cur_header || ctx->cur_header->ptr < PDKIM_MAX_HEADER_LEN)
1044 ctx->cur_header = string_catn(ctx->cur_header, CUS &data[p], 1);
1045 }
1046 }
1047 return PDKIM_OK;
1048 }
1049
1050
1051
1052 /* Extend a growing header with a continuation-linebreak */
1053 static gstring *
1054 pdkim_hdr_cont(gstring * str, int * col)
1055 {
1056 *col = 1;
1057 return string_catn(str, US"\r\n\t", 3);
1058 }
1059
1060
1061
1062 /*
1063 * RFC 5322 specifies that header line length SHOULD be no more than 78
1064 * lets make it so!
1065 * pdkim_headcat
1066 *
1067 * returns uschar * (not nul-terminated)
1068 *
1069 * col: this int holds and receives column number (octets since last '\n')
1070 * str: partial string to append to
1071 * pad: padding, split line or space after before or after eg: ";"
1072 * intro: - must join to payload eg "h=", usually the tag name
1073 * payload: eg base64 data - long data can be split arbitrarily.
1074 *
1075 * this code doesn't fold the header in some of the places that RFC4871
1076 * allows: As per RFC5322(2.2.3) it only folds before or after tag-value
1077 * pairs and inside long values. it also always spaces or breaks after the
1078 * "pad"
1079 *
1080 * no guarantees are made for output given out-of range input. like tag
1081 * names longer than 78, or bogus col. Input is assumed to be free of line breaks.
1082 */
1083
1084 static gstring *
1085 pdkim_headcat(int * col, gstring * str,
1086 const uschar * pad, const uschar * intro, const uschar * payload)
1087 {
1088 size_t l;
1089
1090 if (pad)
1091 {
1092 l = Ustrlen(pad);
1093 if (*col + l > 78)
1094 str = pdkim_hdr_cont(str, col);
1095 str = string_catn(str, pad, l);
1096 *col += l;
1097 }
1098
1099 l = (pad?1:0) + (intro?Ustrlen(intro):0);
1100
1101 if (*col + l > 78)
1102 { /*can't fit intro - start a new line to make room.*/
1103 str = pdkim_hdr_cont(str, col);
1104 l = intro?Ustrlen(intro):0;
1105 }
1106
1107 l += payload ? Ustrlen(payload):0 ;
1108
1109 while (l>77)
1110 { /* this fragment will not fit on a single line */
1111 if (pad)
1112 {
1113 str = string_catn(str, US" ", 1);
1114 *col += 1;
1115 pad = NULL; /* only want this once */
1116 l--;
1117 }
1118
1119 if (intro)
1120 {
1121 size_t sl = Ustrlen(intro);
1122
1123 str = string_catn(str, intro, sl);
1124 *col += sl;
1125 l -= sl;
1126 intro = NULL; /* only want this once */
1127 }
1128
1129 if (payload)
1130 {
1131 size_t sl = Ustrlen(payload);
1132 size_t chomp = *col+sl < 77 ? sl : 78-*col;
1133
1134 str = string_catn(str, payload, chomp);
1135 *col += chomp;
1136 payload += chomp;
1137 l -= chomp-1;
1138 }
1139
1140 /* the while precondition tells us it didn't fit. */
1141 str = pdkim_hdr_cont(str, col);
1142 }
1143
1144 if (*col + l > 78)
1145 {
1146 str = pdkim_hdr_cont(str, col);
1147 pad = NULL;
1148 }
1149
1150 if (pad)
1151 {
1152 str = string_catn(str, US" ", 1);
1153 *col += 1;
1154 pad = NULL;
1155 }
1156
1157 if (intro)
1158 {
1159 size_t sl = Ustrlen(intro);
1160
1161 str = string_catn(str, intro, sl);
1162 *col += sl;
1163 l -= sl;
1164 intro = NULL;
1165 }
1166
1167 if (payload)
1168 {
1169 size_t sl = Ustrlen(payload);
1170
1171 str = string_catn(str, payload, sl);
1172 *col += sl;
1173 }
1174
1175 return str;
1176 }
1177
1178
1179 /* -------------------------------------------------------------------------- */
1180
1181 /* Signing: create signature header
1182 */
1183 static uschar *
1184 pdkim_create_header(pdkim_signature * sig, BOOL final)
1185 {
1186 uschar * base64_bh;
1187 uschar * base64_b;
1188 int col = 0;
1189 gstring * hdr;
1190 gstring * canon_all;
1191
1192 canon_all = string_cat (NULL, pdkim_canons[sig->canon_headers]);
1193 canon_all = string_catn(canon_all, US"/", 1);
1194 canon_all = string_cat (canon_all, pdkim_canons[sig->canon_body]);
1195 (void) string_from_gstring(canon_all);
1196
1197 hdr = string_cat(NULL, US"DKIM-Signature: v="PDKIM_SIGNATURE_VERSION);
1198 col = hdr->ptr;
1199
1200 /* Required and static bits */
1201 hdr = pdkim_headcat(&col, hdr, US";", US"a=", dkim_sig_to_a_tag(sig));
1202 hdr = pdkim_headcat(&col, hdr, US";", US"q=", pdkim_querymethods[sig->querymethod]);
1203 hdr = pdkim_headcat(&col, hdr, US";", US"c=", canon_all->s);
1204 hdr = pdkim_headcat(&col, hdr, US";", US"d=", sig->domain);
1205 hdr = pdkim_headcat(&col, hdr, US";", US"s=", sig->selector);
1206
1207 /* list of header names can be split between items. */
1208 {
1209 uschar * n = string_copy(sig->headernames);
1210 uschar * i = US"h=";
1211 uschar * s = US";";
1212
1213 while (*n)
1214 {
1215 uschar * c = Ustrchr(n, ':');
1216
1217 if (c) *c ='\0';
1218
1219 if (!i)
1220 hdr = pdkim_headcat(&col, hdr, NULL, NULL, US":");
1221
1222 hdr = pdkim_headcat(&col, hdr, s, i, n);
1223
1224 if (!c)
1225 break;
1226
1227 n = c+1;
1228 s = NULL;
1229 i = NULL;
1230 }
1231 }
1232
1233 base64_bh = pdkim_encode_base64(&sig->calc_body_hash->bh);
1234 hdr = pdkim_headcat(&col, hdr, US";", US"bh=", base64_bh);
1235
1236 /* Optional bits */
1237 if (sig->identity)
1238 hdr = pdkim_headcat(&col, hdr, US";", US"i=", sig->identity);
1239
1240 if (sig->created > 0)
1241 {
1242 uschar minibuf[20];
1243
1244 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->created);
1245 hdr = pdkim_headcat(&col, hdr, US";", US"t=", minibuf);
1246 }
1247
1248 if (sig->expires > 0)
1249 {
1250 uschar minibuf[20];
1251
1252 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->expires);
1253 hdr = pdkim_headcat(&col, hdr, US";", US"x=", minibuf);
1254 }
1255
1256 if (sig->bodylength >= 0)
1257 {
1258 uschar minibuf[20];
1259
1260 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->bodylength);
1261 hdr = pdkim_headcat(&col, hdr, US";", US"l=", minibuf);
1262 }
1263
1264 /* Preliminary or final version? */
1265 if (final)
1266 {
1267 base64_b = pdkim_encode_base64(&sig->sighash);
1268 hdr = pdkim_headcat(&col, hdr, US";", US"b=", base64_b);
1269
1270 /* add trailing semicolon: I'm not sure if this is actually needed */
1271 hdr = pdkim_headcat(&col, hdr, NULL, US";", US"");
1272 }
1273 else
1274 {
1275 /* To satisfy the rule "all surrounding whitespace [...] deleted"
1276 ( RFC 6376 section 3.7 ) we ensure there is no whitespace here. Otherwise
1277 the headcat routine could insert a linebreak which the relaxer would reduce
1278 to a single space preceding the terminating semicolon, resulting in an
1279 incorrect header-hash. */
1280 hdr = pdkim_headcat(&col, hdr, US";", US"b=;", US"");
1281 }
1282
1283 return string_from_gstring(hdr);
1284 }
1285
1286
1287 /* -------------------------------------------------------------------------- */
1288
1289 static pdkim_pubkey *
1290 pdkim_key_from_dns(pdkim_ctx * ctx, pdkim_signature * sig, ev_ctx * vctx,
1291 const uschar ** errstr)
1292 {
1293 uschar * dns_txt_name, * dns_txt_reply;
1294 pdkim_pubkey * p;
1295
1296 /* Fetch public key for signing domain, from DNS */
1297
1298 dns_txt_name = string_sprintf("%s._domainkey.%s.", sig->selector, sig->domain);
1299
1300 if ( !(dns_txt_reply = ctx->dns_txt_callback(CS dns_txt_name))
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_bodyhash * b;
1361 pdkim_signature * sig;
1362
1363 /* Check if we must still flush a (partial) header. If that is the
1364 case, the message has no body, and we must compute a body hash
1365 out of '<CR><LF>' */
1366 if (ctx->cur_header && ctx->cur_header->ptr > 0)
1367 {
1368 blob * rnl = NULL;
1369 int rc;
1370
1371 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1372 return rc;
1373
1374 for (b = ctx->bodyhash; b; b = b->next)
1375 rnl = pdkim_update_ctx_bodyhash(b, &lineending, rnl);
1376 if (rnl) store_free(rnl);
1377 }
1378 else
1379 DEBUG(D_acl) debug_printf(
1380 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1381
1382 /* Build (and/or evaluate) body hash */
1383 pdkim_finish_bodyhash(ctx);
1384
1385 for (sig = ctx->sig; sig; sig = sig->next)
1386 {
1387 hctx hhash_ctx;
1388 uschar * sig_hdr = US"";
1389 blob hhash;
1390 gstring * hdata = NULL;
1391
1392 if (!exim_sha_init(&hhash_ctx, pdkim_hashes[sig->hashtype].exim_hashmethod))
1393 {
1394 DEBUG(D_acl)
1395 debug_printf("PDKIM: hash setup error, possibly nonhandled hashtype\n");
1396 break;
1397 }
1398
1399 if (ctx->flags & PDKIM_MODE_SIGN)
1400 DEBUG(D_acl) debug_printf(
1401 "PDKIM >> Headers to be signed: >>>>>>>>>>>>\n"
1402 " %s\n",
1403 sig->sign_headers);
1404
1405 DEBUG(D_acl) debug_printf(
1406 "PDKIM >> Header data for hash, canonicalized, in sequence >>>>>>>>>>>>\n");
1407
1408
1409 /* SIGNING ---------------------------------------------------------------- */
1410 /* When signing, walk through our header list and add them to the hash. As we
1411 go, construct a list of the header's names to use for the h= parameter.
1412 Then append to that list any remaining header names for which there was no
1413 header to sign. */
1414
1415 if (ctx->flags & PDKIM_MODE_SIGN)
1416 {
1417 gstring * g = NULL;
1418 pdkim_stringlist *p;
1419 const uschar * l;
1420 uschar * s;
1421 int sep = 0;
1422
1423 sig->headernames = NULL; /* Collected signed header names */
1424
1425 for (p = sig->headers; p; p = p->next)
1426 {
1427 uschar * rh = p->value;
1428
1429 if (header_name_match(rh, sig->sign_headers) == PDKIM_OK)
1430 {
1431 /* Collect header names (Note: colon presence is guaranteed here) */
1432 g = string_append_listele_n(g, ':', rh, Ustrchr(rh, ':') - rh);
1433
1434 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1435 rh = pdkim_relax_header(rh, TRUE); /* cook header for relaxed canon */
1436
1437 /* Feed header to the hash algorithm */
1438 exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
1439
1440 /* Remember headers block for signing (when the library cannot do incremental) */
1441 hdata = exim_dkim_data_append(hdata, rh);
1442
1443 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1444 }
1445 }
1446
1447 /* Any headers we wanted to sign but were not present must also be listed.
1448 Ignore elements that have been ticked-off or are marked as never-oversign. */
1449
1450 l = sig->sign_headers;
1451 while((s = string_nextinlist(&l, &sep, NULL, 0)))
1452 {
1453 if (*s == '+') /* skip oversigning marker */
1454 s++;
1455 if (*s != '_' && *s != '=')
1456 g = string_append_listele(g, ':', s);
1457 }
1458 sig->headernames = string_from_gstring(g);
1459
1460 /* Create signature header with b= omitted */
1461 sig_hdr = pdkim_create_header(sig, FALSE);
1462 }
1463
1464 /* VERIFICATION ----------------------------------------------------------- */
1465 /* When verifying, walk through the header name list in the h= parameter and
1466 add the headers to the hash in that order. */
1467 else
1468 {
1469 uschar * p = sig->headernames;
1470 uschar * q;
1471 pdkim_stringlist * hdrs;
1472
1473 if (p)
1474 {
1475 /* clear tags */
1476 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1477 hdrs->tag = 0;
1478
1479 p = string_copy(p);
1480 while(1)
1481 {
1482 if ((q = Ustrchr(p, ':')))
1483 *q = '\0';
1484
1485 /*XXX walk the list of headers in same order as received. */
1486 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1487 if ( hdrs->tag == 0
1488 && strncasecmp(CCS hdrs->value, CCS p, Ustrlen(p)) == 0
1489 && (hdrs->value)[Ustrlen(p)] == ':'
1490 )
1491 {
1492 /* cook header for relaxed canon, or just copy it for simple */
1493
1494 uschar * rh = sig->canon_headers == PDKIM_CANON_RELAXED
1495 ? pdkim_relax_header(hdrs->value, TRUE)
1496 : string_copy(CUS hdrs->value);
1497
1498 /* Feed header to the hash algorithm */
1499 exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
1500
1501 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1502 hdrs->tag = 1;
1503 break;
1504 }
1505
1506 if (!q) break;
1507 p = q+1;
1508 }
1509
1510 sig_hdr = string_copy(sig->rawsig_no_b_val);
1511 }
1512 }
1513
1514 DEBUG(D_acl) debug_printf(
1515 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1516
1517 DEBUG(D_acl)
1518 {
1519 debug_printf(
1520 "PDKIM >> Signed DKIM-Signature header, pre-canonicalized >>>>>>>>>>>>>\n");
1521 pdkim_quoteprint(CUS sig_hdr, Ustrlen(sig_hdr));
1522 debug_printf(
1523 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1524 }
1525
1526 /* Relax header if necessary */
1527 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1528 sig_hdr = pdkim_relax_header(sig_hdr, FALSE);
1529
1530 DEBUG(D_acl)
1531 {
1532 debug_printf(
1533 "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
1534 pdkim_quoteprint(CUS sig_hdr, Ustrlen(sig_hdr));
1535 debug_printf(
1536 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1537 }
1538
1539 /* Finalize header hash */
1540 exim_sha_update(&hhash_ctx, CUS sig_hdr, Ustrlen(sig_hdr));
1541 exim_sha_finish(&hhash_ctx, &hhash);
1542
1543 DEBUG(D_acl)
1544 {
1545 debug_printf("PDKIM [%s] Header %s computed: ",
1546 sig->domain, pdkim_hashes[sig->hashtype].dkim_hashname);
1547 pdkim_hexprint(hhash.data, hhash.len);
1548 }
1549
1550 /* Remember headers block for signing (when the signing library cannot do
1551 incremental) */
1552 if (ctx->flags & PDKIM_MODE_SIGN)
1553 hdata = exim_dkim_data_append(hdata, US sig_hdr);
1554
1555 /* SIGNING ---------------------------------------------------------------- */
1556 if (ctx->flags & PDKIM_MODE_SIGN)
1557 {
1558 es_ctx sctx;
1559
1560 /* Import private key, including the keytype */
1561 /*XXX extend for non-RSA algos */
1562 if ((*err = exim_dkim_signing_init(US sig->privkey, &sctx)))
1563 {
1564 DEBUG(D_acl) debug_printf("signing_init: %s\n", *err);
1565 return PDKIM_ERR_RSA_PRIVKEY;
1566 }
1567
1568 /* Do signing. With OpenSSL we are signing the hash of headers just
1569 calculated, with GnuTLS we have to sign an entire block of headers
1570 (due to available interfaces) and it recalculates the hash internally. */
1571
1572 #if defined(SIGN_GNUTLS)
1573 hhash.data = hdata->s;
1574 hhash.len = hdata->ptr;
1575 #endif
1576
1577 /*XXX extend for non-RSA algos */
1578 if ((*err = exim_dkim_sign(&sctx,
1579 pdkim_hashes[sig->hashtype].exim_hashmethod,
1580 &hhash, &sig->sighash)))
1581 {
1582 DEBUG(D_acl) debug_printf("signing: %s\n", *err);
1583 return PDKIM_ERR_RSA_SIGNING;
1584 }
1585
1586 DEBUG(D_acl)
1587 {
1588 debug_printf( "PDKIM [%s] b computed: ", sig->domain);
1589 pdkim_hexprint(sig->sighash.data, sig->sighash.len);
1590 }
1591
1592 sig->signature_header = pdkim_create_header(sig, TRUE);
1593 }
1594
1595 /* VERIFICATION ----------------------------------------------------------- */
1596 else
1597 {
1598 ev_ctx vctx;
1599
1600 /* Make sure we have all required signature tags */
1601 if (!( sig->domain && *sig->domain
1602 && sig->selector && *sig->selector
1603 && sig->headernames && *sig->headernames
1604 && sig->bodyhash.data
1605 && sig->sighash.data
1606 && sig->keytype >= 0
1607 && sig->hashtype >= 0
1608 && sig->version
1609 ) )
1610 {
1611 sig->verify_status = PDKIM_VERIFY_INVALID;
1612 sig->verify_ext_status = PDKIM_VERIFY_INVALID_SIGNATURE_ERROR;
1613
1614 DEBUG(D_acl) debug_printf(
1615 " Error in DKIM-Signature header: tags missing or invalid\n"
1616 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1617 goto NEXT_VERIFY;
1618 }
1619
1620 /* Make sure sig uses supported DKIM version (only v1) */
1621 if (sig->version != 1)
1622 {
1623 sig->verify_status = PDKIM_VERIFY_INVALID;
1624 sig->verify_ext_status = PDKIM_VERIFY_INVALID_DKIM_VERSION;
1625
1626 DEBUG(D_acl) debug_printf(
1627 " Error in DKIM-Signature header: unsupported DKIM version\n"
1628 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1629 goto NEXT_VERIFY;
1630 }
1631
1632 DEBUG(D_acl)
1633 {
1634 debug_printf( "PDKIM [%s] b from mail: ", sig->domain);
1635 pdkim_hexprint(sig->sighash.data, sig->sighash.len);
1636 }
1637
1638 if (!(sig->pubkey = pdkim_key_from_dns(ctx, sig, &vctx, err)))
1639 goto NEXT_VERIFY;
1640
1641 /* If the pubkey limits to a list of specific hashes, ignore sigs that
1642 do not have the hash part of the sig algorithm matching */
1643
1644 if (sig->pubkey->hashes)
1645 {
1646 const uschar * list = sig->pubkey->hashes, * ele;
1647 int sep = ':';
1648 while ((ele = string_nextinlist(&list, &sep, NULL, 0)))
1649 if (Ustrcmp(ele, pdkim_hashes[sig->hashtype].dkim_hashname) == 0) break;
1650 if (!ele)
1651 {
1652 DEBUG(D_acl) debug_printf("pubkey h=%s vs. sig a=%s_%s\n",
1653 sig->pubkey->hashes,
1654 pdkim_keytypes[sig->keytype],
1655 pdkim_hashes[sig->hashtype].dkim_hashname);
1656 sig->verify_status = PDKIM_VERIFY_FAIL;
1657 sig->verify_ext_status = PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH;
1658 goto NEXT_VERIFY;
1659 }
1660 }
1661
1662 /* Check the signature */
1663 /*XXX needs extension for non-RSA */
1664 if ((*err = exim_dkim_verify(&vctx,
1665 pdkim_hashes[sig->hashtype].exim_hashmethod,
1666 &hhash, &sig->sighash)))
1667 {
1668 DEBUG(D_acl) debug_printf("headers verify: %s\n", *err);
1669 sig->verify_status = PDKIM_VERIFY_FAIL;
1670 sig->verify_ext_status = PDKIM_VERIFY_FAIL_MESSAGE;
1671 goto NEXT_VERIFY;
1672 }
1673
1674
1675 /* We have a winner! (if bodyhash was correct earlier) */
1676 if (sig->verify_status == PDKIM_VERIFY_NONE)
1677 sig->verify_status = PDKIM_VERIFY_PASS;
1678
1679 NEXT_VERIFY:
1680
1681 DEBUG(D_acl)
1682 {
1683 debug_printf("PDKIM [%s] signature status: %s",
1684 sig->domain, pdkim_verify_status_str(sig->verify_status));
1685 if (sig->verify_ext_status > 0)
1686 debug_printf(" (%s)\n",
1687 pdkim_verify_ext_status_str(sig->verify_ext_status));
1688 else
1689 debug_printf("\n");
1690 }
1691 }
1692 }
1693
1694 /* If requested, set return pointer to signature(s) */
1695 if (return_signatures)
1696 *return_signatures = ctx->sig;
1697
1698 return PDKIM_OK;
1699 }
1700
1701
1702 /* -------------------------------------------------------------------------- */
1703
1704 DLLEXPORT pdkim_ctx *
1705 pdkim_init_verify(uschar * (*dns_txt_callback)(char *), BOOL dot_stuffing)
1706 {
1707 pdkim_ctx * ctx;
1708
1709 ctx = store_get(sizeof(pdkim_ctx));
1710 memset(ctx, 0, sizeof(pdkim_ctx));
1711
1712 if (dot_stuffing) ctx->flags = PDKIM_DOT_TERM;
1713 ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN);
1714 ctx->dns_txt_callback = dns_txt_callback;
1715
1716 return ctx;
1717 }
1718
1719
1720 /* -------------------------------------------------------------------------- */
1721
1722 /*XXX ? needs extension to cover non-RSA algo? */
1723
1724 DLLEXPORT pdkim_signature *
1725 pdkim_init_sign(pdkim_ctx * ctx,
1726 uschar * domain, uschar * selector, uschar * privkey,
1727 uschar * hashname, const uschar ** errstr)
1728 {
1729 int hashtype;
1730 pdkim_signature * sig;
1731
1732 if (!domain || !selector || !privkey)
1733 return NULL;
1734
1735 /* Allocate & init one signature struct */
1736
1737 sig = store_get(sizeof(pdkim_signature));
1738 memset(sig, 0, sizeof(pdkim_signature));
1739
1740 sig->bodylength = -1;
1741
1742 sig->domain = string_copy(US domain);
1743 sig->selector = string_copy(US selector);
1744 sig->privkey = string_copy(US privkey);
1745 /*XXX no keytype yet; comes from privkey */
1746
1747 for (hashtype = 0; hashtype < nelem(pdkim_hashes); hashtype++)
1748 if (Ustrcmp(hashname, pdkim_hashes[hashtype].dkim_hashname) == 0)
1749 { sig->hashtype = hashtype; break; }
1750 if (hashtype >= nelem(pdkim_hashes))
1751 {
1752 DEBUG(D_acl)
1753 debug_printf("PDKIM: unrecognised hashname '%s'\n", hashname);
1754 return NULL;
1755 }
1756
1757 DEBUG(D_acl)
1758 {
1759 pdkim_signature s = *sig;
1760 ev_ctx vctx;
1761
1762 debug_printf("PDKIM (checking verify key)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1763 if (!pdkim_key_from_dns(ctx, &s, &vctx, errstr))
1764 debug_printf("WARNING: bad dkim key in dns\n");
1765 debug_printf("PDKIM (finished checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1766 }
1767 return sig;
1768 }
1769
1770
1771 /* -------------------------------------------------------------------------- */
1772
1773 DLLEXPORT void
1774 pdkim_set_optional(pdkim_signature * sig,
1775 char * sign_headers,
1776 char * identity,
1777 int canon_headers,
1778 int canon_body,
1779 long bodylength,
1780 unsigned long created,
1781 unsigned long expires)
1782 {
1783 if (identity)
1784 sig->identity = string_copy(US identity);
1785
1786 sig->sign_headers = string_copy(sign_headers
1787 ? US sign_headers : US PDKIM_DEFAULT_SIGN_HEADERS);
1788
1789 sig->canon_headers = canon_headers;
1790 sig->canon_body = canon_body;
1791 sig->bodylength = bodylength;
1792 sig->created = created;
1793 sig->expires = expires;
1794
1795 return;
1796 }
1797
1798
1799
1800 /* Set up a blob for calculating the bodyhash according to the
1801 needs of this signature. Use an existing one if possible, or
1802 create a new one.
1803
1804 Return: hashblob pointer, or NULL on error (only used as a boolean).
1805 */
1806 pdkim_bodyhash *
1807 pdkim_set_bodyhash(pdkim_ctx * ctx, pdkim_signature * sig)
1808 {
1809 pdkim_bodyhash * b;
1810
1811 for (b = ctx->bodyhash; b; b = b->next)
1812 if ( sig->hashtype == b->hashtype
1813 && sig->canon_body == b->canon_method
1814 && sig->bodylength == b->bodylength)
1815 goto old;
1816
1817 b = store_get(sizeof(pdkim_bodyhash));
1818 b->next = ctx->bodyhash;
1819 b->hashtype = sig->hashtype;
1820 b->canon_method = sig->canon_body;
1821 b->bodylength = sig->bodylength;
1822 if (!exim_sha_init(&b->body_hash_ctx, /*XXX hash method: extend for sha512 */
1823 pdkim_hashes[sig->hashtype].exim_hashmethod))
1824 {
1825 DEBUG(D_acl)
1826 debug_printf("PDKIM: hash init error, possibly nonhandled hashtype\n");
1827 return NULL;
1828 }
1829 b->signed_body_bytes = 0;
1830 b->num_buffered_blanklines = 0;
1831 ctx->bodyhash = b;
1832
1833 old:
1834 sig->calc_body_hash = b;
1835 return b;
1836 }
1837
1838
1839 /* -------------------------------------------------------------------------- */
1840
1841
1842 void
1843 pdkim_init_context(pdkim_ctx * ctx, BOOL dot_stuffed,
1844 uschar * (*dns_txt_callback)(char *))
1845 {
1846 memset(ctx, 0, sizeof(pdkim_ctx));
1847 ctx->flags = dot_stuffed ? PDKIM_MODE_SIGN | PDKIM_DOT_TERM : PDKIM_MODE_SIGN;
1848 ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN);
1849 DEBUG(D_acl) ctx->dns_txt_callback = dns_txt_callback;
1850 }
1851
1852
1853 void
1854 pdkim_init(void)
1855 {
1856 exim_dkim_init();
1857 }
1858
1859
1860
1861 #endif /*DISABLE_DKIM*/