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