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