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