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