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