9e76c51a0226babfc9f66bd980cf6c63b3bb8bb1
[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 GET_OPTION("dkim_domain");
628 if ((s = dkim->dkim_domain) && !(dkim_domain = expand_cstring(s)))
629   /* expansion error, do not send message. */
630   { errwhen = US"dkim_domain"; goto expand_bad; }
631
632 /* Set $dkim_domain expansion variable to each unique domain in list. */
633
634 if (dkim_domain)
635   while ((dkim_signing_domain = string_nextinlist(&dkim_domain, &sep, NULL, 0)))
636   {
637   const uschar * dkim_sel;
638   int sel_sep = 0;
639
640   if (dkim_signing_domain[0] == '\0')
641     continue;
642
643   /* Only sign once for each domain, no matter how often it
644   appears in the expanded list. */
645
646   dkim_signing_domain = string_copylc(dkim_signing_domain);
647   if (match_isinlist(dkim_signing_domain, CUSS &seen_doms,
648       0, NULL, NULL, MCL_STRING, TRUE, NULL) == OK)
649     continue;
650
651   seen_doms = string_append_listele(seen_doms, ':', dkim_signing_domain);
652
653   /* Set $dkim_selector expansion variable to each selector in list,
654   for this domain. */
655
656   GET_OPTION("dkim_selector");
657   if (!(dkim_sel = expand_string(dkim->dkim_selector)))
658     { errwhen = US"dkim_selector"; goto expand_bad; }
659
660   while ((dkim_signing_selector = string_nextinlist(&dkim_sel, &sel_sep,
661           NULL, 0)))
662     {
663     uschar * dkim_canon_expanded;
664     int pdkim_canon;
665     uschar * dkim_sign_headers_expanded = NULL;
666     uschar * dkim_private_key_expanded;
667     uschar * dkim_hash_expanded;
668     uschar * dkim_identity_expanded = NULL;
669     uschar * dkim_timestamps_expanded = NULL;
670     unsigned long tval = 0, xval = 0;
671
672     /* Get canonicalization to use */
673
674     GET_OPTION("dkim_canon");
675     dkim_canon_expanded = dkim->dkim_canon
676       ? expand_string(dkim->dkim_canon) : US"relaxed";
677     if (!dkim_canon_expanded)   /* expansion error, do not send message. */
678       { errwhen = US"dkim_canon"; goto expand_bad; }
679
680     if (Ustrcmp(dkim_canon_expanded, "relaxed") == 0)
681       pdkim_canon = PDKIM_CANON_RELAXED;
682     else if (Ustrcmp(dkim_canon_expanded, "simple") == 0)
683       pdkim_canon = PDKIM_CANON_SIMPLE;
684     else
685       {
686       log_write(0, LOG_MAIN,
687                  "DKIM: unknown canonicalization method '%s', defaulting to 'relaxed'.\n",
688                  dkim_canon_expanded);
689       pdkim_canon = PDKIM_CANON_RELAXED;
690       }
691
692     GET_OPTION("dkim_sign_headers");
693     if (  dkim->dkim_sign_headers
694        && !(dkim_sign_headers_expanded = expand_string(dkim->dkim_sign_headers)))
695       { errwhen = US"dkim_sign_header"; goto expand_bad; }
696     /* else pass NULL, which means default header list */
697
698     /* Get private key to use. */
699
700     GET_OPTION("dkim_private_key");
701     if (!(dkim_private_key_expanded = expand_string(dkim->dkim_private_key)))
702       { errwhen = US"dkim_private_key"; goto expand_bad; }
703
704     if (  Ustrlen(dkim_private_key_expanded) == 0
705        || Ustrcmp(dkim_private_key_expanded, "0") == 0
706        || Ustrcmp(dkim_private_key_expanded, "false") == 0
707        )
708       continue;         /* don't sign, but no error */
709
710     if (  dkim_private_key_expanded[0] == '/'
711        && !(dkim_private_key_expanded =
712              expand_file_big_buffer(dkim_private_key_expanded)))
713       goto bad;
714
715     GET_OPTION("dkim_hash");
716     if (!(dkim_hash_expanded = expand_string(dkim->dkim_hash)))
717       { errwhen = US"dkim_hash"; goto expand_bad; }
718
719     GET_OPTION("dkim_identity");
720     if (dkim->dkim_identity)
721       if (!(dkim_identity_expanded = expand_string(dkim->dkim_identity)))
722         { errwhen = US"dkim_identity"; goto expand_bad; }
723       else if (!*dkim_identity_expanded)
724         dkim_identity_expanded = NULL;
725
726     GET_OPTION("dkim_timestamps");
727     if (dkim->dkim_timestamps)
728       if (!(dkim_timestamps_expanded = expand_string(dkim->dkim_timestamps)))
729         { errwhen = US"dkim_timestamps"; goto expand_bad; }
730       else
731         {
732         tval = (unsigned long) time(NULL);
733         xval = strtoul(CCS dkim_timestamps_expanded, NULL, 10);
734         if (xval > 0)
735           xval += tval;
736         }
737
738     if (!(sig = pdkim_init_sign(&dkim_sign_ctx, dkim_signing_domain,
739                           dkim_signing_selector,
740                           dkim_private_key_expanded,
741                           dkim_hash_expanded,
742                           errstr
743                           )))
744       goto bad;
745     dkim_private_key_expanded[0] = '\0';
746
747     pdkim_set_optional(sig,
748                         CS dkim_sign_headers_expanded,
749                         CS dkim_identity_expanded,
750                         pdkim_canon,
751                         pdkim_canon, -1, tval, xval);
752
753     if (!pdkim_set_sig_bodyhash(&dkim_sign_ctx, sig))
754       goto bad;
755
756     dkim_signing_record = string_append_listele(dkim_signing_record, ':', dkim_signing_domain);
757     dkim_signing_record = string_append_listele(dkim_signing_record, ':', dkim_signing_selector);
758
759     if (!dkim_sign_ctx.sig)             /* link sig to context chain */
760       dkim_sign_ctx.sig = sig;
761     else
762       {
763       pdkim_signature * n = dkim_sign_ctx.sig;
764       while (n->next) n = n->next;
765       n->next = sig;
766       }
767     }
768   }
769
770 /* We may need to carry on with the data-feed even if there are no DKIM sigs to
771 produce, if some other package (eg. ARC) is signing. */
772
773 if (!dkim_sign_ctx.sig && !dkim->force_bodyhash)
774   {
775   DEBUG(D_transport) debug_printf("DKIM: no viable signatures to use\n");
776   sigbuf = string_get(1);       /* return a zero-len string */
777   }
778 else
779   {
780   if (prefix && (pdkim_rc = pdkim_feed(&dkim_sign_ctx, prefix, Ustrlen(prefix))) != PDKIM_OK)
781     goto pk_bad;
782
783   if (lseek(fd, off, SEEK_SET) < 0)
784     sread = -1;
785   else
786     while ((sread = read(fd, &buf, sizeof(buf))) > 0)
787       if ((pdkim_rc = pdkim_feed(&dkim_sign_ctx, buf, sread)) != PDKIM_OK)
788         goto pk_bad;
789
790   /* Handle failed read above. */
791   if (sread == -1)
792     {
793     debug_printf("DKIM: Error reading -K file.\n");
794     save_errno = errno;
795     goto bad;
796     }
797
798   /* Build string of headers, one per signature */
799
800   if ((pdkim_rc = pdkim_feed_finish(&dkim_sign_ctx, &sig, errstr)) != PDKIM_OK)
801     goto pk_bad;
802
803   if (!sig)
804     {
805     DEBUG(D_transport) debug_printf("DKIM: no signatures to use\n");
806     sigbuf = string_get(1);     /* return a zero-len string */
807     }
808   else for (sigbuf = NULL; sig; sig = sig->next)
809     sigbuf = string_append(sigbuf, 2, US sig->signature_header, US"\r\n");
810   }
811
812 CLEANUP:
813   (void) string_from_gstring(sigbuf);
814   store_pool = old_pool;
815   errno = save_errno;
816   return sigbuf;
817
818 pk_bad:
819   log_write(0, LOG_MAIN|LOG_PANIC,
820                 "DKIM: signing failed: %.100s", pdkim_errstr(pdkim_rc));
821 bad:
822   sigbuf = NULL;
823   goto CLEANUP;
824
825 expand_bad:
826   *errstr = string_sprintf("failed to expand %s: %s",
827               errwhen, expand_string_message);
828   log_write(0, LOG_MAIN | LOG_PANIC, "%s", *errstr);
829   goto bad;
830 }
831
832
833
834
835 gstring *
836 authres_dkim(gstring * g)
837 {
838 int start = 0;          /* compiler quietening */
839
840 DEBUG(D_acl) start = gstring_length(g);
841
842 for (pdkim_signature * sig = dkim_signatures; sig; sig = sig->next)
843   {
844   g = string_catn(g, US";\n\tdkim=", 8);
845
846   if (sig->verify_status & PDKIM_VERIFY_POLICY)
847     g = string_append(g, 5,
848       US"policy (", dkim_verify_status, US" - ", dkim_verify_reason, US")");
849   else switch(sig->verify_status)
850     {
851     case PDKIM_VERIFY_NONE:    g = string_cat(g, US"none"); break;
852     case PDKIM_VERIFY_INVALID:
853       switch (sig->verify_ext_status)
854         {
855         case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE:
856           g = string_cat(g, US"tmperror (pubkey unavailable)\n\t\t"); break;
857         case PDKIM_VERIFY_INVALID_BUFFER_SIZE:
858           g = string_cat(g, US"permerror (overlong public key record)\n\t\t"); break;
859         case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD:
860         case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT:
861           g = string_cat(g, US"neutral (public key record import problem)\n\t\t");
862           break;
863         case PDKIM_VERIFY_INVALID_SIGNATURE_ERROR:
864           g = string_cat(g, US"neutral (signature tag missing or invalid)\n\t\t");
865           break;
866         case PDKIM_VERIFY_INVALID_DKIM_VERSION:
867           g = string_cat(g, US"neutral (unsupported DKIM version)\n\t\t");
868           break;
869         default:
870           g = string_cat(g, US"permerror (unspecified problem)\n\t\t"); break;
871         }
872       break;
873     case PDKIM_VERIFY_FAIL:
874       switch (sig->verify_ext_status)
875         {
876         case PDKIM_VERIFY_FAIL_BODY:
877           g = string_cat(g,
878             US"fail (body hash mismatch; body probably modified in transit)\n\t\t");
879           break;
880         case PDKIM_VERIFY_FAIL_MESSAGE:
881           g = string_cat(g,
882             US"fail (signature did not verify; headers probably modified in transit)\n\t\t");
883           break;
884         case PDKIM_VERIFY_INVALID_PUBKEY_KEYSIZE:       /* should this really be "polcy"? */
885           g = string_fmt_append(g, "fail (public key too short: %u bits)\n\t\t", sig->keybits);
886           break;
887         default:
888           g = string_cat(g, US"fail (unspecified reason)\n\t\t");
889           break;
890         }
891       break;
892     case PDKIM_VERIFY_PASS:    g = string_cat(g, US"pass"); break;
893     default:                   g = string_cat(g, US"permerror"); break;
894     }
895   if (sig->domain)   g = string_append(g, 2, US" header.d=", sig->domain);
896   if (sig->identity) g = string_append(g, 2, US" header.i=", sig->identity);
897   if (sig->selector) g = string_append(g, 2, US" header.s=", sig->selector);
898   g = string_append(g, 2, US" header.a=", dkim_sig_to_a_tag(sig));
899   }
900
901 DEBUG(D_acl)
902   if (gstring_length(g) == start)
903     debug_printf("DKIM:\tno authres\n");
904   else
905     debug_printf("DKIM:\tauthres '%.*s'\n", g->ptr - start - 3, g->s + start + 3);
906 return g;
907 }
908
909
910 # endif /*!MACRO_PREDEF*/
911 #endif  /*!DISABLE_DKIM*/