tidying
[exim.git] / src / src / dkim.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) The Exim Maintainers 2020 - 2024 */
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 gstring_release_unused(g);
346 dkim_signers = string_from_gstring(g);
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 identity '%s' domain '%s' sel '%s'\n",
362               id, dkim_signing_domain, dkim_signing_selector);
363
364 rc = acl_check(ACL_WHERE_DKIM, NULL, acl_smtp_dkim, user_msgptr, log_msgptr);
365 dkim_exim_verify_log_sig(dkim_cur_sig);
366 *res_ptr = string_append_listele(*res_ptr, ':', dkim_verify_status);
367 return rc;
368 }
369
370
371
372 /* For the given identity, run the DKIM ACL once for each matching signature.
373 If none match, run it once.
374
375 Arguments
376  id             Identity to look for in dkim signatures
377  res_ptr        ptr to growable string-list of status results,
378                 appended to per ACL run
379  user_msgptr    where to put a user error (for SMTP response)
380  log_msgptr     where to put a logging message (not for SMTP response)
381
382 Returns:       OK         access is granted by an ACCEPT verb
383                DISCARD    access is granted by a DISCARD verb
384                FAIL       access is denied
385                FAIL_DROP  access is denied; drop the connection
386                DEFER      can't tell at the moment
387                ERROR      disaster
388 */
389
390 int
391 dkim_exim_acl_run(uschar * id, gstring ** res_ptr,
392   uschar ** user_msgptr, uschar ** log_msgptr)
393 {
394 uschar * cmp_val;
395 int rc = -1;
396
397 dkim_verify_status = US"none";
398 dkim_verify_reason = US"";
399 dkim_cur_signer = id;
400
401 if (f.dkim_disable_verify || !id || !dkim_verify_ctx)
402   return OK;
403
404 /* Find signatures to run ACL on */
405
406 for (pdkim_signature * sig = dkim_signatures; sig; sig = sig->next)
407   if (  (cmp_val = Ustrchr(id, '@') != NULL ? US sig->identity : US sig->domain)
408      && strcmpic(cmp_val, id) == 0
409      )
410     {
411     /* The "dkim_domain" and "dkim_selector" expansion variables have
412     related globals, since they are used in the signing code too.
413     Instead of inventing separate names for verification, we set
414     them here. This is easy since a domain and selector is guaranteed
415     to be in a signature. The other dkim_* expansion items are
416     dynamically fetched from dkim_cur_sig at expansion time (see
417     dkim_exim_expand_query() below). */
418
419     dkim_cur_sig = sig;
420     dkim_signing_domain = US sig->domain;
421     dkim_signing_selector = US sig->selector;
422     dkim_key_length = sig->keybits;
423
424     /* These two return static strings, so we can compare the addr
425     later to see if the ACL overwrote them.  Check that when logging */
426
427     dkim_verify_status = dkim_exim_expand_query(DKIM_VERIFY_STATUS);
428     dkim_verify_reason = dkim_exim_expand_query(DKIM_VERIFY_REASON);
429
430     if (  (rc = dkim_acl_call(id, res_ptr, user_msgptr, log_msgptr)) != OK
431        || dkim_verify_minimal && Ustrcmp(dkim_verify_status, "pass") == 0)
432       return rc;
433     }
434
435 if (rc != -1)
436   return rc;
437
438 /* No matching sig found.  Call ACL once anyway. */
439
440 dkim_cur_sig = NULL;
441 return dkim_acl_call(id, res_ptr, user_msgptr, log_msgptr);
442 }
443
444
445 static uschar *
446 dkim_exim_expand_defaults(int what)
447 {
448 switch (what)
449   {
450   case DKIM_ALGO:               return US"";
451   case DKIM_BODYLENGTH:         return US"9999999999999";
452   case DKIM_CANON_BODY:         return US"";
453   case DKIM_CANON_HEADERS:      return US"";
454   case DKIM_COPIEDHEADERS:      return US"";
455   case DKIM_CREATED:            return US"0";
456   case DKIM_EXPIRES:            return US"9999999999999";
457   case DKIM_HEADERNAMES:        return US"";
458   case DKIM_IDENTITY:           return US"";
459   case DKIM_KEY_GRANULARITY:    return US"*";
460   case DKIM_KEY_SRVTYPE:        return US"*";
461   case DKIM_KEY_NOTES:          return US"";
462   case DKIM_KEY_TESTING:        return US"0";
463   case DKIM_NOSUBDOMAINS:       return US"0";
464   case DKIM_VERIFY_STATUS:      return US"none";
465   case DKIM_VERIFY_REASON:      return US"";
466   default:                      return US"";
467   }
468 }
469
470
471 uschar *
472 dkim_exim_expand_query(int what)
473 {
474 if (!dkim_verify_ctx || f.dkim_disable_verify || !dkim_cur_sig)
475   return dkim_exim_expand_defaults(what);
476
477 switch (what)
478   {
479   case DKIM_ALGO:
480     return dkim_sig_to_a_tag(dkim_cur_sig);
481
482   case DKIM_BODYLENGTH:
483     return dkim_cur_sig->bodylength >= 0
484       ? string_sprintf("%ld", dkim_cur_sig->bodylength)
485       : dkim_exim_expand_defaults(what);
486
487   case DKIM_CANON_BODY:
488     switch (dkim_cur_sig->canon_body)
489       {
490       case PDKIM_CANON_RELAXED: return US"relaxed";
491       case PDKIM_CANON_SIMPLE:
492       default:                  return US"simple";
493       }
494
495   case DKIM_CANON_HEADERS:
496     switch (dkim_cur_sig->canon_headers)
497       {
498       case PDKIM_CANON_RELAXED: return US"relaxed";
499       case PDKIM_CANON_SIMPLE:
500       default:                  return US"simple";
501       }
502
503   case DKIM_COPIEDHEADERS:
504     return dkim_cur_sig->copiedheaders
505       ? US dkim_cur_sig->copiedheaders : dkim_exim_expand_defaults(what);
506
507   case DKIM_CREATED:
508     return dkim_cur_sig->created > 0
509       ? string_sprintf("%lu", dkim_cur_sig->created)
510       : dkim_exim_expand_defaults(what);
511
512   case DKIM_EXPIRES:
513     return dkim_cur_sig->expires > 0
514       ? string_sprintf("%lu", dkim_cur_sig->expires)
515       : dkim_exim_expand_defaults(what);
516
517   case DKIM_HEADERNAMES:
518     return dkim_cur_sig->headernames
519       ? dkim_cur_sig->headernames : dkim_exim_expand_defaults(what);
520
521   case DKIM_IDENTITY:
522     return dkim_cur_sig->identity
523       ? US dkim_cur_sig->identity : dkim_exim_expand_defaults(what);
524
525   case DKIM_KEY_GRANULARITY:
526     return dkim_cur_sig->pubkey
527       ? dkim_cur_sig->pubkey->granularity
528       ? US dkim_cur_sig->pubkey->granularity
529       : dkim_exim_expand_defaults(what)
530       : dkim_exim_expand_defaults(what);
531
532   case DKIM_KEY_SRVTYPE:
533     return dkim_cur_sig->pubkey
534       ? dkim_cur_sig->pubkey->srvtype
535       ? US dkim_cur_sig->pubkey->srvtype
536       : dkim_exim_expand_defaults(what)
537       : dkim_exim_expand_defaults(what);
538
539   case DKIM_KEY_NOTES:
540     return dkim_cur_sig->pubkey
541       ? dkim_cur_sig->pubkey->notes
542       ? US dkim_cur_sig->pubkey->notes
543       : dkim_exim_expand_defaults(what)
544       : dkim_exim_expand_defaults(what);
545
546   case DKIM_KEY_TESTING:
547     return dkim_cur_sig->pubkey
548       ? dkim_cur_sig->pubkey->testing
549       ? US"1"
550       : dkim_exim_expand_defaults(what)
551       : dkim_exim_expand_defaults(what);
552
553   case DKIM_NOSUBDOMAINS:
554     return dkim_cur_sig->pubkey
555       ? dkim_cur_sig->pubkey->no_subdomaining
556       ? US"1"
557       : dkim_exim_expand_defaults(what)
558       : dkim_exim_expand_defaults(what);
559
560   case DKIM_VERIFY_STATUS:
561     switch (dkim_cur_sig->verify_status)
562       {
563       case PDKIM_VERIFY_INVALID:        return US"invalid";
564       case PDKIM_VERIFY_FAIL:           return US"fail";
565       case PDKIM_VERIFY_PASS:           return US"pass";
566       case PDKIM_VERIFY_NONE:
567       default:                          return US"none";
568       }
569
570   case DKIM_VERIFY_REASON:
571     switch (dkim_cur_sig->verify_ext_status)
572       {
573       case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE:
574                                                 return US"pubkey_unavailable";
575       case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD:return US"pubkey_dns_syntax";
576       case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT:  return US"pubkey_der_syntax";
577       case PDKIM_VERIFY_INVALID_PUBKEY_KEYSIZE: return US"pubkey_too_short";
578       case PDKIM_VERIFY_FAIL_BODY:              return US"bodyhash_mismatch";
579       case PDKIM_VERIFY_FAIL_MESSAGE:           return US"signature_incorrect";
580       }
581
582   default:
583     return US"";
584   }
585 }
586
587
588 void
589 dkim_exim_sign_init(void)
590 {
591 int old_pool = store_pool;
592
593 dkim_exim_init();
594 store_pool = POOL_MAIN;
595 pdkim_init_context(&dkim_sign_ctx, FALSE, &dkim_exim_query_dns_txt);
596 store_pool = old_pool;
597 }
598
599
600 /* Generate signatures for the given file.
601 If a prefix is given, prepend it to the file for the calculations.
602
603 Return:
604   NULL:         error; error string written
605   string:       signature header(s), or a zero-length string (not an error)
606 */
607
608 gstring *
609 dkim_exim_sign(int fd, off_t off, uschar * prefix,
610   struct ob_dkim * dkim, const uschar ** errstr)
611 {
612 const uschar * dkim_domain = NULL;
613 int sep = 0;
614 gstring * seen_doms = NULL;
615 pdkim_signature * sig;
616 gstring * sigbuf;
617 int pdkim_rc;
618 int sread;
619 uschar buf[4096];
620 int save_errno = 0;
621 int old_pool = store_pool;
622 uschar * errwhen;
623 const uschar * s;
624
625 if (dkim->dot_stuffed)
626   dkim_sign_ctx.flags |= PDKIM_DOT_TERM;
627
628 store_pool = POOL_MAIN;
629
630 GET_OPTION("dkim_domain");
631 if ((s = dkim->dkim_domain) && !(dkim_domain = expand_cstring(s)))
632   /* expansion error, do not send message. */
633   { errwhen = US"dkim_domain"; goto expand_bad; }
634
635 /* Set $dkim_domain expansion variable to each unique domain in list. */
636
637 if (dkim_domain)
638   while ((dkim_signing_domain = string_nextinlist(&dkim_domain, &sep, NULL, 0)))
639   {
640   const uschar * dkim_sel;
641   int sel_sep = 0;
642
643   if (dkim_signing_domain[0] == '\0')
644     continue;
645
646   /* Only sign once for each domain, no matter how often it
647   appears in the expanded list. */
648
649   dkim_signing_domain = string_copylc(dkim_signing_domain);
650   if (match_isinlist(dkim_signing_domain, CUSS &seen_doms,
651       0, NULL, NULL, MCL_STRING, TRUE, NULL) == OK)
652     continue;
653
654   seen_doms = string_append_listele(seen_doms, ':', dkim_signing_domain);
655
656   /* Set $dkim_selector expansion variable to each selector in list,
657   for this domain. */
658
659   GET_OPTION("dkim_selector");
660   if (!(dkim_sel = expand_string(dkim->dkim_selector)))
661     { errwhen = US"dkim_selector"; goto expand_bad; }
662
663   while ((dkim_signing_selector = string_nextinlist(&dkim_sel, &sel_sep,
664           NULL, 0)))
665     {
666     uschar * dkim_canon_expanded;
667     int pdkim_canon;
668     uschar * dkim_sign_headers_expanded = NULL;
669     uschar * dkim_private_key_expanded;
670     uschar * dkim_hash_expanded;
671     uschar * dkim_identity_expanded = NULL;
672     uschar * dkim_timestamps_expanded = NULL;
673     unsigned long tval = 0, xval = 0;
674
675     /* Get canonicalization to use */
676
677     GET_OPTION("dkim_canon");
678     dkim_canon_expanded = dkim->dkim_canon
679       ? expand_string(dkim->dkim_canon) : US"relaxed";
680     if (!dkim_canon_expanded)   /* expansion error, do not send message. */
681       { errwhen = US"dkim_canon"; goto expand_bad; }
682
683     if (Ustrcmp(dkim_canon_expanded, "relaxed") == 0)
684       pdkim_canon = PDKIM_CANON_RELAXED;
685     else if (Ustrcmp(dkim_canon_expanded, "simple") == 0)
686       pdkim_canon = PDKIM_CANON_SIMPLE;
687     else
688       {
689       log_write(0, LOG_MAIN,
690                  "DKIM: unknown canonicalization method '%s', defaulting to 'relaxed'.\n",
691                  dkim_canon_expanded);
692       pdkim_canon = PDKIM_CANON_RELAXED;
693       }
694
695     GET_OPTION("dkim_sign_headers");
696     if (  dkim->dkim_sign_headers
697        && !(dkim_sign_headers_expanded = expand_string(dkim->dkim_sign_headers)))
698       { errwhen = US"dkim_sign_header"; goto expand_bad; }
699     /* else pass NULL, which means default header list */
700
701     /* Get private key to use. */
702
703     GET_OPTION("dkim_private_key");
704     if (!(dkim_private_key_expanded = expand_string(dkim->dkim_private_key)))
705       { errwhen = US"dkim_private_key"; goto expand_bad; }
706
707     if (  Ustrlen(dkim_private_key_expanded) == 0
708        || Ustrcmp(dkim_private_key_expanded, "0") == 0
709        || Ustrcmp(dkim_private_key_expanded, "false") == 0
710        )
711       continue;         /* don't sign, but no error */
712
713     if (  dkim_private_key_expanded[0] == '/'
714        && !(dkim_private_key_expanded =
715              expand_file_big_buffer(dkim_private_key_expanded)))
716       goto bad;
717
718     GET_OPTION("dkim_hash");
719     if (!(dkim_hash_expanded = expand_string(dkim->dkim_hash)))
720       { errwhen = US"dkim_hash"; goto expand_bad; }
721
722     GET_OPTION("dkim_identity");
723     if (dkim->dkim_identity)
724       if (!(dkim_identity_expanded = expand_string(dkim->dkim_identity)))
725         { errwhen = US"dkim_identity"; goto expand_bad; }
726       else if (!*dkim_identity_expanded)
727         dkim_identity_expanded = NULL;
728
729     GET_OPTION("dkim_timestamps");
730     if (dkim->dkim_timestamps)
731       if (!(dkim_timestamps_expanded = expand_string(dkim->dkim_timestamps)))
732         { errwhen = US"dkim_timestamps"; goto expand_bad; }
733       else
734         {
735         tval = (unsigned long) time(NULL);
736         xval = strtoul(CCS dkim_timestamps_expanded, NULL, 10);
737         if (xval > 0)
738           xval += tval;
739         }
740
741     if (!(sig = pdkim_init_sign(&dkim_sign_ctx, dkim_signing_domain,
742                           dkim_signing_selector,
743                           dkim_private_key_expanded,
744                           dkim_hash_expanded,
745                           errstr
746                           )))
747       goto bad;
748     dkim_private_key_expanded[0] = '\0';
749
750     pdkim_set_optional(sig,
751                         CS dkim_sign_headers_expanded,
752                         CS dkim_identity_expanded,
753                         pdkim_canon,
754                         pdkim_canon, -1, tval, xval);
755
756     if (!pdkim_set_sig_bodyhash(&dkim_sign_ctx, sig))
757       goto bad;
758
759     dkim_signing_record = string_append_listele(dkim_signing_record, ':', dkim_signing_domain);
760     dkim_signing_record = string_append_listele(dkim_signing_record, ':', dkim_signing_selector);
761
762     if (!dkim_sign_ctx.sig)             /* link sig to context chain */
763       dkim_sign_ctx.sig = sig;
764     else
765       {
766       pdkim_signature * n = dkim_sign_ctx.sig;
767       while (n->next) n = n->next;
768       n->next = sig;
769       }
770     }
771   }
772
773 /* We may need to carry on with the data-feed even if there are no DKIM sigs to
774 produce, if some other package (eg. ARC) is signing. */
775
776 if (!dkim_sign_ctx.sig && !dkim->force_bodyhash)
777   {
778   DEBUG(D_transport) debug_printf("DKIM: no viable signatures to use\n");
779   sigbuf = string_get(1);       /* return a zero-len string */
780   }
781 else
782   {
783   if (prefix && (pdkim_rc = pdkim_feed(&dkim_sign_ctx, prefix, Ustrlen(prefix))) != PDKIM_OK)
784     goto pk_bad;
785
786   if (lseek(fd, off, SEEK_SET) < 0)
787     sread = -1;
788   else
789     while ((sread = read(fd, &buf, sizeof(buf))) > 0)
790       if ((pdkim_rc = pdkim_feed(&dkim_sign_ctx, buf, sread)) != PDKIM_OK)
791         goto pk_bad;
792
793   /* Handle failed read above. */
794   if (sread == -1)
795     {
796     debug_printf("DKIM: Error reading -K file.\n");
797     save_errno = errno;
798     goto bad;
799     }
800
801   /* Build string of headers, one per signature */
802
803   if ((pdkim_rc = pdkim_feed_finish(&dkim_sign_ctx, &sig, errstr)) != PDKIM_OK)
804     goto pk_bad;
805
806   if (!sig)
807     {
808     DEBUG(D_transport) debug_printf("DKIM: no signatures to use\n");
809     sigbuf = string_get(1);     /* return a zero-len string */
810     }
811   else for (sigbuf = NULL; sig; sig = sig->next)
812     sigbuf = string_append(sigbuf, 2, US sig->signature_header, US"\r\n");
813   }
814
815 CLEANUP:
816   (void) string_from_gstring(sigbuf);
817   store_pool = old_pool;
818   errno = save_errno;
819   return sigbuf;
820
821 pk_bad:
822   log_write(0, LOG_MAIN|LOG_PANIC,
823                 "DKIM: signing failed: %.100s", pdkim_errstr(pdkim_rc));
824 bad:
825   sigbuf = NULL;
826   goto CLEANUP;
827
828 expand_bad:
829   *errstr = string_sprintf("failed to expand %s: %s",
830               errwhen, expand_string_message);
831   log_write(0, LOG_MAIN | LOG_PANIC, "%s", *errstr);
832   goto bad;
833 }
834
835
836
837
838 gstring *
839 authres_dkim(gstring * g)
840 {
841 int start = 0;          /* compiler quietening */
842
843 DEBUG(D_acl) start = gstring_length(g);
844
845 for (pdkim_signature * sig = dkim_signatures; sig; sig = sig->next)
846   {
847   g = string_catn(g, US";\n\tdkim=", 8);
848
849   if (sig->verify_status & PDKIM_VERIFY_POLICY)
850     g = string_append(g, 5,
851       US"policy (", dkim_verify_status, US" - ", dkim_verify_reason, US")");
852   else switch(sig->verify_status)
853     {
854     case PDKIM_VERIFY_NONE:    g = string_cat(g, US"none"); break;
855     case PDKIM_VERIFY_INVALID:
856       switch (sig->verify_ext_status)
857         {
858         case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE:
859           g = string_cat(g, US"tmperror (pubkey unavailable)\n\t\t"); break;
860         case PDKIM_VERIFY_INVALID_BUFFER_SIZE:
861           g = string_cat(g, US"permerror (overlong public key record)\n\t\t"); break;
862         case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD:
863         case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT:
864           g = string_cat(g, US"neutral (public key record import problem)\n\t\t");
865           break;
866         case PDKIM_VERIFY_INVALID_SIGNATURE_ERROR:
867           g = string_cat(g, US"neutral (signature tag missing or invalid)\n\t\t");
868           break;
869         case PDKIM_VERIFY_INVALID_DKIM_VERSION:
870           g = string_cat(g, US"neutral (unsupported DKIM version)\n\t\t");
871           break;
872         default:
873           g = string_cat(g, US"permerror (unspecified problem)\n\t\t"); break;
874         }
875       break;
876     case PDKIM_VERIFY_FAIL:
877       switch (sig->verify_ext_status)
878         {
879         case PDKIM_VERIFY_FAIL_BODY:
880           g = string_cat(g,
881             US"fail (body hash mismatch; body probably modified in transit)\n\t\t");
882           break;
883         case PDKIM_VERIFY_FAIL_MESSAGE:
884           g = string_cat(g,
885             US"fail (signature did not verify; headers probably modified in transit)\n\t\t");
886           break;
887         case PDKIM_VERIFY_INVALID_PUBKEY_KEYSIZE:       /* should this really be "polcy"? */
888           g = string_fmt_append(g, "fail (public key too short: %u bits)\n\t\t", sig->keybits);
889           break;
890         default:
891           g = string_cat(g, US"fail (unspecified reason)\n\t\t");
892           break;
893         }
894       break;
895     case PDKIM_VERIFY_PASS:    g = string_cat(g, US"pass"); break;
896     default:                   g = string_cat(g, US"permerror"); break;
897     }
898   if (sig->domain)   g = string_append(g, 2, US" header.d=", sig->domain);
899   if (sig->identity) g = string_append(g, 2, US" header.i=", sig->identity);
900   if (sig->selector) g = string_append(g, 2, US" header.s=", sig->selector);
901   g = string_append(g, 2, US" header.a=", dkim_sig_to_a_tag(sig));
902   }
903
904 DEBUG(D_acl)
905   if (gstring_length(g) == start)
906     debug_printf("DKIM:\tno authres\n");
907   else
908     debug_printf("DKIM:\tauthres '%.*s'\n", g->ptr - start - 3, g->s + start + 3);
909 return g;
910 }
911
912
913 # endif /*!MACRO_PREDEF*/
914 #endif  /*!DISABLE_DKIM*/