CHUNKING/DKIM: fix handling of lines having a leading dot
[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             if (cur_tag[1] == 'h')
497               pdkim_decode_base64(cur_val, &sig->bodyhash);
498             else
499               pdkim_decode_base64(cur_val, &sig->sigdata);
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->sigdata.len*8);
582   debug_printf(
583           "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
584   }
585
586 exim_sha_init(&sig->body_hash, sig->algo == PDKIM_ALGO_RSA_SHA1 ? HASH_SHA1 : HASH_SHA256);
587 return sig;
588 }
589
590
591 /* -------------------------------------------------------------------------- */
592
593 static pdkim_pubkey *
594 pdkim_parse_pubkey_record(pdkim_ctx *ctx, const uschar *raw_record)
595 {
596 pdkim_pubkey *pub;
597 const uschar *p;
598 uschar * cur_tag = NULL; int ts = 0, tl = 0;
599 uschar * cur_val = NULL; int vs = 0, vl = 0;
600 int where = PDKIM_HDR_LIMBO;
601
602 pub = store_get(sizeof(pdkim_pubkey));
603 memset(pub, 0, sizeof(pdkim_pubkey));
604
605 for (p = raw_record; ; p++)
606   {
607   char c = *p;
608
609   /* Ignore FWS */
610   if (c == '\r' || c == '\n')
611     goto NEXT_CHAR;
612
613   if (where == PDKIM_HDR_LIMBO)
614     {
615     /* In limbo, just wait for a tag-char to appear */
616     if (!(c >= 'a' && c <= 'z'))
617       goto NEXT_CHAR;
618
619     where = PDKIM_HDR_TAG;
620     }
621
622   if (where == PDKIM_HDR_TAG)
623     {
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       goto NEXT_CHAR;
632       }
633     }
634
635   if (where == PDKIM_HDR_VALUE)
636     {
637     if (c == ';' || c == '\0')
638       {
639       if (tl && vl)
640         {
641         cur_val[vl] = '\0';
642         pdkim_strtrim(cur_val);
643         DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag, cur_val);
644
645         switch (cur_tag[0])
646           {
647           case 'v':
648             /* This tag isn't evaluated because:
649                - We only support version DKIM1.
650                - Which is the default for this value (set below)
651                - Other versions are currently not specified.      */
652             break;
653           case 'h':
654           case 'k':
655             pub->hashes = string_copy(cur_val); break;
656           case 'g':
657             pub->granularity = string_copy(cur_val); break;
658           case 'n':
659             pub->notes = pdkim_decode_qp(cur_val); break;
660           case 'p':
661             pdkim_decode_base64(US cur_val, &pub->key);
662             break;
663           case 's':
664             pub->srvtype = string_copy(cur_val); break;
665           case 't':
666             if (Ustrchr(cur_val, 'y') != NULL) pub->testing = 1;
667             if (Ustrchr(cur_val, 's') != NULL) pub->no_subdomaining = 1;
668             break;
669           default:
670             DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
671             break;
672           }
673         }
674       tl = 0;
675       vl = 0;
676       where = PDKIM_HDR_LIMBO;
677       }
678     else
679       cur_val = string_catn(cur_val, &vs, &vl, p, 1);
680     }
681
682 NEXT_CHAR:
683   if (c == '\0') break;
684   }
685
686 /* Set fallback defaults */
687 if (!pub->version    ) pub->version     = string_copy(PDKIM_PUB_RECORD_VERSION);
688 if (!pub->granularity) pub->granularity = string_copy(US"*");
689 if (!pub->keytype    ) pub->keytype     = string_copy(US"rsa");
690 if (!pub->srvtype    ) pub->srvtype     = string_copy(US"*");
691
692 /* p= is required */
693 if (pub->key.data)
694   return pub;
695
696 return NULL;
697 }
698
699
700 /* -------------------------------------------------------------------------- */
701
702 static int
703 pdkim_update_bodyhash(pdkim_ctx *ctx, const char *data, int len)
704 {
705 pdkim_signature *sig = ctx->sig;
706 /* Cache relaxed version of data */
707 uschar *relaxed_data = NULL;
708 int     relaxed_len  = 0;
709
710 /* Traverse all signatures, updating their hashes. */
711 while (sig)
712   {
713   /* Defaults to simple canon (no further treatment necessary) */
714   const uschar *canon_data = CUS data;
715   int           canon_len = len;
716
717   if (sig->canon_body == PDKIM_CANON_RELAXED)
718     {
719     /* Relax the line if not done already */
720     if (!relaxed_data)
721       {
722       BOOL seen_wsp = FALSE;
723       const char *p;
724       int q = 0;
725
726       relaxed_data = store_get(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, 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   sig = sig->next;
768   }
769
770 return PDKIM_OK;
771 }
772
773
774 /* -------------------------------------------------------------------------- */
775
776 static void
777 pdkim_finish_bodyhash(pdkim_ctx *ctx)
778 {
779 pdkim_signature *sig;
780
781 /* Traverse all signatures */
782 for (sig = ctx->sig; sig; sig = sig->next)
783   {                                     /* Finish hashes */
784   blob bh;
785
786   exim_sha_finish(&sig->body_hash, &bh);
787
788   DEBUG(D_acl)
789     {
790     debug_printf("PDKIM [%s] Body bytes hashed: %lu\n"
791                  "PDKIM [%s] bh  computed: ",
792                 sig->domain, sig->signed_body_bytes, sig->domain);
793     pdkim_hexprint(CUS bh.data, bh.len);
794     }
795
796   /* SIGNING -------------------------------------------------------------- */
797   if (ctx->flags & PDKIM_MODE_SIGN)
798     {
799     sig->bodyhash = bh;
800
801     /* If bodylength limit is set, and we have received less bytes
802        than the requested amount, effectively remove the limit tag. */
803     if (sig->signed_body_bytes < sig->bodylength)
804       sig->bodylength = -1;
805     }
806
807   /* VERIFICATION --------------------------------------------------------- */
808   else
809     {
810     /* Compare bodyhash */
811     if (memcmp(bh.data, sig->bodyhash.data, bh.len) == 0)
812       {
813       DEBUG(D_acl) debug_printf("PDKIM [%s] Body hash verified OK\n", sig->domain);
814       }
815     else
816       {
817       DEBUG(D_acl)
818         {
819         debug_printf("PDKIM [%s] bh signature: ", sig->domain);
820         pdkim_hexprint(sig->bodyhash.data,
821                          exim_sha_hashlen(&sig->body_hash));
822         debug_printf("PDKIM [%s] Body hash did NOT verify\n", sig->domain);
823         }
824       sig->verify_status     = PDKIM_VERIFY_FAIL;
825       sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
826       }
827     }
828   }
829 }
830
831
832
833 static int
834 pdkim_body_complete(pdkim_ctx * ctx)
835 {
836 pdkim_signature * sig = ctx->sig;       /*XXX assumes only one sig */
837
838 /* In simple body mode, if any empty lines were buffered,
839 replace with one. rfc 4871 3.4.3 */
840 /*XXX checking the signed-body-bytes is a gross hack; I think
841 it indicates that all linebreaks should be buffered, including
842 the one terminating a text line */
843
844 if (  sig && sig->canon_body == PDKIM_CANON_SIMPLE
845    && sig->signed_body_bytes == 0
846    && ctx->num_buffered_crlf > 0
847    )
848   pdkim_update_bodyhash(ctx, "\r\n", 2);
849
850 ctx->flags |= PDKIM_SEEN_EOD;
851 ctx->linebuf_offset = 0;
852 return PDKIM_OK;
853 }
854
855
856
857 /* -------------------------------------------------------------------------- */
858 /* Call from pdkim_feed below for processing complete body lines */
859
860 static int
861 pdkim_bodyline_complete(pdkim_ctx *ctx)
862 {
863 char *p = ctx->linebuf;
864 int   n = ctx->linebuf_offset;
865 pdkim_signature *sig = ctx->sig;        /*XXX assumes only one sig */
866
867 /* Ignore extra data if we've seen the end-of-data marker */
868 if (ctx->flags & PDKIM_SEEN_EOD) goto BAIL;
869
870 /* We've always got one extra byte to stuff a zero ... */
871 ctx->linebuf[ctx->linebuf_offset] = '\0';
872
873 /* Terminate on EOD marker */
874 if (ctx->flags & PDKIM_DOT_TERM)
875   {
876   if ( memcmp(p, ".\r\n", 3) == 0)
877     return pdkim_body_complete(ctx);
878
879   /* Unstuff dots */
880   if (memcmp(p, "..", 2) == 0)
881     {
882     p++;
883     n--;
884     }
885   }
886
887 /* Empty lines need to be buffered until we find a non-empty line */
888 if (memcmp(p, "\r\n", 2) == 0)
889   {
890   ctx->num_buffered_crlf++;
891   goto BAIL;
892   }
893
894 if (sig && sig->canon_body == PDKIM_CANON_RELAXED)
895   {
896   /* Lines with just spaces need to be buffered too */
897   char *check = p;
898   while (memcmp(check, "\r\n", 2) != 0)
899     {
900     char c = *check;
901
902     if (c != '\t' && c != ' ')
903       goto PROCESS;
904     check++;
905     }
906
907   ctx->num_buffered_crlf++;
908   goto BAIL;
909 }
910
911 PROCESS:
912 /* At this point, we have a non-empty line, so release the buffered ones. */
913 while (ctx->num_buffered_crlf)
914   {
915   pdkim_update_bodyhash(ctx, "\r\n", 2);
916   ctx->num_buffered_crlf--;
917   }
918
919 pdkim_update_bodyhash(ctx, p, n);
920
921 BAIL:
922 ctx->linebuf_offset = 0;
923 return PDKIM_OK;
924 }
925
926
927 /* -------------------------------------------------------------------------- */
928 /* Callback from pdkim_feed below for processing complete headers */
929 #define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
930
931 static int
932 pdkim_header_complete(pdkim_ctx *ctx)
933 {
934 /* Special case: The last header can have an extra \r appended */
935 if ( (ctx->cur_header_len > 1) &&
936      (ctx->cur_header[(ctx->cur_header_len)-1] == '\r') )
937   --ctx->cur_header_len;
938 ctx->cur_header[ctx->cur_header_len] = '\0';
939
940 ctx->num_headers++;
941 if (ctx->num_headers > PDKIM_MAX_HEADERS) goto BAIL;
942
943 /* SIGNING -------------------------------------------------------------- */
944 if (ctx->flags & PDKIM_MODE_SIGN)
945   {
946   pdkim_signature *sig;
947
948   for (sig = ctx->sig; sig; sig = sig->next)                    /* Traverse all signatures */
949
950     /* Add header to the signed headers list (in reverse order) */
951     sig->headers = pdkim_prepend_stringlist(sig->headers,
952                                   ctx->cur_header);
953   }
954
955 /* VERIFICATION ----------------------------------------------------------- */
956 /* DKIM-Signature: headers are added to the verification list */
957 else
958   {
959   if (strncasecmp(CCS ctx->cur_header,
960                   DKIM_SIGNATURE_HEADERNAME,
961                   Ustrlen(DKIM_SIGNATURE_HEADERNAME)) == 0)
962     {
963     pdkim_signature *new_sig;
964
965     /* Create and chain new signature block */
966     DEBUG(D_acl) debug_printf(
967         "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
968
969     if ((new_sig = pdkim_parse_sig_header(ctx, ctx->cur_header)))
970       {
971       pdkim_signature *last_sig = ctx->sig;
972       if (!last_sig)
973         ctx->sig = new_sig;
974       else
975         {
976         while (last_sig->next) last_sig = last_sig->next;
977         last_sig->next = new_sig;
978         }
979       }
980     else
981       DEBUG(D_acl) debug_printf(
982           "Error while parsing signature header\n"
983           "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
984     }
985
986   /* every other header is stored for signature verification */
987   else
988     ctx->headers = pdkim_prepend_stringlist(ctx->headers, ctx->cur_header);
989   }
990
991 BAIL:
992 *ctx->cur_header = '\0';
993 ctx->cur_header_len = 0;        /* leave buffer for reuse */
994 return PDKIM_OK;
995 }
996
997
998
999 /* -------------------------------------------------------------------------- */
1000 #define HEADER_BUFFER_FRAG_SIZE 256
1001
1002 DLLEXPORT int
1003 pdkim_feed(pdkim_ctx *ctx, char *data, int len)
1004 {
1005 int p;
1006
1007 /* Alternate EOD signal, used in non-dotstuffing mode */
1008 if (!data)
1009   pdkim_body_complete(ctx);
1010
1011 for (p = 0; p<len; p++)
1012   {
1013   uschar c = data[p];
1014
1015   if (ctx->flags & PDKIM_PAST_HDRS)
1016     {
1017     /* Processing body byte */
1018     ctx->linebuf[ctx->linebuf_offset++] = c;
1019     if (c == '\n')
1020       {
1021       int rc = pdkim_bodyline_complete(ctx); /* End of line */
1022       if (rc != PDKIM_OK) return rc;
1023       }
1024     if (ctx->linebuf_offset == (PDKIM_MAX_BODY_LINE_LEN-1))
1025       return PDKIM_ERR_LONG_LINE;
1026     }
1027   else
1028     {
1029     /* Processing header byte */
1030     if (c != '\r')
1031       {
1032       if (c == '\n')
1033         {
1034         if (ctx->flags & PDKIM_SEEN_LF)
1035           {
1036           int rc = pdkim_header_complete(ctx); /* Seen last header line */
1037           if (rc != PDKIM_OK) return rc;
1038
1039           ctx->flags = ctx->flags & ~PDKIM_SEEN_LF | PDKIM_PAST_HDRS;
1040           DEBUG(D_acl) debug_printf(
1041               "PDKIM >> Body data for hash, canonicalized >>>>>>>>>>>>>>>>>>>>>>\n");
1042           continue;
1043           }
1044         else
1045           ctx->flags |= PDKIM_SEEN_LF;
1046         }
1047       else if (ctx->flags & PDKIM_SEEN_LF)
1048         {
1049         if (!(c == '\t' || c == ' '))
1050           {
1051           int rc = pdkim_header_complete(ctx); /* End of header */
1052           if (rc != PDKIM_OK) return rc;
1053           }
1054         ctx->flags &= ~PDKIM_SEEN_LF;
1055         }
1056       }
1057
1058     if (ctx->cur_header_len < PDKIM_MAX_HEADER_LEN)
1059       ctx->cur_header = string_catn(ctx->cur_header, &ctx->cur_header_size,
1060                                   &ctx->cur_header_len, CUS &data[p], 1);
1061     }
1062   }
1063 return PDKIM_OK;
1064 }
1065
1066
1067
1068 /* Extend a grwong header with a continuation-linebreak */
1069 static uschar *
1070 pdkim_hdr_cont(uschar * str, int * size, int * ptr, int * col)
1071 {
1072 *col = 1;
1073 return string_catn(str, size, ptr, US"\r\n\t", 3);
1074 }
1075
1076
1077
1078 /*
1079  * RFC 5322 specifies that header line length SHOULD be no more than 78
1080  * lets make it so!
1081  *  pdkim_headcat
1082  *
1083  * returns uschar * (not nul-terminated)
1084  *
1085  * col: this int holds and receives column number (octets since last '\n')
1086  * str: partial string to append to
1087  * size: current buffer size for str
1088  * ptr: current tail-pointer for str
1089  * pad: padding, split line or space after before or after eg: ";"
1090  * intro: - must join to payload eg "h=", usually the tag name
1091  * payload: eg base64 data - long data can be split arbitrarily.
1092  *
1093  * this code doesn't fold the header in some of the places that RFC4871
1094  * allows: As per RFC5322(2.2.3) it only folds before or after tag-value
1095  * pairs and inside long values. it also always spaces or breaks after the
1096  * "pad"
1097  *
1098  * no guarantees are made for output given out-of range input. like tag
1099  * names longer than 78, or bogus col. Input is assumed to be free of line breaks.
1100  */
1101
1102 static uschar *
1103 pdkim_headcat(int * col, uschar * str, int * size, int * ptr,
1104   const uschar * pad, const uschar * intro, const uschar * payload)
1105 {
1106 size_t l;
1107
1108 if (pad)
1109   {
1110   l = Ustrlen(pad);
1111   if (*col + l > 78)
1112     str = pdkim_hdr_cont(str, size, ptr, col);
1113   str = string_catn(str, size, ptr, pad, l);
1114   *col += l;
1115   }
1116
1117 l = (pad?1:0) + (intro?Ustrlen(intro):0);
1118
1119 if (*col + l > 78)
1120   { /*can't fit intro - start a new line to make room.*/
1121   str = pdkim_hdr_cont(str, size, ptr, col);
1122   l = intro?Ustrlen(intro):0;
1123   }
1124
1125 l += payload ? Ustrlen(payload):0 ;
1126
1127 while (l>77)
1128   { /* this fragment will not fit on a single line */
1129   if (pad)
1130     {
1131     str = string_catn(str, size, ptr, US" ", 1);
1132     *col += 1;
1133     pad = NULL; /* only want this once */
1134     l--;
1135     }
1136
1137   if (intro)
1138     {
1139     size_t sl = Ustrlen(intro);
1140
1141     str = string_catn(str, size, ptr, intro, sl);
1142     *col += sl;
1143     l -= sl;
1144     intro = NULL; /* only want this once */
1145     }
1146
1147   if (payload)
1148     {
1149     size_t sl = Ustrlen(payload);
1150     size_t chomp = *col+sl < 77 ? sl : 78-*col;
1151
1152     str = string_catn(str, size, ptr, payload, chomp);
1153     *col += chomp;
1154     payload += chomp;
1155     l -= chomp-1;
1156     }
1157
1158   /* the while precondition tells us it didn't fit. */
1159   str = pdkim_hdr_cont(str, size, ptr, col);
1160   }
1161
1162 if (*col + l > 78)
1163   {
1164   str = pdkim_hdr_cont(str, size, ptr, col);
1165   pad = NULL;
1166   }
1167
1168 if (pad)
1169   {
1170   str = string_catn(str, size, ptr, US" ", 1);
1171   *col += 1;
1172   pad = NULL;
1173   }
1174
1175 if (intro)
1176   {
1177   size_t sl = Ustrlen(intro);
1178
1179   str = string_catn(str, size, ptr, intro, sl);
1180   *col += sl;
1181   l -= sl;
1182   intro = NULL;
1183   }
1184
1185 if (payload)
1186   {
1187   size_t sl = Ustrlen(payload);
1188
1189   str = string_catn(str, size, ptr, payload, sl);
1190   *col += sl;
1191   }
1192
1193 return str;
1194 }
1195
1196
1197 /* -------------------------------------------------------------------------- */
1198
1199 static uschar *
1200 pdkim_create_header(pdkim_signature *sig, BOOL final)
1201 {
1202 uschar * base64_bh;
1203 uschar * base64_b;
1204 int col = 0;
1205 uschar * hdr;       int hdr_size = 0, hdr_len = 0;
1206 uschar * canon_all; int can_size = 0, can_len = 0;
1207
1208 canon_all = string_cat (NULL, &can_size, &can_len,
1209                       pdkim_canons[sig->canon_headers]);
1210 canon_all = string_catn(canon_all, &can_size, &can_len, US"/", 1);
1211 canon_all = string_cat (canon_all, &can_size, &can_len,
1212                       pdkim_canons[sig->canon_body]);
1213 canon_all[can_len] = '\0';
1214
1215 hdr = string_cat(NULL, &hdr_size, &hdr_len,
1216                       US"DKIM-Signature: v="PDKIM_SIGNATURE_VERSION);
1217 col = hdr_len;
1218
1219 /* Required and static bits */
1220 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"a=",
1221                     pdkim_algos[sig->algo]);
1222 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"q=",
1223                     pdkim_querymethods[sig->querymethod]);
1224 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"c=",
1225                     canon_all);
1226 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"d=",
1227                     sig->domain);
1228 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"s=",
1229                     sig->selector);
1230
1231 /* list of header names can be split between items. */
1232   {
1233   uschar * n = string_copy(sig->headernames);
1234   uschar * i = US"h=";
1235   uschar * s = US";";
1236
1237   while (*n)
1238     {
1239     uschar * c = Ustrchr(n, ':');
1240
1241     if (c) *c ='\0';
1242
1243     if (!i)
1244       hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, NULL, NULL, US":");
1245
1246     hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, s, i, n);
1247
1248     if (!c)
1249       break;
1250
1251     n = c+1;
1252     s = NULL;
1253     i = NULL;
1254     }
1255   }
1256
1257 base64_bh = pdkim_encode_base64(&sig->bodyhash);
1258 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"bh=", base64_bh);
1259
1260 /* Optional bits */
1261 if (sig->identity)
1262   hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"i=", sig->identity);
1263
1264 if (sig->created > 0)
1265   {
1266   uschar minibuf[20];
1267
1268   snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->created);
1269   hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"t=", minibuf);
1270 }
1271
1272 if (sig->expires > 0)
1273   {
1274   uschar minibuf[20];
1275
1276   snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->expires);
1277   hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"x=", minibuf);
1278   }
1279
1280 if (sig->bodylength >= 0)
1281   {
1282   uschar minibuf[20];
1283
1284   snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->bodylength);
1285   hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"l=", minibuf);
1286   }
1287
1288 /* Preliminary or final version? */
1289 base64_b = final ? pdkim_encode_base64(&sig->sigdata) : US"";
1290 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"b=", base64_b);
1291
1292 /* add trailing semicolon: I'm not sure if this is actually needed */
1293 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, NULL, US";", US"");
1294
1295 hdr[hdr_len] = '\0';
1296 return hdr;
1297 }
1298
1299
1300 /* -------------------------------------------------------------------------- */
1301
1302 DLLEXPORT int
1303 pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatures)
1304 {
1305 pdkim_signature *sig = ctx->sig;
1306 uschar * headernames = NULL;             /* Collected signed header names */
1307 int hs = 0, hl = 0;
1308
1309 /* Check if we must still flush a (partial) header. If that is the
1310    case, the message has no body, and we must compute a body hash
1311    out of '<CR><LF>' */
1312 if (ctx->cur_header && ctx->cur_header_len)
1313   {
1314   int rc = pdkim_header_complete(ctx);
1315   if (rc != PDKIM_OK) return rc;
1316   pdkim_update_bodyhash(ctx, "\r\n", 2);
1317   }
1318 else
1319   DEBUG(D_acl) debug_printf(
1320       "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1321
1322 /* Build (and/or evaluate) body hash */
1323 pdkim_finish_bodyhash(ctx);
1324
1325 while (sig)
1326   {
1327   BOOL is_sha1 = sig->algo == PDKIM_ALGO_RSA_SHA1;
1328   hctx hhash_ctx;
1329   uschar * sig_hdr;
1330   blob hhash;
1331   blob hdata;
1332   int hdata_alloc = 0;
1333
1334   hdata.data = NULL;
1335   hdata.len = 0;
1336
1337   exim_sha_init(&hhash_ctx, is_sha1 ? HASH_SHA1 : HASH_SHA256);
1338
1339   DEBUG(D_acl) debug_printf(
1340       "PDKIM >> Hashed header data, canonicalized, in sequence >>>>>>>>>>>>>>\n");
1341
1342   /* SIGNING ---------------------------------------------------------------- */
1343   /* When signing, walk through our header list and add them to the hash. As we
1344      go, construct a list of the header's names to use for the h= parameter.
1345      Then append to that list any remaining header names for which there was no
1346      header to sign. */
1347
1348   if (ctx->flags & PDKIM_MODE_SIGN)
1349     {
1350     pdkim_stringlist *p;
1351     const uschar * l;
1352     uschar * s;
1353     int sep = 0;
1354
1355     for (p = sig->headers; p; p = p->next)
1356       if (header_name_match(p->value, sig->sign_headers) == PDKIM_OK)
1357         {
1358         uschar * rh;
1359         /* Collect header names (Note: colon presence is guaranteed here) */
1360         uschar * q = Ustrchr(p->value, ':');
1361
1362         headernames = string_catn(headernames, &hs, &hl,
1363                         p->value, (q - US p->value) + (p->next ? 1 : 0));
1364
1365         rh = sig->canon_headers == PDKIM_CANON_RELAXED
1366           ? pdkim_relax_header(p->value, 1) /* cook header for relaxed canon */
1367           : string_copy(CUS p->value);      /* just copy it for simple canon */
1368
1369         /* Feed header to the hash algorithm */
1370         exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
1371
1372         /* Remember headers block for signing (when the library cannot do incremental)  */
1373         (void) exim_rsa_data_append(&hdata, &hdata_alloc, rh);
1374
1375         DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1376         }
1377
1378     l = sig->sign_headers;
1379     while((s = string_nextinlist(&l, &sep, NULL, 0)))
1380       if (*s != '_')
1381         {                       /*SSS string_append_listele() */
1382         if (hl > 0 && headernames[hl-1] != ':')
1383           headernames = string_catn(headernames, &hs, &hl, US":", 1);
1384
1385         headernames = string_cat(headernames, &hs, &hl, s);
1386         }
1387     headernames[hl] = '\0';
1388
1389     /* Copy headernames to signature struct */
1390     sig->headernames = headernames;
1391     headernames = NULL, hs = hl = 0;
1392
1393     /* Create signature header with b= omitted */
1394     sig_hdr = pdkim_create_header(sig, FALSE);
1395     }
1396
1397   /* VERIFICATION ----------------------------------------------------------- */
1398   /* When verifying, walk through the header name list in the h= parameter and
1399      add the headers to the hash in that order. */
1400   else
1401     {
1402     uschar * b = string_copy(sig->headernames);
1403     uschar * p = b;
1404     uschar * q;
1405     pdkim_stringlist * hdrs;
1406
1407     /* clear tags */
1408     for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1409       hdrs->tag = 0;
1410
1411     while(1)
1412       {
1413       if ((q = Ustrchr(p, ':')))
1414         *q = '\0';
1415
1416 /*XXX walk the list of headers in same order as received. */
1417       for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1418         if (  hdrs->tag == 0
1419            && strncasecmp(hdrs->value, CS p, Ustrlen(p)) == 0
1420            && (hdrs->value)[Ustrlen(p)] == ':'
1421            )
1422           {
1423           uschar * rh = sig->canon_headers == PDKIM_CANON_RELAXED
1424             ? pdkim_relax_header(hdrs->value, 1) /* cook header for relaxed canon */
1425             : string_copy(CUS hdrs->value);      /* just copy it for simple canon */
1426
1427           /* Feed header to the hash algorithm */
1428           exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
1429
1430           DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1431           hdrs->tag = 1;
1432           break;
1433           }
1434
1435       if (!q) break;
1436       p = q+1;
1437       }
1438
1439     sig_hdr = string_copy(sig->rawsig_no_b_val);
1440     }
1441
1442   DEBUG(D_acl) debug_printf(
1443             "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1444
1445   /* Relax header if necessary */
1446   if (sig->canon_headers == PDKIM_CANON_RELAXED)
1447     sig_hdr = pdkim_relax_header(sig_hdr, 0);
1448
1449   DEBUG(D_acl)
1450     {
1451     debug_printf(
1452             "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
1453     pdkim_quoteprint(CUS sig_hdr, Ustrlen(sig_hdr));
1454     debug_printf(
1455             "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1456     }
1457
1458   /* Finalize header hash */
1459   exim_sha_update(&hhash_ctx, CUS sig_hdr, Ustrlen(sig_hdr));
1460   exim_sha_finish(&hhash_ctx, &hhash);
1461
1462   DEBUG(D_acl)
1463     {
1464     debug_printf("PDKIM [%s] hh computed: ", sig->domain);
1465     pdkim_hexprint(hhash.data, hhash.len);
1466     }
1467
1468   /* Remember headers block for signing (when the library cannot do incremental)  */
1469   if (ctx->flags & PDKIM_MODE_SIGN)
1470     (void) exim_rsa_data_append(&hdata, &hdata_alloc, US sig_hdr);
1471
1472   /* SIGNING ---------------------------------------------------------------- */
1473   if (ctx->flags & PDKIM_MODE_SIGN)
1474     {
1475     es_ctx sctx;
1476     const uschar * errstr;
1477
1478     /* Import private key */
1479     if ((errstr = exim_rsa_signing_init(US sig->rsa_privkey, &sctx)))
1480       {
1481       DEBUG(D_acl) debug_printf("signing_init: %s\n", errstr);
1482       return PDKIM_ERR_RSA_PRIVKEY;
1483       }
1484
1485     /* Do signing.  With OpenSSL we are signing the hash of headers just
1486     calculated, with GnuTLS we have to sign an entire block of headers
1487     (due to available interfaces) and it recalculates the hash internally. */
1488
1489 #if defined(RSA_OPENSSL) || defined(RSA_GCRYPT)
1490     hdata = hhash;
1491 #endif
1492
1493     if ((errstr = exim_rsa_sign(&sctx, is_sha1, &hdata, &sig->sigdata)))
1494       {
1495       DEBUG(D_acl) debug_printf("signing: %s\n", errstr);
1496       return PDKIM_ERR_RSA_SIGNING;
1497       }
1498
1499     DEBUG(D_acl)
1500       {
1501       debug_printf( "PDKIM [%s] b computed: ", sig->domain);
1502       pdkim_hexprint(sig->sigdata.data, sig->sigdata.len);
1503       }
1504
1505     sig->signature_header = pdkim_create_header(sig, TRUE);
1506     }
1507
1508   /* VERIFICATION ----------------------------------------------------------- */
1509   else
1510     {
1511     ev_ctx vctx;
1512     const uschar * errstr;
1513
1514     uschar *dns_txt_name, *dns_txt_reply;
1515
1516     /* Make sure we have all required signature tags */
1517     if (!(  sig->domain        && *sig->domain
1518          && sig->selector      && *sig->selector
1519          && sig->headernames   && *sig->headernames
1520          && sig->bodyhash.data
1521          && sig->sigdata.data
1522          && sig->algo > -1
1523          && sig->version
1524        ) )
1525       {
1526       sig->verify_status     = PDKIM_VERIFY_INVALID;
1527       sig->verify_ext_status = PDKIM_VERIFY_INVALID_SIGNATURE_ERROR;
1528
1529       DEBUG(D_acl) debug_printf(
1530           " Error in DKIM-Signature header: tags missing or invalid\n"
1531           "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1532       goto NEXT_VERIFY;
1533       }
1534
1535     /* Make sure sig uses supported DKIM version (only v1) */
1536     if (sig->version != 1)
1537       {
1538       sig->verify_status     = PDKIM_VERIFY_INVALID;
1539       sig->verify_ext_status = PDKIM_VERIFY_INVALID_DKIM_VERSION;
1540
1541       DEBUG(D_acl) debug_printf(
1542           " Error in DKIM-Signature header: unsupported DKIM version\n"
1543           "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1544       goto NEXT_VERIFY;
1545       }
1546
1547     /* Fetch public key for signing domain, from DNS */
1548
1549     dns_txt_name = string_sprintf("%s._domainkey.%s.",
1550                                  sig->selector, sig->domain);
1551
1552     dns_txt_reply = store_get(PDKIM_DNS_TXT_MAX_RECLEN);
1553     memset(dns_txt_reply, 0, PDKIM_DNS_TXT_MAX_RECLEN);
1554
1555     if (  ctx->dns_txt_callback(CS dns_txt_name, CS dns_txt_reply) != PDKIM_OK 
1556        || dns_txt_reply[0] == '\0')
1557       {
1558       sig->verify_status =      PDKIM_VERIFY_INVALID;
1559       sig->verify_ext_status =  PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE;
1560       goto NEXT_VERIFY;
1561       }
1562
1563     DEBUG(D_acl)
1564       {
1565       debug_printf(
1566           "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
1567           " Raw record: ");
1568       pdkim_quoteprint(CUS dns_txt_reply, Ustrlen(dns_txt_reply));
1569       }
1570
1571     if (!(sig->pubkey = pdkim_parse_pubkey_record(ctx, CUS dns_txt_reply)))
1572       {
1573       sig->verify_status =      PDKIM_VERIFY_INVALID;
1574       sig->verify_ext_status =  PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD;
1575
1576       DEBUG(D_acl) debug_printf(
1577           " Error while parsing public key record\n"
1578           "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1579       goto NEXT_VERIFY;
1580       }
1581
1582     DEBUG(D_acl) debug_printf(
1583           "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1584
1585     /* Import public key */
1586     if ((errstr = exim_rsa_verify_init(&sig->pubkey->key, &vctx)))
1587       {
1588       DEBUG(D_acl) debug_printf("verify_init: %s\n", errstr);
1589       sig->verify_status =      PDKIM_VERIFY_INVALID;
1590       sig->verify_ext_status =  PDKIM_VERIFY_INVALID_PUBKEY_IMPORT;
1591       goto NEXT_VERIFY;
1592       }
1593
1594     /* Check the signature */
1595     if ((errstr = exim_rsa_verify(&vctx, is_sha1, &hhash, &sig->sigdata)))
1596       {
1597       DEBUG(D_acl) debug_printf("headers verify: %s\n", errstr);
1598       sig->verify_status =      PDKIM_VERIFY_FAIL;
1599       sig->verify_ext_status =  PDKIM_VERIFY_FAIL_MESSAGE;
1600       goto NEXT_VERIFY;
1601       }
1602
1603
1604     /* We have a winner! (if bodydhash was correct earlier) */
1605     if (sig->verify_status == PDKIM_VERIFY_NONE)
1606       sig->verify_status = PDKIM_VERIFY_PASS;
1607
1608 NEXT_VERIFY:
1609
1610     DEBUG(D_acl)
1611       {
1612       debug_printf("PDKIM [%s] signature status: %s",
1613               sig->domain, pdkim_verify_status_str(sig->verify_status));
1614       if (sig->verify_ext_status > 0)
1615         debug_printf(" (%s)\n",
1616                 pdkim_verify_ext_status_str(sig->verify_ext_status));
1617       else
1618         debug_printf("\n");
1619       }
1620     }
1621
1622   sig = sig->next;
1623   }
1624
1625 /* If requested, set return pointer to signature(s) */
1626 if (return_signatures)
1627   *return_signatures = ctx->sig;
1628
1629 return PDKIM_OK;
1630 }
1631
1632
1633 /* -------------------------------------------------------------------------- */
1634
1635 DLLEXPORT pdkim_ctx *
1636 pdkim_init_verify(int(*dns_txt_callback)(char *, char *), BOOL dot_stuffing)
1637 {
1638 pdkim_ctx * ctx;
1639
1640 ctx = store_get(sizeof(pdkim_ctx));
1641 memset(ctx, 0, sizeof(pdkim_ctx));
1642
1643 if (dot_stuffing) ctx->flags = PDKIM_DOT_TERM;
1644 ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN);
1645 ctx->dns_txt_callback = dns_txt_callback;
1646
1647 return ctx;
1648 }
1649
1650
1651 /* -------------------------------------------------------------------------- */
1652
1653 DLLEXPORT pdkim_ctx *
1654 pdkim_init_sign(char *domain, char *selector, char *rsa_privkey, int algo,
1655   BOOL dot_stuffed)
1656 {
1657 pdkim_ctx *ctx;
1658 pdkim_signature *sig;
1659
1660 if (!domain || !selector || !rsa_privkey)
1661   return NULL;
1662
1663 ctx = store_get(sizeof(pdkim_ctx));
1664 memset(ctx, 0, sizeof(pdkim_ctx));
1665
1666 ctx->flags = dot_stuffed ? PDKIM_MODE_SIGN | PDKIM_DOT_TERM : PDKIM_MODE_SIGN;
1667 ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN);
1668
1669 sig = store_get(sizeof(pdkim_signature));
1670 memset(sig, 0, sizeof(pdkim_signature));
1671
1672 sig->bodylength = -1;
1673 ctx->sig = sig;
1674
1675 sig->domain = string_copy(US domain);
1676 sig->selector = string_copy(US selector);
1677 sig->rsa_privkey = string_copy(US rsa_privkey);
1678 sig->algo = algo;
1679
1680 exim_sha_init(&sig->body_hash, algo == PDKIM_ALGO_RSA_SHA1 ? HASH_SHA1 : HASH_SHA256);
1681 return ctx;
1682 }
1683
1684
1685 /* -------------------------------------------------------------------------- */
1686
1687 DLLEXPORT int
1688 pdkim_set_optional(pdkim_ctx *ctx,
1689                        char *sign_headers,
1690                        char *identity,
1691                        int canon_headers,
1692                        int canon_body,
1693                        long bodylength,
1694                        unsigned long created,
1695                        unsigned long expires)
1696 {
1697 pdkim_signature * sig = ctx->sig;
1698
1699 if (identity)
1700   sig->identity = string_copy(US identity);
1701
1702 sig->sign_headers = string_copy(sign_headers
1703         ? US sign_headers : US PDKIM_DEFAULT_SIGN_HEADERS);
1704
1705 sig->canon_headers = canon_headers;
1706 sig->canon_body = canon_body;
1707 sig->bodylength = bodylength;
1708 sig->created = created;
1709 sig->expires = expires;
1710
1711 return PDKIM_OK;
1712 }
1713
1714
1715 void
1716 pdkim_init(void)
1717 {
1718 exim_rsa_init();
1719 }
1720
1721
1722
1723 #endif  /*DISABLE_DKIM*/