Mercurial > notdcc
diff dcclib/ckparse.c @ 0:c7f6b056b673
First import of vendor version
author | Peter Gervai <grin@grin.hu> |
---|---|
date | Tue, 10 Mar 2009 13:49:58 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcclib/ckparse.c Tue Mar 10 13:49:58 2009 +0100 @@ -0,0 +1,285 @@ +/* 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); +}