DNS: explicit alloc/free of workspace
[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   {
58   store_free_dns_answer(dnsa);
59   return NULL;  /*XXX better error detail?  logging? */
60   }
61
62 /* Search for TXT record */
63
64 for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS);
65      rr;
66      rr = dns_next_rr(dnsa, &dnss, RESET_NEXT))
67   if (rr->type == T_TXT)
68     {
69     int rr_offset = 0;
70
71     /* Copy record content to the answer buffer */
72
73     while (rr_offset < rr->size)
74       {
75       uschar len = rr->data[rr_offset++];
76
77       g = string_catn(g, US(rr->data + rr_offset), len);
78       if (g->ptr >= PDKIM_DNS_TXT_MAX_RECLEN)
79         goto bad;
80
81       rr_offset += len;
82       }
83
84     /* check if this looks like a DKIM record */
85     if (Ustrncmp(g->s, "v=", 2) != 0 || strncasecmp(CS g->s, "v=dkim", 6) == 0)
86       {
87       store_free_dns_answer(dnsa);
88       gstring_release_unused(g);
89       return string_from_gstring(g);
90       }
91
92     if (g) g->ptr = 0;          /* overwrite previous record */
93     }
94
95 bad:
96 store_reset(reset_point);
97 store_free_dns_answer(dnsa);
98 return NULL;    /*XXX better error detail?  logging? */
99 }
100
101
102 void
103 dkim_exim_init(void)
104 {
105 if (f.dkim_init_done) return;
106 f.dkim_init_done = TRUE;
107 pdkim_init();
108 }
109
110
111
112 void
113 dkim_exim_verify_init(BOOL dot_stuffing)
114 {
115 dkim_exim_init();
116
117 /* There is a store-reset between header & body reception for the main pool
118 (actually, after every header line) so cannot use that as we need the data we
119 store per-header, during header processing, at the end of body reception
120 for evaluating the signature.  Any allocs done for dkim verify
121 memory-handling must use a different pool.  We use a separate one that we
122 can reset per message. */
123
124 dkim_verify_oldpool = store_pool;
125 store_pool = POOL_MESSAGE;
126
127 /* Free previous context if there is one */
128
129 if (dkim_verify_ctx)
130   pdkim_free_ctx(dkim_verify_ctx);
131
132 /* Create new context */
133
134 dkim_verify_ctx = pdkim_init_verify(&dkim_exim_query_dns_txt, dot_stuffing);
135 dkim_collect_input = dkim_verify_ctx ? DKIM_MAX_SIGNATURES : 0;
136 dkim_collect_error = NULL;
137
138 /* Start feed up with any cached data */
139 receive_get_cache();
140
141 store_pool = dkim_verify_oldpool;
142 }
143
144
145 void
146 dkim_exim_verify_feed(uschar * data, int len)
147 {
148 int rc;
149
150 store_pool = POOL_MESSAGE;
151 if (  dkim_collect_input
152    && (rc = pdkim_feed(dkim_verify_ctx, data, len)) != PDKIM_OK)
153   {
154   dkim_collect_error = pdkim_errstr(rc);
155   log_write(0, LOG_MAIN,
156              "DKIM: validation error: %.100s", dkim_collect_error);
157   dkim_collect_input = 0;
158   }
159 store_pool = dkim_verify_oldpool;
160 }
161
162
163 /* Log the result for the given signature */
164 static void
165 dkim_exim_verify_log_sig(pdkim_signature * sig)
166 {
167 gstring * logmsg;
168 uschar * s;
169
170 if (!sig) return;
171
172 /* Remember the domain for the first pass result */
173
174 if (  !dkim_verify_overall
175    && dkim_verify_status
176       ? Ustrcmp(dkim_verify_status, US"pass") == 0
177       : sig->verify_status == PDKIM_VERIFY_PASS
178    )
179   dkim_verify_overall = string_copy(sig->domain);
180
181 /* Rewrite the sig result if the ACL overrode it.  This is only
182 needed because the DMARC code (sigh) peeks at the dkim sigs.
183 Mark the sig for this having been done. */
184
185 if (  dkim_verify_status
186    && (  dkim_verify_status != dkim_exim_expand_query(DKIM_VERIFY_STATUS)
187       || dkim_verify_reason != dkim_exim_expand_query(DKIM_VERIFY_REASON)
188    )  )
189   {                     /* overridden by ACL */
190   sig->verify_ext_status = -1;
191   if (Ustrcmp(dkim_verify_status, US"fail") == 0)
192     sig->verify_status = PDKIM_VERIFY_POLICY | PDKIM_VERIFY_FAIL;
193   else if (Ustrcmp(dkim_verify_status, US"invalid") == 0)
194     sig->verify_status = PDKIM_VERIFY_POLICY | PDKIM_VERIFY_INVALID;
195   else if (Ustrcmp(dkim_verify_status, US"none") == 0)
196     sig->verify_status = PDKIM_VERIFY_POLICY | PDKIM_VERIFY_NONE;
197   else if (Ustrcmp(dkim_verify_status, US"pass") == 0)
198     sig->verify_status = PDKIM_VERIFY_POLICY | PDKIM_VERIFY_PASS;
199   else
200     sig->verify_status = -1;
201   }
202
203 if (!LOGGING(dkim_verbose)) return;
204
205
206 logmsg = string_catn(NULL, US"DKIM: ", 6);
207 if (!(s = sig->domain)) s = US"<UNSET>";
208 logmsg = string_append(logmsg, 2, "d=", s);
209 if (!(s = sig->selector)) s = US"<UNSET>";
210 logmsg = string_append(logmsg, 2, " s=", s);
211 logmsg = string_fmt_append(logmsg, " c=%s/%s a=%s b=" SIZE_T_FMT,
212           sig->canon_headers == PDKIM_CANON_SIMPLE ? "simple" : "relaxed",
213           sig->canon_body    == PDKIM_CANON_SIMPLE ? "simple" : "relaxed",
214           dkim_sig_to_a_tag(sig),
215           (int)sig->sighash.len > -1 ? sig->sighash.len * 8 : (size_t)0);
216 if ((s= sig->identity)) logmsg = string_append(logmsg, 2, " i=", s);
217 if (sig->created > 0) logmsg = string_fmt_append(logmsg, " t=%lu",
218                                     sig->created);
219 if (sig->expires > 0) logmsg = string_fmt_append(logmsg, " x=%lu",
220                                     sig->expires);
221 if (sig->bodylength > -1) logmsg = string_fmt_append(logmsg, " l=%lu",
222                                     sig->bodylength);
223
224 if (sig->verify_status & PDKIM_VERIFY_POLICY)
225   logmsg = string_append(logmsg, 5,
226             US" [", dkim_verify_status, US" - ", dkim_verify_reason, US"]");
227 else
228   switch (sig->verify_status)
229     {
230     case PDKIM_VERIFY_NONE:
231       logmsg = string_cat(logmsg, US" [not verified]");
232       break;
233
234     case PDKIM_VERIFY_INVALID:
235       logmsg = string_cat(logmsg, US" [invalid - ");
236       switch (sig->verify_ext_status)
237         {
238         case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE:
239           logmsg = string_cat(logmsg,
240                         US"public key record (currently?) unavailable]");
241           break;
242
243         case PDKIM_VERIFY_INVALID_BUFFER_SIZE:
244           logmsg = string_cat(logmsg, US"overlong public key record]");
245           break;
246
247         case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD:
248         case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT:
249           logmsg = string_cat(logmsg, US"syntax error in public key record]");
250           break;
251
252         case PDKIM_VERIFY_INVALID_SIGNATURE_ERROR:
253           logmsg = string_cat(logmsg, US"signature tag missing or invalid]");
254           break;
255
256         case PDKIM_VERIFY_INVALID_DKIM_VERSION:
257           logmsg = string_cat(logmsg, US"unsupported DKIM version]");
258           break;
259
260         default:
261           logmsg = string_cat(logmsg, US"unspecified problem]");
262         }
263       break;
264
265     case PDKIM_VERIFY_FAIL:
266       logmsg = string_cat(logmsg, US" [verification failed - ");
267       switch (sig->verify_ext_status)
268         {
269         case PDKIM_VERIFY_FAIL_BODY:
270           logmsg = string_cat(logmsg,
271                US"body hash mismatch (body probably modified in transit)]");
272           break;
273
274         case PDKIM_VERIFY_FAIL_MESSAGE:
275           logmsg = string_cat(logmsg,
276                 US"signature did not verify "
277                 "(headers probably modified in transit)]");
278           break;
279
280         case PDKIM_VERIFY_INVALID_PUBKEY_KEYSIZE:
281           logmsg = string_cat(logmsg,
282                 US"signature invalid (key too short)]");
283           break;
284
285         default:
286           logmsg = string_cat(logmsg, US"unspecified reason]");
287         }
288       break;
289
290     case PDKIM_VERIFY_PASS:
291       logmsg = string_cat(logmsg, US" [verification succeeded]");
292       break;
293     }
294
295 log_write(0, LOG_MAIN, "%s", string_from_gstring(logmsg));
296 return;
297 }
298
299
300 /* Log a line for each signature */
301 void
302 dkim_exim_verify_log_all(void)
303 {
304 for (pdkim_signature * sig = dkim_signatures; sig; sig = sig->next)
305   dkim_exim_verify_log_sig(sig);
306 }
307
308
309 void
310 dkim_exim_verify_finish(void)
311 {
312 int rc;
313 gstring * g = NULL;
314 const uschar * errstr = NULL;
315
316 store_pool = POOL_MESSAGE;
317
318 /* Delete eventual previous signature chain */
319
320 dkim_signers = NULL;
321 dkim_signatures = NULL;
322
323 if (dkim_collect_error)
324   {
325   log_write(0, LOG_MAIN,
326       "DKIM: Error during validation, disabling signature verification: %.100s",
327       dkim_collect_error);
328   f.dkim_disable_verify = TRUE;
329   goto out;
330   }
331
332 dkim_collect_input = 0;
333
334 /* Finish DKIM operation and fetch link to signatures chain */
335
336 rc = pdkim_feed_finish(dkim_verify_ctx, (pdkim_signature **)&dkim_signatures,
337                         &errstr);
338 if (rc != PDKIM_OK && errstr)
339   log_write(0, LOG_MAIN, "DKIM: validation error: %s", errstr);
340
341 /* Build a colon-separated list of signing domains (and identities, if present) in dkim_signers */
342
343 for (pdkim_signature * sig = dkim_signatures; sig; sig = sig->next)
344   {
345   if (sig->domain)   g = string_append_listele(g, ':', sig->domain);
346   if (sig->identity) g = string_append_listele(g, ':', sig->identity);
347   }
348
349 if (g) dkim_signers = g->s;
350
351 out:
352 store_pool = dkim_verify_oldpool;
353 }
354
355
356
357 /* Args as per dkim_exim_acl_run() below */
358 static int
359 dkim_acl_call(uschar * id, gstring ** res_ptr,
360   uschar ** user_msgptr, uschar ** log_msgptr)
361 {
362 int rc;
363 DEBUG(D_receive)
364   debug_printf("calling acl_smtp_dkim for dkim_cur_signer='%s'\n", id);
365
366 rc = acl_check(ACL_WHERE_DKIM, NULL, acl_smtp_dkim, user_msgptr, log_msgptr);
367 dkim_exim_verify_log_sig(dkim_cur_sig);
368 *res_ptr = string_append_listele(*res_ptr, ':', dkim_verify_status);
369 return rc;
370 }
371
372
373
374 /* For the given identity, run the DKIM ACL once for each matching signature.
375
376 Arguments
377  id             Identity to look for in dkim signatures
378  res_ptr        ptr to growable string-list of status results,
379                 appended to per ACL run
380  user_msgptr    where to put a user error (for SMTP response)
381  log_msgptr     where to put a logging message (not for SMTP response)
382
383 Returns:       OK         access is granted by an ACCEPT verb
384                DISCARD    access is granted by a DISCARD verb
385                FAIL       access is denied
386                FAIL_DROP  access is denied; drop the connection
387                DEFER      can't tell at the moment
388                ERROR      disaster
389 */
390
391 int
392 dkim_exim_acl_run(uschar * id, gstring ** res_ptr,
393   uschar ** user_msgptr, uschar ** log_msgptr)
394 {
395 uschar * cmp_val;
396 int rc = -1;
397
398 dkim_verify_status = US"none";
399 dkim_verify_reason = US"";
400 dkim_cur_signer = id;
401
402 if (f.dkim_disable_verify || !id || !dkim_verify_ctx)
403   return OK;
404
405 /* Find signatures to run ACL on */
406
407 for (pdkim_signature * sig = dkim_signatures; sig; sig = sig->next)
408   if (  (cmp_val = Ustrchr(id, '@') != NULL ? US sig->identity : US sig->domain)
409      && strcmpic(cmp_val, id) == 0
410      )
411     {
412     /* The "dkim_domain" and "dkim_selector" expansion variables have
413     related globals, since they are used in the signing code too.
414     Instead of inventing separate names for verification, we set
415     them here. This is easy since a domain and selector is guaranteed
416     to be in a signature. The other dkim_* expansion items are
417     dynamically fetched from dkim_cur_sig at expansion time (see
418     dkim_exim_expand_query() below). */
419
420     dkim_cur_sig = sig;
421     dkim_signing_domain = US sig->domain;
422     dkim_signing_selector = US sig->selector;
423     dkim_key_length = sig->keybits;
424
425     /* These two return static strings, so we can compare the addr
426     later to see if the ACL overwrote them.  Check that when logging */
427
428     dkim_verify_status = dkim_exim_expand_query(DKIM_VERIFY_STATUS);
429     dkim_verify_reason = dkim_exim_expand_query(DKIM_VERIFY_REASON);
430
431     if ((rc = dkim_acl_call(id, res_ptr, user_msgptr, log_msgptr)) != OK)
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 if ((s = dkim->dkim_domain) && !(dkim_domain = expand_cstring(s)))
631   /* expansion error, do not send message. */
632   { errwhen = US"dkim_domain"; goto expand_bad; }
633
634 /* Set $dkim_domain expansion variable to each unique domain in list. */
635
636 if (dkim_domain)
637   while ((dkim_signing_domain = string_nextinlist(&dkim_domain, &sep, NULL, 0)))
638   {
639   const uschar * dkim_sel;
640   int sel_sep = 0;
641
642   if (dkim_signing_domain[0] == '\0')
643     continue;
644
645   /* Only sign once for each domain, no matter how often it
646   appears in the expanded list. */
647
648   dkim_signing_domain = string_copylc(dkim_signing_domain);
649   if (match_isinlist(dkim_signing_domain, CUSS &seen_doms,
650       0, NULL, NULL, MCL_STRING, TRUE, NULL) == OK)
651     continue;
652
653   seen_doms = string_append_listele(seen_doms, ':', dkim_signing_domain);
654
655   /* Set $dkim_selector expansion variable to each selector in list,
656   for this domain. */
657
658   if (!(dkim_sel = expand_string(dkim->dkim_selector)))
659     { errwhen = US"dkim_selector"; goto expand_bad; }
660
661   while ((dkim_signing_selector = string_nextinlist(&dkim_sel, &sel_sep,
662           NULL, 0)))
663     {
664     uschar * dkim_canon_expanded;
665     int pdkim_canon;
666     uschar * dkim_sign_headers_expanded = NULL;
667     uschar * dkim_private_key_expanded;
668     uschar * dkim_hash_expanded;
669     uschar * dkim_identity_expanded = NULL;
670     uschar * dkim_timestamps_expanded = NULL;
671     unsigned long tval = 0, xval = 0;
672
673     /* Get canonicalization to use */
674
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     if (  dkim->dkim_sign_headers
693        && !(dkim_sign_headers_expanded = expand_string(dkim->dkim_sign_headers)))
694       { errwhen = US"dkim_sign_header"; goto expand_bad; }
695     /* else pass NULL, which means default header list */
696
697     /* Get private key to use. */
698
699     if (!(dkim_private_key_expanded = expand_string(dkim->dkim_private_key)))
700       { errwhen = US"dkim_private_key"; goto expand_bad; }
701
702     if (  Ustrlen(dkim_private_key_expanded) == 0
703        || Ustrcmp(dkim_private_key_expanded, "0") == 0
704        || Ustrcmp(dkim_private_key_expanded, "false") == 0
705        )
706       continue;         /* don't sign, but no error */
707
708     if (  dkim_private_key_expanded[0] == '/'
709        && !(dkim_private_key_expanded =
710              expand_file_big_buffer(dkim_private_key_expanded)))
711       goto bad;
712
713     if (!(dkim_hash_expanded = expand_string(dkim->dkim_hash)))
714       { errwhen = US"dkim_hash"; goto expand_bad; }
715
716     if (dkim->dkim_identity)
717       if (!(dkim_identity_expanded = expand_string(dkim->dkim_identity)))
718         { errwhen = US"dkim_identity"; goto expand_bad; }
719       else if (!*dkim_identity_expanded)
720         dkim_identity_expanded = NULL;
721
722     if (dkim->dkim_timestamps)
723       if (!(dkim_timestamps_expanded = expand_string(dkim->dkim_timestamps)))
724         { errwhen = US"dkim_timestamps"; goto expand_bad; }
725       else
726         xval = (tval = (unsigned long) time(NULL))
727               + strtoul(CCS dkim_timestamps_expanded, NULL, 10);
728
729     if (!(sig = pdkim_init_sign(&dkim_sign_ctx, dkim_signing_domain,
730                           dkim_signing_selector,
731                           dkim_private_key_expanded,
732                           dkim_hash_expanded,
733                           errstr
734                           )))
735       goto bad;
736     dkim_private_key_expanded[0] = '\0';
737
738     pdkim_set_optional(sig,
739                         CS dkim_sign_headers_expanded,
740                         CS dkim_identity_expanded,
741                         pdkim_canon,
742                         pdkim_canon, -1, tval, xval);
743
744     if (!pdkim_set_sig_bodyhash(&dkim_sign_ctx, sig))
745       goto bad;
746
747     if (!dkim_sign_ctx.sig)             /* link sig to context chain */
748       dkim_sign_ctx.sig = sig;
749     else
750       {
751       pdkim_signature * n = dkim_sign_ctx.sig;
752       while (n->next) n = n->next;
753       n->next = sig;
754       }
755     }
756   }
757
758 /* We may need to carry on with the data-feed even if there are no DKIM sigs to
759 produce, if some other package (eg. ARC) is signing. */
760
761 if (!dkim_sign_ctx.sig && !dkim->force_bodyhash)
762   {
763   DEBUG(D_transport) debug_printf("DKIM: no viable signatures to use\n");
764   sigbuf = string_get(1);       /* return a zero-len string */
765   }
766 else
767   {
768   if (prefix && (pdkim_rc = pdkim_feed(&dkim_sign_ctx, prefix, Ustrlen(prefix))) != PDKIM_OK)
769     goto pk_bad;
770
771   if (lseek(fd, off, SEEK_SET) < 0)
772     sread = -1;
773   else
774     while ((sread = read(fd, &buf, sizeof(buf))) > 0)
775       if ((pdkim_rc = pdkim_feed(&dkim_sign_ctx, buf, sread)) != PDKIM_OK)
776         goto pk_bad;
777
778   /* Handle failed read above. */
779   if (sread == -1)
780     {
781     debug_printf("DKIM: Error reading -K file.\n");
782     save_errno = errno;
783     goto bad;
784     }
785
786   /* Build string of headers, one per signature */
787
788   if ((pdkim_rc = pdkim_feed_finish(&dkim_sign_ctx, &sig, errstr)) != PDKIM_OK)
789     goto pk_bad;
790
791   if (!sig)
792     {
793     DEBUG(D_transport) debug_printf("DKIM: no signatures to use\n");
794     sigbuf = string_get(1);     /* return a zero-len string */
795     }
796   else for (sigbuf = NULL; sig; sig = sig->next)
797     sigbuf = string_append(sigbuf, 2, US sig->signature_header, US"\r\n");
798   }
799
800 CLEANUP:
801   (void) string_from_gstring(sigbuf);
802   store_pool = old_pool;
803   errno = save_errno;
804   return sigbuf;
805
806 pk_bad:
807   log_write(0, LOG_MAIN|LOG_PANIC,
808                 "DKIM: signing failed: %.100s", pdkim_errstr(pdkim_rc));
809 bad:
810   sigbuf = NULL;
811   goto CLEANUP;
812
813 expand_bad:
814   *errstr = string_sprintf("failed to expand %s: %s",
815               errwhen, expand_string_message);
816   log_write(0, LOG_MAIN | LOG_PANIC, "%s", *errstr);
817   goto bad;
818 }
819
820
821
822
823 gstring *
824 authres_dkim(gstring * g)
825 {
826 int start = 0;          /* compiler quietening */
827
828 DEBUG(D_acl) start = g->ptr;
829
830 for (pdkim_signature * sig = dkim_signatures; sig; sig = sig->next)
831   {
832   g = string_catn(g, US";\n\tdkim=", 8);
833
834   if (sig->verify_status & PDKIM_VERIFY_POLICY)
835     g = string_append(g, 5,
836       US"policy (", dkim_verify_status, US" - ", dkim_verify_reason, US")");
837   else switch(sig->verify_status)
838     {
839     case PDKIM_VERIFY_NONE:    g = string_cat(g, US"none"); break;
840     case PDKIM_VERIFY_INVALID:
841       switch (sig->verify_ext_status)
842         {
843         case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE:
844           g = string_cat(g, US"tmperror (pubkey unavailable)\n\t\t"); break;
845         case PDKIM_VERIFY_INVALID_BUFFER_SIZE:
846           g = string_cat(g, US"permerror (overlong public key record)\n\t\t"); break;
847         case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD:
848         case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT:
849           g = string_cat(g, US"neutral (public key record import problem)\n\t\t");
850           break;
851         case PDKIM_VERIFY_INVALID_SIGNATURE_ERROR:
852           g = string_cat(g, US"neutral (signature tag missing or invalid)\n\t\t");
853           break;
854         case PDKIM_VERIFY_INVALID_DKIM_VERSION:
855           g = string_cat(g, US"neutral (unsupported DKIM version)\n\t\t");
856           break;
857         default:
858           g = string_cat(g, US"permerror (unspecified problem)\n\t\t"); break;
859         }
860       break;
861     case PDKIM_VERIFY_FAIL:
862       switch (sig->verify_ext_status)
863         {
864         case PDKIM_VERIFY_FAIL_BODY:
865           g = string_cat(g,
866             US"fail (body hash mismatch; body probably modified in transit)\n\t\t");
867           break;
868         case PDKIM_VERIFY_FAIL_MESSAGE:
869           g = string_cat(g,
870             US"fail (signature did not verify; headers probably modified in transit)\n\t\t");
871           break;
872         case PDKIM_VERIFY_INVALID_PUBKEY_KEYSIZE:       /* should this really be "polcy"? */
873           g = string_fmt_append(g, "fail (public key too short: %u bits)\n\t\t", sig->keybits);
874           break;
875         default:
876           g = string_cat(g, US"fail (unspecified reason)\n\t\t");
877           break;
878         }
879       break;
880     case PDKIM_VERIFY_PASS:    g = string_cat(g, US"pass"); break;
881     default:                   g = string_cat(g, US"permerror"); break;
882     }
883   if (sig->domain)   g = string_append(g, 2, US" header.d=", sig->domain);
884   if (sig->identity) g = string_append(g, 2, US" header.i=", sig->identity);
885   if (sig->selector) g = string_append(g, 2, US" header.s=", sig->selector);
886   g = string_append(g, 2, US" header.a=", dkim_sig_to_a_tag(sig));
887   }
888
889 DEBUG(D_acl)
890   if (g->ptr == start)
891     debug_printf("DKIM: no authres\n");
892   else
893     debug_printf("DKIM: authres '%.*s'\n", g->ptr - start - 3, g->s + start + 3);
894 return g;
895 }
896
897
898 # endif /*!MACRO_PREDEF*/
899 #endif  /*!DISABLE_DKIM*/