diff options
Diffstat (limited to 'sqmail-4.3.07/src/spfdnsip.c')
-rwxr-xr-x | sqmail-4.3.07/src/spfdnsip.c | 406 |
1 files changed, 0 insertions, 406 deletions
diff --git a/sqmail-4.3.07/src/spfdnsip.c b/sqmail-4.3.07/src/spfdnsip.c deleted file mode 100755 index e9cf9ee..0000000 --- a/sqmail-4.3.07/src/spfdnsip.c +++ /dev/null @@ -1,406 +0,0 @@ -#include <unistd.h> -#include "stralloc.h" -#include "alloc.h" -#include "ip.h" -#include "ipalloc.h" -#include "ipme.h" -#include "str.h" -#include "fmt.h" -#include "scan.h" -#include "byte.h" -#include "now.h" -#include "dns.h" -#include "case.h" -#include "spf.h" - -// shared by spf.c + spfdnsip.c - -extern stralloc dnsname; -extern char ip4remote[4]; -extern char ip6remote[16]; -extern int flagip6; - -/** - @brief match_ip - compares IPv4/IPv6 addreses up to prefix length - @param input: ip_address1,prefix length, ip_address2 - @return 1 ok; 0 failure - */ - -int match_ip4(unsigned char ip1[4],int prefix,char ip2[4]) -{ - stralloc iptest1 = {0}; - stralloc iptest2 = {0}; - - if (flagip6) return 0; - - if (ip4_bytestring(&iptest1,ip1,prefix) == prefix) - if (ip4_bytestring(&iptest2,ip2,prefix) == prefix) - if (byte_diff(iptest1.s,prefix,iptest2.s)) return 0; - - return 1; -} - -int match_ip6(unsigned char ip1[16],int prefix,char ip2[16]) -{ - stralloc iptest1 = {0}; - stralloc iptest2 = {0}; - - if (!flagip6) return 0; - - if (ip6_bytestring(&iptest1,ip1,prefix) == prefix) - if (ip6_bytestring(&iptest2,ip2,prefix) == prefix) - if (byte_diff(iptest1.s,prefix,iptest2.s)) return 0; - - return 1; -} - -/** - @brief get_prefix - return integer value of prefix length - @param input: pointer to prefix - @return (int) length of prefix - */ - -int get_prefix(char *prefix) -{ - unsigned long r; - int pos; - - if (!prefix || *prefix == '0') { - if (flagip6 == 0) return 32; - if (flagip6 == 1) return 128; - } - - pos = scan_ulong(prefix,&r); - if (!pos || (prefix[pos] && !(prefix[pos] == '/'))) return SPF_SYNTAX; - if (flagip6 == 0 && r > 32) return SPF_SYNTAX; - if (flagip6 == 1 && r > 128) return SPF_SYNTAX; - - return r; -} - -/* DNS Record: -------------------------------------- Fetch multiple SPF TXT RRs */ - -/** - @brief spf_records - get TXT records for domain and extract SPF information - @param input: pointer stralloc domain - output: pointer to stralloc spf records - @return SPF_OK, SPF_NONE; SPF_MULTIRR, SPF_DNSSOFT, SPF_NOMEM - */ - -int spf_records(stralloc *spfrec,stralloc *domain) -{ - static stralloc out = {0}; - static stralloc spf = {0}; - int i, k; - int begin; - int r = 0; - - begin = -1; - - DNS_INIT - r = dns_txt(&out,(const stralloc *)domain); - switch (r) { - case DNS_MEM: return SPF_NOMEM; - case DNS_ERR: return SPF_DNSSOFT; /* return 2main */ - case DNS_NXD: return SPF_NONE; - } - r = SPF_NONE; - - for (k = 0; k < out.len; ++k) { - if (case_starts(out.s + k,"v=spf1")) { - begin = k; - break; - } - } - - if (begin >= 0) { - if (case_starts(out.s + k + 6,"v=spf1")) return SPF_MULTIRR; /* return 2main */ - - if (!stralloc_copys(&spf,"")) return SPF_NOMEM; - for (i = begin; i < out.len; ++i) { - if (out.s[i] == '\r' || out.s[i] == '\n' || out.s[i] == '\0') break; - if (!stralloc_append(&spf,out.s + i)) return SPF_NOMEM; - } - if (!stralloc_0(&spf)) return SPF_NOMEM; - if (!stralloc_copys(spfrec,spf.s)) return SPF_NOMEM; - - r = SPF_OK; - } - - return r; -} - -/* Mechanisms: -------------------------------------- Lookup functions */ - -/** - @brief spf_a (a; a:fqdns; a:fqdns/56) - compares A + AAAA records for SPF info and client host - @param input: pointer to spfspecification, pointer to prefix - @return SPF_OK, SPF_NONE; SPF_DNSSOFT, SPF_NOMEM - */ - -int spf_a(char *spfspec,char *prefix) -{ - stralloc sa = {0}; - stralloc ip = {0}; - int ipprefix, r, j; - - ipprefix = get_prefix(prefix); - if (ipprefix < 0) return SPF_SYNTAX; - - if (!stralloc_copys(&sa,spfspec)) return SPF_NOMEM; - if (!stralloc_readyplus(&ip,0)) return SPF_NOMEM; - if (!spf_info("MA/AAAA=",spfspec)) return SPF_NOMEM; - - DNS_INIT - - switch (dns_ip4(&ip,&sa)) { - case DNS_MEM: return SPF_NOMEM; - case DNS_ERR: r = SPF_DNSSOFT; break; - case DNS_NXD: r = SPF_NONE; break; - default: - r = SPF_NONE; - for (j = 0; j + 4 <= ip.len; j += 4) - if (match_ip4(ip.s + j,ipprefix,ip4remote)) - return SPF_OK; - } - - switch (dns_ip6(&ip,&sa)) { - case DNS_MEM: return SPF_NOMEM; - case DNS_ERR: r = SPF_DNSSOFT; break; - case DNS_NXD: r = SPF_NONE; break; - default: - r = SPF_NONE; - for (j = 0; j + 16 <= ip.len; j += 16) - if (match_ip6(ip.s + j,ipprefix,ip6remote)) - return SPF_OK; - } - - return r; -} - -/** - @brief spf_mx (mx; mx:domain; mx:domain/24) - compares MX records for SPF info and client host - @param input: pointer to spfspecification, pointer to prefix - @return SPF_OK, SPF_NONE; SPF_DNSSOFT, SPF_NOMEM - */ - -int spf_mx(char *spfspec,char *prefix) -{ - stralloc sa = {0}; - ipalloc ia = {0}; - unsigned long random; - int ipprefix; - int j, r; - - ipprefix = get_prefix(prefix); - if (ipprefix < 0) return SPF_SYNTAX; - - random = now() + (getpid() << 16); - - if (!stralloc_copys(&sa,spfspec)) return SPF_NOMEM; - if (!spf_info("MMX=",spfspec)) return SPF_NOMEM; - - switch (dns_mxip(&ia,&sa,random)) { - case DNS_MEM: return SPF_NOMEM; - case DNS_ERR: return SPF_DNSSOFT; - default: - r = SPF_NONE; - for (j = 0; j < ia.len; ++j) { - if (byte_diff(ip6remote,16,V6localnet) && !ip6_isv4mapped(ip6remote)) { - if (match_ip6(&ia.ix[j].addr.ip6.d,ipprefix,ip6remote)) - return SPF_OK; - } - if (byte_diff(ip4remote,4,V4localnet)) { - if (match_ip4(&ia.ix[j].addr.ip4.d,ipprefix,ip4remote)) - return SPF_OK; - } - } - } - - return r; -} - -/** - @brief spf_ptr (ptr; ptr:fqdn) - compares PTR records from SPF info and client host - @param input: pointer to spfspecification; prefix not used - @return SPF_OK, SPF_NONE; SPF_DNSSOFT, SPF_NOMEM - */ - -int spf_ptr(char *spfspec,char *prefix) -{ - stralloc fqdn = {0}; - stralloc out = {0}; - stralloc ip = {0}; - int slen = str_len(spfspec); - int rc, r; - int k = 0; - int pos; - int l = 0; - - /* we didn't find host with the matching IP before */ - if (dnsname.len == 7 && str_equal(dnsname.s,"unknown")) - return SPF_NONE; - - if (!spf_info("MPTR=",spfspec)) return SPF_NOMEM; - - /* the hostname found will probably be the same as before */ - while (dnsname.len) { - pos = dnsname.len - slen; - if (pos < 0) break; - if (pos > 0 && dnsname.s[pos - 1] != '.') break; - if (case_diffb(dnsname.s + pos,slen,spfspec)) break; - return SPF_OK; - } - - /* ok, either it's the first test or it's a very weired setup - Assumptions: - ip -> inverse DNS name (only one!) - inverse DNS name -> (same) ip (only one!) - */ - - - if (!stralloc_readyplus(&fqdn,255)) return SPF_NOMEM; - if (!stralloc_readyplus(&out,255)) return SPF_NOMEM; - if (!stralloc_readyplus(&ip,32)) return SPF_NOMEM; - - if (flagip6) { - rc = dns_name6(&out,ip6remote); // usually: 2. . .ip6.addr => only one - switch (rc) { - case DNS_MEM: return SPF_NOMEM; - case DNS_COM: r = SPF_DNSSOFT; break; - case DNS_ERR: r = SPF_NONE; break; - case DNS_NXD: r = SPF_NONE; break; - default: r = SPF_NONE; l++; - if (l > LOOKUP_LIMIT) { r = SPF_ERROR; break; } - switch (dns_ip6(&ip,&out)) { // theoretical more IPs cound be retrieved - case DNS_MEM: return SPF_NOMEM; - case DNS_ERR: r = SPF_DNSSOFT; break; - case DNS_NXD: r = SPF_NONE; break; - default: r = SPF_NONE; - for (k = 0; k + 16 <= ip.len; k += 16) { - if (k > 32 * LOOKUP_LIMIT) { r = SPF_ERROR; break; } - if (match_ip6(ip.s + k,128,ip6remote)) { - if (!dnsname.len) - if (!stralloc_copy(&dnsname,&out)) return SPF_NOMEM; - pos = out.len - slen; - if (pos < 0) continue; - if (pos > 0 && out.s[pos - 1] != '.') continue; - if (case_diffb(out.s + pos,slen,spfspec)) continue; - - if (!stralloc_copy(&dnsname,&out)) return SPF_NOMEM; - r = SPF_OK; - } - } - } - } - } else { // IP4 branch - rc = dns_name4(&out,ip4remote); // usual answer: d.c.b.e.in-arpa.addr for IP4 a.b.c.d => only one - switch (rc) { - case DNS_MEM: return SPF_NOMEM; - case DNS_ERR: r = SPF_DNSSOFT; break; - case DNS_NXD: r = SPF_NONE; break; - default: r = SPF_NONE; l++; - if (l > LOOKUP_LIMIT) { r = SPF_ERROR; break; } - switch (dns_ip4(&ip,&out)) { - case DNS_MEM: return SPF_NOMEM; - case DNS_ERR: r = SPF_DNSSOFT; break; - case DNS_NXD: r = SPF_NONE; break; - default: r = SPF_NONE; - for (k = 0; k + 4 <= ip.len; k += 4) { - if (k > 32 * LOOKUP_LIMIT) { r = SPF_ERROR; break; } - if (match_ip4(ip.s + k,32,ip4remote)) { - if (!dnsname.len) - if (!stralloc_copy(&dnsname,&out)) return SPF_NOMEM; - pos = out.len - slen; - if (pos < 0) continue; - if (pos > 0 && out.s[pos - 1] != '.') continue; - if (case_diffb(out.s + pos,slen,spfspec)) continue; - - if (!stralloc_copy(&dnsname,&out)) return SPF_NOMEM; - r = SPF_OK; - } - } - } - } - } - if (!dnsname.len) - if (!stralloc_copys(&dnsname,"unknown")) return SPF_NOMEM; - - return r; -} - -/** - @brief spf_ip4 (ip4; ip4:fqdn; ip4:fqdn/24) - compares A records for SPF info and client host - @param input: pointer to spfspecification, pointer to prefix - @return SPF_OK, SPF_NONE; SPF_DNSSOFT, SPF_NOMEM - */ - -int spf_ip4(char *spfspec,char *prefix) -{ - char spfip[4]; - - if (flagip6) return SPF_NONE; - int ipprefix = get_prefix(prefix); - - if (ipprefix < 0) return SPF_SYNTAX; - if (!ip4_scan(spfspec,spfip)) return SPF_SYNTAX; - - if (!spf_info("MIPv4=",spfspec)) return SPF_NOMEM; - if (!match_ip4(spfip,ipprefix,ip4remote)) return SPF_NONE; - - return SPF_OK; -} - -/** - @brief spf_ip6 (ip6; ip6:fqdn; ip6:fqdn/56) - compares AAAA records for SPF info and client host - @param input: pointer to spfspecification, pointer to prefix - @return SPF_OK, SPF_NONE; SPF_DNSSOFT, SPF_NOMEM - */ - -int spf_ip6(char *spfspec,char *prefix) -{ - char spfip[16]; - - if (!flagip6) return SPF_NONE; - int ipprefix = get_prefix(prefix); - - if (ipprefix < 0) return SPF_SYNTAX; - if (!ip6_scan(spfspec,spfip)) return SPF_SYNTAX; - - if (!spf_info("MIPv6=",spfspec)) return SPF_NOMEM; - if (!match_ip6(spfip,ipprefix,ip6remote)) return SPF_NONE; - - return SPF_OK; -} - -/** - @brief spf_exists (exists; exists:fqdn) - simply looks for a A records only for SPF info and client host - @param input: pointer to spfspecification, prefix not used - @return SPF_OK, SPF_NONE; SPF_DNSSOFT, SPF_NOMEM - */ - -int spf_exists(char *spfspec,char *prefix) -{ - stralloc sa = {0}; - stralloc ip = {0}; - - if (!stralloc_copys(&sa,spfspec)) return SPF_NOMEM; - if (!spf_info("MExists=",spfspec)) return SPF_NOMEM; - - switch (dns_ip4(&ip,&sa)) { - case DNS_MEM: return SPF_NOMEM; - case DNS_ERR: return SPF_DNSSOFT; - case DNS_NXD: return SPF_NONE; - default: return SPF_OK; - } - -} |