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