+if (final)
+ {
+ base64_b = pdkim_encode_base64(&sig->sighash);
+ hdr = pdkim_headcat(&col, hdr, US";", US"b=", base64_b);
+
+ /* add trailing semicolon: I'm not sure if this is actually needed */
+ hdr = pdkim_headcat(&col, hdr, NULL, US";", US"");
+ }
+else
+ {
+ /* To satisfy the rule "all surrounding whitespace [...] deleted"
+ ( RFC 6376 section 3.7 ) we ensure there is no whitespace here. Otherwise
+ the headcat routine could insert a linebreak which the relaxer would reduce
+ to a single space preceding the terminating semicolon, resulting in an
+ incorrect header-hash. */
+ hdr = pdkim_headcat(&col, hdr, US";", US"b=;", US"");
+ }
+
+return string_from_gstring(hdr);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+static pdkim_pubkey *
+pdkim_key_from_dns(pdkim_ctx * ctx, pdkim_signature * sig, ev_ctx * vctx,
+ const uschar ** errstr)
+{
+uschar * dns_txt_name, * dns_txt_reply;
+pdkim_pubkey * p;
+
+/* Fetch public key for signing domain, from DNS */
+
+dns_txt_name = string_sprintf("%s._domainkey.%s.", sig->selector, sig->domain);
+
+dns_txt_reply = store_get(PDKIM_DNS_TXT_MAX_RECLEN);
+memset(dns_txt_reply, 0, PDKIM_DNS_TXT_MAX_RECLEN);
+
+if ( ctx->dns_txt_callback(CS dns_txt_name, CS dns_txt_reply) != PDKIM_OK
+ || dns_txt_reply[0] == '\0'
+ )
+ {
+ sig->verify_status = PDKIM_VERIFY_INVALID;
+ sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE;
+ return NULL;
+ }
+
+DEBUG(D_acl)
+ {
+ debug_printf(
+ "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
+ " %s\n"
+ " Raw record: ",
+ dns_txt_name);
+ pdkim_quoteprint(CUS dns_txt_reply, Ustrlen(dns_txt_reply));
+ }