DKIM: fix selection of header for signing/verification given several. Bug 1792
[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 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 RSA_OPENSSL
36 # include <openssl/rsa.h>
37 # include <openssl/ssl.h>
38 # include <openssl/err.h>
39 #elif defined(RSA_GNUTLS)
40 # include <gnutls/gnutls.h>
41 # include <gnutls/x509.h>
42 #endif
43
44 #include "pdkim.h"
45 #include "rsa.h"
46
47 #define PDKIM_SIGNATURE_VERSION "1"
48 #define PDKIM_PUB_RECORD_VERSION "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 #define PDKIM_DEFAULT_SIGN_HEADERS "From:Sender:Reply-To:Subject:Date:"\
55 "Message-ID:To:Cc:MIME-Version:Content-Type:"\
56 "Content-Transfer-Encoding:Content-ID:"\
57 "Content-Description:Resent-Date:Resent-From:"\
58 "Resent-Sender:Resent-To:Resent-Cc:"\
59 "Resent-Message-ID:In-Reply-To:References:"\
60 "List-Id:List-Help:List-Unsubscribe:"\
61 "List-Subscribe:List-Post:List-Owner:List-Archive"
62
63 /* -------------------------------------------------------------------------- */
64 struct pdkim_stringlist {
65 char *value;
66 int tag;
67 void *next;
68 };
69
70 #define PDKIM_STR_ALLOC_FRAG 256
71 struct pdkim_str {
72 char *str;
73 unsigned int len;
74 unsigned int allocated;
75 };
76
77 /* -------------------------------------------------------------------------- */
78 /* A bunch of list constants */
79 const char *pdkim_querymethods[] = {
80 "dns/txt",
81 NULL
82 };
83 const char *pdkim_algos[] = {
84 "rsa-sha256",
85 "rsa-sha1",
86 NULL
87 };
88 const char *pdkim_canons[] = {
89 "simple",
90 "relaxed",
91 NULL
92 };
93 const char *pdkim_hashes[] = {
94 "sha256",
95 "sha1",
96 NULL
97 };
98 const char *pdkim_keytypes[] = {
99 "rsa",
100 NULL
101 };
102
103 typedef struct pdkim_combined_canon_entry {
104 const char *str;
105 int canon_headers;
106 int canon_body;
107 } pdkim_combined_canon_entry;
108
109 pdkim_combined_canon_entry pdkim_combined_canons[] = {
110 { "simple/simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
111 { "simple/relaxed", PDKIM_CANON_SIMPLE, PDKIM_CANON_RELAXED },
112 { "relaxed/simple", PDKIM_CANON_RELAXED, PDKIM_CANON_SIMPLE },
113 { "relaxed/relaxed", PDKIM_CANON_RELAXED, PDKIM_CANON_RELAXED },
114 { "simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
115 { "relaxed", PDKIM_CANON_RELAXED, PDKIM_CANON_SIMPLE },
116 { NULL, 0, 0 }
117 };
118
119
120 /* -------------------------------------------------------------------------- */
121
122 const char *
123 pdkim_verify_status_str(int status)
124 {
125 switch(status) {
126 case PDKIM_VERIFY_NONE: return "PDKIM_VERIFY_NONE";
127 case PDKIM_VERIFY_INVALID: return "PDKIM_VERIFY_INVALID";
128 case PDKIM_VERIFY_FAIL: return "PDKIM_VERIFY_FAIL";
129 case PDKIM_VERIFY_PASS: return "PDKIM_VERIFY_PASS";
130 default: return "PDKIM_VERIFY_UNKNOWN";
131 }
132 }
133
134 const char *
135 pdkim_verify_ext_status_str(int ext_status)
136 {
137 switch(ext_status) {
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_INVALID_PUBKEY_UNAVAILABLE: return "PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE";
141 case PDKIM_VERIFY_INVALID_BUFFER_SIZE: return "PDKIM_VERIFY_INVALID_BUFFER_SIZE";
142 case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD: return "PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD";
143 case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT: return "PDKIM_VERIFY_INVALID_PUBKEY_IMPORT";
144 default: return "PDKIM_VERIFY_UNKNOWN";
145 }
146 }
147
148
149 /* -------------------------------------------------------------------------- */
150 /* Print debugging functions */
151 static void
152 pdkim_quoteprint(const char *data, int len)
153 {
154 int i;
155 const unsigned char *p = (const unsigned char *)data;
156
157 for (i = 0; i < len; i++)
158 {
159 const int c = p[i];
160 switch (c)
161 {
162 case ' ' : debug_printf("{SP}"); break;
163 case '\t': debug_printf("{TB}"); break;
164 case '\r': debug_printf("{CR}"); break;
165 case '\n': debug_printf("{LF}"); break;
166 case '{' : debug_printf("{BO}"); break;
167 case '}' : debug_printf("{BC}"); break;
168 default:
169 if ( (c < 32) || (c > 127) )
170 debug_printf("{%02x}", c);
171 else
172 debug_printf("%c", c);
173 break;
174 }
175 }
176 debug_printf("\n");
177 }
178
179 static void
180 pdkim_hexprint(const char *data, int len)
181 {
182 int i;
183 const unsigned char *p = (const unsigned char *)data;
184
185 for (i = 0 ; i < len; i++)
186 debug_printf("%02x", p[i]);
187 debug_printf("\n");
188 }
189
190
191
192 /* SSS probably want to keep the "stringlist" notion */
193
194 static pdkim_stringlist *
195 pdkim_prepend_stringlist(pdkim_stringlist *base, char *str)
196 {
197 pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist));
198
199 if (!new_entry) return NULL;
200 memset(new_entry, 0, sizeof(pdkim_stringlist));
201 if (!(new_entry->value = strdup(str))) return NULL;
202 if (base) new_entry->next = base;
203 return new_entry;
204 }
205
206
207 /* -------------------------------------------------------------------------- */
208 /* A small "growing string" implementation to escape malloc/realloc hell */
209 /* String package: should be replaced by Exim standard ones */
210 /* SSS Ustrcpy */
211
212 static pdkim_str *
213 pdkim_strnew (const char *cstr)
214 {
215 unsigned int len = cstr ? strlen(cstr) : 0;
216 pdkim_str *p = malloc(sizeof(pdkim_str));
217
218 if (!p) return NULL;
219 memset(p, 0, sizeof(pdkim_str));
220 if (!(p->str = malloc(len+1)))
221 {
222 free(p);
223 return NULL;
224 }
225 p->allocated = len+1;
226 p->len = len;
227 if (cstr)
228 strcpy(p->str, cstr);
229 else
230 p->str[p->len] = '\0';
231 return p;
232 }
233
234
235 /*SSS Ustrncat */
236
237 static char *
238 pdkim_strncat(pdkim_str *str, const char *data, int len)
239 {
240 if ((str->allocated - str->len) < (len+1))
241 {
242 /* Extend the buffer */
243 int num_frags = ((len+1)/PDKIM_STR_ALLOC_FRAG)+1;
244 char *n = realloc(str->str,
245 (str->allocated+(num_frags*PDKIM_STR_ALLOC_FRAG)));
246 if (n == NULL) return NULL;
247 str->str = n;
248 str->allocated += (num_frags*PDKIM_STR_ALLOC_FRAG);
249 }
250 strncpy(&(str->str[str->len]), data, len);
251 str->len += len;
252 str->str[str->len] = '\0';
253 return str->str;
254 }
255
256
257 /* SSS Ustrcat */
258
259 static char *
260 pdkim_strcat(pdkim_str *str, const char *cstr)
261 {
262 return pdkim_strncat(str, cstr, strlen(cstr));
263 }
264
265
266
267 /* Trim whitespace fore & aft */
268
269 static char *
270 pdkim_strtrim(pdkim_str *str)
271 {
272 char *p = str->str;
273 char *q = str->str;
274 while (*p == '\t' || *p == ' ') p++; /* skip whitespace */
275 while (*p) {*q = *p; q++; p++;} /* dump the leading whitespace */
276 *q = '\0';
277 while (q != str->str && ( (*q == '\0') || (*q == '\t') || (*q == ' ') ) )
278 { /* dump trailing whitespace */
279 *q = '\0';
280 q--;
281 }
282 str->len = strlen(str->str);
283 return str->str;
284 }
285
286
287
288 static char *
289 pdkim_strclear(pdkim_str *str)
290 {
291 str->str[0] = '\0';
292 str->len = 0;
293 return str->str;
294 }
295
296
297
298 static void
299 pdkim_strfree(pdkim_str *str)
300 {
301 if (!str) return;
302 if (str->str) free(str->str);
303 free(str);
304 }
305
306
307 static void
308 pdkim_stringlist_free(pdkim_stringlist * e)
309 {
310 while(e)
311 {
312 pdkim_stringlist * c = e;
313 if (e->value) free(e->value);
314 e = e->next;
315 free(c);
316 }
317 }
318
319
320
321 /* -------------------------------------------------------------------------- */
322
323 static void
324 pdkim_free_pubkey(pdkim_pubkey *pub)
325 {
326 if (pub)
327 {
328 if (pub->version ) free(pub->version);
329 if (pub->granularity) free(pub->granularity);
330 if (pub->hashes ) free(pub->hashes);
331 if (pub->keytype ) free(pub->keytype);
332 if (pub->srvtype ) free(pub->srvtype);
333 if (pub->notes ) free(pub->notes);
334 free(pub);
335 }
336 }
337
338
339 /* -------------------------------------------------------------------------- */
340
341 static void
342 pdkim_free_sig(pdkim_signature *sig)
343 {
344 if (sig)
345 {
346 pdkim_signature *next = (pdkim_signature *)sig->next;
347
348 pdkim_stringlist_free(sig->headers);
349 if (sig->selector ) free(sig->selector);
350 if (sig->domain ) free(sig->domain);
351 if (sig->identity ) free(sig->identity);
352 if (sig->copiedheaders ) free(sig->copiedheaders);
353 if (sig->rsa_privkey ) free(sig->rsa_privkey);
354 if (sig->sign_headers ) free(sig->sign_headers);
355 if (sig->signature_header) free(sig->signature_header);
356
357 if (sig->pubkey) pdkim_free_pubkey(sig->pubkey);
358
359 free(sig);
360 if (next) pdkim_free_sig(next);
361 }
362 }
363
364
365 /* -------------------------------------------------------------------------- */
366
367 DLLEXPORT void
368 pdkim_free_ctx(pdkim_ctx *ctx)
369 {
370 if (ctx)
371 {
372 pdkim_stringlist_free(ctx->headers);
373 pdkim_free_sig(ctx->sig);
374 pdkim_strfree(ctx->cur_header);
375 free(ctx);
376 }
377 }
378
379
380 /* -------------------------------------------------------------------------- */
381 /* Matches the name of the passed raw "header" against
382 the passed colon-separated "tick", and invalidates
383 the entry in tick. Returns OK or fail-code */
384 /*XXX might be safer done using a pdkim_stringlist for "tick" */
385
386 static int
387 header_name_match(const char * header, char * tick)
388 {
389 char *hname;
390 char *lcopy;
391 char *p;
392 char *q;
393 int rc = PDKIM_FAIL;
394
395 /* Get header name */
396 char *hcolon = strchr(header, ':');
397
398 if (!hcolon) return rc; /* This isn't a header */
399
400 if (!(hname = malloc((hcolon-header)+1)))
401 return PDKIM_ERR_OOM;
402 memset(hname, 0, (hcolon-header)+1);
403 strncpy(hname, header, (hcolon-header));
404
405 /* Copy tick-off list locally, so we can punch zeroes into it */
406 if (!(lcopy = strdup(tick)))
407 {
408 free(hname);
409 return PDKIM_ERR_OOM;
410 }
411 p = lcopy;
412 q = strchr(p, ':');
413 while (q)
414 {
415 *q = '\0';
416
417 if (strcasecmp(p, hname) == 0)
418 {
419 rc = PDKIM_OK;
420 /* Invalidate header name instance in tick-off list */
421 tick[p-lcopy] = '_';
422 goto BAIL;
423 }
424
425 p = q+1;
426 q = strchr(p, ':');
427 }
428
429 if (strcasecmp(p, hname) == 0)
430 {
431 rc = PDKIM_OK;
432 /* Invalidate header name instance in tick-off list */
433 tick[p-lcopy] = '_';
434 }
435
436 BAIL:
437 free(hname);
438 free(lcopy);
439 return rc;
440 }
441
442
443 /* -------------------------------------------------------------------------- */
444 /* Performs "relaxed" canonicalization of a header. The returned pointer needs
445 to be free()d. */
446
447 static char *
448 pdkim_relax_header (char *header, int crlf)
449 {
450 BOOL past_field_name = FALSE;
451 BOOL seen_wsp = FALSE;
452 char *p;
453 char *q;
454 char *relaxed = malloc(strlen(header)+3);
455
456 if (!relaxed) return NULL;
457
458 q = relaxed;
459 for (p = header; *p != '\0'; p++)
460 {
461 int c = *p;
462 /* Ignore CR & LF */
463 if (c == '\r' || c == '\n')
464 continue;
465 if (c == '\t' || c == ' ')
466 {
467 if (seen_wsp)
468 continue;
469 c = ' '; /* Turns WSP into SP */
470 seen_wsp = TRUE;
471 }
472 else
473 if (!past_field_name && c == ':')
474 {
475 if (seen_wsp) q--; /* This removes WSP before the colon */
476 seen_wsp = TRUE; /* This removes WSP after the colon */
477 past_field_name = TRUE;
478 }
479 else
480 seen_wsp = FALSE;
481
482 /* Lowercase header name */
483 if (!past_field_name) c = tolower(c);
484 *q++ = c;
485 }
486
487 if (q > relaxed && q[-1] == ' ') q--; /* Squash eventual trailing SP */
488 *q = '\0';
489
490 if (crlf) strcat(relaxed, "\r\n");
491 return relaxed;
492 }
493
494
495 /* -------------------------------------------------------------------------- */
496 #define PDKIM_QP_ERROR_DECODE -1
497
498 static char *
499 pdkim_decode_qp_char(char *qp_p, int *c)
500 {
501 char *initial_pos = qp_p;
502
503 /* Advance one char */
504 qp_p++;
505
506 /* Check for two hex digits and decode them */
507 if (isxdigit(*qp_p) && isxdigit(qp_p[1]))
508 {
509 /* Do hex conversion */
510 *c = (isdigit(*qp_p) ? *qp_p - '0' : toupper(*qp_p) - 'A' + 10) << 4;
511 *c |= isdigit(qp_p[1]) ? qp_p[1] - '0' : toupper(qp_p[1]) - 'A' + 10;
512 return qp_p + 2;
513 }
514
515 /* Illegal char here */
516 *c = PDKIM_QP_ERROR_DECODE;
517 return initial_pos;
518 }
519
520
521 /* -------------------------------------------------------------------------- */
522
523 static char *
524 pdkim_decode_qp(char *str)
525 {
526 int nchar = 0;
527 char *q;
528 char *p = str;
529 char *n = malloc(strlen(p)+1);
530
531 if (!n) return NULL;
532
533 *n = '\0';
534 q = n;
535 while (*p != '\0')
536 {
537 if (*p == '=')
538 {
539 p = pdkim_decode_qp_char(p, &nchar);
540 if (nchar >= 0)
541 {
542 *q++ = nchar;
543 continue;
544 }
545 }
546 else
547 *q++ = *p;
548 p++;
549 }
550 *q = '\0';
551 return n;
552 }
553
554
555 /* -------------------------------------------------------------------------- */
556
557 static void
558 pdkim_decode_base64(uschar *str, blob * b)
559 {
560 int dlen;
561 char *res;
562 dlen = b64decode(str, &b->data);
563 if (dlen < 0) b->data = NULL;
564 b->len = dlen;
565 }
566
567 /* -------------------------------------------------------------------------- */
568
569 static char *
570 pdkim_encode_base64(blob * b)
571 {
572 char * ret;
573 int old_pool = store_pool;
574
575 store_pool = POOL_PERM;
576 ret = CS b64encode(b->data, b->len);
577 store_pool = old_pool;
578 return ret;
579 }
580
581
582 /* -------------------------------------------------------------------------- */
583 #define PDKIM_HDR_LIMBO 0
584 #define PDKIM_HDR_TAG 1
585 #define PDKIM_HDR_VALUE 2
586
587 static pdkim_signature *
588 pdkim_parse_sig_header(pdkim_ctx *ctx, char *raw_hdr)
589 {
590 pdkim_signature *sig ;
591 char *p, *q;
592 pdkim_str *cur_tag = NULL;
593 pdkim_str *cur_val = NULL;
594 BOOL past_hname = FALSE;
595 BOOL in_b_val = FALSE;
596 int where = PDKIM_HDR_LIMBO;
597 int i;
598 int old_pool = store_pool;
599
600 /* There is a store-reset between header & body reception
601 so cannot use the main pool. Any allocs done by Exim
602 memory-handling must use the perm pool. */
603
604 store_pool = POOL_PERM;
605
606 if (!(sig = malloc(sizeof(pdkim_signature)))) return NULL;
607 memset(sig, 0, sizeof(pdkim_signature));
608 sig->bodylength = -1;
609
610 if (!(sig->rawsig_no_b_val = malloc(strlen(raw_hdr)+1)))
611 {
612 free(sig);
613 return NULL;
614 }
615
616 q = sig->rawsig_no_b_val;
617
618 for (p = raw_hdr; ; p++)
619 {
620 char c = *p;
621
622 /* Ignore FWS */
623 if (c == '\r' || c == '\n')
624 goto NEXT_CHAR;
625
626 /* Fast-forward through header name */
627 if (!past_hname)
628 {
629 if (c == ':') past_hname = TRUE;
630 goto NEXT_CHAR;
631 }
632
633 if (where == PDKIM_HDR_LIMBO)
634 {
635 /* In limbo, just wait for a tag-char to appear */
636 if (!(c >= 'a' && c <= 'z'))
637 goto NEXT_CHAR;
638
639 where = PDKIM_HDR_TAG;
640 }
641
642 if (where == PDKIM_HDR_TAG)
643 {
644 if (!cur_tag)
645 cur_tag = pdkim_strnew(NULL);
646
647 if (c >= 'a' && c <= 'z')
648 pdkim_strncat(cur_tag, p, 1);
649
650 if (c == '=')
651 {
652 if (strcmp(cur_tag->str, "b") == 0)
653 {
654 *q = '='; q++;
655 in_b_val = TRUE;
656 }
657 where = PDKIM_HDR_VALUE;
658 goto NEXT_CHAR;
659 }
660 }
661
662 if (where == PDKIM_HDR_VALUE)
663 {
664 if (!cur_val)
665 cur_val = pdkim_strnew(NULL);
666
667 if (c == '\r' || c == '\n' || c == ' ' || c == '\t')
668 goto NEXT_CHAR;
669
670 if (c == ';' || c == '\0')
671 {
672 if (cur_tag->len > 0)
673 {
674 pdkim_strtrim(cur_val);
675
676 DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag->str, cur_val->str);
677
678 switch (cur_tag->str[0])
679 {
680 case 'b':
681 if (cur_tag->str[1] == 'h')
682 pdkim_decode_base64(US cur_val->str, &sig->bodyhash);
683 else
684 pdkim_decode_base64(US cur_val->str, &sig->sigdata);
685 break;
686 case 'v':
687 /* We only support version 1, and that is currently the
688 only version there is. */
689 if (strcmp(cur_val->str, PDKIM_SIGNATURE_VERSION) == 0)
690 sig->version = 1;
691 break;
692 case 'a':
693 for (i = 0; pdkim_algos[i]; i++)
694 if (strcmp(cur_val->str, pdkim_algos[i]) == 0)
695 {
696 sig->algo = i;
697 break;
698 }
699 break;
700 case 'c':
701 for (i = 0; pdkim_combined_canons[i].str; i++)
702 if (strcmp(cur_val->str, pdkim_combined_canons[i].str) == 0)
703 {
704 sig->canon_headers = pdkim_combined_canons[i].canon_headers;
705 sig->canon_body = pdkim_combined_canons[i].canon_body;
706 break;
707 }
708 break;
709 case 'q':
710 for (i = 0; pdkim_querymethods[i]; i++)
711 if (strcmp(cur_val->str, pdkim_querymethods[i]) == 0)
712 {
713 sig->querymethod = i;
714 break;
715 }
716 break;
717 case 's':
718 sig->selector = strdup(cur_val->str); break;
719 case 'd':
720 sig->domain = strdup(cur_val->str); break;
721 case 'i':
722 sig->identity = pdkim_decode_qp(cur_val->str); break;
723 case 't':
724 sig->created = strtoul(cur_val->str, NULL, 10); break;
725 case 'x':
726 sig->expires = strtoul(cur_val->str, NULL, 10); break;
727 case 'l':
728 sig->bodylength = strtol(cur_val->str, NULL, 10); break;
729 case 'h':
730 sig->headernames = string_copy(cur_val->str); break;
731 case 'z':
732 sig->copiedheaders = pdkim_decode_qp(cur_val->str); break;
733 default:
734 DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
735 break;
736 }
737 }
738 pdkim_strclear(cur_tag);
739 pdkim_strclear(cur_val);
740 in_b_val = FALSE;
741 where = PDKIM_HDR_LIMBO;
742 }
743 else
744 pdkim_strncat(cur_val, p, 1);
745 }
746
747 NEXT_CHAR:
748 if (c == '\0')
749 break;
750
751 if (!in_b_val)
752 *q++ = c;
753 }
754
755 store_pool = old_pool;
756
757 /* Make sure the most important bits are there. */
758 if (!(sig->domain && (*(sig->domain) != '\0') &&
759 sig->selector && (*(sig->selector) != '\0') &&
760 sig->headernames && (*(sig->headernames) != '\0') &&
761 sig->version))
762 {
763 pdkim_free_sig(sig);
764 return NULL;
765 }
766
767 *q = '\0';
768 /* Chomp raw header. The final newline must not be added to the signature. */
769 q--;
770 while (q > sig->rawsig_no_b_val && (*q == '\r' || *q == '\n'))
771 *q = '\0'; q--; /*XXX questionable code layout; possible bug */
772
773 DEBUG(D_acl)
774 {
775 debug_printf(
776 "PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
777 pdkim_quoteprint(sig->rawsig_no_b_val, strlen(sig->rawsig_no_b_val));
778 debug_printf(
779 "PDKIM >> Sig size: %4d bits\n", sig->sigdata.len*8);
780 debug_printf(
781 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
782 }
783
784 exim_sha_init(&sig->body_hash, sig->algo == PDKIM_ALGO_RSA_SHA1);
785 return sig;
786 }
787
788
789 /* -------------------------------------------------------------------------- */
790
791 static pdkim_pubkey *
792 pdkim_parse_pubkey_record(pdkim_ctx *ctx, char *raw_record)
793 {
794 pdkim_pubkey *pub;
795 char *p;
796 pdkim_str *cur_tag = NULL;
797 pdkim_str *cur_val = NULL;
798 int where = PDKIM_HDR_LIMBO;
799
800 if (!(pub = malloc(sizeof(pdkim_pubkey)))) return NULL;
801 memset(pub, 0, sizeof(pdkim_pubkey));
802
803 for (p = raw_record; ; p++)
804 {
805 char c = *p;
806
807 /* Ignore FWS */
808 if (c == '\r' || c == '\n')
809 goto NEXT_CHAR;
810
811 if (where == PDKIM_HDR_LIMBO)
812 {
813 /* In limbo, just wait for a tag-char to appear */
814 if (!(c >= 'a' && c <= 'z'))
815 goto NEXT_CHAR;
816
817 where = PDKIM_HDR_TAG;
818 }
819
820 if (where == PDKIM_HDR_TAG)
821 {
822 if (!cur_tag)
823 cur_tag = pdkim_strnew(NULL);
824
825 if (c >= 'a' && c <= 'z')
826 pdkim_strncat(cur_tag, p, 1);
827
828 if (c == '=')
829 {
830 where = PDKIM_HDR_VALUE;
831 goto NEXT_CHAR;
832 }
833 }
834
835 if (where == PDKIM_HDR_VALUE)
836 {
837 if (!cur_val)
838 cur_val = pdkim_strnew(NULL);
839
840 if (c == '\r' || c == '\n')
841 goto NEXT_CHAR;
842
843 if (c == ';' || c == '\0')
844 {
845 if (cur_tag->len > 0)
846 {
847 pdkim_strtrim(cur_val);
848 DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag->str, cur_val->str);
849
850 switch (cur_tag->str[0])
851 {
852 case 'v':
853 /* This tag isn't evaluated because:
854 - We only support version DKIM1.
855 - Which is the default for this value (set below)
856 - Other versions are currently not specified. */
857 break;
858 case 'h':
859 pub->hashes = strdup(cur_val->str); break;
860 case 'g':
861 pub->granularity = strdup(cur_val->str); break;
862 case 'n':
863 pub->notes = pdkim_decode_qp(cur_val->str); break;
864 case 'p':
865 pdkim_decode_base64(US cur_val->str, &pub->key);
866 break;
867 case 'k':
868 pub->hashes = strdup(cur_val->str); break;
869 case 's':
870 pub->srvtype = strdup(cur_val->str); break;
871 case 't':
872 if (strchr(cur_val->str, 'y') != NULL) pub->testing = 1;
873 if (strchr(cur_val->str, 's') != NULL) pub->no_subdomaining = 1;
874 break;
875 default:
876 DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
877 break;
878 }
879 }
880 pdkim_strclear(cur_tag);
881 pdkim_strclear(cur_val);
882 where = PDKIM_HDR_LIMBO;
883 }
884 else
885 pdkim_strncat(cur_val, p, 1);
886 }
887
888 NEXT_CHAR:
889 if (c == '\0') break;
890 }
891
892 /* Set fallback defaults */
893 if (!pub->version ) pub->version = strdup(PDKIM_PUB_RECORD_VERSION);
894 if (!pub->granularity) pub->granularity = strdup("*");
895 if (!pub->keytype ) pub->keytype = strdup("rsa");
896 if (!pub->srvtype ) pub->srvtype = strdup("*");
897
898 /* p= is required */
899 if (pub->key.data)
900 return pub;
901
902 pdkim_free_pubkey(pub);
903 return NULL;
904 }
905
906
907 /* -------------------------------------------------------------------------- */
908
909 static int
910 pdkim_update_bodyhash(pdkim_ctx *ctx, const char *data, int len)
911 {
912 pdkim_signature *sig = ctx->sig;
913 /* Cache relaxed version of data */
914 char *relaxed_data = NULL;
915 int relaxed_len = 0;
916
917 /* Traverse all signatures, updating their hashes. */
918 while (sig)
919 {
920 /* Defaults to simple canon (no further treatment necessary) */
921 const char *canon_data = data;
922 int canon_len = len;
923
924 if (sig->canon_body == PDKIM_CANON_RELAXED)
925 {
926 /* Relax the line if not done already */
927 if (!relaxed_data)
928 {
929 BOOL seen_wsp = FALSE;
930 const char *p;
931 int q = 0;
932
933 if (!(relaxed_data = malloc(len+1)))
934 return PDKIM_ERR_OOM;
935
936 for (p = data; *p; p++)
937 {
938 char c = *p;
939 if (c == '\r')
940 {
941 if (q > 0 && relaxed_data[q-1] == ' ')
942 q--;
943 }
944 else if (c == '\t' || c == ' ')
945 {
946 c = ' '; /* Turns WSP into SP */
947 if (seen_wsp)
948 continue;
949 seen_wsp = TRUE;
950 }
951 else
952 seen_wsp = FALSE;
953 relaxed_data[q++] = c;
954 }
955 relaxed_data[q] = '\0';
956 relaxed_len = q;
957 }
958 canon_data = relaxed_data;
959 canon_len = relaxed_len;
960 }
961
962 /* Make sure we don't exceed the to-be-signed body length */
963 if ( sig->bodylength >= 0
964 && sig->signed_body_bytes + (unsigned long)canon_len > sig->bodylength
965 )
966 canon_len = sig->bodylength - sig->signed_body_bytes;
967
968 if (canon_len > 0)
969 {
970 exim_sha_update(&sig->body_hash, canon_data, canon_len);
971 sig->signed_body_bytes += canon_len;
972 DEBUG(D_acl) pdkim_quoteprint(canon_data, canon_len);
973 }
974
975 sig = sig->next;
976 }
977
978 if (relaxed_data) free(relaxed_data);
979 return PDKIM_OK;
980 }
981
982
983 /* -------------------------------------------------------------------------- */
984
985 static int
986 pdkim_finish_bodyhash(pdkim_ctx *ctx)
987 {
988 pdkim_signature *sig;
989
990 /* Traverse all signatures */
991 for (sig = ctx->sig; sig; sig = sig->next)
992 { /* Finish hashes */
993 blob bh;
994
995 exim_sha_finish(&sig->body_hash, &bh);
996
997 DEBUG(D_acl)
998 {
999 debug_printf("PDKIM [%s] Body bytes hashed: %lu\n"
1000 "PDKIM [%s] bh computed: ",
1001 sig->domain, sig->signed_body_bytes, sig->domain);
1002 pdkim_hexprint(CS bh.data, bh.len);
1003 }
1004
1005 /* SIGNING -------------------------------------------------------------- */
1006 if (ctx->mode == PDKIM_MODE_SIGN)
1007 {
1008 sig->bodyhash = bh;
1009
1010 /* If bodylength limit is set, and we have received less bytes
1011 than the requested amount, effectively remove the limit tag. */
1012 if (sig->signed_body_bytes < sig->bodylength)
1013 sig->bodylength = -1;
1014 }
1015
1016 /* VERIFICATION --------------------------------------------------------- */
1017 else
1018 {
1019 /* Compare bodyhash */
1020 if (memcmp(bh.data, sig->bodyhash.data, bh.len) == 0)
1021 {
1022 DEBUG(D_acl) debug_printf("PDKIM [%s] Body hash verified OK\n", sig->domain);
1023 }
1024 else
1025 {
1026 DEBUG(D_acl)
1027 {
1028 debug_printf("PDKIM [%s] bh signature: ", sig->domain);
1029 pdkim_hexprint(sig->bodyhash.data,
1030 exim_sha_hashlen(&sig->body_hash));
1031 debug_printf("PDKIM [%s] Body hash did NOT verify\n", sig->domain);
1032 }
1033 sig->verify_status = PDKIM_VERIFY_FAIL;
1034 sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
1035 }
1036 }
1037 }
1038
1039 return PDKIM_OK;
1040 }
1041
1042
1043
1044 /* -------------------------------------------------------------------------- */
1045 /* Callback from pdkim_feed below for processing complete body lines */
1046
1047 static int
1048 pdkim_bodyline_complete(pdkim_ctx *ctx)
1049 {
1050 char *p = ctx->linebuf;
1051 int n = ctx->linebuf_offset;
1052 pdkim_signature *sig = ctx->sig; /*XXX assumes only one sig */
1053
1054 /* Ignore extra data if we've seen the end-of-data marker */
1055 if (ctx->seen_eod) goto BAIL;
1056
1057 /* We've always got one extra byte to stuff a zero ... */
1058 ctx->linebuf[ctx->linebuf_offset] = '\0';
1059
1060 /* Terminate on EOD marker */
1061 if (memcmp(p, ".\r\n", 3) == 0)
1062 {
1063 /* In simple body mode, if any empty lines were buffered,
1064 replace with one. rfc 4871 3.4.3 */
1065 /*XXX checking the signed-body-bytes is a gross hack; I think
1066 it indicates that all linebreaks should be buffered, including
1067 the one terminating a text line */
1068 if ( sig && sig->canon_body == PDKIM_CANON_SIMPLE
1069 && sig->signed_body_bytes == 0
1070 && ctx->num_buffered_crlf > 0
1071 )
1072 pdkim_update_bodyhash(ctx, "\r\n", 2);
1073
1074 ctx->seen_eod = TRUE;
1075 goto BAIL;
1076 }
1077 /* Unstuff dots */
1078 if (memcmp(p, "..", 2) == 0)
1079 {
1080 p++;
1081 n--;
1082 }
1083
1084 /* Empty lines need to be buffered until we find a non-empty line */
1085 if (memcmp(p, "\r\n", 2) == 0)
1086 {
1087 ctx->num_buffered_crlf++;
1088 goto BAIL;
1089 }
1090
1091 if (sig && sig->canon_body == PDKIM_CANON_RELAXED)
1092 {
1093 /* Lines with just spaces need to be buffered too */
1094 char *check = p;
1095 while (memcmp(check, "\r\n", 2) != 0)
1096 {
1097 char c = *check;
1098
1099 if (c != '\t' && c != ' ')
1100 goto PROCESS;
1101 check++;
1102 }
1103
1104 ctx->num_buffered_crlf++;
1105 goto BAIL;
1106 }
1107
1108 PROCESS:
1109 /* At this point, we have a non-empty line, so release the buffered ones. */
1110 while (ctx->num_buffered_crlf)
1111 {
1112 pdkim_update_bodyhash(ctx, "\r\n", 2);
1113 ctx->num_buffered_crlf--;
1114 }
1115
1116 pdkim_update_bodyhash(ctx, p, n);
1117
1118 BAIL:
1119 ctx->linebuf_offset = 0;
1120 return PDKIM_OK;
1121 }
1122
1123
1124 /* -------------------------------------------------------------------------- */
1125 /* Callback from pdkim_feed below for processing complete headers */
1126 #define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
1127
1128 static int
1129 pdkim_header_complete(pdkim_ctx *ctx)
1130 {
1131 /* Special case: The last header can have an extra \r appended */
1132 if ( (ctx->cur_header->len > 1) &&
1133 (ctx->cur_header->str[(ctx->cur_header->len)-1] == '\r') )
1134 {
1135 ctx->cur_header->str[(ctx->cur_header->len)-1] = '\0';
1136 ctx->cur_header->len--;
1137 }
1138
1139 ctx->num_headers++;
1140 if (ctx->num_headers > PDKIM_MAX_HEADERS) goto BAIL;
1141
1142 /* SIGNING -------------------------------------------------------------- */
1143 if (ctx->mode == PDKIM_MODE_SIGN)
1144 {
1145 pdkim_signature *sig;
1146
1147 for (sig = ctx->sig; sig; sig = sig->next) /* Traverse all signatures */
1148 {
1149 pdkim_stringlist *list;
1150
1151 /* Add header to the signed headers list (in reverse order) */
1152 if (!(list = pdkim_prepend_stringlist(sig->headers,
1153 ctx->cur_header->str)))
1154 return PDKIM_ERR_OOM;
1155 sig->headers = list;
1156 }
1157 }
1158
1159 /* VERIFICATION ----------------------------------------------------------- */
1160 /* DKIM-Signature: headers are added to the verification list */
1161 if (ctx->mode == PDKIM_MODE_VERIFY)
1162 {
1163 if (strncasecmp(ctx->cur_header->str,
1164 DKIM_SIGNATURE_HEADERNAME,
1165 strlen(DKIM_SIGNATURE_HEADERNAME)) == 0)
1166 {
1167 pdkim_signature *new_sig;
1168
1169 /* Create and chain new signature block */
1170 DEBUG(D_acl) debug_printf(
1171 "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1172
1173 if ((new_sig = pdkim_parse_sig_header(ctx, ctx->cur_header->str)))
1174 {
1175 pdkim_signature *last_sig = ctx->sig;
1176 if (!last_sig)
1177 ctx->sig = new_sig;
1178 else
1179 {
1180 while (last_sig->next) last_sig = last_sig->next;
1181 last_sig->next = new_sig;
1182 }
1183 }
1184 else
1185 DEBUG(D_acl) debug_printf(
1186 "Error while parsing signature header\n"
1187 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1188 }
1189
1190 /* every other header is stored for signature verification */
1191 else
1192 {
1193 pdkim_stringlist *list;
1194
1195 if (!(list = pdkim_prepend_stringlist(ctx->headers, ctx->cur_header->str)))
1196 return PDKIM_ERR_OOM;
1197 ctx->headers = list;
1198 }
1199 }
1200
1201 BAIL:
1202 pdkim_strclear(ctx->cur_header); /* Re-use existing pdkim_str */
1203 return PDKIM_OK;
1204 }
1205
1206
1207
1208 /* -------------------------------------------------------------------------- */
1209 #define HEADER_BUFFER_FRAG_SIZE 256
1210
1211 DLLEXPORT int
1212 pdkim_feed (pdkim_ctx *ctx, char *data, int len)
1213 {
1214 int p;
1215
1216 for (p = 0; p<len; p++)
1217 {
1218 char c = data[p];
1219
1220 if (ctx->past_headers)
1221 {
1222 /* Processing body byte */
1223 ctx->linebuf[ctx->linebuf_offset++] = c;
1224 if (c == '\n')
1225 {
1226 int rc = pdkim_bodyline_complete(ctx); /* End of line */
1227 if (rc != PDKIM_OK) return rc;
1228 }
1229 if (ctx->linebuf_offset == (PDKIM_MAX_BODY_LINE_LEN-1))
1230 return PDKIM_ERR_LONG_LINE;
1231 }
1232 else
1233 {
1234 /* Processing header byte */
1235 if (c != '\r')
1236 {
1237 if (c == '\n')
1238 {
1239 if (ctx->seen_lf)
1240 {
1241 int rc = pdkim_header_complete(ctx); /* Seen last header line */
1242 if (rc != PDKIM_OK) return rc;
1243
1244 ctx->past_headers = TRUE;
1245 ctx->seen_lf = 0;
1246 DEBUG(D_acl) debug_printf(
1247 "PDKIM >> Body data for hash, canonicalized >>>>>>>>>>>>>>>>>>>>>>\n");
1248 continue;
1249 }
1250 else
1251 ctx->seen_lf = TRUE;
1252 }
1253 else if (ctx->seen_lf)
1254 {
1255 if (!(c == '\t' || c == ' '))
1256 {
1257 int rc = pdkim_header_complete(ctx); /* End of header */
1258 if (rc != PDKIM_OK) return rc;
1259 }
1260 ctx->seen_lf = FALSE;
1261 }
1262 }
1263
1264 if (!ctx->cur_header)
1265 if (!(ctx->cur_header = pdkim_strnew(NULL)))
1266 return PDKIM_ERR_OOM;
1267
1268 if (ctx->cur_header->len < PDKIM_MAX_HEADER_LEN)
1269 if (!pdkim_strncat(ctx->cur_header, &data[p], 1))
1270 return PDKIM_ERR_OOM;
1271 }
1272 }
1273 return PDKIM_OK;
1274 }
1275
1276 /*
1277 * RFC 5322 specifies that header line length SHOULD be no more than 78
1278 * lets make it so!
1279 * pdkim_headcat
1280 * returns char*
1281 *
1282 * col: this int holds and receives column number (octets since last '\n')
1283 * str: partial string to append to
1284 * pad: padding, split line or space after before or after eg: ";"
1285 * intro: - must join to payload eg "h=", usually the tag name
1286 * payload: eg base64 data - long data can be split arbitrarily.
1287 *
1288 * this code doesn't fold the header in some of the places that RFC4871
1289 * allows: As per RFC5322(2.2.3) it only folds before or after tag-value
1290 * pairs and inside long values. it also always spaces or breaks after the
1291 * "pad"
1292 *
1293 * no guarantees are made for output given out-of range input. like tag
1294 * names longer than 78, or bogus col. Input is assumed to be free of line breaks.
1295 */
1296
1297 static char *
1298 pdkim_headcat(int *col, pdkim_str *str, const char * pad,
1299 const char *intro, const char *payload)
1300 {
1301 size_t l;
1302
1303 if (pad)
1304 {
1305 l = strlen(pad);
1306 if (*col + l > 78)
1307 {
1308 pdkim_strcat(str, "\r\n\t");
1309 *col = 1;
1310 }
1311 pdkim_strncat(str, pad, l);
1312 *col += l;
1313 }
1314
1315 l = (pad?1:0) + (intro?strlen(intro):0);
1316
1317 if (*col + l > 78)
1318 { /*can't fit intro - start a new line to make room.*/
1319 pdkim_strcat(str, "\r\n\t");
1320 *col = 1;
1321 l = intro?strlen(intro):0;
1322 }
1323
1324 l += payload ? strlen(payload):0 ;
1325
1326 while (l>77)
1327 { /* this fragment will not fit on a single line */
1328 if (pad)
1329 {
1330 pdkim_strcat(str, " ");
1331 *col += 1;
1332 pad = NULL; /* only want this once */
1333 l--;
1334 }
1335
1336 if (intro)
1337 {
1338 size_t sl = strlen(intro);
1339
1340 pdkim_strncat(str, intro, sl);
1341 *col += sl;
1342 l -= sl;
1343 intro = NULL; /* only want this once */
1344 }
1345
1346 if (payload)
1347 {
1348 size_t sl = strlen(payload);
1349 size_t chomp = *col+sl < 77 ? sl : 78-*col;
1350
1351 pdkim_strncat(str, payload, chomp);
1352 *col += chomp;
1353 payload += chomp;
1354 l -= chomp-1;
1355 }
1356
1357 /* the while precondition tells us it didn't fit. */
1358 pdkim_strcat(str, "\r\n\t");
1359 *col = 1;
1360 }
1361
1362 if (*col + l > 78)
1363 {
1364 pdkim_strcat(str, "\r\n\t");
1365 *col = 1;
1366 pad = NULL;
1367 }
1368
1369 if (pad)
1370 {
1371 pdkim_strcat(str, " ");
1372 *col += 1;
1373 pad = NULL;
1374 }
1375
1376 if (intro)
1377 {
1378 size_t sl = strlen(intro);
1379
1380 pdkim_strncat(str, intro, sl);
1381 *col += sl;
1382 l -= sl;
1383 intro = NULL;
1384 }
1385
1386 if (payload)
1387 {
1388 size_t sl = strlen(payload);
1389
1390 pdkim_strncat(str, payload, sl);
1391 *col += sl;
1392 }
1393
1394 return str->str;
1395 }
1396
1397
1398 /* -------------------------------------------------------------------------- */
1399
1400 static char *
1401 pdkim_create_header(pdkim_signature *sig, BOOL final)
1402 {
1403 char *rc = NULL;
1404 char *base64_bh = NULL;
1405 char *base64_b = NULL;
1406 int col = 0;
1407 pdkim_str *hdr;
1408 pdkim_str *canon_all;
1409
1410 if (!(hdr = pdkim_strnew("DKIM-Signature: v="PDKIM_SIGNATURE_VERSION)))
1411 return NULL;
1412
1413 if (!(canon_all = pdkim_strnew(pdkim_canons[sig->canon_headers])))
1414 goto BAIL;
1415
1416 if (!(base64_bh = pdkim_encode_base64(&sig->bodyhash)))
1417 goto BAIL;
1418
1419 col = strlen(hdr->str);
1420
1421 /* Required and static bits */
1422 if ( pdkim_headcat(&col, hdr, ";", "a=", pdkim_algos[sig->algo])
1423 && pdkim_headcat(&col, hdr, ";", "q=", pdkim_querymethods[sig->querymethod])
1424 && pdkim_strcat(canon_all, "/")
1425 && pdkim_strcat(canon_all, pdkim_canons[sig->canon_body])
1426 && pdkim_headcat(&col, hdr, ";", "c=", canon_all->str)
1427 && pdkim_headcat(&col, hdr, ";", "d=", sig->domain)
1428 && pdkim_headcat(&col, hdr, ";", "s=", sig->selector)
1429 )
1430 {
1431 /* list of header names can be split between items. */
1432 {
1433 char *n = CS string_copy(sig->headernames);
1434 char *f = n;
1435 char *i = "h=";
1436 char *s = ";";
1437
1438 if (!n) goto BAIL;
1439 while (*n)
1440 {
1441 char *c = strchr(n, ':');
1442
1443 if (c) *c ='\0';
1444
1445 if (!i)
1446 if (!pdkim_headcat(&col, hdr, NULL, NULL, ":"))
1447 {
1448 goto BAIL;
1449 }
1450
1451 if (!pdkim_headcat(&col, hdr, s, i, n))
1452 {
1453 goto BAIL;
1454 }
1455
1456 if (!c)
1457 break;
1458
1459 n = c+1;
1460 s = NULL;
1461 i = NULL;
1462 }
1463 }
1464
1465 if(!pdkim_headcat(&col, hdr, ";", "bh=", base64_bh))
1466 goto BAIL;
1467
1468 /* Optional bits */
1469 if (sig->identity)
1470 if(!pdkim_headcat(&col, hdr, ";", "i=", sig->identity))
1471 goto BAIL;
1472
1473 if (sig->created > 0)
1474 {
1475 char minibuf[20];
1476
1477 snprintf(minibuf, 20, "%lu", sig->created);
1478 if(!pdkim_headcat(&col, hdr, ";", "t=", minibuf))
1479 goto BAIL;
1480 }
1481
1482 if (sig->expires > 0)
1483 {
1484 char minibuf[20];
1485
1486 snprintf(minibuf, 20, "%lu", sig->expires);
1487 if(!pdkim_headcat(&col, hdr, ";", "x=", minibuf))
1488 goto BAIL;
1489 }
1490
1491 if (sig->bodylength >= 0)
1492 {
1493 char minibuf[20];
1494
1495 snprintf(minibuf, 20, "%lu", sig->bodylength);
1496 if(!pdkim_headcat(&col, hdr, ";", "l=", minibuf))
1497 goto BAIL;
1498 }
1499
1500 /* Preliminary or final version? */
1501 if (final)
1502 {
1503 if (!(base64_b = pdkim_encode_base64(&sig->sigdata)))
1504 goto BAIL;
1505 if (!pdkim_headcat(&col, hdr, ";", "b=", base64_b))
1506 goto BAIL;
1507 }
1508 else
1509 if(!pdkim_headcat(&col, hdr, ";", "b=", ""))
1510 goto BAIL;
1511
1512 /* add trailing semicolon: I'm not sure if this is actually needed */
1513 if (!pdkim_headcat(&col, hdr, NULL, ";", ""))
1514 goto BAIL;
1515 }
1516
1517 rc = strdup(hdr->str);
1518
1519 BAIL:
1520 pdkim_strfree(hdr);
1521 if (canon_all) pdkim_strfree(canon_all);
1522 return rc;
1523 }
1524
1525
1526 /* -------------------------------------------------------------------------- */
1527
1528 DLLEXPORT int
1529 pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatures)
1530 {
1531 pdkim_signature *sig = ctx->sig;
1532 pdkim_str *headernames = NULL; /* Collected signed header names */
1533
1534 /* Check if we must still flush a (partial) header. If that is the
1535 case, the message has no body, and we must compute a body hash
1536 out of '<CR><LF>' */
1537 if (ctx->cur_header && ctx->cur_header->len)
1538 {
1539 int rc = pdkim_header_complete(ctx);
1540 if (rc != PDKIM_OK) return rc;
1541 pdkim_update_bodyhash(ctx, "\r\n", 2);
1542 }
1543 else
1544 DEBUG(D_acl) debug_printf(
1545 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1546
1547 /* Build (and/or evaluate) body hash */
1548 if (pdkim_finish_bodyhash(ctx) != PDKIM_OK)
1549 return PDKIM_ERR_OOM;
1550
1551 /* SIGNING -------------------------------------------------------------- */
1552 if (ctx->mode == PDKIM_MODE_SIGN)
1553 if (!(headernames = pdkim_strnew(NULL)))
1554 return PDKIM_ERR_OOM;
1555 /* ---------------------------------------------------------------------- */
1556
1557 while (sig)
1558 {
1559 BOOL is_sha1 = sig->algo == PDKIM_ALGO_RSA_SHA1;
1560 hctx hhash_ctx;
1561 char * sig_hdr;
1562 blob hhash;
1563 blob hdata;
1564 int hdata_alloc = 0;
1565
1566 hdata.data = NULL;
1567 hdata.len = 0;
1568
1569 exim_sha_init(&hhash_ctx, is_sha1);
1570
1571 DEBUG(D_acl) debug_printf(
1572 "PDKIM >> Hashed header data, canonicalized, in sequence >>>>>>>>>>>>>>\n");
1573
1574 /* SIGNING ---------------------------------------------------------------- */
1575 /* When signing, walk through our header list and add them to the hash. As we
1576 go, construct a list of the header's names to use for the h= parameter.
1577 Then append to that list any remaining header names for which there was no
1578 header to sign. */
1579
1580 if (ctx->mode == PDKIM_MODE_SIGN)
1581 {
1582 pdkim_stringlist *p;
1583 const uschar * l;
1584 uschar * s;
1585 int sep = 0;
1586
1587 for (p = sig->headers; p; p = p->next)
1588 if (header_name_match(p->value, sig->sign_headers) == PDKIM_OK)
1589 {
1590 uschar * rh;
1591 /* Collect header names (Note: colon presence is guaranteed here) */
1592 uschar * q = Ustrchr(p->value, ':');
1593
1594 if (!(pdkim_strncat(headernames, p->value,
1595 (q - US p->value) + (p->next ? 1 : 0))))
1596 return PDKIM_ERR_OOM;
1597
1598 rh = sig->canon_headers == PDKIM_CANON_RELAXED
1599 ? US pdkim_relax_header(p->value, 1) /* cook header for relaxed canon */
1600 : string_copy(p->value); /* just copy it for simple canon */
1601 if (!rh)
1602 return PDKIM_ERR_OOM;
1603
1604 /* Feed header to the hash algorithm */
1605 exim_sha_update(&hhash_ctx, rh, strlen(rh));
1606
1607 /* Remember headers block for signing (when the library cannot do incremental) */
1608 (void) exim_rsa_data_append(&hdata, &hdata_alloc, rh);
1609
1610 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1611 }
1612
1613 l = US sig->sign_headers;
1614 while((s = string_nextinlist(&l, &sep, NULL, 0)))
1615 if (*s != '_')
1616 { /*SSS string_append_listele() */
1617 if (headernames->len > 0 && headernames->str[headernames->len-1] != ':')
1618 if (!(pdkim_strncat(headernames, ":", 1)))
1619 return PDKIM_ERR_OOM;
1620 if (!(pdkim_strncat(headernames, CS s, Ustrlen(s))))
1621 return PDKIM_ERR_OOM;
1622 }
1623 }
1624
1625 /* VERIFICATION ----------------------------------------------------------- */
1626 /* When verifying, walk through the header name list in the h= parameter and
1627 add the headers to the hash in that order. */
1628 else
1629 {
1630 uschar * b = string_copy(sig->headernames);
1631 uschar * p = b;
1632 uschar * q;
1633 pdkim_stringlist * hdrs;
1634
1635 if (!b) return PDKIM_ERR_OOM;
1636
1637 /* clear tags */
1638 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1639 hdrs->tag = 0;
1640
1641 while(1)
1642 {
1643 if ((q = Ustrchr(p, ':')))
1644 *q = '\0';
1645
1646 /*XXX walk the list of headers in same order as received. */
1647 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1648 if ( hdrs->tag == 0
1649 && strncasecmp(hdrs->value, CS p, Ustrlen(p)) == 0
1650 && (hdrs->value)[Ustrlen(p)] == ':'
1651 )
1652 {
1653 uschar * rh = sig->canon_headers == PDKIM_CANON_RELAXED
1654 ? US pdkim_relax_header(hdrs->value, 1) /* cook header for relaxed canon */
1655 : string_copy(hdrs->value); /* just copy it for simple canon */
1656 if (!rh)
1657 return PDKIM_ERR_OOM;
1658
1659 /* Feed header to the hash algorithm */
1660 exim_sha_update(&hhash_ctx, rh, strlen(rh));
1661
1662 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1663 hdrs->tag = 1;
1664 break;
1665 }
1666
1667 if (!q) break;
1668 p = q+1;
1669 }
1670 }
1671
1672 DEBUG(D_acl) debug_printf(
1673 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1674
1675 /* SIGNING ---------------------------------------------------------------- */
1676 if (ctx->mode == PDKIM_MODE_SIGN)
1677 {
1678 /* Copy headernames to signature struct */
1679 sig->headernames = string_copy(US headernames->str);
1680 pdkim_strfree(headernames);
1681
1682 /* Create signature header with b= omitted */
1683 sig_hdr = pdkim_create_header(sig, FALSE);
1684 }
1685
1686 /* VERIFICATION ----------------------------------------------------------- */
1687 else
1688 sig_hdr = strdup(sig->rawsig_no_b_val);
1689 /* ------------------------------------------------------------------------ */
1690
1691 if (!sig_hdr)
1692 return PDKIM_ERR_OOM;
1693
1694 /* Relax header if necessary */
1695 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1696 {
1697 char *relaxed_hdr = pdkim_relax_header(sig_hdr, 0);
1698
1699 free(sig_hdr);
1700 if (!relaxed_hdr)
1701 return PDKIM_ERR_OOM;
1702 sig_hdr = relaxed_hdr;
1703 }
1704
1705 DEBUG(D_acl)
1706 {
1707 debug_printf(
1708 "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
1709 pdkim_quoteprint(sig_hdr, strlen(sig_hdr));
1710 debug_printf(
1711 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1712 }
1713
1714 /* Finalize header hash */
1715 exim_sha_update(&hhash_ctx, sig_hdr, strlen(sig_hdr));
1716 exim_sha_finish(&hhash_ctx, &hhash);
1717
1718 DEBUG(D_acl)
1719 {
1720 debug_printf("PDKIM [%s] hh computed: ", sig->domain);
1721 pdkim_hexprint(hhash.data, hhash.len);
1722 }
1723
1724 /* Remember headers block for signing (when the library cannot do incremental) */
1725 if (ctx->mode == PDKIM_MODE_SIGN)
1726 (void) exim_rsa_data_append(&hdata, &hdata_alloc, sig_hdr);
1727
1728 free(sig_hdr);
1729
1730 /* SIGNING ---------------------------------------------------------------- */
1731 if (ctx->mode == PDKIM_MODE_SIGN)
1732 {
1733 es_ctx sctx;
1734 const uschar * errstr;
1735
1736 /* Import private key */
1737 if ((errstr = exim_rsa_signing_init(sig->rsa_privkey, &sctx)))
1738 {
1739 DEBUG(D_acl) debug_printf("signing_init: %s\n", errstr);
1740 return PDKIM_ERR_RSA_PRIVKEY;
1741 }
1742
1743 /* Do signing. With OpenSSL we are signing the hash of headers just
1744 calculated, with GnuTLS we have to sign an entire block of headers
1745 (due to available interfaces) and it recalculates the hash internally. */
1746
1747 #if defined(RSA_OPENSSL) || defined(RSA_GCRYPT)
1748 hdata = hhash;
1749 #endif
1750
1751 if ((errstr = exim_rsa_sign(&sctx, is_sha1, &hdata, &sig->sigdata)))
1752 {
1753 DEBUG(D_acl) debug_printf("signing: %s\n", errstr);
1754 return PDKIM_ERR_RSA_SIGNING;
1755 }
1756
1757 DEBUG(D_acl)
1758 {
1759 debug_printf( "PDKIM [%s] b computed: ", sig->domain);
1760 pdkim_hexprint(sig->sigdata.data, sig->sigdata.len);
1761 }
1762
1763 if (!(sig->signature_header = pdkim_create_header(sig, TRUE)))
1764 return PDKIM_ERR_OOM;
1765 }
1766
1767 /* VERIFICATION ----------------------------------------------------------- */
1768 else
1769 {
1770 ev_ctx vctx;
1771 const uschar * errstr;
1772
1773 char *dns_txt_name, *dns_txt_reply;
1774
1775 /* Fetch public key for signing domain, from DNS */
1776
1777 if (!(dns_txt_name = malloc(PDKIM_DNS_TXT_MAX_NAMELEN)))
1778 return PDKIM_ERR_OOM;
1779
1780 if (!(dns_txt_reply = malloc(PDKIM_DNS_TXT_MAX_RECLEN)))
1781 {
1782 free(dns_txt_name);
1783 return PDKIM_ERR_OOM;
1784 }
1785
1786 memset(dns_txt_reply, 0, PDKIM_DNS_TXT_MAX_RECLEN);
1787 memset(dns_txt_name , 0, PDKIM_DNS_TXT_MAX_NAMELEN);
1788
1789 if (snprintf(dns_txt_name, PDKIM_DNS_TXT_MAX_NAMELEN,
1790 "%s._domainkey.%s.",
1791 sig->selector, sig->domain) >= PDKIM_DNS_TXT_MAX_NAMELEN)
1792 {
1793 sig->verify_status = PDKIM_VERIFY_INVALID;
1794 sig->verify_ext_status = PDKIM_VERIFY_INVALID_BUFFER_SIZE;
1795 goto NEXT_VERIFY;
1796 }
1797
1798 if ( ctx->dns_txt_callback(dns_txt_name, dns_txt_reply) != PDKIM_OK
1799 || dns_txt_reply[0] == '\0')
1800 {
1801 sig->verify_status = PDKIM_VERIFY_INVALID;
1802 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE;
1803 goto NEXT_VERIFY;
1804 }
1805
1806 DEBUG(D_acl)
1807 {
1808 debug_printf(
1809 "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
1810 " Raw record: ");
1811 pdkim_quoteprint(dns_txt_reply, strlen(dns_txt_reply));
1812 }
1813
1814 if (!(sig->pubkey = pdkim_parse_pubkey_record(ctx, dns_txt_reply)))
1815 {
1816 sig->verify_status = PDKIM_VERIFY_INVALID;
1817 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD;
1818
1819 DEBUG(D_acl) debug_printf(
1820 " Error while parsing public key record\n"
1821 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1822 goto NEXT_VERIFY;
1823 }
1824
1825 DEBUG(D_acl) debug_printf(
1826 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1827
1828 /* Import public key */
1829 if ((errstr = exim_rsa_verify_init(&sig->pubkey->key, &vctx)))
1830 {
1831 DEBUG(D_acl) debug_printf("verify_init: %s\n", errstr);
1832 sig->verify_status = PDKIM_VERIFY_INVALID;
1833 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_IMPORT;
1834 goto NEXT_VERIFY;
1835 }
1836
1837 /* Check the signature */
1838 if ((errstr = exim_rsa_verify(&vctx, is_sha1, &hhash, &sig->sigdata)))
1839 {
1840 DEBUG(D_acl) debug_printf("headers verify: %s\n", errstr);
1841 sig->verify_status = PDKIM_VERIFY_FAIL;
1842 sig->verify_ext_status = PDKIM_VERIFY_FAIL_MESSAGE;
1843 goto NEXT_VERIFY;
1844 }
1845
1846
1847 /* We have a winner! (if bodydhash was correct earlier) */
1848 if (sig->verify_status == PDKIM_VERIFY_NONE)
1849 sig->verify_status = PDKIM_VERIFY_PASS;
1850
1851 NEXT_VERIFY:
1852
1853 DEBUG(D_acl)
1854 {
1855 debug_printf("PDKIM [%s] signature status: %s",
1856 sig->domain, pdkim_verify_status_str(sig->verify_status));
1857 if (sig->verify_ext_status > 0)
1858 debug_printf(" (%s)\n",
1859 pdkim_verify_ext_status_str(sig->verify_ext_status));
1860 else
1861 debug_printf("\n");
1862 }
1863
1864 free(dns_txt_name);
1865 free(dns_txt_reply);
1866 }
1867
1868 sig = sig->next;
1869 }
1870
1871 /* If requested, set return pointer to signature(s) */
1872 if (return_signatures)
1873 *return_signatures = ctx->sig;
1874
1875 return PDKIM_OK;
1876 }
1877
1878
1879 /* -------------------------------------------------------------------------- */
1880
1881 DLLEXPORT pdkim_ctx *
1882 pdkim_init_verify(int(*dns_txt_callback)(char *, char *))
1883 {
1884 pdkim_ctx *ctx = malloc(sizeof(pdkim_ctx));
1885
1886 if (!ctx)
1887 return NULL;
1888 memset(ctx, 0, sizeof(pdkim_ctx));
1889
1890 if (!(ctx->linebuf = malloc(PDKIM_MAX_BODY_LINE_LEN)))
1891 {
1892 free(ctx);
1893 return NULL;
1894 }
1895
1896 ctx->mode = PDKIM_MODE_VERIFY;
1897 ctx->dns_txt_callback = dns_txt_callback;
1898
1899 return ctx;
1900 }
1901
1902
1903 /* -------------------------------------------------------------------------- */
1904
1905 DLLEXPORT pdkim_ctx *
1906 pdkim_init_sign(char *domain, char *selector, char *rsa_privkey, int algo)
1907 {
1908 pdkim_ctx *ctx;
1909 pdkim_signature *sig;
1910
1911 if (!domain || !selector || !rsa_privkey)
1912 return NULL;
1913
1914 if (!(ctx = malloc(sizeof(pdkim_ctx))))
1915 return NULL;
1916 memset(ctx, 0, sizeof(pdkim_ctx));
1917
1918 if (!(ctx->linebuf = malloc(PDKIM_MAX_BODY_LINE_LEN)))
1919 {
1920 free(ctx);
1921 return NULL;
1922 }
1923
1924 if (!(sig = malloc(sizeof(pdkim_signature))))
1925 {
1926 free(ctx->linebuf);
1927 free(ctx);
1928 return NULL;
1929 }
1930 memset(sig, 0, sizeof(pdkim_signature));
1931
1932 sig->bodylength = -1;
1933
1934 ctx->mode = PDKIM_MODE_SIGN;
1935 ctx->sig = sig;
1936
1937 sig->domain = strdup(domain);
1938 sig->selector = strdup(selector);
1939 sig->rsa_privkey = strdup(rsa_privkey);
1940 sig->algo = algo;
1941
1942 if (!sig->domain || !sig->selector || !sig->rsa_privkey)
1943 goto BAIL;
1944
1945 exim_sha_init(&sig->body_hash, algo == PDKIM_ALGO_RSA_SHA1);
1946 return ctx;
1947
1948 BAIL:
1949 pdkim_free_ctx(ctx);
1950 return NULL;
1951 }
1952
1953
1954 /* -------------------------------------------------------------------------- */
1955
1956 DLLEXPORT int
1957 pdkim_set_optional(pdkim_ctx *ctx,
1958 char *sign_headers,
1959 char *identity,
1960 int canon_headers,
1961 int canon_body,
1962 long bodylength,
1963 unsigned long created,
1964 unsigned long expires)
1965 {
1966 pdkim_signature * sig = ctx->sig;
1967
1968 if (identity)
1969 if (!(sig->identity = strdup(identity)))
1970 return PDKIM_ERR_OOM;
1971
1972 if (!(sig->sign_headers = strdup(sign_headers
1973 ? sign_headers : PDKIM_DEFAULT_SIGN_HEADERS)))
1974 return PDKIM_ERR_OOM;
1975
1976 sig->canon_headers = canon_headers;
1977 sig->canon_body = canon_body;
1978 sig->bodylength = bodylength;
1979 sig->created = created;
1980 sig->expires = expires;
1981
1982 return PDKIM_OK;
1983 }
1984
1985
1986 void
1987 pdkim_init(void)
1988 {
1989 exim_rsa_init();
1990 }
1991
1992
1993
1994 #endif /*DISABLE_DKIM*/