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