0
|
1 /* Distributed Checksum Clearinghouse |
|
2 * |
|
3 * checksum routines |
|
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.182 $Revision$ |
|
40 */ |
|
41 |
|
42 #ifndef DCC_CK_H |
|
43 #define DCC_CK_H |
|
44 |
|
45 #include "dcc_clnt.h" |
|
46 #include "dcc_md5.h" |
|
47 |
|
48 |
|
49 typedef DCC_TGTS DCC_CKSUM_THOLDS[DCC_DIM_CKS]; |
|
50 #define DCC_THOLD_NEVER (DCC_TGTS_TOO_MANY+1) |
|
51 #define DCC_THOLD_UNSET (DCC_TGTS_INVALID) |
|
52 |
|
53 extern DCC_CKSUM_THOLDS dcc_tholds_rej; |
|
54 |
|
55 |
|
56 /* MIME boundary |
|
57 * RFC 1341 says boundaries can be 70 bytes, but handle non-conformant spam */ |
|
58 #define DCC_CK_BND_MAX 94 |
|
59 #define DCC_CK_BND_DIM (DCC_CK_BND_MAX+2) /* including leading -- */ |
|
60 #define DCC_CK_BND_MISS (DCC_CK_BND_DIM+1) |
|
61 typedef struct { |
|
62 u_char bnd_len; /* length including leading "--" */ |
|
63 u_char cmp_len; /* compared so far */ |
|
64 char bnd[DCC_CK_BND_DIM]; /* "--"boundary */ |
|
65 } DCC_CK_BND; |
|
66 |
|
67 |
|
68 typedef u_char DCC_CK_FC[256]; |
|
69 extern const DCC_CK_FC dcc_cset_1, dcc_cset_2; |
|
70 |
|
71 /* state machine for ignoring parts of URLs */ |
|
72 typedef struct { |
|
73 enum { |
|
74 DCC_URL_ST_IDLE, /* waiting for H or = */ |
|
75 DCC_URL_ST_QUOTE, /* " " '"' or 'H' after = */ |
|
76 DCC_URL_ST_QH, /* " " H after quote */ |
|
77 DCC_URL_ST_T1, /* " " T */ |
|
78 DCC_URL_ST_T2, /* " " T */ |
|
79 DCC_URL_ST_P, /* " " P */ |
|
80 DCC_URL_ST_S, /* " " [S] */ |
|
81 DCC_URL_ST_COLON, /* " " : */ |
|
82 DCC_URL_ST_SLASH1, /* " " / */ |
|
83 DCC_URL_ST_SLASH2, /* " " / */ |
|
84 DCC_URL_ST_SLASH3_START, |
|
85 DCC_URL_ST_SLASH3, /* " " third / */ |
|
86 DCC_URL_ST_SKIP /* skipping rest of URL */ |
|
87 } st; |
|
88 char *start; /* start of hostname in URL */ |
|
89 char *dot; /* last '.' in hostname */ |
|
90 int total; /* length of URL */ |
|
91 u_char flags; |
|
92 # define DCC_URL_QUOTED 0x01 |
|
93 # define DCC_URL_DEL_DOMAIN 0x02 /* waiting for domain to delete */ |
|
94 # define DCC_URL_PERCENT1 0x04 /* waiting for 1st digit after % */ |
|
95 # define DCC_URL_PERCENT2 0x08 /* waiting for 2nd digit after % */ |
|
96 # define DCC_URL_SQUOTED 0x10 /* single quoted (') URL */ |
|
97 # define DCC_URL_DQUOTED 0x20 /* double quoted (") URL */ |
|
98 # define DCC_URL_QUOTES (DCC_URL_DQUOTED | DCC_URL_SQUOTED) |
|
99 # define DCC_URL_SIMPLE (DCC_URL_DEL_DOMAIN \ |
|
100 | DCC_URL_PERCENT1 \ |
|
101 | DCC_URL_PERCENT2) |
|
102 u_char percent; |
|
103 } DCC_URL_SKIP; |
|
104 #define DCC_URL_MAX 65 /* 63 is RFC 1034 limit on labels */ |
|
105 #define DCC_URL_FAILSAFE 2000 /* big bogus "username:password@" */ |
|
106 |
|
107 |
|
108 /* a template for generating a reply to an SMTP command */ |
|
109 typedef enum { |
|
110 REPLY_TPLT_NULL, |
|
111 REPLY_TPLT_ID, /* queue ID for sendmail, fake for dccifd */ |
|
112 REPLY_TPLT_CIP, /* SMTP client IP address */ |
|
113 REPLY_TPLT_BTYPE, /* type of DNSBL hit */ |
|
114 REPLY_TPLT_BTGT, /* DNSBL hit IP address or name */ |
|
115 REPLY_TPLT_BPROBE, /* DNSBL probe domain name */ |
|
116 REPLY_TPLT_BRESULT /* DNSBL probe result */ |
|
117 } REPLY_TPLT_ARGS; |
|
118 typedef struct { |
|
119 const char *log_result; /* "reject" etc. for log */ |
|
120 # define NUM_REPLY_TPLT_ARGS 6 |
|
121 REPLY_TPLT_ARGS args[NUM_REPLY_TPLT_ARGS]; |
|
122 char rcode[sizeof("5yz")]; |
|
123 char xcode[sizeof("1.2.3")]; |
|
124 u_char is_pat; /* template has %s references */ |
|
125 # define REPLY_BUF_LEN 256 |
|
126 char pat[REPLY_BUF_LEN]; /* pattern for SMTP message */ |
|
127 } REPLY_TPLT; |
|
128 |
|
129 |
|
130 /* specify a DNS blacklist */ |
|
131 typedef struct { |
|
132 char c[DCC_MAXDOMAINLEN]; /* null terminated */ |
|
133 } DNSBL_DOM; |
|
134 |
|
135 typedef u_char DNSBL_FGS; |
|
136 #define DNSBL_FG_DUP 0x01 /* duplicate blacklist */ |
|
137 #define DNSBL_FG_TIMEO 0x02 /* suffered a timeout */ |
|
138 #define DNSBL_FG_TFAIL 0x04 /* want SMTP failure on timeout */ |
|
139 #define DNSBL_FG_CLIENT 0x08 /* check client IP address */ |
|
140 #define DNSBL_FG_MAIL_HOST 0x10 /* check env_from domain */ |
|
141 #define DNSBL_FG_URL 0x20 /* check URLs in message body */ |
|
142 #define DNSBL_FG_MX 0x40 /* MX for _URL & _MAIL_HOST */ |
|
143 #define DNSBL_FG_NS 0x80 /* NS for _URL & _MAIL_HOST */ |
|
144 # define DNSBL_FG_HITS (DNSBL_FG_CLIENT | DNSBL_FG_MAIL_HOST | DNSBL_FG_URL) |
|
145 # define DNSBL_FG_TYPES (DNSBL_FG_HITS | DNSBL_FG_MX | DNSBL_FG_NS) |
|
146 # define DNSBL_FG_DEFAULT DNSBL_FG_TYPES |
|
147 |
|
148 typedef enum DNSBL_TYPE { |
|
149 DNSBL_TYPE_IPV4, |
|
150 DNSBL_TYPE_IPV6, |
|
151 DNSBL_TYPE_NAME |
|
152 } DNSBL_TYPE; |
|
153 |
|
154 #define MAX_DNSBL_GROUPS 3 |
|
155 typedef u_char DNSBL_GBITS; |
|
156 #define DNSBL_G2B(n) ((1<<(n)) & ((2<<MAX_DNSBL_GROUPS)-1)) |
|
157 |
|
158 typedef struct dnsbl { |
|
159 struct dnsbl *fwd; |
|
160 struct dnsbl *dup; /* same except result */ |
|
161 u_char group; /* 1-indexed */ |
|
162 struct in6_addr tgt; /* hit if DNSBL matches this block */ |
|
163 struct in6_addr tgt_mask; |
|
164 u_char tgt_use_ipv6; /* ipv4 vs. ipv6 result weighting */ |
|
165 DNSBL_TYPE bl_type; |
|
166 int bl_num; |
|
167 int bl_dom_len; |
|
168 DNSBL_DOM bl_dom; |
|
169 const REPLY_TPLT *reply; |
|
170 DNSBL_FGS fgs; |
|
171 } DNSBL; |
|
172 |
|
173 /* working storage for one set of DNSBLs */ |
|
174 typedef struct { |
|
175 DNSBL_FGS fgs; /* kind of DNSBL hit */ |
|
176 const char *btype; /* type of hit string */ |
|
177 const DNSBL *dnsbl; /* hit DNSBL */ |
|
178 char btype_buf[64]; |
|
179 char result[DCC_SU2STR_SIZE]; /* IP address found in DNSBL */ |
|
180 DNSBL_DOM tgt; /* IP address or name sought in DNSBL */ |
|
181 DNSBL_DOM probe; /* what was actually looked up */ |
|
182 } DNSBL_GROUP; |
|
183 |
|
184 /* working storage for all DNSBLs */ |
|
185 typedef struct { |
|
186 DNSBL_DOM dom; /* domain name */ |
|
187 struct in6_addr addr; /* and/or IP address sought in DNSBL */ |
|
188 } DNSBL_TGT; |
|
189 typedef struct { |
|
190 DNSBL_GBITS all; |
|
191 DNSBL_GBITS client; |
|
192 DNSBL_GBITS mail_host; |
|
193 DNSBL_GBITS mail_host_ns; |
|
194 DNSBL_GBITS mail_host_mx; |
|
195 DNSBL_GBITS url; |
|
196 DNSBL_GBITS url_ns; |
|
197 DNSBL_GBITS url_mx; |
|
198 } DNSBL_UNHIT; |
|
199 typedef struct { |
|
200 DCC_CLNT_CTXT *dcc_ctxt; |
|
201 void *log_ctxt; |
|
202 const char *id; |
|
203 time_t msg_us; /* microseconds remaining for msg */ |
|
204 struct timeval url_start; |
|
205 time_t url_us; /* microseconds to look up URL */ |
|
206 time_t url_us_used; |
|
207 DNSBL_UNHIT unhit; /* groups of DNSBLs not yet hit */ |
|
208 u_short tgt_dom_len; |
|
209 DNSBL_TGT tgt; |
|
210 struct { |
|
211 DNSBL_DOM dom; |
|
212 } tgt_cache[8]; |
|
213 int tgt_cache_pos; |
|
214 DNSBL_GROUP groups[MAX_DNSBL_GROUPS]; |
|
215 } DNSBL_WORK; |
|
216 |
|
217 extern DNSBL *dnsbls; |
|
218 extern u_char have_dnsbl_groups; |
|
219 extern u_char have_helpers; |
|
220 extern DCC_PATH dnsbl_progpath; |
|
221 |
|
222 |
|
223 |
|
224 /* accumulated checksums for an SMTP message */ |
|
225 typedef struct { |
|
226 const char *hdr_nm; /* name if substitute checksum */ |
|
227 DCC_TGTS tgts; /* server's answer or previous total */ |
|
228 DCC_CK_TYPE_B type; |
|
229 u_char rpt2srvr; /* 1=report to server */ |
|
230 DCC_SUM sum; |
|
231 } DCC_GOT_SUM; |
|
232 #define CLR_GOT_SUM(g) ((g)->hdr_nm = 0, (g)->tgts = DCC_TGTS_INVALID, \ |
|
233 (g)->type = DCC_CK_INVALID, (g)->rpt2srvr = 0) |
|
234 |
|
235 typedef union { |
|
236 u_int32_t w32[4]; |
|
237 u_char b[16]; |
|
238 } DCC_FUZ2_WORD; |
|
239 #define DCC_FUZ2_WORD_CLEAR(_w) ((_w)->w32[0]=0, (_w)->w32[1]=0, \ |
|
240 (_w)->w32[2]=0, (_w)->w32[3]=0) |
|
241 |
|
242 typedef struct { |
|
243 DCC_URL_SKIP url; |
|
244 u_int total; /* bytes */ |
|
245 char *cp; /* end of data in buffer */ |
|
246 char *eol; /* most recent eol */ |
|
247 # define DCC_FUZ1_MAX_LINE 78 |
|
248 # define DCC_HTTPS_STR "https" |
|
249 # define DCC_HTTPS_LEN LITZ(DCC_HTTPS_STR) |
|
250 char buf[DCC_FUZ1_MAX_LINE*4 |
|
251 +DCC_HTTPS_LEN]; |
|
252 MD5_CTX md5; |
|
253 } DCC_CTX_FUZ1; |
|
254 |
|
255 |
|
256 typedef struct { /* per-language counts */ |
|
257 u_int wsummed; /* bytes of words summed */ |
|
258 u_int wtotal; /* words summed */ |
|
259 MD5_CTX md5; |
|
260 } FUZ2_LANG; |
|
261 |
|
262 typedef struct { |
|
263 u_int btotal; /* total non-whitespace bytes seen */ |
|
264 u_int xsummed; /* non-word bytes checksummed */ |
|
265 u_int wlen; /* length of current word */ |
|
266 u_int cref_cnt; /* fancy character length */ |
|
267 u_int tag_len; /* HTML tag length */ |
|
268 DCC_FUZ2_WORD w; |
|
269 DCC_FUZ2_WORD cref_w; |
|
270 DCC_FUZ2_WORD tag; |
|
271 int urls; /* # of URLs seen */ |
|
272 char *url_cp; /* accumulated URLs */ |
|
273 # define DCC_FUZ2_URL_MAX (1+DCC_URL_MAX) |
|
274 char url_buf[DCC_FUZ2_URL_MAX*2]; |
|
275 DCC_URL_SKIP url; /* state machine for skipping URLs */ |
|
276 enum { |
|
277 DCC_CREF_ST_IDLE = 0, |
|
278 DCC_CREF_ST_START, /* get HTML character reference */ |
|
279 DCC_CREF_ST_NUM, /* hex or decimal */ |
|
280 DCC_CREF_ST_DEC, |
|
281 DCC_CREF_ST_HEX, |
|
282 DCC_CREF_ST_NAME |
|
283 } cref_st; |
|
284 enum { |
|
285 DCC_FUZ2_ST_WORD = 0, /* gathering word */ |
|
286 DCC_FUZ2_ST_START_TAG, /* gathering start of HTML tag */ |
|
287 DCC_FUZ2_ST_SKIP_TAG, /* skipping HTML tag */ |
|
288 DCC_FUZ2_ST_SKIP_COMMENT /* skipping HTML comment */ |
|
289 } st; |
|
290 # define FUZ2_LAN_NUM 3 |
|
291 FUZ2_LANG lang[FUZ2_LAN_NUM]; |
|
292 } DCC_CTX_FUZ2; |
|
293 |
|
294 /* The maximum length of a checksumed HELO value and the continuation string |
|
295 * need to be the same for all users of the local white-/blacklist */ |
|
296 #define DCC_HELO_MAX (DCC_MAXDOMAINLEN+8) |
|
297 #define DCC_HELO_CONT "..." |
|
298 |
|
299 /* local-part maximum in RFC 2821 */ |
|
300 #define DCC_LOCAL_PART_MAX 64 |
|
301 #define DCC_ENV_FROM_MAX (DCC_LOCAL_PART_MAX+DCC_MAXDOMAINLEN) |
|
302 |
|
303 #define DCC_MSG_ID_LEN 24 |
|
304 |
|
305 /* do not checksum more than this much of a header line */ |
|
306 #define DCC_HDR_CK_MAX 1024 |
|
307 |
|
308 /* substitute or locally configured checksums */ |
|
309 #define DCC_MAX_SUB_CKS 6 |
|
310 |
|
311 #define DCC_WSUMS (DCC_DIM_CKS+DCC_MAX_SUB_CKS) /* max whitelist checksums */ |
|
312 typedef struct { |
|
313 DCC_GOT_SUM sums[DCC_WSUMS]; |
|
314 struct in6_addr ip_addr; /* SMTP client IP address */ |
|
315 struct { /* quoted-printable state machine */ |
|
316 int x; |
|
317 int y; |
|
318 u_char n; |
|
319 enum { |
|
320 DCC_CK_QP_IDLE, /* waiting for '=' */ |
|
321 DCC_CK_QP_EQ, /* seen "=" */ |
|
322 DCC_CK_QP_1, /* seen "=X" of "=XY" */ |
|
323 DCC_CK_QP_FAIL1, /* have output '=' after bad =X */ |
|
324 DCC_CK_QP_FAIL2, /* have output '=' after bad =XY */ |
|
325 DCC_CK_QP_FAIL3 /* have output 'X' after bad =XY */ |
|
326 } state; |
|
327 } qp; |
|
328 struct { /* base64 state machine */ |
|
329 u_int32_t quantum; |
|
330 int quantum_cnt; |
|
331 } b64; |
|
332 enum { |
|
333 CK_MP_ST_PREAMBLE, /* preamble before first boundary */ |
|
334 CK_MP_ST_BND, /* MIME boundary */ |
|
335 CK_MP_ST_HDRS, /* headers after a boundary */ |
|
336 CK_MP_ST_TEXT, /* body or entity */ |
|
337 CK_MP_ST_EPILOGUE /* text after last boundary */ |
|
338 } mp_st; |
|
339 enum CK_MHDR_ST { /* parse entity fields */ |
|
340 CK_MHDR_ST_IDLE, |
|
341 CK_MHDR_ST_CE_CT, /* matching "Content-T" */ |
|
342 CK_MHDR_ST_CE, /* "ransfer-Encoding:" */ |
|
343 CK_MHDR_ST_CE_WS, /* white space after "encoding:" */ |
|
344 CK_MHDR_ST_CT, /* "ype:" */ |
|
345 CK_MHDR_ST_CT_WS, /* white space after "type:" */ |
|
346 CK_MHDR_ST_QP, /* "quoted-printable" */ |
|
347 CK_MHDR_ST_B64, /* "base64" */ |
|
348 CK_MHDR_ST_TEXT, /* "text" */ |
|
349 CK_MHDR_ST_HTML, /* "/html" */ |
|
350 CK_MHDR_ST_CSET_SKIP_PARAM, /* skip to ";" after "text" */ |
|
351 CK_MHDR_ST_CSET_SPAN_WS, /* skip blanks before "charset" */ |
|
352 CK_MHDR_ST_CSET, /* match "charset=" */ |
|
353 CK_MHDR_ST_CSET_ISO_8859, /* "ISO-8859-" */ |
|
354 CK_MHDR_ST_CSET_ISO_X, /* find the 8859 type number */ |
|
355 CK_MHDR_ST_MULTIPART, /* match "multipart" */ |
|
356 CK_MHDR_ST_BND_SKIP_PARAM, /* skip "/alternative;" or similar */ |
|
357 CK_MHDR_ST_BND_SPAN_WS, /* skip whitespace before "boundary" */ |
|
358 CK_MHDR_ST_BND, /* match "boundary=" */ |
|
359 CK_MHDR_ST_BND_VALUE /* collecting boundary */ |
|
360 } mhdr_st; |
|
361 u_char mhdr_pos; |
|
362 u_char mime_nest; /* # of nested MIME entities */ |
|
363 u_char mime_bnd_matches; /* # of active boundary matches */ |
|
364 DCC_CK_BND mime_bnd[3]; |
|
365 enum { |
|
366 DCC_CK_CT_TEXT = 0, |
|
367 DCC_CK_CT_HTML, |
|
368 DCC_CK_CT_BINARY |
|
369 } mime_ct; |
|
370 const u_char *mime_cset; |
|
371 enum { |
|
372 DCC_CK_CE_ASCII = 0, |
|
373 DCC_CK_CE_QP, |
|
374 DCC_CK_CE_B64 |
|
375 } mime_ce; |
|
376 struct { |
|
377 u_int total; /* non-whitespace text */ |
|
378 u_char flen; /* bytes of ">From" seen */ |
|
379 MD5_CTX md5; |
|
380 } ctx_body; |
|
381 DCC_CTX_FUZ1 fuz1; |
|
382 DCC_CTX_FUZ2 fuz2; |
|
383 DNSBL_WORK *dnsbl; /* pointer to malloc()'ed state */ |
|
384 DCC_CKSUM_THOLDS tholds_rej; |
|
385 u_char flags; |
|
386 # define DCC_CKS_MIME_BOL 0x01 /* header decoder is at BOL */ |
|
387 # define DCC_CKS_MIME_QUOTED 0x02 /* quoted boundary */ |
|
388 } DCC_GOT_CKS; |
|
389 |
|
390 typedef DCC_TGTS DCC_CKS_WTGTS[DCC_WSUMS]; |
|
391 |
|
392 |
|
393 /* sscanf() a checksum */ |
|
394 #define DCC_CKSUM_HEX_PAT "%8x %8x %8x %8x" |
|
395 |
|
396 |
|
397 |
|
398 |
|
399 /* whiteclnt files */ |
|
400 |
|
401 #define DCC_WHITE_SUFFIX ".dccw" |
|
402 #define DCC_WHITE_NEW_SUFFIX ".dccx" /* hash table under construction */ |
|
403 |
|
404 typedef char DCC_WHITE_MAGIC[128]; |
|
405 #define WHITE_MAGIC_B_STR "DCC client whitelist hash table version " |
|
406 #define WHITE_MAGIC_V_STR "23" |
|
407 |
|
408 typedef struct { |
|
409 DCC_TGTS tgts; |
|
410 int bits; |
|
411 struct in6_addr addr; |
|
412 struct in6_addr mask; |
|
413 u_short lno; |
|
414 u_char fno; |
|
415 } DCC_WHITE_CIDR_ENTRY; |
|
416 |
|
417 typedef struct { |
|
418 u_char len; |
|
419 # define WHITE_CIDR_MAX_ENTRIES 64 |
|
420 DCC_WHITE_CIDR_ENTRY e[WHITE_CIDR_MAX_ENTRIES]; |
|
421 } DCC_WHITE_CIDR; |
|
422 |
|
423 typedef u_int DCC_WHITE_INX; /* 1-based index into hash table */ |
|
424 |
|
425 typedef struct { |
|
426 DCC_WHITE_INX fwd; |
|
427 DCC_TGTS tgts; |
|
428 u_short lno; |
|
429 u_char fno; |
|
430 DCC_CK_TYPE_B type; |
|
431 DCC_SUM sum; |
|
432 } DCC_WHITE_ENTRY; |
|
433 |
|
434 #ifdef DCC_WIN32 |
|
435 #define DCC_WHITE_TBL_BINS 521 /* should be prime */ |
|
436 #else |
|
437 #define DCC_WHITE_TBL_BINS 8209 /* should be prime */ |
|
438 #endif |
|
439 typedef u_int DCC_WHITE_FGS; |
|
440 typedef struct { |
|
441 DCC_WHITE_MAGIC magic; /* WHITE_MAGIC_* in ckwhite.c */ |
|
442 struct { |
|
443 DCC_WHITE_INX entries; /* # of entries in the file */ |
|
444 DCC_WHITE_FGS flags; |
|
445 # define DCC_WHITE_FG_PER_USER 0x00000001 |
|
446 # define DCC_WHITE_FG_HOSTNAMES 0x00000002 /* have some */ |
|
447 # define DCC_WHITE_FG_GREY_LOG_ON 0x00000004 |
|
448 # define DCC_WHITE_FG_GREY_LOG_OFF 0x00000008 |
|
449 # define DCC_WHITE_FG_GREY_ON 0x00000010 |
|
450 # define DCC_WHITE_FG_GREY_OFF 0x00000020 |
|
451 # define DCC_WHITE_FG_LOG_ALL 0x00000040 |
|
452 # define DCC_WHITE_FG_LOG_NORMAL 0x00000080 |
|
453 # define DCC_WHITE_FG_DISCARD_OK 0x00000100 |
|
454 # define DCC_WHITE_FG_NO_DISCARD 0x00000200 |
|
455 # define DCC_WHITE_FG_DCC_ON 0x00000400 |
|
456 # define DCC_WHITE_FG_DCC_OFF 0x00000800 |
|
457 # define DCC_WHITE_FG_REP_ON 0x00001000 |
|
458 # define DCC_WHITE_FG_REP_OFF 0x00002000 |
|
459 # define DCC_WHITE_FG_MTA_FIRST 0x00004000 |
|
460 # define DCC_WHITE_FG_MTA_LAST 0x00008000 |
|
461 # define DCC_WHITE_FG_LOG_D 0x00010000 |
|
462 # define DCC_WHITE_FG_LOG_H 0x00020000 |
|
463 # define DCC_WHITE_FG_LOG_M 0x00040000 |
|
464 # define DCC_WHITE_FG_TRAP_ACC 0x00080000 /* spam trap */ |
|
465 # define DCC_WHITE_FG_TRAP_REJ 0x00100000 /* spam trap */ |
|
466 # define DCC_WHITE_FG_TRAPS (DCC_WHITE_FG_TRAP_ACC \ |
|
467 | DCC_WHITE_FG_TRAP_REJ) |
|
468 # define DCC_WHITE_FG_DNSBL_ON(n) (0x00200000*DNSBL_G2B(n)) |
|
469 # define DCC_WHITE_FG_DNSBL_ON_M 0x00e00000 |
|
470 # define DCC_WHITE_FG_DNSBL_OFF(n) (0x01000000*DNSBL_G2B(n)) |
|
471 # define DCC_WHITE_FG_DNSBL_OFF_M 0x07000000 |
|
472 time_t reparse; /* re-parse after this */ |
|
473 time_t broken; /* serious broken until then */ |
|
474 time_t ascii_mtime; /* ASCII file mtime at last parsing */ |
|
475 struct { /* included files */ |
|
476 time_t mtime; |
|
477 DCC_PATH nm; |
|
478 } white_incs[8]; |
|
479 |
|
480 DCC_CKSUM_THOLDS tholds_rej; |
|
481 |
|
482 DCC_SUM ck_sum; /* checksum of following contents */ |
|
483 DCC_WHITE_CIDR cidr; |
|
484 } hdr; |
|
485 DCC_WHITE_INX bins[DCC_WHITE_TBL_BINS]; /* 1-based indeces or 0 for empty */ |
|
486 DCC_WHITE_ENTRY tbl[1]; |
|
487 } DCC_WHITE_TBL; |
|
488 |
|
489 |
|
490 /* a ASCII whiteclnt file (including the files it includes) can be |
|
491 * OK |
|
492 * unreadable or otherwise badly broken |
|
493 * missing |
|
494 * if permanent, the hash table should be removed, but |
|
495 * it might be temporary as an editor changes it |
|
496 * a hash table can be |
|
497 * OK |
|
498 * out of date compared to the ASCII file(s) |
|
499 * badly broken but not removable (e.g. bad directory permissions). |
|
500 * |
|
501 * Do not stat() the files iand so do not complain on every message by |
|
502 * using wf->next_stat_time |
|
503 * Avoid generating a complaint on every error message using wf->broken |
|
504 * Reparse ASCII files with errors using wf->reparse or when their mtimes |
|
505 * change, but not more often than we use stat() to check mtimes.. |
|
506 * Reparse the main ASCII file if it contains host names by noticing the |
|
507 * DCC_WHITE_FG_HOSTNAMES bit and that the mtime of the hash table is |
|
508 * more than DCC_WHITECLNT_RESOLVE seconds old |
|
509 */ |
|
510 #define DCC_WHITE_REPARSE_DELAY (30*60) /* look for new DNS values */ |
|
511 #define DCC_WHITE_BROKEN_DELAY (5*60) /* do not complain more often */ |
|
512 #define DCC_WHITE_STAT_DELAY 10 /* don't stat() more often */ |
|
513 |
|
514 /* computed from DCC_WHITE_FGS */ |
|
515 typedef u_int32_t FLTR_SWS; |
|
516 #define FLTR_SW_SET 0x00000001 |
|
517 #define FLTR_SW_NO_DISCARD 0x00000002 /* always reject spam */ |
|
518 #define FLTR_SW_DCC_OFF 0x00000004 /* no DCC check */ |
|
519 #define FLTR_SW_REP_ON 0x00000008 /* honor DCC reputation */ |
|
520 #define FLTR_SW_LOG_ALL 0x00000010 |
|
521 #define FLTR_SW_GREY_OFF 0x00000020 /* greylisting off */ |
|
522 #define FLTR_SW_GREY_LOG_OFF 0x00000040 /* log greylist embargos */ |
|
523 #define FLTR_SW_LOG_D 0x00000080 |
|
524 #define FLTR_SW_LOG_H 0x00000100 |
|
525 #define FLTR_SW_LOG_M 0x00000200 |
|
526 #define FLTR_SW_MTA_FIRST 0x00000400 /* MTA IS/NOTSPAM checked first */ |
|
527 #define FLTR_SW_TRAP_ACC 0x00000800 /* accepting spam trap */ |
|
528 #define FLTR_SW_TRAP_REJ 0x00001000 /* rejecting spam trap */ |
|
529 # define FLTR_SW_TRAPS (FLTR_SW_TRAP_ACC | FLTR_SW_TRAP_REJ) |
|
530 #define FLTR_SW_DNSBL(n) (0x00002000*DNSBL_G2B(n)) /* check DNSBL */ |
|
531 # define FLTR_SW_DNSBL_M 0x0000e000 |
|
532 # define FLTR_SW_DNSBL_BITS(sws) (((sws)&FLTR_SW_DNSBL_M) \ |
|
533 / FLTR_SW_DNSBL(0)) |
|
534 |
|
535 /* bits set to enable something */ |
|
536 #define FLTR_SWS_SETTINGS_ON (FLTR_SW_REP_ON \ |
|
537 | FLTR_SW_LOG_ALL \ |
|
538 | FLTR_SW_MTA_FIRST \ |
|
539 | FLTR_SW_DNSBL_M \ |
|
540 | FLTR_SW_TRAPS) |
|
541 /* bits set to disable something */ |
|
542 #define FLTR_SWS_SETTINGS_OFF (FLTR_SW_DCC_OFF \ |
|
543 | FLTR_SW_NO_DISCARD \ |
|
544 | FLTR_SW_TRAP_REJ \ |
|
545 | FLTR_SW_GREY_OFF \ |
|
546 | FLTR_SW_GREY_LOG_OFF) |
|
547 /* get bits of enabled FILTERS */ |
|
548 #define FLTR_SWS_ON(sws) (((sws) ^ FLTR_SW_DCC_OFF) \ |
|
549 & (FLTR_SW_DCC_OFF \ |
|
550 | FLTR_SW_REP_ON \ |
|
551 | FLTR_SW_DNSBL_M \ |
|
552 | FLTR_SW_TRAP_REJ)) |
|
553 |
|
554 |
|
555 /* everything there is to know about a currently active whitelist file */ |
|
556 typedef struct { |
|
557 DCC_WHITE_TBL *wtbl; |
|
558 int ht_fd; /* hash table file */ |
|
559 struct stat ht_sb; |
|
560 DCC_WHITE_FGS wtbl_flags; |
|
561 u_int wtbl_entries; /* # of entries mapped window */ |
|
562 u_int wtbl_size; /* bytes in mapped window */ |
|
563 time_t next_stat_time; |
|
564 time_t reparse; /* when to re-parse file */ |
|
565 time_t broken; /* something very sick until then */ |
|
566 #ifdef DCC_WIN32 |
|
567 HANDLE ht_map; /* WIN32 hash table map handle */ |
|
568 #endif |
|
569 u_int ascii_nm_len; |
|
570 DCC_PATH ascii_nm; |
|
571 DCC_PATH ht_nm; |
|
572 int fno, lno; /* currently being parsed */ |
|
573 u_char wf_flags; |
|
574 # define DCC_WF_PER_USER 0x01 /* hostnames not allowed */ |
|
575 # define DCC_WF_NOFILE 0x02 /* no whiteclnt file */ |
|
576 # define DCC_WF_EITHER 0x04 /* either global or per-user ok */ |
|
577 # define DCC_WF_RO 0x08 /* read only access */ |
|
578 # define DCC_WF_WLIST 0x10 /* wlist command */ |
|
579 # define DCC_WF_WLIST_RO 0x20 /* read-only wlist command */ |
|
580 # define DCC_WF_WLIST_RW 0x40 /* read/write wlist command */ |
|
581 u_char closed; |
|
582 u_char need_reopen; /* lock-safe change flag */ |
|
583 } DCC_WF; |
|
584 |
|
585 extern DCC_WF cmn_wf, cmn_tmp_wf; |
|
586 |
|
587 typedef enum { /* greylist result */ |
|
588 ASK_GREY_FAIL, /* greylist server or other failure */ |
|
589 ASK_GREY_OFF, /* client whitelist or blacklist */ |
|
590 ASK_GREY_EMBARGO, |
|
591 ASK_GREY_EMBARGO_END, /* first time server says ok */ |
|
592 ASK_GREY_PASS, /* greylist server says ok */ |
|
593 ASK_GREY_WHITE, /* greylist server says whitelisted */ |
|
594 ASK_GREY_SPAM /* reported as spam to server */ |
|
595 } ASK_GREY_RESULT; |
|
596 |
|
597 extern u_char grey_on; |
|
598 extern u_char grey_query_only; |
|
599 |
|
600 extern u_int dcc_ck_qp_decode(DCC_GOT_CKS *, const char **, u_int *, |
|
601 char *, u_int); |
|
602 extern u_int dcc_ck_b64_decode(DCC_GOT_CKS *, const char **, u_int *, |
|
603 char *, u_int); |
|
604 |
|
605 extern int dcc_ck_url(DCC_URL_SKIP *, char, char **); |
|
606 #define DCC_CK_URL_MASK 0xff |
|
607 #define DCC_CK_URL_SHIFT 8 |
|
608 typedef enum { |
|
609 DCC_CK_URL_CHAR, /* character in URL after host name */ |
|
610 DCC_CK_URL_CK_LEN, /* 2nd slash */ |
|
611 DCC_CK_URL_HOST, /* character in URL host name */ |
|
612 DCC_CK_URL_DOT, /* dot in host name */ |
|
613 DCC_CK_URL_HOST_END, /* end of host name */ |
|
614 DCC_CK_URL_HOST_RESET, /* wasn't in host name after all */ |
|
615 DCC_CK_URL_SKIP /* shipping URL or not in URL */ |
|
616 } DCC_CK_URL; |
|
617 |
|
618 extern void dcc_ck_fuz1_init(DCC_GOT_CKS *); |
|
619 extern void dcc_ck_fuz1(DCC_GOT_CKS *, const char *, u_int); |
|
620 extern void dcc_ck_fuz1_fin(DCC_GOT_CKS *); |
|
621 |
|
622 extern void dcc_ck_fuz2_init(DCC_GOT_CKS *); |
|
623 extern void dcc_ck_fuz2(DCC_GOT_CKS *, const char *, u_int); |
|
624 extern void dcc_ck_fuz2_fin(DCC_GOT_CKS *); |
|
625 |
|
626 |
|
627 extern void dcc_wf_init(DCC_WF *, u_int); |
|
628 extern void dcc_wf_lock(DCC_WF *); |
|
629 extern void dcc_wf_unlock(DCC_WF *); |
|
630 |
|
631 extern void dcc_str2ck(DCC_SUM, const char *, u_int, const char *); |
|
632 extern u_char dcc_get_cks(DCC_GOT_CKS *, DCC_CK_TYPES, const char *, u_char); |
|
633 extern u_char dcc_ck_get_sub(DCC_GOT_CKS *, const char *, const char *); |
|
634 extern u_char dcc_add_sub_hdr(DCC_EMSG, const char *); |
|
635 extern void dcc_ck_ipv6(DCC_SUM, const struct in6_addr *); |
|
636 extern void dcc_get_ipv6_ck(DCC_GOT_CKS *, const struct in6_addr *); |
|
637 extern void dcc_unget_ip_ck(DCC_GOT_CKS *); |
|
638 extern u_char dcc_get_str_ip_ck(DCC_GOT_CKS *, const char *); |
|
639 extern const char *parse_received(const char *, DCC_GOT_CKS *, |
|
640 char *, int, char *, int, char *, int); |
|
641 extern u_char parse_return_path(const char *, char *, int); |
|
642 extern u_char parse_unix_from(const char *, char *, int); |
|
643 extern u_char parse_mail_host(const char *, char *, int); |
|
644 extern void dcc_print_cks(LOG_WRITE_FNC, void *, u_char, DCC_TGTS, |
|
645 const DCC_GOT_CKS *, DCC_CKS_WTGTS, u_char); |
|
646 #define PRINT_CK_TYPE_LEN 25 |
|
647 #define PRINT_CK_SUM_LEN 35 |
|
648 #define PRINT_CK_PAT_CK "%25s: %-35s" |
|
649 #define PRINT_CK_PAT_LIM_CK "%25.*s%c %-35.*s" |
|
650 #define PRINT_CK_PAT_SRVR " %7s" |
|
651 #define PRINT_CK_PAT_SRVR_LEN 8 |
|
652 #define PRINT_CK_PAT_WLIST " %5s" |
|
653 #define PRINT_CK_PAT_WLIST_LEN 6 |
|
654 #define PRINT_CK_PAT_THOLD PRINT_CK_PAT_WLIST |
|
655 |
|
656 extern void dcc_cks_init(DCC_GOT_CKS *); |
|
657 extern void dcc_ck_mime_hdr(DCC_GOT_CKS *, const char *, const char *); |
|
658 extern u_char parse_mime_hdr(DCC_GOT_CKS *, const char *, u_int, u_char); |
|
659 extern void dcc_ck_body(DCC_GOT_CKS *, const void *, u_int); |
|
660 extern void dcc_cks_fin(DCC_GOT_CKS *); |
|
661 |
|
662 extern u_char dcc_get_white(DCC_EMSG, DCC_WHITE_INX); |
|
663 |
|
664 typedef int (*DCC_PARSED_CK_FNC)(DCC_EMSG, DCC_WF *, |
|
665 DCC_CK_TYPES, /* type of checksum */ |
|
666 DCC_SUM, /* computed checksum */ |
|
667 DCC_TGTS); /* "OK2" etc */ |
|
668 typedef int (*DCC_PARSED_CK_CIDR_FNC)(DCC_EMSG, DCC_WF *, |
|
669 int, |
|
670 const struct in6_addr *, |
|
671 const struct in6_addr *, |
|
672 DCC_TGTS); |
|
673 extern int dcc_parse_ck(DCC_EMSG, DCC_WF *wf, |
|
674 const char *, DCC_CK_TYPES, const char *, DCC_TGTS, |
|
675 DCC_PARSED_CK_FNC, DCC_PARSED_CK_CIDR_FNC); |
|
676 extern int dcc_parse_hex_ck(DCC_EMSG, DCC_WF *wf, |
|
677 const char *, DCC_CK_TYPES, const char *, DCC_TGTS, |
|
678 DCC_PARSED_CK_FNC); |
|
679 extern const char *wf_fnm(const DCC_WF *, int); |
|
680 extern const char *wf_fnm_lno(DCC_FNM_LNO_BUF *, const DCC_WF *); |
|
681 extern DCC_TGTS dcc_str2thold(DCC_CK_TYPES, const char *); |
|
682 extern int dcc_parse_whitefile(DCC_EMSG, DCC_WF *, int, |
|
683 DCC_PARSED_CK_FNC, DCC_PARSED_CK_CIDR_FNC); |
|
684 |
|
685 typedef enum { |
|
686 DCC_WHITE_USE_DCC, |
|
687 DCC_WHITE_LISTED, |
|
688 DCC_WHITE_UNLISTED, |
|
689 DCC_WHITE_BLACK |
|
690 } DCC_WHITE_LISTING; |
|
691 |
|
692 typedef enum { |
|
693 DCC_WHITE_OK, |
|
694 DCC_WHITE_NOFILE, /* no ASCII file */ |
|
695 DCC_WHITE_CONTINUE, /* modest error or bad host name */ |
|
696 DCC_WHITE_COMPLAIN, /* bad hash table */ |
|
697 DCC_WHITE_SILENT /* no more complaints */ |
|
698 } DCC_WHITE_RESULT; |
|
699 #define DCC_WHITE_RESULT_FAILURE DCC_WHITE_UNLISTED |
|
700 |
|
701 u_char dcc_new_white_nm(DCC_EMSG, DCC_WF *, const char *); |
|
702 extern DCC_WHITE_RESULT dcc_rdy_white(DCC_EMSG, DCC_WF *, DCC_WF *); |
|
703 extern DCC_WHITE_RESULT dcc_white_sum(DCC_EMSG, DCC_WF *, |
|
704 DCC_CK_TYPES, const DCC_SUM, |
|
705 DCC_TGTS *, DCC_WHITE_LISTING *); |
|
706 extern u_char dcc_white_mx(DCC_EMSG, DCC_TGTS *, const DCC_GOT_CKS *); |
|
707 extern DCC_WHITE_RESULT dcc_white_cks(DCC_EMSG, DCC_WF *, DCC_GOT_CKS *, |
|
708 DCC_CKS_WTGTS, DCC_WHITE_LISTING *); |
|
709 |
|
710 |
|
711 typedef u_int32_t ASK_ST; |
|
712 #define ASK_ST_INVALID_MSG 0x00000001 /* incomplete SMTP transaction */ |
|
713 #define ASK_ST_QUERY 0x00000002 /* ask but do not report */ |
|
714 #define ASK_ST_QUERY_GREY 0x00000004 |
|
715 #define ASK_ST_SRVR_OK2 0x00000008 /* have honored DCC_TGTS_OK2 */ |
|
716 #define ASK_ST_SRVR_NOTSPAM 0x00000010 /* not spam by DCC server */ |
|
717 #define ASK_ST_SRVR_ISSPAM 0x00000020 /* spam by DCC server & threshold */ |
|
718 #define ASK_ST_REP_ISSPAM 0x00000040 /* spam by reputation & threshold */ |
|
719 #define ASK_ST_MTA_NOTSPAM 0x00000080 /* MTA says it is not spam */ |
|
720 #define ASK_ST_MTA_ISSPAM 0x00000100 /* MTA says it is spam */ |
|
721 #define ASK_ST_WLIST_NOTSPAM 0x00000200 /* locally whitelisted message */ |
|
722 #define ASK_ST_WLIST_ISSPAM 0x00000400 /* locally blacklisted message */ |
|
723 #define ASK_ST_CLNT_ISSPAM 0x00000800 /* report to DCC server as spam */ |
|
724 #define ASK_ST_GREY_EMBARGO 0x00001000 /* embargo this message */ |
|
725 #define ASK_ST_GREY_LOGIT 0x00002000 /* greylist logging indicated */ |
|
726 #define ASK_ST_LOGIT 0x00004000 /* log message for all recipients */ |
|
727 #define ASK_ST_DNSBL_HIT(n) (0x00008000*DNSBL_G2B(n)) /* DNSBL hit */ |
|
728 # define ASK_ST_DNSBL_HIT_M 0x00038000 |
|
729 # define ASK_ST_DNSBL_HIT_BITS(st) (((st)&ASK_ST_DNSBL_HIT_M) \ |
|
730 / ASK_ST_DNSBL_HIT(0)) |
|
731 #define ASK_ST_DNSBL_TIMEO(n) (0x00040000*DNSBL_G2B(n)) /* DNSBL timeout */ |
|
732 # define ASK_ST_DNSBL_TIMEO_M 0x001c0000 |
|
733 # define ASK_ST_DNSBL_TIMEO_BITS(st) (((st)&ASK_ST_DNSBL_TIMEO_M) \ |
|
734 / ASK_ST_DNSBL_TIMEO(0)) |
|
735 #define ASK_ST_DNSBL_TFAIL(n) (0x00200000*DNSBL_G2B(n)) |
|
736 # define ASK_ST_DNSBL_TFAIL_M 0x00e00000 |
|
737 # define ASK_ST_DNSBL_TFAIL_BITS(st) (((st)&ASK_ST_DNSBL_TFAIL_M) \ |
|
738 / ASK_ST_DNSBL_TFAIL(0)) |
|
739 |
|
740 |
|
741 extern u_char dcc_ck_grey_answer(DCC_EMSG, const DCC_OP_RESP *); |
|
742 extern int ask_dcc(DCC_EMSG, DCC_CLNT_CTXT *, u_char, |
|
743 DCC_HEADER_BUF *, DCC_GOT_CKS *, ASK_ST *, u_char, |
|
744 DCC_TGTS); |
|
745 extern u_char unthr_ask_white(DCC_EMSG, ASK_ST *, FLTR_SWS *, const char *, |
|
746 DCC_GOT_CKS *, DCC_CKS_WTGTS); |
|
747 extern u_char unthr_ask_dcc(DCC_EMSG, DCC_CLNT_CTXT*, DCC_HEADER_BUF*, ASK_ST *, |
|
748 DCC_GOT_CKS *, u_char, DCC_TGTS); |
|
749 extern void dcc_clear_tholds(void); |
|
750 extern u_char dcc_merge_tholds(DCC_CKSUM_THOLDS, |
|
751 const DCC_CKSUM_THOLDS, const DCC_WHITE_TBL *); |
|
752 extern void dcc_parse_honor(const char *); |
|
753 extern u_char dcc_parse_tholds(const char *, const char *); |
|
754 extern void dcc_honor_log_cnts(ASK_ST *, const DCC_GOT_CKS *, DCC_TGTS); |
|
755 extern FLTR_SWS wf2sws(FLTR_SWS, const DCC_WF *); |
|
756 extern void log_ask_st(LOG_WRITE_FNC, void *, ASK_ST, FLTR_SWS, u_char, |
|
757 const DCC_HEADER_BUF *); |
|
758 extern u_char dcc_parse_client_grey(const char *); |
|
759 extern ASK_GREY_RESULT ask_grey(DCC_EMSG, DCC_CLNT_CTXT *, DCC_OPS, |
|
760 DCC_SUM, DCC_SUM, |
|
761 const DCC_GOT_CKS *, const DCC_SUM, |
|
762 DCC_TGTS *, DCC_TGTS *, DCC_TGTS *); |
|
763 |
|
764 extern u_char dcc_parse_dnsbl(DCC_EMSG, const char *, const char *, u_char); |
|
765 extern const REPLY_TPLT *dnsbl_parse_reply(const char *); |
|
766 extern void helper_save_arg(const char *, const char *); |
|
767 extern void helper_init(int); |
|
768 extern void dcc_dnsbl_init(DCC_GOT_CKS *, |
|
769 DCC_CLNT_CTXT *, void *, const char *); |
|
770 extern void url_dnsbl(DNSBL_WORK *); |
|
771 extern void dcc_mail_host_dnsbl(DNSBL_WORK *, const char *); |
|
772 extern void dcc_client_dnsbl(DNSBL_WORK *, const struct in6_addr *, |
|
773 const char *); |
|
774 extern void dcc_dnsbl_result(ASK_ST *, DNSBL_WORK *); |
|
775 extern int PATTRIB(3,4) thr_log_print(void *, u_char, const char *, ...); |
|
776 extern int PATTRIB(2,3) thr_error_msg(void *, const char *, ...); |
|
777 extern void PATTRIB(2,3) thr_trace_msg(void *, const char *, ...); |
|
778 |
|
779 #endif /* DCC_CK_H */ |