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