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