2d5f621b4da6c9ba16dc97d01741bc68eb6ef604
[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 goto BAIL;
1447
1448 if (!pdkim_headcat(&col, hdr, s, i, n))
1449 goto BAIL;
1450
1451 if (!c)
1452 break;
1453
1454 n = c+1;
1455 s = NULL;
1456 i = NULL;
1457 }
1458 }
1459
1460 if(!pdkim_headcat(&col, hdr, ";", "bh=", base64_bh))
1461 goto BAIL;
1462
1463 /* Optional bits */
1464 if (sig->identity)
1465 if(!pdkim_headcat(&col, hdr, ";", "i=", sig->identity))
1466 goto BAIL;
1467
1468 if (sig->created > 0)
1469 {
1470 char minibuf[20];
1471
1472 snprintf(minibuf, 20, "%lu", sig->created);
1473 if(!pdkim_headcat(&col, hdr, ";", "t=", minibuf))
1474 goto BAIL;
1475 }
1476
1477 if (sig->expires > 0)
1478 {
1479 char minibuf[20];
1480
1481 snprintf(minibuf, 20, "%lu", sig->expires);
1482 if(!pdkim_headcat(&col, hdr, ";", "x=", minibuf))
1483 goto BAIL;
1484 }
1485
1486 if (sig->bodylength >= 0)
1487 {
1488 char minibuf[20];
1489
1490 snprintf(minibuf, 20, "%lu", sig->bodylength);
1491 if(!pdkim_headcat(&col, hdr, ";", "l=", minibuf))
1492 goto BAIL;
1493 }
1494
1495 /* Preliminary or final version? */
1496 if (final)
1497 {
1498 if (!(base64_b = pdkim_encode_base64(&sig->sigdata)))
1499 goto BAIL;
1500 if (!pdkim_headcat(&col, hdr, ";", "b=", base64_b))
1501 goto BAIL;
1502 }
1503 else
1504 if(!pdkim_headcat(&col, hdr, ";", "b=", ""))
1505 goto BAIL;
1506
1507 /* add trailing semicolon: I'm not sure if this is actually needed */
1508 if (!pdkim_headcat(&col, hdr, NULL, ";", ""))
1509 goto BAIL;
1510 }
1511
1512 rc = strdup(hdr->str);
1513
1514 BAIL:
1515 pdkim_strfree(hdr);
1516 if (canon_all) pdkim_strfree(canon_all);
1517 return rc;
1518 }
1519
1520
1521 /* -------------------------------------------------------------------------- */
1522
1523 DLLEXPORT int
1524 pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatures)
1525 {
1526 pdkim_signature *sig = ctx->sig;
1527 pdkim_str *headernames = NULL; /* Collected signed header names */
1528
1529 /* Check if we must still flush a (partial) header. If that is the
1530 case, the message has no body, and we must compute a body hash
1531 out of '<CR><LF>' */
1532 if (ctx->cur_header && ctx->cur_header->len)
1533 {
1534 int rc = pdkim_header_complete(ctx);
1535 if (rc != PDKIM_OK) return rc;
1536 pdkim_update_bodyhash(ctx, "\r\n", 2);
1537 }
1538 else
1539 DEBUG(D_acl) debug_printf(
1540 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1541
1542 /* Build (and/or evaluate) body hash */
1543 if (pdkim_finish_bodyhash(ctx) != PDKIM_OK)
1544 return PDKIM_ERR_OOM;
1545
1546 /* SIGNING -------------------------------------------------------------- */
1547 if (ctx->mode == PDKIM_MODE_SIGN)
1548 if (!(headernames = pdkim_strnew(NULL)))
1549 return PDKIM_ERR_OOM;
1550 /* ---------------------------------------------------------------------- */
1551
1552 while (sig)
1553 {
1554 BOOL is_sha1 = sig->algo == PDKIM_ALGO_RSA_SHA1;
1555 hctx hhash_ctx;
1556 char * sig_hdr;
1557 blob hhash;
1558 blob hdata;
1559 int hdata_alloc = 0;
1560
1561 hdata.data = NULL;
1562 hdata.len = 0;
1563
1564 exim_sha_init(&hhash_ctx, is_sha1);
1565
1566 DEBUG(D_acl) debug_printf(
1567 "PDKIM >> Hashed header data, canonicalized, in sequence >>>>>>>>>>>>>>\n");
1568
1569 /* SIGNING ---------------------------------------------------------------- */
1570 /* When signing, walk through our header list and add them to the hash. As we
1571 go, construct a list of the header's names to use for the h= parameter. */
1572
1573 if (ctx->mode == PDKIM_MODE_SIGN)
1574 {
1575 pdkim_stringlist *p;
1576
1577 for (p = sig->headers; p; p = p->next)
1578 {
1579 uschar * rh;
1580 /* Collect header names (Note: colon presence is guaranteed here) */
1581 uschar * q = Ustrchr(p->value, ':');
1582
1583 if (!(pdkim_strncat(headernames, p->value,
1584 (q-US (p->value)) + (p->next ? 1 : 0))))
1585 return PDKIM_ERR_OOM;
1586
1587 rh = sig->canon_headers == PDKIM_CANON_RELAXED
1588 ? US pdkim_relax_header(p->value, 1) /* cook header for relaxed canon */
1589 : string_copy(p->value); /* just copy it for simple canon */
1590 if (!rh)
1591 return PDKIM_ERR_OOM;
1592
1593 /* Feed header to the hash algorithm */
1594 exim_sha_update(&hhash_ctx, rh, strlen(rh));
1595
1596 /* Remember headers block for signing (when the library cannot do incremental) */
1597 (void) exim_rsa_data_append(&hdata, &hdata_alloc, rh);
1598
1599 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1600 }
1601 }
1602
1603 /* VERIFICATION ----------------------------------------------------------- */
1604 /* When verifying, walk through the header name list in the h= parameter and
1605 add the headers to the hash in that order. */
1606 else
1607 {
1608 uschar * b = string_copy(sig->headernames);
1609 uschar * p = b;
1610 uschar * q;
1611 pdkim_stringlist * hdrs;
1612
1613 if (!b) return PDKIM_ERR_OOM;
1614
1615 /* clear tags */
1616 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1617 hdrs->tag = 0;
1618
1619 while(1)
1620 {
1621 if ((q = Ustrchr(p, ':')))
1622 *q = '\0';
1623
1624 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1625 if ( hdrs->tag == 0
1626 && strncasecmp(hdrs->value, CS p, Ustrlen(p)) == 0
1627 && (hdrs->value)[Ustrlen(p)] == ':'
1628 )
1629 {
1630 uschar * rh = sig->canon_headers == PDKIM_CANON_RELAXED
1631 ? US pdkim_relax_header(hdrs->value, 1) /* cook header for relaxed canon */
1632 : string_copy(hdrs->value); /* just copy it for simple canon */
1633 if (!rh)
1634 return PDKIM_ERR_OOM;
1635
1636 /* Feed header to the hash algorithm */
1637 exim_sha_update(&hhash_ctx, rh, strlen(rh));
1638
1639 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1640 hdrs->tag = 1;
1641 break;
1642 }
1643
1644 if (!q) break;
1645 p = q+1;
1646 }
1647 }
1648
1649 DEBUG(D_acl) debug_printf(
1650 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1651
1652 /* SIGNING ---------------------------------------------------------------- */
1653 if (ctx->mode == PDKIM_MODE_SIGN)
1654 {
1655 /* Copy headernames to signature struct */
1656 sig->headernames = string_copy(US headernames->str);
1657 pdkim_strfree(headernames);
1658
1659 /* Create signature header with b= omitted */
1660 sig_hdr = pdkim_create_header(ctx->sig, FALSE);
1661 }
1662
1663 /* VERIFICATION ----------------------------------------------------------- */
1664 else
1665 sig_hdr = strdup(sig->rawsig_no_b_val);
1666 /* ------------------------------------------------------------------------ */
1667
1668 if (!sig_hdr)
1669 return PDKIM_ERR_OOM;
1670
1671 /* Relax header if necessary */
1672 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1673 {
1674 char *relaxed_hdr = pdkim_relax_header(sig_hdr, 0);
1675
1676 free(sig_hdr);
1677 if (!relaxed_hdr)
1678 return PDKIM_ERR_OOM;
1679 sig_hdr = relaxed_hdr;
1680 }
1681
1682 DEBUG(D_acl)
1683 {
1684 debug_printf(
1685 "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
1686 pdkim_quoteprint(sig_hdr, strlen(sig_hdr));
1687 debug_printf(
1688 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1689 }
1690
1691 /* Finalize header hash */
1692 exim_sha_update(&hhash_ctx, sig_hdr, strlen(sig_hdr));
1693 exim_sha_finish(&hhash_ctx, &hhash);
1694
1695 DEBUG(D_acl)
1696 {
1697 debug_printf("PDKIM [%s] hh computed: ", sig->domain);
1698 pdkim_hexprint(hhash.data, hhash.len);
1699 }
1700
1701 /* Remember headers block for signing (when the library cannot do incremental) */
1702 if (ctx->mode == PDKIM_MODE_SIGN)
1703 (void) exim_rsa_data_append(&hdata, &hdata_alloc, sig_hdr);
1704
1705 free(sig_hdr);
1706
1707 /* SIGNING ---------------------------------------------------------------- */
1708 if (ctx->mode == PDKIM_MODE_SIGN)
1709 {
1710 es_ctx sctx;
1711 const uschar * errstr;
1712
1713 /* Import private key */
1714 if ((errstr = exim_rsa_signing_init(sig->rsa_privkey, &sctx)))
1715 {
1716 DEBUG(D_acl) debug_printf("signing_init: %s\n", errstr);
1717 return PDKIM_ERR_RSA_PRIVKEY;
1718 }
1719
1720 /* Do signing. With OpenSSL we are signing the hash of headers just
1721 calculated, with GnuTLS we have to sign an entire block of headers
1722 (due to available interfaces) and it recalculates the hash internally. */
1723
1724 #if defined(RSA_OPENSSL) || defined(RSA_GCRYPT)
1725 hdata = hhash;
1726 #endif
1727
1728 if ((errstr = exim_rsa_sign(&sctx, is_sha1, &hdata, &sig->sigdata)))
1729 {
1730 DEBUG(D_acl) debug_printf("signing: %s\n", errstr);
1731 return PDKIM_ERR_RSA_SIGNING;
1732 }
1733
1734 DEBUG(D_acl)
1735 {
1736 debug_printf( "PDKIM [%s] b computed: ", sig->domain);
1737 pdkim_hexprint(sig->sigdata.data, sig->sigdata.len);
1738 }
1739
1740 if (!(sig->signature_header = pdkim_create_header(ctx->sig, TRUE)))
1741 return PDKIM_ERR_OOM;
1742 }
1743
1744 /* VERIFICATION ----------------------------------------------------------- */
1745 else
1746 {
1747 ev_ctx vctx;
1748 const uschar * errstr;
1749
1750 char *dns_txt_name, *dns_txt_reply;
1751
1752 /* Fetch public key for signing domain, from DNS */
1753
1754 if (!(dns_txt_name = malloc(PDKIM_DNS_TXT_MAX_NAMELEN)))
1755 return PDKIM_ERR_OOM;
1756
1757 if (!(dns_txt_reply = malloc(PDKIM_DNS_TXT_MAX_RECLEN)))
1758 {
1759 free(dns_txt_name);
1760 return PDKIM_ERR_OOM;
1761 }
1762
1763 memset(dns_txt_reply, 0, PDKIM_DNS_TXT_MAX_RECLEN);
1764 memset(dns_txt_name , 0, PDKIM_DNS_TXT_MAX_NAMELEN);
1765
1766 if (snprintf(dns_txt_name, PDKIM_DNS_TXT_MAX_NAMELEN,
1767 "%s._domainkey.%s.",
1768 sig->selector, sig->domain) >= PDKIM_DNS_TXT_MAX_NAMELEN)
1769 {
1770 sig->verify_status = PDKIM_VERIFY_INVALID;
1771 sig->verify_ext_status = PDKIM_VERIFY_INVALID_BUFFER_SIZE;
1772 goto NEXT_VERIFY;
1773 }
1774
1775 if ( ctx->dns_txt_callback(dns_txt_name, dns_txt_reply) != PDKIM_OK
1776 || dns_txt_reply[0] == '\0')
1777 {
1778 sig->verify_status = PDKIM_VERIFY_INVALID;
1779 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE;
1780 goto NEXT_VERIFY;
1781 }
1782
1783 DEBUG(D_acl)
1784 {
1785 debug_printf(
1786 "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
1787 " Raw record: ");
1788 pdkim_quoteprint(dns_txt_reply, strlen(dns_txt_reply));
1789 }
1790
1791 if (!(sig->pubkey = pdkim_parse_pubkey_record(ctx, dns_txt_reply)))
1792 {
1793 sig->verify_status = PDKIM_VERIFY_INVALID;
1794 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD;
1795
1796 DEBUG(D_acl) debug_printf(
1797 " Error while parsing public key record\n"
1798 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1799 goto NEXT_VERIFY;
1800 }
1801
1802 DEBUG(D_acl) debug_printf(
1803 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1804
1805 /* Import public key */
1806 if ((errstr = exim_rsa_verify_init(&sig->pubkey->key, &vctx)))
1807 {
1808 DEBUG(D_acl) debug_printf("verify_init: %s\n", errstr);
1809 sig->verify_status = PDKIM_VERIFY_INVALID;
1810 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_IMPORT;
1811 goto NEXT_VERIFY;
1812 }
1813
1814 /* Check the signature */
1815 if ((errstr = exim_rsa_verify(&vctx, is_sha1, &hhash, &sig->sigdata)))
1816 {
1817 DEBUG(D_acl) debug_printf("headers verify: %s\n", errstr);
1818 sig->verify_status = PDKIM_VERIFY_FAIL;
1819 sig->verify_ext_status = PDKIM_VERIFY_FAIL_MESSAGE;
1820 goto NEXT_VERIFY;
1821 }
1822
1823
1824 /* We have a winner! (if bodydhash was correct earlier) */
1825 if (sig->verify_status == PDKIM_VERIFY_NONE)
1826 sig->verify_status = PDKIM_VERIFY_PASS;
1827
1828 NEXT_VERIFY:
1829
1830 DEBUG(D_acl)
1831 {
1832 debug_printf("PDKIM [%s] signature status: %s",
1833 sig->domain, pdkim_verify_status_str(sig->verify_status));
1834 if (sig->verify_ext_status > 0)
1835 debug_printf(" (%s)\n",
1836 pdkim_verify_ext_status_str(sig->verify_ext_status));
1837 else
1838 debug_printf("\n");
1839 }
1840
1841 free(dns_txt_name);
1842 free(dns_txt_reply);
1843 }
1844
1845 sig = sig->next;
1846 }
1847
1848 /* If requested, set return pointer to signature(s) */
1849 if (return_signatures)
1850 *return_signatures = ctx->sig;
1851
1852 return PDKIM_OK;
1853 }
1854
1855
1856 /* -------------------------------------------------------------------------- */
1857
1858 DLLEXPORT pdkim_ctx *
1859 pdkim_init_verify(int(*dns_txt_callback)(char *, char *))
1860 {
1861 pdkim_ctx *ctx = malloc(sizeof(pdkim_ctx));
1862
1863 if (!ctx)
1864 return NULL;
1865 memset(ctx, 0, sizeof(pdkim_ctx));
1866
1867 if (!(ctx->linebuf = malloc(PDKIM_MAX_BODY_LINE_LEN)))
1868 {
1869 free(ctx);
1870 return NULL;
1871 }
1872
1873 ctx->mode = PDKIM_MODE_VERIFY;
1874 ctx->dns_txt_callback = dns_txt_callback;
1875
1876 return ctx;
1877 }
1878
1879
1880 /* -------------------------------------------------------------------------- */
1881
1882 DLLEXPORT pdkim_ctx *
1883 pdkim_init_sign(char *domain, char *selector, char *rsa_privkey, int algo)
1884 {
1885 pdkim_ctx *ctx;
1886 pdkim_signature *sig;
1887
1888 if (!domain || !selector || !rsa_privkey)
1889 return NULL;
1890
1891 if (!(ctx = malloc(sizeof(pdkim_ctx))))
1892 return NULL;
1893 memset(ctx, 0, sizeof(pdkim_ctx));
1894
1895 if (!(ctx->linebuf = malloc(PDKIM_MAX_BODY_LINE_LEN)))
1896 {
1897 free(ctx);
1898 return NULL;
1899 }
1900
1901 if (!(sig = malloc(sizeof(pdkim_signature))))
1902 {
1903 free(ctx->linebuf);
1904 free(ctx);
1905 return NULL;
1906 }
1907 memset(sig, 0, sizeof(pdkim_signature));
1908
1909 sig->bodylength = -1;
1910
1911 ctx->mode = PDKIM_MODE_SIGN;
1912 ctx->sig = sig;
1913
1914 sig->domain = strdup(domain);
1915 sig->selector = strdup(selector);
1916 sig->rsa_privkey = strdup(rsa_privkey);
1917 sig->algo = algo;
1918
1919 if (!sig->domain || !sig->selector || !sig->rsa_privkey)
1920 goto BAIL;
1921
1922 exim_sha_init(&sig->body_hash, algo == PDKIM_ALGO_RSA_SHA1);
1923 return ctx;
1924
1925 BAIL:
1926 pdkim_free_ctx(ctx);
1927 return NULL;
1928 }
1929
1930
1931 /* -------------------------------------------------------------------------- */
1932
1933 DLLEXPORT int
1934 pdkim_set_optional(pdkim_ctx *ctx,
1935 char *sign_headers,
1936 char *identity,
1937 int canon_headers,
1938 int canon_body,
1939 long bodylength,
1940 unsigned long created,
1941 unsigned long expires)
1942 {
1943 if (identity)
1944 if (!(ctx->sig->identity = strdup(identity)))
1945 return PDKIM_ERR_OOM;
1946
1947 if (sign_headers)
1948 if (!(ctx->sig->sign_headers = strdup(sign_headers)))
1949 return PDKIM_ERR_OOM;
1950
1951 ctx->sig->canon_headers = canon_headers;
1952 ctx->sig->canon_body = canon_body;
1953 ctx->sig->bodylength = bodylength;
1954 ctx->sig->created = created;
1955 ctx->sig->expires = expires;
1956
1957 return PDKIM_OK;
1958 }
1959
1960
1961 void
1962 pdkim_init(void)
1963 {
1964 exim_rsa_init();
1965 }
1966
1967
1968
1969 #endif /*DISABLE_DKIM*/