Mercurial > notdcc
view dcclib/ckparse.c @ 3:b689077d4918
Ignore old patches
author | Peter Gervai <grin@grin.hu> |
---|---|
date | Tue, 10 Mar 2009 14:31:24 +0100 |
parents | c7f6b056b673 |
children |
line wrap: on
line source
/* Distributed Checksum Clearinghouse * * parse a named checksum * * Copyright (c) 2008 by Rhyolite Software, LLC * * This agreement is not applicable to any entity which sells anti-spam * solutions to others or provides an anti-spam solution as part of a * security solution sold to other entities, or to a private network * which employs the DCC or uses data provided by operation of the DCC * but does not provide corresponding data to other users. * * Permission to use, copy, modify, and distribute this software without * changes for any purpose with or without fee is hereby granted, provided * that the above copyright notice and this permission notice appear in all * copies and any distributed versions or copies are either unchanged * or not called anything similar to "DCC" or "Distributed Checksum * Clearinghouse". * * Parties not eligible to receive a license under this agreement can * obtain a commercial license to use DCC by contacting Rhyolite Software * at sales@rhyolite.com. * * A commercial license would be for Distributed Checksum and Reputation * Clearinghouse software. That software includes additional features. This * free license for Distributed ChecksumClearinghouse Software does not in any * way grant permision to use Distributed Checksum and Reputation Clearinghouse * software * * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * * Rhyolite Software DCC 1.3.103-1.67 $Revision$ */ #include "dcc_ck.h" #include "dcc_xhdr.h" #ifndef DCC_WIN32 #include <arpa/inet.h> #endif #define MAX_SERVER_CIDR_BITS 16 /* fix dcc.8 if this changes */ static int /* -1=fatal 0=problem */ dcc_host2ck(DCC_EMSG emsg, DCC_WF *wf, const char *ck, /* this string of an IP address */ DCC_TGTS tgts, /* # of targets */ DCC_PARSED_CK_FNC fnc, /* do something with each checksum */ DCC_PARSED_CK_CIDR_FNC cidr_fnc) { int error; DCC_FNM_LNO_BUF fnm_buf; struct in6_addr addr6, mask6, *addr6p; DCC_SUM sum; DCC_SOCKU *sup; int i, j, bits; /* recognize xxx.xxx.xxx.xxx/y for IP address blocks * as well as simple IP addresses */ bits = dcc_str2cidr(emsg, &addr6, &mask6, 0, ck, wf_fnm(wf, wf->fno), wf->lno); if (bits < 0) return 0; if (bits > 0) { /* use client CIDR blocks if possible */ if (cidr_fnc) return cidr_fnc(emsg, wf, bits, &addr6, &mask6, tgts); /* This is for a server whitelist, because client whitelists * come here with non-null cidr_fnc * Allow only class-B sized blocks, because server whitelist * entries for a CIDR block consist of one checksum per IP * address in the CIDR block. A line in a whitelist file * specifying a class-B block requires the addition of 65,536 * checksums to the server database. Instead, use whiteclnt * entries. */ if (128-bits > MAX_SERVER_CIDR_BITS) { dcc_pemsg(EX_NOHOST, emsg, "CIDR block length in %s too large%s", ck, wf_fnm_lno(&fnm_buf, wf)); return 0; } for (i = 1 << (128-bits); i > 0; --i) { dcc_ck_ipv6(sum, &addr6); j = fnc(emsg, wf, DCC_CK_IP, sum, tgts); if (j <= 0) return j; addr6.s6_addr32[3] = ntohl(addr6.s6_addr32[3]); ++addr6.s6_addr32[3]; addr6.s6_addr32[3] = htonl(addr6.s6_addr32[3]); } return 1; } /* we appear to have a host name, * which is not allowed in a per-user whitelist */ if (wf->wf_flags & DCC_WF_PER_USER) { dcc_pemsg(EX_NOHOST, emsg, "hostname checksum illegal in per-user whitelist%s", wf_fnm_lno(&fnm_buf, wf)); return 0; } if (wf->wtbl) /* need future host name resolutions */ wf->wtbl->hdr.flags |= DCC_WHITE_FG_HOSTNAMES; memset(&addr6, 0, sizeof(addr6)); dcc_host_lock(); /* don't use SOCKS host name resolution because the host names that * most need whitelisting are inside the SOCKS firewall and may not * be known to outside DNS servers. */ if (!dcc_get_host(ck, 2, &error)) { dcc_pemsg(EX_NOHOST, emsg, "hostname \"%s\": %s%s", ck, DCC_HSTRERROR(error), wf_fnm_lno(&fnm_buf, wf)); dcc_host_unlock(); return 0; } for (sup = dcc_hostaddrs; sup < dcc_hostaddrs_end; ++sup) { if (sup->sa.sa_family == AF_INET6) { addr6p = &sup->ipv6.sin6_addr; } else { dcc_ipv4toipv6(&addr6, sup->ipv4.sin_addr); addr6p = &addr6; } if (cidr_fnc) { bits = 128; dcc_bits2mask(&mask6, bits); j = cidr_fnc(emsg, wf, bits, addr6p, &mask6, tgts); } else { dcc_ck_ipv6(sum, addr6p); j = fnc(emsg, wf, DCC_CK_IP, sum, tgts); } if (j <= 0) { dcc_host_unlock(); return j; } } dcc_host_unlock(); return 1; } /* generate checksum value from the name of the checksum and a string */ int /* 1=ok 0=problem -1=fatal */ dcc_parse_ck(DCC_EMSG emsg, /* failure message here */ DCC_WF *wf, const char *type_nm, DCC_CK_TYPES type, const char *str, /* ASCII string to generate checksum */ DCC_TGTS tgts, /* # of targets */ DCC_PARSED_CK_FNC add_fnc, /* do something with the checksum */ DCC_PARSED_CK_CIDR_FNC cidr_fnc) { DCC_FNM_LNO_BUF fnm_buf; char *phdr, c, hdr_buf[80]; DCC_SUM sum; const char *pstr; /* compute the checksum */ switch (type) { case DCC_CK_IP: return dcc_host2ck(emsg, wf, str, tgts, add_fnc, cidr_fnc); case DCC_CK_ENV_FROM: case DCC_CK_FROM: case DCC_CK_MESSAGE_ID: case DCC_CK_RECEIVED: case DCC_CK_ENV_TO: dcc_str2ck(sum, 0, 0, str); return add_fnc(emsg, wf, type, sum, tgts); case DCC_CK_SUB: str += strspn(str, DCC_WHITESPACE); pstr = str; phdr = hdr_buf; for (;;) { c = *pstr++; if (c == '\0' || c == ':' || DCC_IS_WHITE(c)) break; c = DCC_TO_LOWER(c); *phdr++ = c; if (phdr >= &hdr_buf[sizeof(hdr_buf)]) { dcc_pemsg(EX_DATAERR, emsg, " imposible substitute header name" " in \"%s\"%s", str, wf_fnm_lno(&fnm_buf, wf)); return 0; } } pstr += strspn(pstr, DCC_WHITESPACE); if (*pstr == '\0' || phdr == hdr_buf) { dcc_pemsg(EX_DATAERR, emsg, " substitute header name absent in \"%s\"%s", str, wf_fnm_lno(&fnm_buf, wf)); return 0; } dcc_str2ck(sum, hdr_buf, phdr-hdr_buf, pstr); return add_fnc(emsg, wf, type, sum, tgts); case DCC_CK_INVALID: case DCC_CK_BODY: case DCC_CK_FUZ1: case DCC_CK_FUZ2: case DCC_CK_G_MSG_R_TOTAL: case DCC_CK_G_TRIPLE_R_BULK: case DCC_CK_SRVR_ID: break; } dcc_pemsg(EX_DATAERR, emsg, "unrecognized checksum type \"%s\"%s", type_nm, wf_fnm_lno(&fnm_buf, wf)); return 0; } /* generate checksum value from the name of the checksum and hex values */ int /* 1=ok 0=syntax -1=fatal */ dcc_parse_hex_ck(DCC_EMSG emsg, /* failure message here */ DCC_WF *wf, const char *type_nm, DCC_CK_TYPES type, const char *str, /* ASCII string to generate checksum */ DCC_TGTS tgts, /* # of targets */ DCC_PARSED_CK_FNC add_fnc) /* do something with the checksum */ { union { u_int32_t n[4]; DCC_SUM sum; } u; DCC_FNM_LNO_BUF fnm_buf; int id; if (type == DCC_CK_INVALID) { dcc_pemsg(EX_DATAERR, emsg, "unrecognized checksum type \"%s\"%s", type_nm, wf_fnm_lno(&fnm_buf, wf)); return 0; } if (4 == sscanf(str, DCC_CKSUM_HEX_PAT"\n", &u.n[0], &u.n[1], &u.n[2], &u.n[3]) || (type == DCC_CK_SUB && 4 == sscanf(str, "%*s "DCC_CKSUM_HEX_PAT"\n", &u.n[0], &u.n[1], &u.n[2], &u.n[3]))) { /* recognize simple hex checksums */ u.n[0] = htonl(u.n[0]); u.n[1] = htonl(u.n[1]); u.n[2] = htonl(u.n[2]); u.n[3] = htonl(u.n[3]); } else if (1 == sscanf(str, DCC_XHDR_ID_SIMPLE" at %d", &id) || 1 == sscanf(str, DCC_XHDR_ID_REP_OK" at %d", &id) || 1 == sscanf(str, DCC_XHDR_ID_IGNORE" at %d", &id) || 1 == sscanf(str, DCC_XHDR_ID_ROGUE" at %d", &id)) { /* parse server-ID declarations */ memset(&u, 0, sizeof(u)); u.sum[0] = DCC_CK_SRVR_ID; u.sum[1] = id >> 8; u.sum[2] = id; } else { dcc_pemsg(EX_DATAERR, emsg, "unrecognized checksum value \"%s\"%s", str, wf_fnm_lno(&fnm_buf, wf)); return 0; } /* apply the function to the checksum */ return add_fnc(emsg, wf, type, u.sum, tgts); }