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