comparison include/dcc_ck.h @ 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 * 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 */