Merge branch '4.next'
[exim.git] / src / src / dkim.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) University of Cambridge, 1995 - 2017 */
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
30 int dkim_verify_oldpool;
31 pdkim_ctx *dkim_verify_ctx = NULL;
32 pdkim_signature *dkim_signatures = NULL;
33 pdkim_signature *dkim_cur_sig = NULL;
34 static const uschar * dkim_collect_error = NULL;
35
36
37
38 /*XXX the caller only uses the first record if we return multiple.
39 Could we hand back an allocated string?
40 */
41
42 static int
43 dkim_exim_query_dns_txt(char *name, char *answer)
44 {
45 dns_answer dnsa;
46 dns_scan dnss;
47 dns_record *rr;
48
49 lookup_dnssec_authenticated = NULL;
50 if (dns_lookup(&dnsa, US name, T_TXT, NULL) != DNS_SUCCEED)
51   return PDKIM_FAIL;    /*XXX better error detail?  logging? */
52
53 /* Search for TXT record */
54
55 for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
56      rr;
57      rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
58   if (rr->type == T_TXT)
59     {
60     int rr_offset = 0;
61     int answer_offset = 0;
62
63     /* Copy record content to the answer buffer */
64
65     while (rr_offset < rr->size)
66       {
67       uschar len = rr->data[rr_offset++];
68       snprintf(answer + answer_offset,
69                 PDKIM_DNS_TXT_MAX_RECLEN - answer_offset,
70                 "%.*s", (int)len, CS  (rr->data + rr_offset));
71       rr_offset += len;
72       answer_offset += len;
73       if (answer_offset >= PDKIM_DNS_TXT_MAX_RECLEN)
74         return PDKIM_FAIL;      /*XXX better error detail?  logging? */
75       }
76
77     /* check if this looks like a DKIM record */
78     if (strncasecmp(answer, "v=dkim", 6) != 0) continue;
79     return PDKIM_OK;
80     }
81
82 return PDKIM_FAIL;      /*XXX better error detail?  logging? */
83 }
84
85
86 void
87 dkim_exim_init(void)
88 {
89 pdkim_init();
90 }
91
92
93
94 void
95 dkim_exim_verify_init(BOOL dot_stuffing)
96 {
97 /* There is a store-reset between header & body reception
98 so cannot use the main pool. Any allocs done by Exim
99 memory-handling must use the perm pool. */
100
101 dkim_verify_oldpool = store_pool;
102 store_pool = POOL_PERM;
103
104 /* Free previous context if there is one */
105
106 if (dkim_verify_ctx)
107   pdkim_free_ctx(dkim_verify_ctx);
108
109 /* Create new context */
110
111 dkim_verify_ctx = pdkim_init_verify(&dkim_exim_query_dns_txt, dot_stuffing);
112 dkim_collect_input = !!dkim_verify_ctx;
113 dkim_collect_error = NULL;
114
115 /* Start feed up with any cached data */
116 receive_get_cache();
117
118 store_pool = dkim_verify_oldpool;
119 }
120
121
122 void
123 dkim_exim_verify_feed(uschar * data, int len)
124 {
125 int rc;
126
127 store_pool = POOL_PERM;
128 if (  dkim_collect_input
129    && (rc = pdkim_feed(dkim_verify_ctx, data, len)) != PDKIM_OK)
130   {
131   dkim_collect_error = pdkim_errstr(rc);
132   log_write(0, LOG_MAIN,
133              "DKIM: validation error: %.100s", dkim_collect_error);
134   dkim_collect_input = FALSE;
135   }
136 store_pool = dkim_verify_oldpool;
137 }
138
139
140 /* Log the result for the given signature */
141 static void
142 dkim_exim_verify_log_sig(pdkim_signature * sig)
143 {
144 gstring * logmsg;
145 uschar * s;
146
147 if (!sig) return;
148
149 logmsg = string_catn(NULL, US"DKIM: ", 6);
150 if (!(s = sig->domain)) s = US"<UNSET>";
151 logmsg = string_append(logmsg, 2, "d=", s);
152 if (!(s = sig->selector)) s = US"<UNSET>";
153 logmsg = string_append(logmsg, 2, " s=", s);
154 logmsg = string_append(logmsg, 7,
155 " c=", sig->canon_headers == PDKIM_CANON_SIMPLE ? "simple" : "relaxed",
156 "/",   sig->canon_body    == PDKIM_CANON_SIMPLE ? "simple" : "relaxed",
157 " a=", dkim_sig_to_a_tag(sig),
158 string_sprintf(" b=" SIZE_T_FMT,
159                 (int)sig->sighash.len > -1 ? sig->sighash.len * 8 : 0));
160 if ((s= sig->identity)) logmsg = string_append(logmsg, 2, " i=", s);
161 if (sig->created > 0) logmsg = string_cat(logmsg,
162                               string_sprintf(" t=%lu", sig->created));
163 if (sig->expires > 0) logmsg = string_cat(logmsg,
164                               string_sprintf(" x=%lu", sig->expires));
165 if (sig->bodylength > -1) logmsg = string_cat(logmsg,
166                               string_sprintf(" l=%lu", sig->bodylength));
167
168 if (  !dkim_verify_status
169    || (  dkim_verify_status == dkim_exim_expand_query(DKIM_VERIFY_STATUS)
170       && dkim_verify_reason == dkim_exim_expand_query(DKIM_VERIFY_REASON)
171    )  )
172   switch (sig->verify_status)
173     {
174     case PDKIM_VERIFY_NONE:
175       logmsg = string_cat(logmsg, US" [not verified]");
176       break;
177
178     case PDKIM_VERIFY_INVALID:
179       logmsg = string_cat(logmsg, US" [invalid - ");
180       switch (sig->verify_ext_status)
181         {
182         case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE:
183           logmsg = string_cat(logmsg,
184                         US"public key record (currently?) unavailable]");
185           break;
186
187         case PDKIM_VERIFY_INVALID_BUFFER_SIZE:
188           logmsg = string_cat(logmsg, US"overlong public key record]");
189           break;
190
191         case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD:
192         case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT:
193           logmsg = string_cat(logmsg, US"syntax error in public key record]");
194           break;
195
196         case PDKIM_VERIFY_INVALID_SIGNATURE_ERROR:
197           logmsg = string_cat(logmsg, US"signature tag missing or invalid]");
198           break;
199
200         case PDKIM_VERIFY_INVALID_DKIM_VERSION:
201           logmsg = string_cat(logmsg, US"unsupported DKIM version]");
202           break;
203
204         default:
205           logmsg = string_cat(logmsg, US"unspecified problem]");
206         }
207       break;
208
209     case PDKIM_VERIFY_FAIL:
210       logmsg = string_cat(logmsg, US" [verification failed - ");
211       switch (sig->verify_ext_status)
212         {
213         case PDKIM_VERIFY_FAIL_BODY:
214           logmsg = string_cat(logmsg,
215                US"body hash mismatch (body probably modified in transit)]");
216           break;
217
218         case PDKIM_VERIFY_FAIL_MESSAGE:
219           logmsg = string_cat(logmsg,
220                 US"signature did not verify "
221                 "(headers probably modified in transit)]");
222         break;
223
224         default:
225           logmsg = string_cat(logmsg, US"unspecified reason]");
226         }
227       break;
228
229     case PDKIM_VERIFY_PASS:
230       logmsg = string_cat(logmsg, US" [verification succeeded]");
231       break;
232     }
233 else
234   logmsg = string_append(logmsg, 5,
235             US" [", dkim_verify_status, US" - ", dkim_verify_reason, US"]");
236
237 log_write(0, LOG_MAIN, "%s", string_from_gstring(logmsg));
238 return;
239 }
240
241
242 /* Log a line for each signature */
243 void
244 dkim_exim_verify_log_all(void)
245 {
246 pdkim_signature * sig;
247 for (sig = dkim_signatures; sig; sig = sig->next) dkim_exim_verify_log_sig(sig);
248 }
249
250
251 void
252 dkim_exim_verify_finish(void)
253 {
254 pdkim_signature * sig;
255 int rc;
256 gstring * g = NULL;
257 const uschar * errstr;
258
259 store_pool = POOL_PERM;
260
261 /* Delete eventual previous signature chain */
262
263 dkim_signers = NULL;
264 dkim_signatures = NULL;
265
266 if (dkim_collect_error)
267   {
268   log_write(0, LOG_MAIN,
269       "DKIM: Error during validation, disabling signature verification: %.100s",
270       dkim_collect_error);
271   dkim_disable_verify = TRUE;
272   goto out;
273   }
274
275 dkim_collect_input = FALSE;
276
277 /* Finish DKIM operation and fetch link to signatures chain */
278
279 rc = pdkim_feed_finish(dkim_verify_ctx, &dkim_signatures, &errstr);
280 if (rc != PDKIM_OK)
281   {
282   log_write(0, LOG_MAIN, "DKIM: validation error: %.100s%s%s", pdkim_errstr(rc),
283             errstr ? ": " : "", errstr ? errstr : US"");
284   goto out;
285   }
286
287 /* Build a colon-separated list of signing domains (and identities, if present) in dkim_signers */
288
289 for (sig = dkim_signatures; sig; sig = sig->next)
290   {
291   if (sig->domain)   g = string_append_listele(g, ':', sig->domain);
292   if (sig->identity) g = string_append_listele(g, ':', sig->identity);
293   }
294
295 if (g) dkim_signers = g->s;
296
297 out:
298 store_pool = dkim_verify_oldpool;
299 }
300
301
302
303 /* Args as per dkim_exim_acl_run() below */
304 static int
305 dkim_acl_call(uschar * id, gstring ** res_ptr,
306   uschar ** user_msgptr, uschar ** log_msgptr)
307 {
308 int rc;
309 DEBUG(D_receive)
310   debug_printf("calling acl_smtp_dkim for dkim_cur_signer='%s'\n", id);
311
312 rc = acl_check(ACL_WHERE_DKIM, NULL, acl_smtp_dkim, user_msgptr, log_msgptr);
313 dkim_exim_verify_log_sig(dkim_cur_sig);
314 *res_ptr = string_append_listele(*res_ptr, ':', dkim_verify_status);
315 return rc;
316 }
317
318
319
320 /* For the given identity, run the DKIM ACL once for each matching signature.
321
322 Arguments
323  id             Identity to look for in dkim signatures
324  res_ptr        ptr to growable string-list of status results,
325                 appended to per ACL run
326  user_msgptr    where to put a user error (for SMTP response)
327  log_msgptr     where to put a logging message (not for SMTP response)
328
329 Returns:       OK         access is granted by an ACCEPT verb
330                DISCARD    access is granted by a DISCARD verb
331                FAIL       access is denied
332                FAIL_DROP  access is denied; drop the connection
333                DEFER      can't tell at the moment
334                ERROR      disaster
335 */
336
337 int
338 dkim_exim_acl_run(uschar * id, gstring ** res_ptr,
339   uschar ** user_msgptr, uschar ** log_msgptr)
340 {
341 pdkim_signature * sig;
342 uschar * cmp_val;
343 int rc = -1;
344
345 dkim_verify_status = US"none";
346 dkim_verify_reason = US"";
347 dkim_cur_signer = id;
348
349 if (dkim_disable_verify || !id || !dkim_verify_ctx)
350   return OK;
351
352 /* Find signatures to run ACL on */
353
354 for (sig = dkim_signatures; sig; sig = sig->next)
355   if (  (cmp_val = Ustrchr(id, '@') != NULL ? US sig->identity : US sig->domain)
356      && strcmpic(cmp_val, id) == 0
357      )
358     {
359     /* The "dkim_domain" and "dkim_selector" expansion variables have
360     related globals, since they are used in the signing code too.
361     Instead of inventing separate names for verification, we set
362     them here. This is easy since a domain and selector is guaranteed
363     to be in a signature. The other dkim_* expansion items are
364     dynamically fetched from dkim_cur_sig at expansion time (see
365     function below). */
366
367     dkim_cur_sig = sig;
368     dkim_signing_domain = US sig->domain;
369     dkim_signing_selector = US sig->selector;
370     dkim_key_length = sig->sighash.len * 8;
371
372     /* These two return static strings, so we can compare the addr
373     later to see if the ACL overwrote them.  Check that when logging */
374
375     dkim_verify_status = dkim_exim_expand_query(DKIM_VERIFY_STATUS);
376     dkim_verify_reason = dkim_exim_expand_query(DKIM_VERIFY_REASON);
377
378     if ((rc = dkim_acl_call(id, res_ptr, user_msgptr, log_msgptr)) != OK)
379       return rc;
380     }
381
382 if (rc != -1)
383   return rc;
384
385 /* No matching sig found.  Call ACL once anyway. */
386
387 dkim_cur_sig = NULL;
388 return dkim_acl_call(id, res_ptr, user_msgptr, log_msgptr);
389 }
390
391
392 static uschar *
393 dkim_exim_expand_defaults(int what)
394 {
395 switch (what)
396   {
397   case DKIM_ALGO:               return US"";
398   case DKIM_BODYLENGTH:         return US"9999999999999";
399   case DKIM_CANON_BODY:         return US"";
400   case DKIM_CANON_HEADERS:      return US"";
401   case DKIM_COPIEDHEADERS:      return US"";
402   case DKIM_CREATED:            return US"0";
403   case DKIM_EXPIRES:            return US"9999999999999";
404   case DKIM_HEADERNAMES:        return US"";
405   case DKIM_IDENTITY:           return US"";
406   case DKIM_KEY_GRANULARITY:    return US"*";
407   case DKIM_KEY_SRVTYPE:        return US"*";
408   case DKIM_KEY_NOTES:          return US"";
409   case DKIM_KEY_TESTING:        return US"0";
410   case DKIM_NOSUBDOMAINS:       return US"0";
411   case DKIM_VERIFY_STATUS:      return US"none";
412   case DKIM_VERIFY_REASON:      return US"";
413   default:                      return US"";
414   }
415 }
416
417
418 uschar *
419 dkim_exim_expand_query(int what)
420 {
421 if (!dkim_verify_ctx || dkim_disable_verify || !dkim_cur_sig)
422   return dkim_exim_expand_defaults(what);
423
424 switch (what)
425   {
426   case DKIM_ALGO:
427     return dkim_sig_to_a_tag(dkim_cur_sig);
428
429   case DKIM_BODYLENGTH:
430     return dkim_cur_sig->bodylength >= 0
431       ? string_sprintf("%ld", dkim_cur_sig->bodylength)
432       : dkim_exim_expand_defaults(what);
433
434   case DKIM_CANON_BODY:
435     switch (dkim_cur_sig->canon_body)
436       {
437       case PDKIM_CANON_RELAXED: return US"relaxed";
438       case PDKIM_CANON_SIMPLE:
439       default:                  return US"simple";
440       }
441
442   case DKIM_CANON_HEADERS:
443     switch (dkim_cur_sig->canon_headers)
444       {
445       case PDKIM_CANON_RELAXED: return US"relaxed";
446       case PDKIM_CANON_SIMPLE:
447       default:                  return US"simple";
448       }
449
450   case DKIM_COPIEDHEADERS:
451     return dkim_cur_sig->copiedheaders
452       ? US dkim_cur_sig->copiedheaders : dkim_exim_expand_defaults(what);
453
454   case DKIM_CREATED:
455     return dkim_cur_sig->created > 0
456       ? string_sprintf("%lu", dkim_cur_sig->created)
457       : dkim_exim_expand_defaults(what);
458
459   case DKIM_EXPIRES:
460     return dkim_cur_sig->expires > 0
461       ? string_sprintf("%lu", dkim_cur_sig->expires)
462       : dkim_exim_expand_defaults(what);
463
464   case DKIM_HEADERNAMES:
465     return dkim_cur_sig->headernames
466       ? dkim_cur_sig->headernames : dkim_exim_expand_defaults(what);
467
468   case DKIM_IDENTITY:
469     return dkim_cur_sig->identity
470       ? US dkim_cur_sig->identity : dkim_exim_expand_defaults(what);
471
472   case DKIM_KEY_GRANULARITY:
473     return dkim_cur_sig->pubkey
474       ? dkim_cur_sig->pubkey->granularity
475       ? US dkim_cur_sig->pubkey->granularity
476       : dkim_exim_expand_defaults(what)
477       : dkim_exim_expand_defaults(what);
478
479   case DKIM_KEY_SRVTYPE:
480     return dkim_cur_sig->pubkey
481       ? dkim_cur_sig->pubkey->srvtype
482       ? US dkim_cur_sig->pubkey->srvtype
483       : dkim_exim_expand_defaults(what)
484       : dkim_exim_expand_defaults(what);
485
486   case DKIM_KEY_NOTES:
487     return dkim_cur_sig->pubkey
488       ? dkim_cur_sig->pubkey->notes
489       ? US dkim_cur_sig->pubkey->notes
490       : dkim_exim_expand_defaults(what)
491       : dkim_exim_expand_defaults(what);
492
493   case DKIM_KEY_TESTING:
494     return dkim_cur_sig->pubkey
495       ? dkim_cur_sig->pubkey->testing
496       ? US"1"
497       : dkim_exim_expand_defaults(what)
498       : dkim_exim_expand_defaults(what);
499
500   case DKIM_NOSUBDOMAINS:
501     return dkim_cur_sig->pubkey
502       ? dkim_cur_sig->pubkey->no_subdomaining
503       ? US"1"
504       : dkim_exim_expand_defaults(what)
505       : dkim_exim_expand_defaults(what);
506
507   case DKIM_VERIFY_STATUS:
508     switch (dkim_cur_sig->verify_status)
509       {
510       case PDKIM_VERIFY_INVALID:        return US"invalid";
511       case PDKIM_VERIFY_FAIL:           return US"fail";
512       case PDKIM_VERIFY_PASS:           return US"pass";
513       case PDKIM_VERIFY_NONE:
514       default:                          return US"none";
515       }
516
517   case DKIM_VERIFY_REASON:
518     switch (dkim_cur_sig->verify_ext_status)
519       {
520       case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE:
521                                                 return US"pubkey_unavailable";
522       case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD:return US"pubkey_dns_syntax";
523       case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT:  return US"pubkey_der_syntax";
524       case PDKIM_VERIFY_FAIL_BODY:              return US"bodyhash_mismatch";
525       case PDKIM_VERIFY_FAIL_MESSAGE:           return US"signature_incorrect";
526       }
527
528   default:
529     return US"";
530   }
531 }
532
533
534 /* Generate signatures for the given file, returning a string.
535 If a prefix is given, prepend it to the file for the calculations.
536 */
537
538 gstring *
539 dkim_exim_sign(int fd, off_t off, uschar * prefix,
540   struct ob_dkim * dkim, const uschar ** errstr)
541 {
542 const uschar * dkim_domain;
543 int sep = 0;
544 gstring * seen_doms = NULL;
545 pdkim_ctx ctx;
546 pdkim_signature * sig;
547 gstring * sigbuf;
548 int pdkim_rc;
549 int sread;
550 uschar buf[4096];
551 int save_errno = 0;
552 int old_pool = store_pool;
553 uschar * errwhen;
554
555 store_pool = POOL_MAIN;
556
557 pdkim_init_context(&ctx, dkim->dot_stuffed, &dkim_exim_query_dns_txt);
558
559 if (!(dkim_domain = expand_cstring(dkim->dkim_domain)))
560   /* expansion error, do not send message. */
561   { errwhen = US"dkim_domain"; goto expand_bad; }
562
563 /* Set $dkim_domain expansion variable to each unique domain in list. */
564
565 while ((dkim_signing_domain = string_nextinlist(&dkim_domain, &sep, NULL, 0)))
566   {
567   const uschar * dkim_sel;
568   int sel_sep = 0;
569
570   if (dkim_signing_domain[0] == '\0')
571     continue;
572
573   /* Only sign once for each domain, no matter how often it
574   appears in the expanded list. */
575
576   if (match_isinlist(dkim_signing_domain, CUSS &seen_doms,
577       0, NULL, NULL, MCL_STRING, TRUE, NULL) == OK)
578     continue;
579
580   seen_doms = string_append_listele(seen_doms, ':', dkim_signing_domain);
581
582   /* Set $dkim_selector expansion variable to each selector in list,
583   for this domain. */
584
585   if (!(dkim_sel = expand_string(dkim->dkim_selector)))
586   if (!(dkim_signing_selector = expand_string(dkim->dkim_selector)))
587     { errwhen = US"dkim_selector"; goto expand_bad; }
588
589   while ((dkim_signing_selector = string_nextinlist(&dkim_sel, &sel_sep,
590           NULL, 0)))
591     {
592     uschar * dkim_canon_expanded;
593     int pdkim_canon;
594     uschar * dkim_sign_headers_expanded = NULL;
595     uschar * dkim_private_key_expanded;
596     uschar * dkim_hash_expanded;
597     uschar * dkim_identity_expanded = NULL;
598
599     /* Get canonicalization to use */
600
601     dkim_canon_expanded = dkim->dkim_canon
602       ? expand_string(dkim->dkim_canon) : US"relaxed";
603     if (!dkim_canon_expanded)   /* expansion error, do not send message. */
604       { errwhen = US"dkim_canon"; goto expand_bad; }
605
606     if (Ustrcmp(dkim_canon_expanded, "relaxed") == 0)
607       pdkim_canon = PDKIM_CANON_RELAXED;
608     else if (Ustrcmp(dkim_canon_expanded, "simple") == 0)
609       pdkim_canon = PDKIM_CANON_SIMPLE;
610     else
611       {
612       log_write(0, LOG_MAIN,
613                  "DKIM: unknown canonicalization method '%s', defaulting to 'relaxed'.\n",
614                  dkim_canon_expanded);
615       pdkim_canon = PDKIM_CANON_RELAXED;
616       }
617
618     if (  dkim->dkim_sign_headers
619        && !(dkim_sign_headers_expanded = expand_string(dkim->dkim_sign_headers)))
620       { errwhen = US"dkim_sign_header"; goto expand_bad; }
621     /* else pass NULL, which means default header list */
622
623     /* Get private key to use. */
624
625     if (!(dkim_private_key_expanded = expand_string(dkim->dkim_private_key)))
626       { errwhen = US"dkim_private_key"; goto expand_bad; }
627
628     if (  Ustrlen(dkim_private_key_expanded) == 0
629        || Ustrcmp(dkim_private_key_expanded, "0") == 0
630        || Ustrcmp(dkim_private_key_expanded, "false") == 0
631        )
632       continue;         /* don't sign, but no error */
633
634     if (dkim_private_key_expanded[0] == '/')
635       {
636       int privkey_fd, off = 0, len;
637
638       /* Looks like a filename, load the private key. */
639
640       memset(big_buffer, 0, big_buffer_size);
641
642       if ((privkey_fd = open(CS dkim_private_key_expanded, O_RDONLY)) < 0)
643         {
644         log_write(0, LOG_MAIN | LOG_PANIC, "unable to open "
645                    "private key file for reading: %s",
646                    dkim_private_key_expanded);
647         goto bad;
648         }
649
650       do
651         {
652         if ((len = read(privkey_fd, big_buffer + off, big_buffer_size - 2 - off)) < 0)
653           {
654           (void) close(privkey_fd);
655           log_write(0, LOG_MAIN|LOG_PANIC, "unable to read private key file: %s",
656                      dkim_private_key_expanded);
657           goto bad;
658           }
659         off += len;
660         }
661       while (len > 0);
662
663       (void) close(privkey_fd);
664       big_buffer[off] = '\0';
665       dkim_private_key_expanded = big_buffer;
666       }
667
668     if (!(dkim_hash_expanded = expand_string(dkim->dkim_hash)))
669       { errwhen = US"dkim_hash"; goto expand_bad; }
670
671     if (dkim->dkim_identity)
672       if (!(dkim_identity_expanded = expand_string(dkim->dkim_identity)))
673         { errwhen = US"dkim_identity"; goto expand_bad; }
674       else if (!*dkim_identity_expanded)
675         dkim_identity_expanded = NULL;
676
677   /*XXX so we currently nail signing to RSA + this hash.
678   Need to extract algo from privkey and check for disallowed combos. */
679
680     if (!(sig = pdkim_init_sign(&ctx, dkim_signing_domain,
681                           dkim_signing_selector,
682                           dkim_private_key_expanded,
683                           dkim_hash_expanded,
684                           errstr
685                           )))
686       goto bad;
687     dkim_private_key_expanded[0] = '\0';
688
689     pdkim_set_optional(sig,
690                         CS dkim_sign_headers_expanded,
691                         CS dkim_identity_expanded,
692                         pdkim_canon,
693                         pdkim_canon, -1, 0, 0);
694
695     if (!ctx.sig)               /* link sig to context chain */
696       ctx.sig = sig;
697     else
698       {
699       pdkim_signature * n = ctx.sig;
700       while (n->next) n = n->next;
701       n->next = sig;
702       }
703     }
704   }
705
706 if (prefix)
707   pdkim_feed(&ctx, prefix, Ustrlen(prefix));
708
709 if (lseek(fd, off, SEEK_SET) < 0)
710   sread = -1;
711 else
712   while ((sread = read(fd, &buf, sizeof(buf))) > 0)
713     if ((pdkim_rc = pdkim_feed(&ctx, buf, sread)) != PDKIM_OK)
714       goto pk_bad;
715
716 /* Handle failed read above. */
717 if (sread == -1)
718   {
719   debug_printf("DKIM: Error reading -K file.\n");
720   save_errno = errno;
721   goto bad;
722   }
723
724 /* Build string of headers, one per signature */
725
726 if ((pdkim_rc = pdkim_feed_finish(&ctx, &sig, errstr)) != PDKIM_OK)
727   goto pk_bad;
728
729 for (sigbuf = NULL; sig; sig = sig->next)
730   sigbuf = string_append(sigbuf, 2, US sig->signature_header, US"\r\n");
731
732 (void) string_from_gstring(sigbuf);
733
734 CLEANUP:
735   store_pool = old_pool;
736   errno = save_errno;
737   return sigbuf;
738
739 pk_bad:
740   log_write(0, LOG_MAIN|LOG_PANIC,
741                 "DKIM: signing failed: %.100s", pdkim_errstr(pdkim_rc));
742 bad:
743   sigbuf = NULL;
744   goto CLEANUP;
745
746 expand_bad:
747   log_write(0, LOG_MAIN | LOG_PANIC, "failed to expand %s: %s",
748               errwhen, expand_string_message);
749   goto bad;
750 }
751
752 # endif /*!MACRO_PREDEF*/
753 #endif  /*!DISABLE_DKIM*/