comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:c7f6b056b673
1 /* Distributed Checksum Clearinghouse
2 *
3 * parse a named checksum
4 *
5 * Copyright (c) 2008 by Rhyolite Software, LLC
6 *
7 * This agreement is not applicable to any entity which sells anti-spam
8 * solutions to others or provides an anti-spam solution as part of a
9 * security solution sold to other entities, or to a private network
10 * which employs the DCC or uses data provided by operation of the DCC
11 * but does not provide corresponding data to other users.
12 *
13 * Permission to use, copy, modify, and distribute this software without
14 * changes for any purpose with or without fee is hereby granted, provided
15 * that the above copyright notice and this permission notice appear in all
16 * copies and any distributed versions or copies are either unchanged
17 * or not called anything similar to "DCC" or "Distributed Checksum
18 * Clearinghouse".
19 *
20 * Parties not eligible to receive a license under this agreement can
21 * obtain a commercial license to use DCC by contacting Rhyolite Software
22 * at sales@rhyolite.com.
23 *
24 * A commercial license would be for Distributed Checksum and Reputation
25 * Clearinghouse software. That software includes additional features. This
26 * free license for Distributed ChecksumClearinghouse Software does not in any
27 * way grant permision to use Distributed Checksum and Reputation Clearinghouse
28 * software
29 *
30 * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL
31 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
32 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC
33 * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
34 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
35 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
36 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
37 * SOFTWARE.
38 *
39 * Rhyolite Software DCC 1.3.103-1.67 $Revision$
40 */
41
42 #include "dcc_ck.h"
43 #include "dcc_xhdr.h"
44 #ifndef DCC_WIN32
45 #include <arpa/inet.h>
46 #endif
47
48 #define MAX_SERVER_CIDR_BITS 16 /* fix dcc.8 if this changes */
49
50
51 static int /* -1=fatal 0=problem */
52 dcc_host2ck(DCC_EMSG emsg, DCC_WF *wf,
53 const char *ck, /* this string of an IP address */
54 DCC_TGTS tgts, /* # of targets */
55 DCC_PARSED_CK_FNC fnc, /* do something with each checksum */
56 DCC_PARSED_CK_CIDR_FNC cidr_fnc)
57 {
58 int error;
59 DCC_FNM_LNO_BUF fnm_buf;
60 struct in6_addr addr6, mask6, *addr6p;
61 DCC_SUM sum;
62 DCC_SOCKU *sup;
63 int i, j, bits;
64
65 /* recognize xxx.xxx.xxx.xxx/y for IP address blocks
66 * as well as simple IP addresses */
67 bits = dcc_str2cidr(emsg, &addr6, &mask6, 0, ck,
68 wf_fnm(wf, wf->fno), wf->lno);
69 if (bits < 0)
70 return 0;
71
72 if (bits > 0) {
73 /* use client CIDR blocks if possible */
74 if (cidr_fnc)
75 return cidr_fnc(emsg, wf, bits, &addr6, &mask6, tgts);
76
77 /* This is for a server whitelist, because client whitelists
78 * come here with non-null cidr_fnc
79 * Allow only class-B sized blocks, because server whitelist
80 * entries for a CIDR block consist of one checksum per IP
81 * address in the CIDR block. A line in a whitelist file
82 * specifying a class-B block requires the addition of 65,536
83 * checksums to the server database. Instead, use whiteclnt
84 * entries. */
85 if (128-bits > MAX_SERVER_CIDR_BITS) {
86 dcc_pemsg(EX_NOHOST, emsg,
87 "CIDR block length in %s too large%s",
88 ck, wf_fnm_lno(&fnm_buf, wf));
89 return 0;
90 }
91
92 for (i = 1 << (128-bits); i > 0; --i) {
93 dcc_ck_ipv6(sum, &addr6);
94 j = fnc(emsg, wf, DCC_CK_IP, sum, tgts);
95 if (j <= 0)
96 return j;
97 addr6.s6_addr32[3] = ntohl(addr6.s6_addr32[3]);
98 ++addr6.s6_addr32[3];
99 addr6.s6_addr32[3] = htonl(addr6.s6_addr32[3]);
100 }
101 return 1;
102 }
103
104 /* we appear to have a host name,
105 * which is not allowed in a per-user whitelist */
106 if (wf->wf_flags & DCC_WF_PER_USER) {
107 dcc_pemsg(EX_NOHOST, emsg,
108 "hostname checksum illegal in per-user whitelist%s",
109 wf_fnm_lno(&fnm_buf, wf));
110 return 0;
111 }
112
113 if (wf->wtbl) /* need future host name resolutions */
114 wf->wtbl->hdr.flags |= DCC_WHITE_FG_HOSTNAMES;
115
116 memset(&addr6, 0, sizeof(addr6));
117 dcc_host_lock();
118 /* don't use SOCKS host name resolution because the host names that
119 * most need whitelisting are inside the SOCKS firewall and may not
120 * be known to outside DNS servers. */
121 if (!dcc_get_host(ck, 2, &error)) {
122 dcc_pemsg(EX_NOHOST, emsg,
123 "hostname \"%s\": %s%s",
124 ck, DCC_HSTRERROR(error),
125 wf_fnm_lno(&fnm_buf, wf));
126 dcc_host_unlock();
127 return 0;
128 }
129
130 for (sup = dcc_hostaddrs; sup < dcc_hostaddrs_end; ++sup) {
131 if (sup->sa.sa_family == AF_INET6) {
132 addr6p = &sup->ipv6.sin6_addr;
133 } else {
134 dcc_ipv4toipv6(&addr6, sup->ipv4.sin_addr);
135 addr6p = &addr6;
136 }
137 if (cidr_fnc) {
138 bits = 128;
139 dcc_bits2mask(&mask6, bits);
140 j = cidr_fnc(emsg, wf, bits, addr6p, &mask6, tgts);
141 } else {
142 dcc_ck_ipv6(sum, addr6p);
143 j = fnc(emsg, wf, DCC_CK_IP, sum, tgts);
144 }
145 if (j <= 0) {
146 dcc_host_unlock();
147 return j;
148 }
149 }
150 dcc_host_unlock();
151 return 1;
152 }
153
154
155
156 /* generate checksum value from the name of the checksum and a string */
157 int /* 1=ok 0=problem -1=fatal */
158 dcc_parse_ck(DCC_EMSG emsg, /* failure message here */
159 DCC_WF *wf,
160 const char *type_nm,
161 DCC_CK_TYPES type,
162 const char *str, /* ASCII string to generate checksum */
163 DCC_TGTS tgts, /* # of targets */
164 DCC_PARSED_CK_FNC add_fnc, /* do something with the checksum */
165 DCC_PARSED_CK_CIDR_FNC cidr_fnc)
166 {
167 DCC_FNM_LNO_BUF fnm_buf;
168 char *phdr, c, hdr_buf[80];
169 DCC_SUM sum;
170 const char *pstr;
171
172 /* compute the checksum */
173 switch (type) {
174 case DCC_CK_IP:
175 return dcc_host2ck(emsg, wf, str, tgts, add_fnc, cidr_fnc);
176
177 case DCC_CK_ENV_FROM:
178 case DCC_CK_FROM:
179 case DCC_CK_MESSAGE_ID:
180 case DCC_CK_RECEIVED:
181 case DCC_CK_ENV_TO:
182 dcc_str2ck(sum, 0, 0, str);
183 return add_fnc(emsg, wf, type, sum, tgts);
184
185 case DCC_CK_SUB:
186 str += strspn(str, DCC_WHITESPACE);
187 pstr = str;
188 phdr = hdr_buf;
189 for (;;) {
190 c = *pstr++;
191 if (c == '\0' || c == ':'
192 || DCC_IS_WHITE(c))
193 break;
194 c = DCC_TO_LOWER(c);
195 *phdr++ = c;
196 if (phdr >= &hdr_buf[sizeof(hdr_buf)]) {
197 dcc_pemsg(EX_DATAERR, emsg,
198 " imposible substitute header name"
199 " in \"%s\"%s",
200 str, wf_fnm_lno(&fnm_buf, wf));
201 return 0;
202 }
203 }
204 pstr += strspn(pstr, DCC_WHITESPACE);
205 if (*pstr == '\0' || phdr == hdr_buf) {
206 dcc_pemsg(EX_DATAERR, emsg,
207 " substitute header name absent in \"%s\"%s",
208 str, wf_fnm_lno(&fnm_buf, wf));
209 return 0;
210 }
211 dcc_str2ck(sum, hdr_buf, phdr-hdr_buf, pstr);
212 return add_fnc(emsg, wf, type, sum, tgts);
213
214 case DCC_CK_INVALID:
215 case DCC_CK_BODY:
216 case DCC_CK_FUZ1:
217 case DCC_CK_FUZ2:
218 case DCC_CK_G_MSG_R_TOTAL:
219 case DCC_CK_G_TRIPLE_R_BULK:
220 case DCC_CK_SRVR_ID:
221 break;
222 }
223
224 dcc_pemsg(EX_DATAERR, emsg, "unrecognized checksum type \"%s\"%s",
225 type_nm, wf_fnm_lno(&fnm_buf, wf));
226 return 0;
227 }
228
229
230
231 /* generate checksum value from the name of the checksum and hex values */
232 int /* 1=ok 0=syntax -1=fatal */
233 dcc_parse_hex_ck(DCC_EMSG emsg, /* failure message here */
234 DCC_WF *wf,
235 const char *type_nm,
236 DCC_CK_TYPES type,
237 const char *str, /* ASCII string to generate checksum */
238 DCC_TGTS tgts, /* # of targets */
239 DCC_PARSED_CK_FNC add_fnc) /* do something with the checksum */
240 {
241 union {
242 u_int32_t n[4];
243 DCC_SUM sum;
244 } u;
245 DCC_FNM_LNO_BUF fnm_buf;
246 int id;
247
248 if (type == DCC_CK_INVALID) {
249 dcc_pemsg(EX_DATAERR, emsg,
250 "unrecognized checksum type \"%s\"%s",
251 type_nm, wf_fnm_lno(&fnm_buf, wf));
252 return 0;
253 }
254
255 if (4 == sscanf(str, DCC_CKSUM_HEX_PAT"\n",
256 &u.n[0], &u.n[1], &u.n[2], &u.n[3])
257 || (type == DCC_CK_SUB
258 && 4 == sscanf(str, "%*s "DCC_CKSUM_HEX_PAT"\n",
259 &u.n[0], &u.n[1], &u.n[2], &u.n[3]))) {
260 /* recognize simple hex checksums */
261 u.n[0] = htonl(u.n[0]);
262 u.n[1] = htonl(u.n[1]);
263 u.n[2] = htonl(u.n[2]);
264 u.n[3] = htonl(u.n[3]);
265
266 } else if (1 == sscanf(str, DCC_XHDR_ID_SIMPLE" at %d", &id)
267 || 1 == sscanf(str, DCC_XHDR_ID_REP_OK" at %d", &id)
268 || 1 == sscanf(str, DCC_XHDR_ID_IGNORE" at %d", &id)
269 || 1 == sscanf(str, DCC_XHDR_ID_ROGUE" at %d", &id)) {
270 /* parse server-ID declarations */
271 memset(&u, 0, sizeof(u));
272 u.sum[0] = DCC_CK_SRVR_ID;
273 u.sum[1] = id >> 8;
274 u.sum[2] = id;
275
276 } else {
277 dcc_pemsg(EX_DATAERR, emsg,
278 "unrecognized checksum value \"%s\"%s",
279 str, wf_fnm_lno(&fnm_buf, wf));
280 return 0;
281 }
282
283 /* apply the function to the checksum */
284 return add_fnc(emsg, wf, type, u.sum, tgts);
285 }