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