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