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