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