1767eb6206b8bd1ba3ee5e43cb4bf4383a1961eb
[users/heiko/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_signatures = NULL;
34 pdkim_signature *dkim_cur_sig = NULL;
35 static const uschar * dkim_collect_error = NULL;
36
37
38
39 /*XXX the caller only uses the first record if we return multiple.
40 */
41
42 uschar *
43 dkim_exim_query_dns_txt(uschar * name)
44 {
45 dns_answer dnsa;
46 dns_scan dnss;
47 dns_record *rr;
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 (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;
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 = FALSE;
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_append(logmsg, 7,
195   " c=", sig->canon_headers == PDKIM_CANON_SIMPLE ? "simple" : "relaxed",
196   "/",   sig->canon_body    == PDKIM_CANON_SIMPLE ? "simple" : "relaxed",
197   " a=", dkim_sig_to_a_tag(sig),
198 string_sprintf(" b=" SIZE_T_FMT,
199                 (int)sig->sighash.len > -1 ? sig->sighash.len * 8 : 0));
200 if ((s= sig->identity)) logmsg = string_append(logmsg, 2, " i=", s);
201 if (sig->created > 0) logmsg = string_cat(logmsg,
202                               string_sprintf(" t=%lu", sig->created));
203 if (sig->expires > 0) logmsg = string_cat(logmsg,
204                               string_sprintf(" x=%lu", sig->expires));
205 if (sig->bodylength > -1) logmsg = string_cat(logmsg,
206                               string_sprintf(" l=%lu", sig->bodylength));
207
208 if (sig->verify_status & PDKIM_VERIFY_POLICY)
209   logmsg = string_append(logmsg, 5,
210             US" [", dkim_verify_status, US" - ", dkim_verify_reason, US"]");
211 else
212   switch (sig->verify_status)
213     {
214     case PDKIM_VERIFY_NONE:
215       logmsg = string_cat(logmsg, US" [not verified]");
216       break;
217
218     case PDKIM_VERIFY_INVALID:
219       logmsg = string_cat(logmsg, US" [invalid - ");
220       switch (sig->verify_ext_status)
221         {
222         case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE:
223           logmsg = string_cat(logmsg,
224                         US"public key record (currently?) unavailable]");
225           break;
226
227         case PDKIM_VERIFY_INVALID_BUFFER_SIZE:
228           logmsg = string_cat(logmsg, US"overlong public key record]");
229           break;
230
231         case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD:
232         case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT:
233           logmsg = string_cat(logmsg, US"syntax error in public key record]");
234           break;
235
236         case PDKIM_VERIFY_INVALID_SIGNATURE_ERROR:
237           logmsg = string_cat(logmsg, US"signature tag missing or invalid]");
238           break;
239
240         case PDKIM_VERIFY_INVALID_DKIM_VERSION:
241           logmsg = string_cat(logmsg, US"unsupported DKIM version]");
242           break;
243
244         default:
245           logmsg = string_cat(logmsg, US"unspecified problem]");
246         }
247       break;
248
249     case PDKIM_VERIFY_FAIL:
250       logmsg = string_cat(logmsg, US" [verification failed - ");
251       switch (sig->verify_ext_status)
252         {
253         case PDKIM_VERIFY_FAIL_BODY:
254           logmsg = string_cat(logmsg,
255                US"body hash mismatch (body probably modified in transit)]");
256           break;
257
258         case PDKIM_VERIFY_FAIL_MESSAGE:
259           logmsg = string_cat(logmsg,
260                 US"signature did not verify "
261                 "(headers probably modified in transit)]");
262           break;
263
264         default:
265           logmsg = string_cat(logmsg, US"unspecified reason]");
266         }
267       break;
268
269     case PDKIM_VERIFY_PASS:
270       logmsg = string_cat(logmsg, US" [verification succeeded]");
271       break;
272     }
273
274 log_write(0, LOG_MAIN, "%s", string_from_gstring(logmsg));
275 return;
276 }
277
278
279 /* Log a line for each signature */
280 void
281 dkim_exim_verify_log_all(void)
282 {
283 pdkim_signature * sig;
284 for (sig = dkim_signatures; sig; sig = sig->next) dkim_exim_verify_log_sig(sig);
285 }
286
287
288 void
289 dkim_exim_verify_finish(void)
290 {
291 pdkim_signature * sig;
292 int rc;
293 gstring * g = NULL;
294 const uschar * errstr = NULL;
295
296 store_pool = POOL_PERM;
297
298 /* Delete eventual previous signature chain */
299
300 dkim_signers = NULL;
301 dkim_signatures = NULL;
302
303 if (dkim_collect_error)
304   {
305   log_write(0, LOG_MAIN,
306       "DKIM: Error during validation, disabling signature verification: %.100s",
307       dkim_collect_error);
308   dkim_disable_verify = TRUE;
309   goto out;
310   }
311
312 dkim_collect_input = FALSE;
313
314 /* Finish DKIM operation and fetch link to signatures chain */
315
316 rc = pdkim_feed_finish(dkim_verify_ctx, &dkim_signatures, &errstr);
317 if (rc != PDKIM_OK && errstr)
318   log_write(0, LOG_MAIN, "DKIM: validation error: %s", errstr);
319
320 /* Build a colon-separated list of signing domains (and identities, if present) in dkim_signers */
321
322 for (sig = dkim_signatures; sig; sig = sig->next)
323   {
324   if (sig->domain)   g = string_append_listele(g, ':', sig->domain);
325   if (sig->identity) g = string_append_listele(g, ':', sig->identity);
326   }
327
328 if (g) dkim_signers = g->s;
329
330 out:
331 store_pool = dkim_verify_oldpool;
332 }
333
334
335
336 /* Args as per dkim_exim_acl_run() below */
337 static int
338 dkim_acl_call(uschar * id, gstring ** res_ptr,
339   uschar ** user_msgptr, uschar ** log_msgptr)
340 {
341 int rc;
342 DEBUG(D_receive)
343   debug_printf("calling acl_smtp_dkim for dkim_cur_signer='%s'\n", id);
344
345 rc = acl_check(ACL_WHERE_DKIM, NULL, acl_smtp_dkim, user_msgptr, log_msgptr);
346 dkim_exim_verify_log_sig(dkim_cur_sig);
347 *res_ptr = string_append_listele(*res_ptr, ':', dkim_verify_status);
348 return rc;
349 }
350
351
352
353 /* For the given identity, run the DKIM ACL once for each matching signature.
354
355 Arguments
356  id             Identity to look for in dkim signatures
357  res_ptr        ptr to growable string-list of status results,
358                 appended to per ACL run
359  user_msgptr    where to put a user error (for SMTP response)
360  log_msgptr     where to put a logging message (not for SMTP response)
361
362 Returns:       OK         access is granted by an ACCEPT verb
363                DISCARD    access is granted by a DISCARD verb
364                FAIL       access is denied
365                FAIL_DROP  access is denied; drop the connection
366                DEFER      can't tell at the moment
367                ERROR      disaster
368 */
369
370 int
371 dkim_exim_acl_run(uschar * id, gstring ** res_ptr,
372   uschar ** user_msgptr, uschar ** log_msgptr)
373 {
374 pdkim_signature * sig;
375 uschar * cmp_val;
376 int rc = -1;
377
378 dkim_verify_status = US"none";
379 dkim_verify_reason = US"";
380 dkim_cur_signer = id;
381
382 if (dkim_disable_verify || !id || !dkim_verify_ctx)
383   return OK;
384
385 /* Find signatures to run ACL on */
386
387 for (sig = dkim_signatures; sig; sig = sig->next)
388   if (  (cmp_val = Ustrchr(id, '@') != NULL ? US sig->identity : US sig->domain)
389      && strcmpic(cmp_val, id) == 0
390      )
391     {
392     /* The "dkim_domain" and "dkim_selector" expansion variables have
393     related globals, since they are used in the signing code too.
394     Instead of inventing separate names for verification, we set
395     them here. This is easy since a domain and selector is guaranteed
396     to be in a signature. The other dkim_* expansion items are
397     dynamically fetched from dkim_cur_sig at expansion time (see
398     function below). */
399
400     dkim_cur_sig = sig;
401     dkim_signing_domain = US sig->domain;
402     dkim_signing_selector = US sig->selector;
403     dkim_key_length = sig->sighash.len * 8;
404
405     /* These two return static strings, so we can compare the addr
406     later to see if the ACL overwrote them.  Check that when logging */
407
408     dkim_verify_status = dkim_exim_expand_query(DKIM_VERIFY_STATUS);
409     dkim_verify_reason = dkim_exim_expand_query(DKIM_VERIFY_REASON);
410
411     if ((rc = dkim_acl_call(id, res_ptr, user_msgptr, log_msgptr)) != OK)
412       return rc;
413     }
414
415 if (rc != -1)
416   return rc;
417
418 /* No matching sig found.  Call ACL once anyway. */
419
420 dkim_cur_sig = NULL;
421 return dkim_acl_call(id, res_ptr, user_msgptr, log_msgptr);
422 }
423
424
425 static uschar *
426 dkim_exim_expand_defaults(int what)
427 {
428 switch (what)
429   {
430   case DKIM_ALGO:               return US"";
431   case DKIM_BODYLENGTH:         return US"9999999999999";
432   case DKIM_CANON_BODY:         return US"";
433   case DKIM_CANON_HEADERS:      return US"";
434   case DKIM_COPIEDHEADERS:      return US"";
435   case DKIM_CREATED:            return US"0";
436   case DKIM_EXPIRES:            return US"9999999999999";
437   case DKIM_HEADERNAMES:        return US"";
438   case DKIM_IDENTITY:           return US"";
439   case DKIM_KEY_GRANULARITY:    return US"*";
440   case DKIM_KEY_SRVTYPE:        return US"*";
441   case DKIM_KEY_NOTES:          return US"";
442   case DKIM_KEY_TESTING:        return US"0";
443   case DKIM_NOSUBDOMAINS:       return US"0";
444   case DKIM_VERIFY_STATUS:      return US"none";
445   case DKIM_VERIFY_REASON:      return US"";
446   default:                      return US"";
447   }
448 }
449
450
451 uschar *
452 dkim_exim_expand_query(int what)
453 {
454 if (!dkim_verify_ctx || dkim_disable_verify || !dkim_cur_sig)
455   return dkim_exim_expand_defaults(what);
456
457 switch (what)
458   {
459   case DKIM_ALGO:
460     return dkim_sig_to_a_tag(dkim_cur_sig);
461
462   case DKIM_BODYLENGTH:
463     return dkim_cur_sig->bodylength >= 0
464       ? string_sprintf("%ld", dkim_cur_sig->bodylength)
465       : dkim_exim_expand_defaults(what);
466
467   case DKIM_CANON_BODY:
468     switch (dkim_cur_sig->canon_body)
469       {
470       case PDKIM_CANON_RELAXED: return US"relaxed";
471       case PDKIM_CANON_SIMPLE:
472       default:                  return US"simple";
473       }
474
475   case DKIM_CANON_HEADERS:
476     switch (dkim_cur_sig->canon_headers)
477       {
478       case PDKIM_CANON_RELAXED: return US"relaxed";
479       case PDKIM_CANON_SIMPLE:
480       default:                  return US"simple";
481       }
482
483   case DKIM_COPIEDHEADERS:
484     return dkim_cur_sig->copiedheaders
485       ? US dkim_cur_sig->copiedheaders : dkim_exim_expand_defaults(what);
486
487   case DKIM_CREATED:
488     return dkim_cur_sig->created > 0
489       ? string_sprintf("%lu", dkim_cur_sig->created)
490       : dkim_exim_expand_defaults(what);
491
492   case DKIM_EXPIRES:
493     return dkim_cur_sig->expires > 0
494       ? string_sprintf("%lu", dkim_cur_sig->expires)
495       : dkim_exim_expand_defaults(what);
496
497   case DKIM_HEADERNAMES:
498     return dkim_cur_sig->headernames
499       ? dkim_cur_sig->headernames : dkim_exim_expand_defaults(what);
500
501   case DKIM_IDENTITY:
502     return dkim_cur_sig->identity
503       ? US dkim_cur_sig->identity : dkim_exim_expand_defaults(what);
504
505   case DKIM_KEY_GRANULARITY:
506     return dkim_cur_sig->pubkey
507       ? dkim_cur_sig->pubkey->granularity
508       ? US dkim_cur_sig->pubkey->granularity
509       : dkim_exim_expand_defaults(what)
510       : dkim_exim_expand_defaults(what);
511
512   case DKIM_KEY_SRVTYPE:
513     return dkim_cur_sig->pubkey
514       ? dkim_cur_sig->pubkey->srvtype
515       ? US dkim_cur_sig->pubkey->srvtype
516       : dkim_exim_expand_defaults(what)
517       : dkim_exim_expand_defaults(what);
518
519   case DKIM_KEY_NOTES:
520     return dkim_cur_sig->pubkey
521       ? dkim_cur_sig->pubkey->notes
522       ? US dkim_cur_sig->pubkey->notes
523       : dkim_exim_expand_defaults(what)
524       : dkim_exim_expand_defaults(what);
525
526   case DKIM_KEY_TESTING:
527     return dkim_cur_sig->pubkey
528       ? dkim_cur_sig->pubkey->testing
529       ? US"1"
530       : dkim_exim_expand_defaults(what)
531       : dkim_exim_expand_defaults(what);
532
533   case DKIM_NOSUBDOMAINS:
534     return dkim_cur_sig->pubkey
535       ? dkim_cur_sig->pubkey->no_subdomaining
536       ? US"1"
537       : dkim_exim_expand_defaults(what)
538       : dkim_exim_expand_defaults(what);
539
540   case DKIM_VERIFY_STATUS:
541     switch (dkim_cur_sig->verify_status)
542       {
543       case PDKIM_VERIFY_INVALID:        return US"invalid";
544       case PDKIM_VERIFY_FAIL:           return US"fail";
545       case PDKIM_VERIFY_PASS:           return US"pass";
546       case PDKIM_VERIFY_NONE:
547       default:                          return US"none";
548       }
549
550   case DKIM_VERIFY_REASON:
551     switch (dkim_cur_sig->verify_ext_status)
552       {
553       case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE:
554                                                 return US"pubkey_unavailable";
555       case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD:return US"pubkey_dns_syntax";
556       case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT:  return US"pubkey_der_syntax";
557       case PDKIM_VERIFY_FAIL_BODY:              return US"bodyhash_mismatch";
558       case PDKIM_VERIFY_FAIL_MESSAGE:           return US"signature_incorrect";
559       }
560
561   default:
562     return US"";
563   }
564 }
565
566
567 void
568 dkim_exim_sign_init(void)
569 {
570 int old_pool = store_pool;
571 store_pool = POOL_MAIN;
572 pdkim_init_context(&dkim_sign_ctx, FALSE, &dkim_exim_query_dns_txt);
573 store_pool = old_pool;
574 }
575
576
577 /* Generate signatures for the given file.
578 If a prefix is given, prepend it to the file for the calculations.
579
580 Return:
581   NULL:         error; error string written
582   string:       signature header(s), or a zero-length string (not an error)
583 */
584
585 gstring *
586 dkim_exim_sign(int fd, off_t off, uschar * prefix,
587   struct ob_dkim * dkim, const uschar ** errstr)
588 {
589 const uschar * dkim_domain = NULL;
590 int sep = 0;
591 gstring * seen_doms = NULL;
592 pdkim_signature * sig;
593 gstring * sigbuf;
594 int pdkim_rc;
595 int sread;
596 uschar buf[4096];
597 int save_errno = 0;
598 int old_pool = store_pool;
599 uschar * errwhen;
600 const uschar * s;
601
602 if (dkim->dot_stuffed)
603   dkim_sign_ctx.flags |= PDKIM_DOT_TERM;
604
605 store_pool = POOL_MAIN;
606
607 if ((s = dkim->dkim_domain) && !(dkim_domain = expand_cstring(s)))
608   /* expansion error, do not send message. */
609   { errwhen = US"dkim_domain"; goto expand_bad; }
610
611 /* Set $dkim_domain expansion variable to each unique domain in list. */
612
613 if (dkim_domain)
614   while ((dkim_signing_domain = string_nextinlist(&dkim_domain, &sep, NULL, 0)))
615   {
616   const uschar * dkim_sel;
617   int sel_sep = 0;
618
619   if (dkim_signing_domain[0] == '\0')
620     continue;
621
622   /* Only sign once for each domain, no matter how often it
623   appears in the expanded list. */
624
625   if (match_isinlist(dkim_signing_domain, CUSS &seen_doms,
626       0, NULL, NULL, MCL_STRING, TRUE, NULL) == OK)
627     continue;
628
629   seen_doms = string_append_listele(seen_doms, ':', dkim_signing_domain);
630
631   /* Set $dkim_selector expansion variable to each selector in list,
632   for this domain. */
633
634   if (!(dkim_sel = expand_string(dkim->dkim_selector)))
635   if (!(dkim_signing_selector = expand_string(dkim->dkim_selector)))
636     { errwhen = US"dkim_selector"; goto expand_bad; }
637
638   while ((dkim_signing_selector = string_nextinlist(&dkim_sel, &sel_sep,
639           NULL, 0)))
640     {
641     uschar * dkim_canon_expanded;
642     int pdkim_canon;
643     uschar * dkim_sign_headers_expanded = NULL;
644     uschar * dkim_private_key_expanded;
645     uschar * dkim_hash_expanded;
646     uschar * dkim_identity_expanded = NULL;
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 (!(sig = pdkim_init_sign(&dkim_sign_ctx, dkim_signing_domain,
698                           dkim_signing_selector,
699                           dkim_private_key_expanded,
700                           dkim_hash_expanded,
701                           errstr
702                           )))
703       goto bad;
704     dkim_private_key_expanded[0] = '\0';
705
706     pdkim_set_optional(sig,
707                         CS dkim_sign_headers_expanded,
708                         CS dkim_identity_expanded,
709                         pdkim_canon,
710                         pdkim_canon, -1, 0, 0);
711
712     if (!pdkim_set_sig_bodyhash(&dkim_sign_ctx, sig))
713       goto bad;
714
715     if (!dkim_sign_ctx.sig)             /* link sig to context chain */
716       dkim_sign_ctx.sig = sig;
717     else
718       {
719       pdkim_signature * n = dkim_sign_ctx.sig;
720       while (n->next) n = n->next;
721       n->next = sig;
722       }
723     }
724   }
725
726 /* We may need to carry on with the data-feed even if there are no DKIM sigs to
727 produce, if some other package (eg. ARC) is signing. */
728
729 if (!dkim_sign_ctx.sig && !dkim->force_bodyhash)
730   {
731   DEBUG(D_transport) debug_printf("DKIM: no viable signatures to use\n");
732   sigbuf = string_get(1);       /* return a zero-len string */
733   }
734 else
735   {
736   if (prefix && (pdkim_rc = pdkim_feed(&dkim_sign_ctx, prefix, Ustrlen(prefix))) != PDKIM_OK)
737     goto pk_bad;
738
739   if (lseek(fd, off, SEEK_SET) < 0)
740     sread = -1;
741   else
742     while ((sread = read(fd, &buf, sizeof(buf))) > 0)
743       if ((pdkim_rc = pdkim_feed(&dkim_sign_ctx, buf, sread)) != PDKIM_OK)
744         goto pk_bad;
745
746   /* Handle failed read above. */
747   if (sread == -1)
748     {
749     debug_printf("DKIM: Error reading -K file.\n");
750     save_errno = errno;
751     goto bad;
752     }
753
754   /* Build string of headers, one per signature */
755
756   if ((pdkim_rc = pdkim_feed_finish(&dkim_sign_ctx, &sig, errstr)) != PDKIM_OK)
757     goto pk_bad;
758
759   if (!sig)
760     {
761     DEBUG(D_transport) debug_printf("DKIM: no signatures to use\n");
762     sigbuf = string_get(1);     /* return a zero-len string */
763     }
764   else for (sigbuf = NULL; sig; sig = sig->next)
765     sigbuf = string_append(sigbuf, 2, US sig->signature_header, US"\r\n");
766   }
767
768 CLEANUP:
769   (void) string_from_gstring(sigbuf);
770   store_pool = old_pool;
771   errno = save_errno;
772   return sigbuf;
773
774 pk_bad:
775   log_write(0, LOG_MAIN|LOG_PANIC,
776                 "DKIM: signing failed: %.100s", pdkim_errstr(pdkim_rc));
777 bad:
778   sigbuf = NULL;
779   goto CLEANUP;
780
781 expand_bad:
782   log_write(0, LOG_MAIN | LOG_PANIC, "failed to expand %s: %s",
783               errwhen, expand_string_message);
784   goto bad;
785 }
786
787
788
789
790 gstring *
791 authres_dkim(gstring * g)
792 {
793 pdkim_signature * sig;
794 int start;
795
796 DEBUG(D_acl) start = g->ptr;
797
798 for (sig = dkim_signatures; sig; sig = sig->next)
799   {
800   g = string_catn(g, US";\n\tdkim=", 8);
801
802   if (sig->verify_status & PDKIM_VERIFY_POLICY)
803     g = string_append(g, 5,
804       US"policy (", dkim_verify_status, US" - ", dkim_verify_reason, US")");
805   else switch(sig->verify_status)
806     {
807     case PDKIM_VERIFY_NONE:    g = string_cat(g, US"none"); break;
808     case PDKIM_VERIFY_INVALID:
809       switch (sig->verify_ext_status)
810         {
811         case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE:
812           g = string_cat(g, US"tmperror (pubkey unavailable)\n\t\t"); break;
813         case PDKIM_VERIFY_INVALID_BUFFER_SIZE:
814           g = string_cat(g, US"permerror (overlong public key record)\n\t\t"); break;
815         case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD:
816         case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT:
817           g = string_cat(g, US"neutral (syntax error in public key record)\n\t\t");
818           break;
819         case PDKIM_VERIFY_INVALID_SIGNATURE_ERROR:
820           g = string_cat(g, US"neutral (signature tag missing or invalid)\n\t\t");
821           break;
822         case PDKIM_VERIFY_INVALID_DKIM_VERSION:
823           g = string_cat(g, US"neutral (unsupported DKIM version)\n\t\t");
824           break;
825         default:
826           g = string_cat(g, US"permerror (unspecified problem)\n\t\t"); break;
827         }
828       break;
829     case PDKIM_VERIFY_FAIL:
830       switch (sig->verify_ext_status)
831         {
832         case PDKIM_VERIFY_FAIL_BODY:
833           g = string_cat(g,
834             US"fail (body hash mismatch; body probably modified in transit)\n\t\t");
835           break;
836         case PDKIM_VERIFY_FAIL_MESSAGE:
837           g = string_cat(g,
838             US"fail (signature did not verify; headers probably modified in transit)\n\t\t");
839           break;
840         default:
841           g = string_cat(g, US"fail (unspecified reason)\n\t\t");
842           break;
843         }
844       break;
845     case PDKIM_VERIFY_PASS:    g = string_cat(g, US"pass"); break;
846     default:                   g = string_cat(g, US"permerror"); break;
847     }
848   if (sig->domain)   g = string_append(g, 2, US" header.d=", sig->domain);
849   if (sig->identity) g = string_append(g, 2, US" header.i=", sig->identity);
850   if (sig->selector) g = string_append(g, 2, US" header.s=", sig->selector);
851   g = string_append(g, 2, US" header.a=", dkim_sig_to_a_tag(sig));
852   }
853
854 DEBUG(D_acl)
855   if (g->ptr == start)
856     debug_printf("DKIM: no authres\n");
857   else
858     debug_printf("DKIM: authres '%.*s'\n", g->ptr - start - 3, g->s + start + 3);
859 return g;
860 }
861
862
863 # endif /*!MACRO_PREDEF*/
864 #endif  /*!DISABLE_DKIM*/