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