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