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