+ while ((dkim_signing_selector = string_nextinlist(&dkim_sel, &sel_sep,
+ NULL, 0)))
+ {
+ uschar * dkim_canon_expanded;
+ int pdkim_canon;
+ uschar * dkim_sign_headers_expanded = NULL;
+ uschar * dkim_private_key_expanded;
+ uschar * dkim_hash_expanded;
+
+ /* Get canonicalization to use */
+
+ dkim_canon_expanded = dkim->dkim_canon
+ ? expand_string(dkim->dkim_canon) : US"relaxed";
+ if (!dkim_canon_expanded)
+ {
+ /* expansion error, do not send message. */
+ log_write(0, LOG_MAIN | LOG_PANIC, "failed to expand "
+ "dkim_canon: %s", expand_string_message);
+ goto bad;
+ }
+
+ if (Ustrcmp(dkim_canon_expanded, "relaxed") == 0)
+ pdkim_canon = PDKIM_CANON_RELAXED;
+ else if (Ustrcmp(dkim_canon_expanded, "simple") == 0)
+ pdkim_canon = PDKIM_CANON_SIMPLE;
+ else
+ {
+ log_write(0, LOG_MAIN,
+ "DKIM: unknown canonicalization method '%s', defaulting to 'relaxed'.\n",
+ dkim_canon_expanded);
+ pdkim_canon = PDKIM_CANON_RELAXED;
+ }
+
+ if (dkim->dkim_sign_headers)
+ if (!(dkim_sign_headers_expanded = expand_string(dkim->dkim_sign_headers)))
+ {
+ log_write(0, LOG_MAIN | LOG_PANIC, "failed to expand "
+ "dkim_sign_headers: %s", expand_string_message);
+ goto bad;
+ }
+ /* else pass NULL, which means default header list */
+
+ /* Get private key to use. */
+
+ if (!(dkim_private_key_expanded = expand_string(dkim->dkim_private_key)))
+ {
+ log_write(0, LOG_MAIN | LOG_PANIC, "failed to expand "
+ "dkim_private_key: %s", expand_string_message);
+ goto bad;
+ }
+
+ if ( Ustrlen(dkim_private_key_expanded) == 0
+ || Ustrcmp(dkim_private_key_expanded, "0") == 0
+ || Ustrcmp(dkim_private_key_expanded, "false") == 0
+ )
+ continue; /* don't sign, but no error */
+
+ if (dkim_private_key_expanded[0] == '/')
+ {
+ int privkey_fd, off = 0, len;
+
+ /* Looks like a filename, load the private key. */
+
+ memset(big_buffer, 0, big_buffer_size);
+
+ if ((privkey_fd = open(CS dkim_private_key_expanded, O_RDONLY)) < 0)
+ {
+ log_write(0, LOG_MAIN | LOG_PANIC, "unable to open "
+ "private key file for reading: %s",
+ dkim_private_key_expanded);
+ goto bad;
+ }
+
+ do
+ {
+ if ((len = read(privkey_fd, big_buffer + off, big_buffer_size - 2 - off)) < 0)
+ {
+ (void) close(privkey_fd);
+ log_write(0, LOG_MAIN|LOG_PANIC, "unable to read private key file: %s",
+ dkim_private_key_expanded);
+ goto bad;
+ }
+ off += len;
+ }
+ while (len > 0);
+
+ (void) close(privkey_fd);
+ big_buffer[off] = '\0';
+ dkim_private_key_expanded = big_buffer;
+ }
+
+ if (!(dkim_hash_expanded = expand_string(dkim->dkim_hash)))
+ {
+ log_write(0, LOG_MAIN | LOG_PANIC, "failed to expand "
+ "dkim_hash: %s", expand_string_message);
+ goto bad;
+ }
+
+ /*XXX so we currently nail signing to RSA + this hash.
+ Need to extract algo from privkey and check for disallowed combos. */
+
+ if (!(sig = pdkim_init_sign(&ctx, dkim_signing_domain,
+ dkim_signing_selector,
+ dkim_private_key_expanded,
+ dkim_hash_expanded,
+ errstr
+ )))
+ goto bad;
+ dkim_private_key_expanded[0] = '\0';
+
+ pdkim_set_optional(sig,
+ CS dkim_sign_headers_expanded,
+ NULL,
+ pdkim_canon,
+ pdkim_canon, -1, 0, 0);
+
+ if (!ctx.sig) /* link sig to context chain */
+ ctx.sig = sig;
+ else
+ {
+ pdkim_signature * n = ctx.sig;
+ while (n->next) n = n->next;
+ n->next = sig;
+ }