Mercurial > notdcc
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 } |