*************************************************/
/* SPF support.
+ Copyright (c) The Exim Maintainers 2015 - 2023
Copyright (c) Tom Kistner <tom@duncanthrax.net> 2004 - 2014
License: GPL
- Copyright (c) The Exim Maintainers 2015 - 2021
+ SPDX-License-Identifier: GPL-2.0-or-later
*/
/* Code for calling spf checks via libspf-alt. Called from acl.c. */
.hook = NULL, /* misc information */
.source = spf_dns_server
};
-int dns_rc;
DEBUG(D_receive) debug_printf("SPF_dns_exim_lookup '%s'\n", domain);
return spfrr;
}
-switch (dns_rc = dns_lookup(dnsa, US domain, rr_type, NULL))
+switch (dns_lookup(dnsa, US domain, rr_type, NULL))
{
- case DNS_SUCCEED: srr.herrno = NETDB_SUCCESS; break;
case DNS_AGAIN: srr.herrno = TRY_AGAIN; break;
case DNS_NOMATCH: srr.herrno = HOST_NOT_FOUND; break;
case DNS_NODATA: srr.herrno = NO_DATA; break;
case DNS_FAIL:
default: srr.herrno = NO_RECOVERY; break;
+ case DNS_SUCCEED:
+ srr.herrno = NETDB_SUCCESS;
+ for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr;
+ rr = dns_next_rr(dnsa, &dnss, RESET_NEXT))
+ /* Need to alloc space for all records, so no early-out */
+ if (rr->type == rr_type) found++;
+ break;
}
-for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr;
- rr = dns_next_rr(dnsa, &dnss, RESET_NEXT))
- if (rr->type == rr_type) found++;
-
if (found == 0)
{
SPF_dns_rr_dup(&spfrr, &srr);
switch(rr_type)
{
case T_MX:
+ if (rr->size < 2) continue;
s += 2; /* skip the MX precedence field */
case T_PTR:
{
gstring * g = NULL;
uschar chunk_len;
+ if (rr->size < 1+6) continue; /* min for version str */
if (strncmpic(rr->data+1, US SPF_VER_STR, 6) != 0)
{
HDEBUG(D_host_lookup) debug_printf("not an spf record: %.*s\n",
continue;
}
- for (int off = 0; off < rr->size; off += chunk_len)
+ /* require 1 byte for the chunk_len */
+ for (int off = 0; off < rr->size - 1; off += chunk_len)
{
- if (!(chunk_len = s[off++])) break;
+ if ( !(chunk_len = s[off++])
+ || rr->size < off + chunk_len /* ignore bogus size chunks */
+ ) break;
g = string_catn(g, s+off, chunk_len);
}
if (!g)
"", ns_t_any, 24 * 60 * 60, HOST_NOT_FOUND);
if (!spf_nxdomain)
{
- free(spf_dns_server);
+ store_free(spf_dns_server);
return NULL;
}
Return: OK/FAIL */
int
-spf_process(const uschar **listptr, uschar *spf_envelope_sender, int action)
+spf_process(const uschar ** listptr, const uschar * spf_envelope_sender,
+ int action)
{
int sep = 0;
const uschar *list = *listptr;
authres_spf(gstring * g)
{
uschar * s;
-if (!spf_result) return g;
-
-g = string_append(g, 2, US";\n\tspf=", spf_result);
-if (spf_result_guessed)
- g = string_cat(g, US" (best guess record for domain)");
+if (spf_result)
+ {
+ int start = 0; /* Compiler quietening */
+ DEBUG(D_acl) start = gstring_length(g);
-s = expand_string(US"$sender_address_domain");
-if (s && *s)
- return string_append(g, 2, US" smtp.mailfrom=", s);
+ g = string_append(g, 2, US";\n\tspf=", spf_result);
+ if (spf_result_guessed)
+ g = string_cat(g, US" (best guess record for domain)");
-s = sender_helo_name;
-return s && *s
- ? string_append(g, 2, US" smtp.helo=", s)
- : string_cat(g, US" smtp.mailfrom=<>");
+ s = expand_string(US"$sender_address_domain");
+ if (s && *s)
+ g = string_append(g, 2, US" smtp.mailfrom=", s);
+ else
+ {
+ s = sender_helo_name;
+ g = s && *s
+ ? string_append(g, 2, US" smtp.helo=", s)
+ : string_cat(g, US" smtp.mailfrom=<>");
+ }
+ DEBUG(D_acl) debug_printf("SPF:\tauthres '%.*s'\n",
+ gstring_length(g) - start - 3, g->s + start + 3);
+ }
+else
+ DEBUG(D_acl) debug_printf("SPF:\tno authres\n");
+return g;
}