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