DKIM: ensure that dkim_domain elements are lowercased before use. Bug 2371
[exim.git] / src / src / dkim.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) University of Cambridge, 1995 - 2018 */
6 /* See the file NOTICE for conditions of use and distribution. */
7
8 /* Code for DKIM support. Other DKIM relevant code is in
9    receive.c, transport.c and transports/smtp.c */
10
11 #include "exim.h"
12
13 #ifndef DISABLE_DKIM
14
15 # include "pdkim/pdkim.h"
16
17 # ifdef MACRO_PREDEF
18 #  include "macro_predef.h"
19
20 void
21 params_dkim(void)
22 {
23 builtin_macro_create_var(US"_DKIM_SIGN_HEADERS", US PDKIM_DEFAULT_SIGN_HEADERS);
24 }
25 # else  /*!MACRO_PREDEF*/
26
27
28
29 pdkim_ctx dkim_sign_ctx;
30
31 int dkim_verify_oldpool;
32 pdkim_ctx *dkim_verify_ctx = NULL;
33 pdkim_signature *dkim_cur_sig = NULL;
34 static const uschar * dkim_collect_error = NULL;
35
36 #define DKIM_MAX_SIGNATURES 20
37
38
39
40 /*XXX the caller only uses the first record if we return multiple.
41 */
42
43 uschar *
44 dkim_exim_query_dns_txt(uschar * name)
45 {
46 dns_answer dnsa;
47 dns_scan dnss;
48 gstring * g = NULL;
49
50 lookup_dnssec_authenticated = NULL;
51 if (dns_lookup(&dnsa, name, T_TXT, NULL) != DNS_SUCCEED)
52   return NULL;  /*XXX better error detail?  logging? */
53
54 /* Search for TXT record */
55
56 for (dns_record * rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
57      rr;
58      rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
59   if (rr->type == T_TXT)
60     {
61     int rr_offset = 0;
62
63     /* Copy record content to the answer buffer */
64
65     while (rr_offset < rr->size)
66       {
67       uschar len = rr->data[rr_offset++];
68
69       g = string_catn(g, US(rr->data + rr_offset), len);
70       if (g->ptr >= PDKIM_DNS_TXT_MAX_RECLEN)
71         goto bad;
72
73       rr_offset += len;
74       }
75
76     /* check if this looks like a DKIM record */
77     if (Ustrncmp(g->s, "v=", 2) != 0 || strncasecmp(CS g->s, "v=dkim", 6) == 0)
78       {
79       gstring_reset_unused(g);
80       return string_from_gstring(g);
81       }
82
83     if (g) g->ptr = 0;          /* overwrite previous record */
84     }
85
86 bad:
87 if (g) store_reset(g);
88 return NULL;    /*XXX better error detail?  logging? */
89 }
90
91
92 void
93 dkim_exim_init(void)
94 {
95 pdkim_init();
96 }
97
98
99
100 void
101 dkim_exim_verify_init(BOOL dot_stuffing)
102 {
103 /* There is a store-reset between header & body reception
104 so cannot use the main pool. Any allocs done by Exim
105 memory-handling must use the perm pool. */
106
107 dkim_verify_oldpool = store_pool;
108 store_pool = POOL_PERM;
109
110 /* Free previous context if there is one */
111
112 if (dkim_verify_ctx)
113   pdkim_free_ctx(dkim_verify_ctx);
114
115 /* Create new context */
116
117 dkim_verify_ctx = pdkim_init_verify(&dkim_exim_query_dns_txt, dot_stuffing);
118 dkim_collect_input = dkim_verify_ctx ? DKIM_MAX_SIGNATURES : 0;
119 dkim_collect_error = NULL;
120
121 /* Start feed up with any cached data */
122 receive_get_cache();
123
124 store_pool = dkim_verify_oldpool;
125 }
126
127
128 void
129 dkim_exim_verify_feed(uschar * data, int len)
130 {
131 int rc;
132
133 store_pool = POOL_PERM;
134 if (  dkim_collect_input
135    && (rc = pdkim_feed(dkim_verify_ctx, data, len)) != PDKIM_OK)
136   {
137   dkim_collect_error = pdkim_errstr(rc);
138   log_write(0, LOG_MAIN,
139              "DKIM: validation error: %.100s", dkim_collect_error);
140   dkim_collect_input = 0;
141   }
142 store_pool = dkim_verify_oldpool;
143 }
144
145
146 /* Log the result for the given signature */
147 static void
148 dkim_exim_verify_log_sig(pdkim_signature * sig)
149 {
150 gstring * logmsg;
151 uschar * s;
152
153 if (!sig) return;
154
155 /* Remember the domain for the first pass result */
156
157 if (  !dkim_verify_overall
158    && dkim_verify_status
159       ? Ustrcmp(dkim_verify_status, US"pass") == 0
160       : sig->verify_status == PDKIM_VERIFY_PASS
161    )
162   dkim_verify_overall = string_copy(sig->domain);
163
164 /* Rewrite the sig result if the ACL overrode it.  This is only
165 needed because the DMARC code (sigh) peeks at the dkim sigs.
166 Mark the sig for this having been done. */
167
168 if (  dkim_verify_status
169    && (  dkim_verify_status != dkim_exim_expand_query(DKIM_VERIFY_STATUS)
170       || dkim_verify_reason != dkim_exim_expand_query(DKIM_VERIFY_REASON)
171    )  )
172   {                     /* overridden by ACL */
173   sig->verify_ext_status = -1;
174   if (Ustrcmp(dkim_verify_status, US"fail") == 0)
175     sig->verify_status = PDKIM_VERIFY_POLICY | PDKIM_VERIFY_FAIL;
176   else if (Ustrcmp(dkim_verify_status, US"invalid") == 0)
177     sig->verify_status = PDKIM_VERIFY_POLICY | PDKIM_VERIFY_INVALID;
178   else if (Ustrcmp(dkim_verify_status, US"none") == 0)
179     sig->verify_status = PDKIM_VERIFY_POLICY | PDKIM_VERIFY_NONE;
180   else if (Ustrcmp(dkim_verify_status, US"pass") == 0)
181     sig->verify_status = PDKIM_VERIFY_POLICY | PDKIM_VERIFY_PASS;
182   else
183     sig->verify_status = -1;
184   }
185
186 if (!LOGGING(dkim_verbose)) return;
187
188
189 logmsg = string_catn(NULL, US"DKIM: ", 6);
190 if (!(s = sig->domain)) s = US"<UNSET>";
191 logmsg = string_append(logmsg, 2, "d=", s);
192 if (!(s = sig->selector)) s = US"<UNSET>";
193 logmsg = string_append(logmsg, 2, " s=", s);
194 logmsg = string_fmt_append(logmsg, " c=%s/%s a=%s b=" SIZE_T_FMT,
195           sig->canon_headers == PDKIM_CANON_SIMPLE ? "simple" : "relaxed",
196           sig->canon_body    == PDKIM_CANON_SIMPLE ? "simple" : "relaxed",
197           dkim_sig_to_a_tag(sig),
198           (int)sig->sighash.len > -1 ? sig->sighash.len * 8 : (size_t)0);
199 if ((s= sig->identity)) logmsg = string_append(logmsg, 2, " i=", s);
200 if (sig->created > 0) logmsg = string_fmt_append(logmsg, " t=%lu",
201                                     sig->created);
202 if (sig->expires > 0) logmsg = string_fmt_append(logmsg, " x=%lu",
203                                     sig->expires);
204 if (sig->bodylength > -1) logmsg = string_fmt_append(logmsg, " l=%lu",
205                                     sig->bodylength);
206
207 if (sig->verify_status & PDKIM_VERIFY_POLICY)
208   logmsg = string_append(logmsg, 5,
209             US" [", dkim_verify_status, US" - ", dkim_verify_reason, US"]");
210 else
211   switch (sig->verify_status)
212     {
213     case PDKIM_VERIFY_NONE:
214       logmsg = string_cat(logmsg, US" [not verified]");
215       break;
216
217     case PDKIM_VERIFY_INVALID:
218       logmsg = string_cat(logmsg, US" [invalid - ");
219       switch (sig->verify_ext_status)
220         {
221         case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE:
222           logmsg = string_cat(logmsg,
223                         US"public key record (currently?) unavailable]");
224           break;
225
226         case PDKIM_VERIFY_INVALID_BUFFER_SIZE:
227           logmsg = string_cat(logmsg, US"overlong public key record]");
228           break;
229
230         case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD:
231         case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT:
232           logmsg = string_cat(logmsg, US"syntax error in public key record]");
233           break;
234
235         case PDKIM_VERIFY_INVALID_SIGNATURE_ERROR:
236           logmsg = string_cat(logmsg, US"signature tag missing or invalid]");
237           break;
238
239         case PDKIM_VERIFY_INVALID_DKIM_VERSION:
240           logmsg = string_cat(logmsg, US"unsupported DKIM version]");
241           break;
242
243         default:
244           logmsg = string_cat(logmsg, US"unspecified problem]");
245         }
246       break;
247
248     case PDKIM_VERIFY_FAIL:
249       logmsg = string_cat(logmsg, US" [verification failed - ");
250       switch (sig->verify_ext_status)
251         {
252         case PDKIM_VERIFY_FAIL_BODY:
253           logmsg = string_cat(logmsg,
254                US"body hash mismatch (body probably modified in transit)]");
255           break;
256
257         case PDKIM_VERIFY_FAIL_MESSAGE:
258           logmsg = string_cat(logmsg,
259                 US"signature did not verify "
260                 "(headers probably modified in transit)]");
261           break;
262
263         default:
264           logmsg = string_cat(logmsg, US"unspecified reason]");
265         }
266       break;
267
268     case PDKIM_VERIFY_PASS:
269       logmsg = string_cat(logmsg, US" [verification succeeded]");
270       break;
271     }
272
273 log_write(0, LOG_MAIN, "%s", string_from_gstring(logmsg));
274 return;
275 }
276
277
278 /* Log a line for each signature */
279 void
280 dkim_exim_verify_log_all(void)
281 {
282 for (pdkim_signature * sig = dkim_signatures; sig; sig = sig->next)
283   dkim_exim_verify_log_sig(sig);
284 }
285
286
287 void
288 dkim_exim_verify_finish(void)
289 {
290 int rc;
291 gstring * g = NULL;
292 const uschar * errstr = NULL;
293
294 store_pool = POOL_PERM;
295
296 /* Delete eventual previous signature chain */
297
298 dkim_signers = NULL;
299 dkim_signatures = NULL;
300
301 if (dkim_collect_error)
302   {
303   log_write(0, LOG_MAIN,
304       "DKIM: Error during validation, disabling signature verification: %.100s",
305       dkim_collect_error);
306   f.dkim_disable_verify = TRUE;
307   goto out;
308   }
309
310 dkim_collect_input = 0;
311
312 /* Finish DKIM operation and fetch link to signatures chain */
313
314 rc = pdkim_feed_finish(dkim_verify_ctx, (pdkim_signature **)&dkim_signatures,
315                         &errstr);
316 if (rc != PDKIM_OK && errstr)
317   log_write(0, LOG_MAIN, "DKIM: validation error: %s", errstr);
318
319 /* Build a colon-separated list of signing domains (and identities, if present) in dkim_signers */
320
321 for (pdkim_signature * sig = dkim_signatures; sig; sig = sig->next)
322   {
323   if (sig->domain)   g = string_append_listele(g, ':', sig->domain);
324   if (sig->identity) g = string_append_listele(g, ':', sig->identity);
325   }
326
327 if (g) dkim_signers = g->s;
328
329 out:
330 store_pool = dkim_verify_oldpool;
331 }
332
333
334
335 /* Args as per dkim_exim_acl_run() below */
336 static int
337 dkim_acl_call(uschar * id, gstring ** res_ptr,
338   uschar ** user_msgptr, uschar ** log_msgptr)
339 {
340 int rc;
341 DEBUG(D_receive)
342   debug_printf("calling acl_smtp_dkim for dkim_cur_signer='%s'\n", id);
343
344 rc = acl_check(ACL_WHERE_DKIM, NULL, acl_smtp_dkim, user_msgptr, log_msgptr);
345 dkim_exim_verify_log_sig(dkim_cur_sig);
346 *res_ptr = string_append_listele(*res_ptr, ':', dkim_verify_status);
347 return rc;
348 }
349
350
351
352 /* For the given identity, run the DKIM ACL once for each matching signature.
353
354 Arguments
355  id             Identity to look for in dkim signatures
356  res_ptr        ptr to growable string-list of status results,
357                 appended to per ACL run
358  user_msgptr    where to put a user error (for SMTP response)
359  log_msgptr     where to put a logging message (not for SMTP response)
360
361 Returns:       OK         access is granted by an ACCEPT verb
362                DISCARD    access is granted by a DISCARD verb
363                FAIL       access is denied
364                FAIL_DROP  access is denied; drop the connection
365                DEFER      can't tell at the moment
366                ERROR      disaster
367 */
368
369 int
370 dkim_exim_acl_run(uschar * id, gstring ** res_ptr,
371   uschar ** user_msgptr, uschar ** log_msgptr)
372 {
373 uschar * cmp_val;
374 int rc = -1;
375
376 dkim_verify_status = US"none";
377 dkim_verify_reason = US"";
378 dkim_cur_signer = id;
379
380 if (f.dkim_disable_verify || !id || !dkim_verify_ctx)
381   return OK;
382
383 /* Find signatures to run ACL on */
384
385 for (pdkim_signature * sig = dkim_signatures; sig; sig = sig->next)
386   if (  (cmp_val = Ustrchr(id, '@') != NULL ? US sig->identity : US sig->domain)
387      && strcmpic(cmp_val, id) == 0
388      )
389     {
390     /* The "dkim_domain" and "dkim_selector" expansion variables have
391     related globals, since they are used in the signing code too.
392     Instead of inventing separate names for verification, we set
393     them here. This is easy since a domain and selector is guaranteed
394     to be in a signature. The other dkim_* expansion items are
395     dynamically fetched from dkim_cur_sig at expansion time (see
396     dkim_exim_expand_query() below). */
397
398     dkim_cur_sig = sig;
399     dkim_signing_domain = US sig->domain;
400     dkim_signing_selector = US sig->selector;
401     dkim_key_length = sig->sighash.len * 8;
402
403     /* These two return static strings, so we can compare the addr
404     later to see if the ACL overwrote them.  Check that when logging */
405
406     dkim_verify_status = dkim_exim_expand_query(DKIM_VERIFY_STATUS);
407     dkim_verify_reason = dkim_exim_expand_query(DKIM_VERIFY_REASON);
408
409     if ((rc = dkim_acl_call(id, res_ptr, user_msgptr, log_msgptr)) != OK)
410       return rc;
411     }
412
413 if (rc != -1)
414   return rc;
415
416 /* No matching sig found.  Call ACL once anyway. */
417
418 dkim_cur_sig = NULL;
419 return dkim_acl_call(id, res_ptr, user_msgptr, log_msgptr);
420 }
421
422
423 static uschar *
424 dkim_exim_expand_defaults(int what)
425 {
426 switch (what)
427   {
428   case DKIM_ALGO:               return US"";
429   case DKIM_BODYLENGTH:         return US"9999999999999";
430   case DKIM_CANON_BODY:         return US"";
431   case DKIM_CANON_HEADERS:      return US"";
432   case DKIM_COPIEDHEADERS:      return US"";
433   case DKIM_CREATED:            return US"0";
434   case DKIM_EXPIRES:            return US"9999999999999";
435   case DKIM_HEADERNAMES:        return US"";
436   case DKIM_IDENTITY:           return US"";
437   case DKIM_KEY_GRANULARITY:    return US"*";
438   case DKIM_KEY_SRVTYPE:        return US"*";
439   case DKIM_KEY_NOTES:          return US"";
440   case DKIM_KEY_TESTING:        return US"0";
441   case DKIM_NOSUBDOMAINS:       return US"0";
442   case DKIM_VERIFY_STATUS:      return US"none";
443   case DKIM_VERIFY_REASON:      return US"";
444   default:                      return US"";
445   }
446 }
447
448
449 uschar *
450 dkim_exim_expand_query(int what)
451 {
452 if (!dkim_verify_ctx || f.dkim_disable_verify || !dkim_cur_sig)
453   return dkim_exim_expand_defaults(what);
454
455 switch (what)
456   {
457   case DKIM_ALGO:
458     return dkim_sig_to_a_tag(dkim_cur_sig);
459
460   case DKIM_BODYLENGTH:
461     return dkim_cur_sig->bodylength >= 0
462       ? string_sprintf("%ld", dkim_cur_sig->bodylength)
463       : dkim_exim_expand_defaults(what);
464
465   case DKIM_CANON_BODY:
466     switch (dkim_cur_sig->canon_body)
467       {
468       case PDKIM_CANON_RELAXED: return US"relaxed";
469       case PDKIM_CANON_SIMPLE:
470       default:                  return US"simple";
471       }
472
473   case DKIM_CANON_HEADERS:
474     switch (dkim_cur_sig->canon_headers)
475       {
476       case PDKIM_CANON_RELAXED: return US"relaxed";
477       case PDKIM_CANON_SIMPLE:
478       default:                  return US"simple";
479       }
480
481   case DKIM_COPIEDHEADERS:
482     return dkim_cur_sig->copiedheaders
483       ? US dkim_cur_sig->copiedheaders : dkim_exim_expand_defaults(what);
484
485   case DKIM_CREATED:
486     return dkim_cur_sig->created > 0
487       ? string_sprintf("%lu", dkim_cur_sig->created)
488       : dkim_exim_expand_defaults(what);
489
490   case DKIM_EXPIRES:
491     return dkim_cur_sig->expires > 0
492       ? string_sprintf("%lu", dkim_cur_sig->expires)
493       : dkim_exim_expand_defaults(what);
494
495   case DKIM_HEADERNAMES:
496     return dkim_cur_sig->headernames
497       ? dkim_cur_sig->headernames : dkim_exim_expand_defaults(what);
498
499   case DKIM_IDENTITY:
500     return dkim_cur_sig->identity
501       ? US dkim_cur_sig->identity : dkim_exim_expand_defaults(what);
502
503   case DKIM_KEY_GRANULARITY:
504     return dkim_cur_sig->pubkey
505       ? dkim_cur_sig->pubkey->granularity
506       ? US dkim_cur_sig->pubkey->granularity
507       : dkim_exim_expand_defaults(what)
508       : dkim_exim_expand_defaults(what);
509
510   case DKIM_KEY_SRVTYPE:
511     return dkim_cur_sig->pubkey
512       ? dkim_cur_sig->pubkey->srvtype
513       ? US dkim_cur_sig->pubkey->srvtype
514       : dkim_exim_expand_defaults(what)
515       : dkim_exim_expand_defaults(what);
516
517   case DKIM_KEY_NOTES:
518     return dkim_cur_sig->pubkey
519       ? dkim_cur_sig->pubkey->notes
520       ? US dkim_cur_sig->pubkey->notes
521       : dkim_exim_expand_defaults(what)
522       : dkim_exim_expand_defaults(what);
523
524   case DKIM_KEY_TESTING:
525     return dkim_cur_sig->pubkey
526       ? dkim_cur_sig->pubkey->testing
527       ? US"1"
528       : dkim_exim_expand_defaults(what)
529       : dkim_exim_expand_defaults(what);
530
531   case DKIM_NOSUBDOMAINS:
532     return dkim_cur_sig->pubkey
533       ? dkim_cur_sig->pubkey->no_subdomaining
534       ? US"1"
535       : dkim_exim_expand_defaults(what)
536       : dkim_exim_expand_defaults(what);
537
538   case DKIM_VERIFY_STATUS:
539     switch (dkim_cur_sig->verify_status)
540       {
541       case PDKIM_VERIFY_INVALID:        return US"invalid";
542       case PDKIM_VERIFY_FAIL:           return US"fail";
543       case PDKIM_VERIFY_PASS:           return US"pass";
544       case PDKIM_VERIFY_NONE:
545       default:                          return US"none";
546       }
547
548   case DKIM_VERIFY_REASON:
549     switch (dkim_cur_sig->verify_ext_status)
550       {
551       case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE:
552                                                 return US"pubkey_unavailable";
553       case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD:return US"pubkey_dns_syntax";
554       case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT:  return US"pubkey_der_syntax";
555       case PDKIM_VERIFY_FAIL_BODY:              return US"bodyhash_mismatch";
556       case PDKIM_VERIFY_FAIL_MESSAGE:           return US"signature_incorrect";
557       }
558
559   default:
560     return US"";
561   }
562 }
563
564
565 void
566 dkim_exim_sign_init(void)
567 {
568 int old_pool = store_pool;
569 store_pool = POOL_MAIN;
570 pdkim_init_context(&dkim_sign_ctx, FALSE, &dkim_exim_query_dns_txt);
571 store_pool = old_pool;
572 }
573
574
575 /* Generate signatures for the given file.
576 If a prefix is given, prepend it to the file for the calculations.
577
578 Return:
579   NULL:         error; error string written
580   string:       signature header(s), or a zero-length string (not an error)
581 */
582
583 gstring *
584 dkim_exim_sign(int fd, off_t off, uschar * prefix,
585   struct ob_dkim * dkim, const uschar ** errstr)
586 {
587 const uschar * dkim_domain = NULL;
588 int sep = 0;
589 gstring * seen_doms = NULL;
590 pdkim_signature * sig;
591 gstring * sigbuf;
592 int pdkim_rc;
593 int sread;
594 uschar buf[4096];
595 int save_errno = 0;
596 int old_pool = store_pool;
597 uschar * errwhen;
598 const uschar * s;
599
600 if (dkim->dot_stuffed)
601   dkim_sign_ctx.flags |= PDKIM_DOT_TERM;
602
603 store_pool = POOL_MAIN;
604
605 if ((s = dkim->dkim_domain) && !(dkim_domain = expand_cstring(s)))
606   /* expansion error, do not send message. */
607   { errwhen = US"dkim_domain"; goto expand_bad; }
608
609 /* Set $dkim_domain expansion variable to each unique domain in list. */
610
611 if (dkim_domain)
612   while ((dkim_signing_domain = string_nextinlist(&dkim_domain, &sep, NULL, 0)))
613   {
614   const uschar * dkim_sel;
615   int sel_sep = 0;
616
617   if (dkim_signing_domain[0] == '\0')
618     continue;
619
620   /* Only sign once for each domain, no matter how often it
621   appears in the expanded list. */
622
623   dkim_signing_domain = string_copylc(dkim_signing_domain);
624   if (match_isinlist(dkim_signing_domain, CUSS &seen_doms,
625       0, NULL, NULL, MCL_STRING, TRUE, NULL) == OK)
626     continue;
627
628   seen_doms = string_append_listele(seen_doms, ':', dkim_signing_domain);
629
630   /* Set $dkim_selector expansion variable to each selector in list,
631   for this domain. */
632
633   if (!(dkim_sel = expand_string(dkim->dkim_selector)))
634     { errwhen = US"dkim_selector"; goto expand_bad; }
635
636   while ((dkim_signing_selector = string_nextinlist(&dkim_sel, &sel_sep,
637           NULL, 0)))
638     {
639     uschar * dkim_canon_expanded;
640     int pdkim_canon;
641     uschar * dkim_sign_headers_expanded = NULL;
642     uschar * dkim_private_key_expanded;
643     uschar * dkim_hash_expanded;
644     uschar * dkim_identity_expanded = NULL;
645     uschar * dkim_timestamps_expanded = NULL;
646     unsigned long tval = 0, xval = 0;
647
648     /* Get canonicalization to use */
649
650     dkim_canon_expanded = dkim->dkim_canon
651       ? expand_string(dkim->dkim_canon) : US"relaxed";
652     if (!dkim_canon_expanded)   /* expansion error, do not send message. */
653       { errwhen = US"dkim_canon"; goto expand_bad; }
654
655     if (Ustrcmp(dkim_canon_expanded, "relaxed") == 0)
656       pdkim_canon = PDKIM_CANON_RELAXED;
657     else if (Ustrcmp(dkim_canon_expanded, "simple") == 0)
658       pdkim_canon = PDKIM_CANON_SIMPLE;
659     else
660       {
661       log_write(0, LOG_MAIN,
662                  "DKIM: unknown canonicalization method '%s', defaulting to 'relaxed'.\n",
663                  dkim_canon_expanded);
664       pdkim_canon = PDKIM_CANON_RELAXED;
665       }
666
667     if (  dkim->dkim_sign_headers
668        && !(dkim_sign_headers_expanded = expand_string(dkim->dkim_sign_headers)))
669       { errwhen = US"dkim_sign_header"; goto expand_bad; }
670     /* else pass NULL, which means default header list */
671
672     /* Get private key to use. */
673
674     if (!(dkim_private_key_expanded = expand_string(dkim->dkim_private_key)))
675       { errwhen = US"dkim_private_key"; goto expand_bad; }
676
677     if (  Ustrlen(dkim_private_key_expanded) == 0
678        || Ustrcmp(dkim_private_key_expanded, "0") == 0
679        || Ustrcmp(dkim_private_key_expanded, "false") == 0
680        )
681       continue;         /* don't sign, but no error */
682
683     if (  dkim_private_key_expanded[0] == '/'
684        && !(dkim_private_key_expanded =
685              expand_file_big_buffer(dkim_private_key_expanded)))
686       goto bad;
687
688     if (!(dkim_hash_expanded = expand_string(dkim->dkim_hash)))
689       { errwhen = US"dkim_hash"; goto expand_bad; }
690
691     if (dkim->dkim_identity)
692       if (!(dkim_identity_expanded = expand_string(dkim->dkim_identity)))
693         { errwhen = US"dkim_identity"; goto expand_bad; }
694       else if (!*dkim_identity_expanded)
695         dkim_identity_expanded = NULL;
696
697     if (dkim->dkim_timestamps)
698       if (!(dkim_timestamps_expanded = expand_string(dkim->dkim_timestamps)))
699         { errwhen = US"dkim_timestamps"; goto expand_bad; }
700       else
701         xval = (tval = (unsigned long) time(NULL))
702               + strtoul(CCS dkim_timestamps_expanded, NULL, 10);
703
704     if (!(sig = pdkim_init_sign(&dkim_sign_ctx, dkim_signing_domain,
705                           dkim_signing_selector,
706                           dkim_private_key_expanded,
707                           dkim_hash_expanded,
708                           errstr
709                           )))
710       goto bad;
711     dkim_private_key_expanded[0] = '\0';
712
713     pdkim_set_optional(sig,
714                         CS dkim_sign_headers_expanded,
715                         CS dkim_identity_expanded,
716                         pdkim_canon,
717                         pdkim_canon, -1, tval, xval);
718
719     if (!pdkim_set_sig_bodyhash(&dkim_sign_ctx, sig))
720       goto bad;
721
722     if (!dkim_sign_ctx.sig)             /* link sig to context chain */
723       dkim_sign_ctx.sig = sig;
724     else
725       {
726       pdkim_signature * n = dkim_sign_ctx.sig;
727       while (n->next) n = n->next;
728       n->next = sig;
729       }
730     }
731   }
732
733 /* We may need to carry on with the data-feed even if there are no DKIM sigs to
734 produce, if some other package (eg. ARC) is signing. */
735
736 if (!dkim_sign_ctx.sig && !dkim->force_bodyhash)
737   {
738   DEBUG(D_transport) debug_printf("DKIM: no viable signatures to use\n");
739   sigbuf = string_get(1);       /* return a zero-len string */
740   }
741 else
742   {
743   if (prefix && (pdkim_rc = pdkim_feed(&dkim_sign_ctx, prefix, Ustrlen(prefix))) != PDKIM_OK)
744     goto pk_bad;
745
746   if (lseek(fd, off, SEEK_SET) < 0)
747     sread = -1;
748   else
749     while ((sread = read(fd, &buf, sizeof(buf))) > 0)
750       if ((pdkim_rc = pdkim_feed(&dkim_sign_ctx, buf, sread)) != PDKIM_OK)
751         goto pk_bad;
752
753   /* Handle failed read above. */
754   if (sread == -1)
755     {
756     debug_printf("DKIM: Error reading -K file.\n");
757     save_errno = errno;
758     goto bad;
759     }
760
761   /* Build string of headers, one per signature */
762
763   if ((pdkim_rc = pdkim_feed_finish(&dkim_sign_ctx, &sig, errstr)) != PDKIM_OK)
764     goto pk_bad;
765
766   if (!sig)
767     {
768     DEBUG(D_transport) debug_printf("DKIM: no signatures to use\n");
769     sigbuf = string_get(1);     /* return a zero-len string */
770     }
771   else for (sigbuf = NULL; sig; sig = sig->next)
772     sigbuf = string_append(sigbuf, 2, US sig->signature_header, US"\r\n");
773   }
774
775 CLEANUP:
776   (void) string_from_gstring(sigbuf);
777   store_pool = old_pool;
778   errno = save_errno;
779   return sigbuf;
780
781 pk_bad:
782   log_write(0, LOG_MAIN|LOG_PANIC,
783                 "DKIM: signing failed: %.100s", pdkim_errstr(pdkim_rc));
784 bad:
785   sigbuf = NULL;
786   goto CLEANUP;
787
788 expand_bad:
789   log_write(0, LOG_MAIN | LOG_PANIC, "failed to expand %s: %s",
790               errwhen, expand_string_message);
791   goto bad;
792 }
793
794
795
796
797 gstring *
798 authres_dkim(gstring * g)
799 {
800 int start = 0;          /* compiler quietening */
801
802 DEBUG(D_acl) start = g->ptr;
803
804 for (pdkim_signature * sig = dkim_signatures; sig; sig = sig->next)
805   {
806   g = string_catn(g, US";\n\tdkim=", 8);
807
808   if (sig->verify_status & PDKIM_VERIFY_POLICY)
809     g = string_append(g, 5,
810       US"policy (", dkim_verify_status, US" - ", dkim_verify_reason, US")");
811   else switch(sig->verify_status)
812     {
813     case PDKIM_VERIFY_NONE:    g = string_cat(g, US"none"); break;
814     case PDKIM_VERIFY_INVALID:
815       switch (sig->verify_ext_status)
816         {
817         case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE:
818           g = string_cat(g, US"tmperror (pubkey unavailable)\n\t\t"); break;
819         case PDKIM_VERIFY_INVALID_BUFFER_SIZE:
820           g = string_cat(g, US"permerror (overlong public key record)\n\t\t"); break;
821         case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD:
822         case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT:
823           g = string_cat(g, US"neutral (public key record import problem)\n\t\t");
824           break;
825         case PDKIM_VERIFY_INVALID_SIGNATURE_ERROR:
826           g = string_cat(g, US"neutral (signature tag missing or invalid)\n\t\t");
827           break;
828         case PDKIM_VERIFY_INVALID_DKIM_VERSION:
829           g = string_cat(g, US"neutral (unsupported DKIM version)\n\t\t");
830           break;
831         default:
832           g = string_cat(g, US"permerror (unspecified problem)\n\t\t"); break;
833         }
834       break;
835     case PDKIM_VERIFY_FAIL:
836       switch (sig->verify_ext_status)
837         {
838         case PDKIM_VERIFY_FAIL_BODY:
839           g = string_cat(g,
840             US"fail (body hash mismatch; body probably modified in transit)\n\t\t");
841           break;
842         case PDKIM_VERIFY_FAIL_MESSAGE:
843           g = string_cat(g,
844             US"fail (signature did not verify; headers probably modified in transit)\n\t\t");
845           break;
846         default:
847           g = string_cat(g, US"fail (unspecified reason)\n\t\t");
848           break;
849         }
850       break;
851     case PDKIM_VERIFY_PASS:    g = string_cat(g, US"pass"); break;
852     default:                   g = string_cat(g, US"permerror"); break;
853     }
854   if (sig->domain)   g = string_append(g, 2, US" header.d=", sig->domain);
855   if (sig->identity) g = string_append(g, 2, US" header.i=", sig->identity);
856   if (sig->selector) g = string_append(g, 2, US" header.s=", sig->selector);
857   g = string_append(g, 2, US" header.a=", dkim_sig_to_a_tag(sig));
858   }
859
860 DEBUG(D_acl)
861   if (g->ptr == start)
862     debug_printf("DKIM: no authres\n");
863   else
864     debug_printf("DKIM: authres '%.*s'\n", g->ptr - start - 3, g->s + start + 3);
865 return g;
866 }
867
868
869 # endif /*!MACRO_PREDEF*/
870 #endif  /*!DISABLE_DKIM*/