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