Mercurial > notdcc
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/dcc_ck.h Tue Mar 10 13:49:58 2009 +0100 @@ -0,0 +1,779 @@ +/* Distributed Checksum Clearinghouse + * + * checksum routines + * + * 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.182 $Revision$ + */ + +#ifndef DCC_CK_H +#define DCC_CK_H + +#include "dcc_clnt.h" +#include "dcc_md5.h" + + +typedef DCC_TGTS DCC_CKSUM_THOLDS[DCC_DIM_CKS]; +#define DCC_THOLD_NEVER (DCC_TGTS_TOO_MANY+1) +#define DCC_THOLD_UNSET (DCC_TGTS_INVALID) + +extern DCC_CKSUM_THOLDS dcc_tholds_rej; + + +/* MIME boundary + * RFC 1341 says boundaries can be 70 bytes, but handle non-conformant spam */ +#define DCC_CK_BND_MAX 94 +#define DCC_CK_BND_DIM (DCC_CK_BND_MAX+2) /* including leading -- */ +#define DCC_CK_BND_MISS (DCC_CK_BND_DIM+1) +typedef struct { + u_char bnd_len; /* length including leading "--" */ + u_char cmp_len; /* compared so far */ + char bnd[DCC_CK_BND_DIM]; /* "--"boundary */ +} DCC_CK_BND; + + +typedef u_char DCC_CK_FC[256]; +extern const DCC_CK_FC dcc_cset_1, dcc_cset_2; + +/* state machine for ignoring parts of URLs */ +typedef struct { + enum { + DCC_URL_ST_IDLE, /* waiting for H or = */ + DCC_URL_ST_QUOTE, /* " " '"' or 'H' after = */ + DCC_URL_ST_QH, /* " " H after quote */ + DCC_URL_ST_T1, /* " " T */ + DCC_URL_ST_T2, /* " " T */ + DCC_URL_ST_P, /* " " P */ + DCC_URL_ST_S, /* " " [S] */ + DCC_URL_ST_COLON, /* " " : */ + DCC_URL_ST_SLASH1, /* " " / */ + DCC_URL_ST_SLASH2, /* " " / */ + DCC_URL_ST_SLASH3_START, + DCC_URL_ST_SLASH3, /* " " third / */ + DCC_URL_ST_SKIP /* skipping rest of URL */ + } st; + char *start; /* start of hostname in URL */ + char *dot; /* last '.' in hostname */ + int total; /* length of URL */ + u_char flags; +# define DCC_URL_QUOTED 0x01 +# define DCC_URL_DEL_DOMAIN 0x02 /* waiting for domain to delete */ +# define DCC_URL_PERCENT1 0x04 /* waiting for 1st digit after % */ +# define DCC_URL_PERCENT2 0x08 /* waiting for 2nd digit after % */ +# define DCC_URL_SQUOTED 0x10 /* single quoted (') URL */ +# define DCC_URL_DQUOTED 0x20 /* double quoted (") URL */ +# define DCC_URL_QUOTES (DCC_URL_DQUOTED | DCC_URL_SQUOTED) +# define DCC_URL_SIMPLE (DCC_URL_DEL_DOMAIN \ + | DCC_URL_PERCENT1 \ + | DCC_URL_PERCENT2) + u_char percent; +} DCC_URL_SKIP; +#define DCC_URL_MAX 65 /* 63 is RFC 1034 limit on labels */ +#define DCC_URL_FAILSAFE 2000 /* big bogus "username:password@" */ + + +/* a template for generating a reply to an SMTP command */ +typedef enum { + REPLY_TPLT_NULL, + REPLY_TPLT_ID, /* queue ID for sendmail, fake for dccifd */ + REPLY_TPLT_CIP, /* SMTP client IP address */ + REPLY_TPLT_BTYPE, /* type of DNSBL hit */ + REPLY_TPLT_BTGT, /* DNSBL hit IP address or name */ + REPLY_TPLT_BPROBE, /* DNSBL probe domain name */ + REPLY_TPLT_BRESULT /* DNSBL probe result */ +} REPLY_TPLT_ARGS; +typedef struct { + const char *log_result; /* "reject" etc. for log */ +# define NUM_REPLY_TPLT_ARGS 6 + REPLY_TPLT_ARGS args[NUM_REPLY_TPLT_ARGS]; + char rcode[sizeof("5yz")]; + char xcode[sizeof("1.2.3")]; + u_char is_pat; /* template has %s references */ +# define REPLY_BUF_LEN 256 + char pat[REPLY_BUF_LEN]; /* pattern for SMTP message */ +} REPLY_TPLT; + + +/* specify a DNS blacklist */ +typedef struct { + char c[DCC_MAXDOMAINLEN]; /* null terminated */ +} DNSBL_DOM; + +typedef u_char DNSBL_FGS; +#define DNSBL_FG_DUP 0x01 /* duplicate blacklist */ +#define DNSBL_FG_TIMEO 0x02 /* suffered a timeout */ +#define DNSBL_FG_TFAIL 0x04 /* want SMTP failure on timeout */ +#define DNSBL_FG_CLIENT 0x08 /* check client IP address */ +#define DNSBL_FG_MAIL_HOST 0x10 /* check env_from domain */ +#define DNSBL_FG_URL 0x20 /* check URLs in message body */ +#define DNSBL_FG_MX 0x40 /* MX for _URL & _MAIL_HOST */ +#define DNSBL_FG_NS 0x80 /* NS for _URL & _MAIL_HOST */ +# define DNSBL_FG_HITS (DNSBL_FG_CLIENT | DNSBL_FG_MAIL_HOST | DNSBL_FG_URL) +# define DNSBL_FG_TYPES (DNSBL_FG_HITS | DNSBL_FG_MX | DNSBL_FG_NS) +# define DNSBL_FG_DEFAULT DNSBL_FG_TYPES + +typedef enum DNSBL_TYPE { + DNSBL_TYPE_IPV4, + DNSBL_TYPE_IPV6, + DNSBL_TYPE_NAME +} DNSBL_TYPE; + +#define MAX_DNSBL_GROUPS 3 +typedef u_char DNSBL_GBITS; +#define DNSBL_G2B(n) ((1<<(n)) & ((2<<MAX_DNSBL_GROUPS)-1)) + +typedef struct dnsbl { + struct dnsbl *fwd; + struct dnsbl *dup; /* same except result */ + u_char group; /* 1-indexed */ + struct in6_addr tgt; /* hit if DNSBL matches this block */ + struct in6_addr tgt_mask; + u_char tgt_use_ipv6; /* ipv4 vs. ipv6 result weighting */ + DNSBL_TYPE bl_type; + int bl_num; + int bl_dom_len; + DNSBL_DOM bl_dom; + const REPLY_TPLT *reply; + DNSBL_FGS fgs; +} DNSBL; + +/* working storage for one set of DNSBLs */ +typedef struct { + DNSBL_FGS fgs; /* kind of DNSBL hit */ + const char *btype; /* type of hit string */ + const DNSBL *dnsbl; /* hit DNSBL */ + char btype_buf[64]; + char result[DCC_SU2STR_SIZE]; /* IP address found in DNSBL */ + DNSBL_DOM tgt; /* IP address or name sought in DNSBL */ + DNSBL_DOM probe; /* what was actually looked up */ +} DNSBL_GROUP; + +/* working storage for all DNSBLs */ +typedef struct { + DNSBL_DOM dom; /* domain name */ + struct in6_addr addr; /* and/or IP address sought in DNSBL */ +} DNSBL_TGT; +typedef struct { + DNSBL_GBITS all; + DNSBL_GBITS client; + DNSBL_GBITS mail_host; + DNSBL_GBITS mail_host_ns; + DNSBL_GBITS mail_host_mx; + DNSBL_GBITS url; + DNSBL_GBITS url_ns; + DNSBL_GBITS url_mx; +} DNSBL_UNHIT; +typedef struct { + DCC_CLNT_CTXT *dcc_ctxt; + void *log_ctxt; + const char *id; + time_t msg_us; /* microseconds remaining for msg */ + struct timeval url_start; + time_t url_us; /* microseconds to look up URL */ + time_t url_us_used; + DNSBL_UNHIT unhit; /* groups of DNSBLs not yet hit */ + u_short tgt_dom_len; + DNSBL_TGT tgt; + struct { + DNSBL_DOM dom; + } tgt_cache[8]; + int tgt_cache_pos; + DNSBL_GROUP groups[MAX_DNSBL_GROUPS]; +} DNSBL_WORK; + +extern DNSBL *dnsbls; +extern u_char have_dnsbl_groups; +extern u_char have_helpers; +extern DCC_PATH dnsbl_progpath; + + + +/* accumulated checksums for an SMTP message */ +typedef struct { + const char *hdr_nm; /* name if substitute checksum */ + DCC_TGTS tgts; /* server's answer or previous total */ + DCC_CK_TYPE_B type; + u_char rpt2srvr; /* 1=report to server */ + DCC_SUM sum; +} DCC_GOT_SUM; +#define CLR_GOT_SUM(g) ((g)->hdr_nm = 0, (g)->tgts = DCC_TGTS_INVALID, \ + (g)->type = DCC_CK_INVALID, (g)->rpt2srvr = 0) + +typedef union { + u_int32_t w32[4]; + u_char b[16]; +} DCC_FUZ2_WORD; +#define DCC_FUZ2_WORD_CLEAR(_w) ((_w)->w32[0]=0, (_w)->w32[1]=0, \ + (_w)->w32[2]=0, (_w)->w32[3]=0) + +typedef struct { + DCC_URL_SKIP url; + u_int total; /* bytes */ + char *cp; /* end of data in buffer */ + char *eol; /* most recent eol */ +# define DCC_FUZ1_MAX_LINE 78 +# define DCC_HTTPS_STR "https" +# define DCC_HTTPS_LEN LITZ(DCC_HTTPS_STR) + char buf[DCC_FUZ1_MAX_LINE*4 + +DCC_HTTPS_LEN]; + MD5_CTX md5; +} DCC_CTX_FUZ1; + + +typedef struct { /* per-language counts */ + u_int wsummed; /* bytes of words summed */ + u_int wtotal; /* words summed */ + MD5_CTX md5; +} FUZ2_LANG; + +typedef struct { + u_int btotal; /* total non-whitespace bytes seen */ + u_int xsummed; /* non-word bytes checksummed */ + u_int wlen; /* length of current word */ + u_int cref_cnt; /* fancy character length */ + u_int tag_len; /* HTML tag length */ + DCC_FUZ2_WORD w; + DCC_FUZ2_WORD cref_w; + DCC_FUZ2_WORD tag; + int urls; /* # of URLs seen */ + char *url_cp; /* accumulated URLs */ +# define DCC_FUZ2_URL_MAX (1+DCC_URL_MAX) + char url_buf[DCC_FUZ2_URL_MAX*2]; + DCC_URL_SKIP url; /* state machine for skipping URLs */ + enum { + DCC_CREF_ST_IDLE = 0, + DCC_CREF_ST_START, /* get HTML character reference */ + DCC_CREF_ST_NUM, /* hex or decimal */ + DCC_CREF_ST_DEC, + DCC_CREF_ST_HEX, + DCC_CREF_ST_NAME + } cref_st; + enum { + DCC_FUZ2_ST_WORD = 0, /* gathering word */ + DCC_FUZ2_ST_START_TAG, /* gathering start of HTML tag */ + DCC_FUZ2_ST_SKIP_TAG, /* skipping HTML tag */ + DCC_FUZ2_ST_SKIP_COMMENT /* skipping HTML comment */ + } st; +# define FUZ2_LAN_NUM 3 + FUZ2_LANG lang[FUZ2_LAN_NUM]; +} DCC_CTX_FUZ2; + +/* The maximum length of a checksumed HELO value and the continuation string + * need to be the same for all users of the local white-/blacklist */ +#define DCC_HELO_MAX (DCC_MAXDOMAINLEN+8) +#define DCC_HELO_CONT "..." + +/* local-part maximum in RFC 2821 */ +#define DCC_LOCAL_PART_MAX 64 +#define DCC_ENV_FROM_MAX (DCC_LOCAL_PART_MAX+DCC_MAXDOMAINLEN) + +#define DCC_MSG_ID_LEN 24 + +/* do not checksum more than this much of a header line */ +#define DCC_HDR_CK_MAX 1024 + +/* substitute or locally configured checksums */ +#define DCC_MAX_SUB_CKS 6 + +#define DCC_WSUMS (DCC_DIM_CKS+DCC_MAX_SUB_CKS) /* max whitelist checksums */ +typedef struct { + DCC_GOT_SUM sums[DCC_WSUMS]; + struct in6_addr ip_addr; /* SMTP client IP address */ + struct { /* quoted-printable state machine */ + int x; + int y; + u_char n; + enum { + DCC_CK_QP_IDLE, /* waiting for '=' */ + DCC_CK_QP_EQ, /* seen "=" */ + DCC_CK_QP_1, /* seen "=X" of "=XY" */ + DCC_CK_QP_FAIL1, /* have output '=' after bad =X */ + DCC_CK_QP_FAIL2, /* have output '=' after bad =XY */ + DCC_CK_QP_FAIL3 /* have output 'X' after bad =XY */ + } state; + } qp; + struct { /* base64 state machine */ + u_int32_t quantum; + int quantum_cnt; + } b64; + enum { + CK_MP_ST_PREAMBLE, /* preamble before first boundary */ + CK_MP_ST_BND, /* MIME boundary */ + CK_MP_ST_HDRS, /* headers after a boundary */ + CK_MP_ST_TEXT, /* body or entity */ + CK_MP_ST_EPILOGUE /* text after last boundary */ + } mp_st; + enum CK_MHDR_ST { /* parse entity fields */ + CK_MHDR_ST_IDLE, + CK_MHDR_ST_CE_CT, /* matching "Content-T" */ + CK_MHDR_ST_CE, /* "ransfer-Encoding:" */ + CK_MHDR_ST_CE_WS, /* white space after "encoding:" */ + CK_MHDR_ST_CT, /* "ype:" */ + CK_MHDR_ST_CT_WS, /* white space after "type:" */ + CK_MHDR_ST_QP, /* "quoted-printable" */ + CK_MHDR_ST_B64, /* "base64" */ + CK_MHDR_ST_TEXT, /* "text" */ + CK_MHDR_ST_HTML, /* "/html" */ + CK_MHDR_ST_CSET_SKIP_PARAM, /* skip to ";" after "text" */ + CK_MHDR_ST_CSET_SPAN_WS, /* skip blanks before "charset" */ + CK_MHDR_ST_CSET, /* match "charset=" */ + CK_MHDR_ST_CSET_ISO_8859, /* "ISO-8859-" */ + CK_MHDR_ST_CSET_ISO_X, /* find the 8859 type number */ + CK_MHDR_ST_MULTIPART, /* match "multipart" */ + CK_MHDR_ST_BND_SKIP_PARAM, /* skip "/alternative;" or similar */ + CK_MHDR_ST_BND_SPAN_WS, /* skip whitespace before "boundary" */ + CK_MHDR_ST_BND, /* match "boundary=" */ + CK_MHDR_ST_BND_VALUE /* collecting boundary */ + } mhdr_st; + u_char mhdr_pos; + u_char mime_nest; /* # of nested MIME entities */ + u_char mime_bnd_matches; /* # of active boundary matches */ + DCC_CK_BND mime_bnd[3]; + enum { + DCC_CK_CT_TEXT = 0, + DCC_CK_CT_HTML, + DCC_CK_CT_BINARY + } mime_ct; + const u_char *mime_cset; + enum { + DCC_CK_CE_ASCII = 0, + DCC_CK_CE_QP, + DCC_CK_CE_B64 + } mime_ce; + struct { + u_int total; /* non-whitespace text */ + u_char flen; /* bytes of ">From" seen */ + MD5_CTX md5; + } ctx_body; + DCC_CTX_FUZ1 fuz1; + DCC_CTX_FUZ2 fuz2; + DNSBL_WORK *dnsbl; /* pointer to malloc()'ed state */ + DCC_CKSUM_THOLDS tholds_rej; + u_char flags; +# define DCC_CKS_MIME_BOL 0x01 /* header decoder is at BOL */ +# define DCC_CKS_MIME_QUOTED 0x02 /* quoted boundary */ +} DCC_GOT_CKS; + +typedef DCC_TGTS DCC_CKS_WTGTS[DCC_WSUMS]; + + +/* sscanf() a checksum */ +#define DCC_CKSUM_HEX_PAT "%8x %8x %8x %8x" + + + + +/* whiteclnt files */ + +#define DCC_WHITE_SUFFIX ".dccw" +#define DCC_WHITE_NEW_SUFFIX ".dccx" /* hash table under construction */ + +typedef char DCC_WHITE_MAGIC[128]; +#define WHITE_MAGIC_B_STR "DCC client whitelist hash table version " +#define WHITE_MAGIC_V_STR "23" + +typedef struct { + DCC_TGTS tgts; + int bits; + struct in6_addr addr; + struct in6_addr mask; + u_short lno; + u_char fno; +} DCC_WHITE_CIDR_ENTRY; + +typedef struct { + u_char len; +# define WHITE_CIDR_MAX_ENTRIES 64 + DCC_WHITE_CIDR_ENTRY e[WHITE_CIDR_MAX_ENTRIES]; +} DCC_WHITE_CIDR; + +typedef u_int DCC_WHITE_INX; /* 1-based index into hash table */ + +typedef struct { + DCC_WHITE_INX fwd; + DCC_TGTS tgts; + u_short lno; + u_char fno; + DCC_CK_TYPE_B type; + DCC_SUM sum; +} DCC_WHITE_ENTRY; + +#ifdef DCC_WIN32 +#define DCC_WHITE_TBL_BINS 521 /* should be prime */ +#else +#define DCC_WHITE_TBL_BINS 8209 /* should be prime */ +#endif +typedef u_int DCC_WHITE_FGS; +typedef struct { + DCC_WHITE_MAGIC magic; /* WHITE_MAGIC_* in ckwhite.c */ + struct { + DCC_WHITE_INX entries; /* # of entries in the file */ + DCC_WHITE_FGS flags; +# define DCC_WHITE_FG_PER_USER 0x00000001 +# define DCC_WHITE_FG_HOSTNAMES 0x00000002 /* have some */ +# define DCC_WHITE_FG_GREY_LOG_ON 0x00000004 +# define DCC_WHITE_FG_GREY_LOG_OFF 0x00000008 +# define DCC_WHITE_FG_GREY_ON 0x00000010 +# define DCC_WHITE_FG_GREY_OFF 0x00000020 +# define DCC_WHITE_FG_LOG_ALL 0x00000040 +# define DCC_WHITE_FG_LOG_NORMAL 0x00000080 +# define DCC_WHITE_FG_DISCARD_OK 0x00000100 +# define DCC_WHITE_FG_NO_DISCARD 0x00000200 +# define DCC_WHITE_FG_DCC_ON 0x00000400 +# define DCC_WHITE_FG_DCC_OFF 0x00000800 +# define DCC_WHITE_FG_REP_ON 0x00001000 +# define DCC_WHITE_FG_REP_OFF 0x00002000 +# define DCC_WHITE_FG_MTA_FIRST 0x00004000 +# define DCC_WHITE_FG_MTA_LAST 0x00008000 +# define DCC_WHITE_FG_LOG_D 0x00010000 +# define DCC_WHITE_FG_LOG_H 0x00020000 +# define DCC_WHITE_FG_LOG_M 0x00040000 +# define DCC_WHITE_FG_TRAP_ACC 0x00080000 /* spam trap */ +# define DCC_WHITE_FG_TRAP_REJ 0x00100000 /* spam trap */ +# define DCC_WHITE_FG_TRAPS (DCC_WHITE_FG_TRAP_ACC \ + | DCC_WHITE_FG_TRAP_REJ) +# define DCC_WHITE_FG_DNSBL_ON(n) (0x00200000*DNSBL_G2B(n)) +# define DCC_WHITE_FG_DNSBL_ON_M 0x00e00000 +# define DCC_WHITE_FG_DNSBL_OFF(n) (0x01000000*DNSBL_G2B(n)) +# define DCC_WHITE_FG_DNSBL_OFF_M 0x07000000 + time_t reparse; /* re-parse after this */ + time_t broken; /* serious broken until then */ + time_t ascii_mtime; /* ASCII file mtime at last parsing */ + struct { /* included files */ + time_t mtime; + DCC_PATH nm; + } white_incs[8]; + + DCC_CKSUM_THOLDS tholds_rej; + + DCC_SUM ck_sum; /* checksum of following contents */ + DCC_WHITE_CIDR cidr; + } hdr; + DCC_WHITE_INX bins[DCC_WHITE_TBL_BINS]; /* 1-based indeces or 0 for empty */ + DCC_WHITE_ENTRY tbl[1]; +} DCC_WHITE_TBL; + + +/* a ASCII whiteclnt file (including the files it includes) can be + * OK + * unreadable or otherwise badly broken + * missing + * if permanent, the hash table should be removed, but + * it might be temporary as an editor changes it + * a hash table can be + * OK + * out of date compared to the ASCII file(s) + * badly broken but not removable (e.g. bad directory permissions). + * + * Do not stat() the files iand so do not complain on every message by + * using wf->next_stat_time + * Avoid generating a complaint on every error message using wf->broken + * Reparse ASCII files with errors using wf->reparse or when their mtimes + * change, but not more often than we use stat() to check mtimes.. + * Reparse the main ASCII file if it contains host names by noticing the + * DCC_WHITE_FG_HOSTNAMES bit and that the mtime of the hash table is + * more than DCC_WHITECLNT_RESOLVE seconds old + */ +#define DCC_WHITE_REPARSE_DELAY (30*60) /* look for new DNS values */ +#define DCC_WHITE_BROKEN_DELAY (5*60) /* do not complain more often */ +#define DCC_WHITE_STAT_DELAY 10 /* don't stat() more often */ + +/* computed from DCC_WHITE_FGS */ +typedef u_int32_t FLTR_SWS; +#define FLTR_SW_SET 0x00000001 +#define FLTR_SW_NO_DISCARD 0x00000002 /* always reject spam */ +#define FLTR_SW_DCC_OFF 0x00000004 /* no DCC check */ +#define FLTR_SW_REP_ON 0x00000008 /* honor DCC reputation */ +#define FLTR_SW_LOG_ALL 0x00000010 +#define FLTR_SW_GREY_OFF 0x00000020 /* greylisting off */ +#define FLTR_SW_GREY_LOG_OFF 0x00000040 /* log greylist embargos */ +#define FLTR_SW_LOG_D 0x00000080 +#define FLTR_SW_LOG_H 0x00000100 +#define FLTR_SW_LOG_M 0x00000200 +#define FLTR_SW_MTA_FIRST 0x00000400 /* MTA IS/NOTSPAM checked first */ +#define FLTR_SW_TRAP_ACC 0x00000800 /* accepting spam trap */ +#define FLTR_SW_TRAP_REJ 0x00001000 /* rejecting spam trap */ +# define FLTR_SW_TRAPS (FLTR_SW_TRAP_ACC | FLTR_SW_TRAP_REJ) +#define FLTR_SW_DNSBL(n) (0x00002000*DNSBL_G2B(n)) /* check DNSBL */ +# define FLTR_SW_DNSBL_M 0x0000e000 +# define FLTR_SW_DNSBL_BITS(sws) (((sws)&FLTR_SW_DNSBL_M) \ + / FLTR_SW_DNSBL(0)) + +/* bits set to enable something */ +#define FLTR_SWS_SETTINGS_ON (FLTR_SW_REP_ON \ + | FLTR_SW_LOG_ALL \ + | FLTR_SW_MTA_FIRST \ + | FLTR_SW_DNSBL_M \ + | FLTR_SW_TRAPS) +/* bits set to disable something */ +#define FLTR_SWS_SETTINGS_OFF (FLTR_SW_DCC_OFF \ + | FLTR_SW_NO_DISCARD \ + | FLTR_SW_TRAP_REJ \ + | FLTR_SW_GREY_OFF \ + | FLTR_SW_GREY_LOG_OFF) +/* get bits of enabled FILTERS */ +#define FLTR_SWS_ON(sws) (((sws) ^ FLTR_SW_DCC_OFF) \ + & (FLTR_SW_DCC_OFF \ + | FLTR_SW_REP_ON \ + | FLTR_SW_DNSBL_M \ + | FLTR_SW_TRAP_REJ)) + + +/* everything there is to know about a currently active whitelist file */ +typedef struct { + DCC_WHITE_TBL *wtbl; + int ht_fd; /* hash table file */ + struct stat ht_sb; + DCC_WHITE_FGS wtbl_flags; + u_int wtbl_entries; /* # of entries mapped window */ + u_int wtbl_size; /* bytes in mapped window */ + time_t next_stat_time; + time_t reparse; /* when to re-parse file */ + time_t broken; /* something very sick until then */ +#ifdef DCC_WIN32 + HANDLE ht_map; /* WIN32 hash table map handle */ +#endif + u_int ascii_nm_len; + DCC_PATH ascii_nm; + DCC_PATH ht_nm; + int fno, lno; /* currently being parsed */ + u_char wf_flags; +# define DCC_WF_PER_USER 0x01 /* hostnames not allowed */ +# define DCC_WF_NOFILE 0x02 /* no whiteclnt file */ +# define DCC_WF_EITHER 0x04 /* either global or per-user ok */ +# define DCC_WF_RO 0x08 /* read only access */ +# define DCC_WF_WLIST 0x10 /* wlist command */ +# define DCC_WF_WLIST_RO 0x20 /* read-only wlist command */ +# define DCC_WF_WLIST_RW 0x40 /* read/write wlist command */ + u_char closed; + u_char need_reopen; /* lock-safe change flag */ +} DCC_WF; + +extern DCC_WF cmn_wf, cmn_tmp_wf; + +typedef enum { /* greylist result */ + ASK_GREY_FAIL, /* greylist server or other failure */ + ASK_GREY_OFF, /* client whitelist or blacklist */ + ASK_GREY_EMBARGO, + ASK_GREY_EMBARGO_END, /* first time server says ok */ + ASK_GREY_PASS, /* greylist server says ok */ + ASK_GREY_WHITE, /* greylist server says whitelisted */ + ASK_GREY_SPAM /* reported as spam to server */ +} ASK_GREY_RESULT; + +extern u_char grey_on; +extern u_char grey_query_only; + +extern u_int dcc_ck_qp_decode(DCC_GOT_CKS *, const char **, u_int *, + char *, u_int); +extern u_int dcc_ck_b64_decode(DCC_GOT_CKS *, const char **, u_int *, + char *, u_int); + +extern int dcc_ck_url(DCC_URL_SKIP *, char, char **); +#define DCC_CK_URL_MASK 0xff +#define DCC_CK_URL_SHIFT 8 +typedef enum { + DCC_CK_URL_CHAR, /* character in URL after host name */ + DCC_CK_URL_CK_LEN, /* 2nd slash */ + DCC_CK_URL_HOST, /* character in URL host name */ + DCC_CK_URL_DOT, /* dot in host name */ + DCC_CK_URL_HOST_END, /* end of host name */ + DCC_CK_URL_HOST_RESET, /* wasn't in host name after all */ + DCC_CK_URL_SKIP /* shipping URL or not in URL */ +} DCC_CK_URL; + +extern void dcc_ck_fuz1_init(DCC_GOT_CKS *); +extern void dcc_ck_fuz1(DCC_GOT_CKS *, const char *, u_int); +extern void dcc_ck_fuz1_fin(DCC_GOT_CKS *); + +extern void dcc_ck_fuz2_init(DCC_GOT_CKS *); +extern void dcc_ck_fuz2(DCC_GOT_CKS *, const char *, u_int); +extern void dcc_ck_fuz2_fin(DCC_GOT_CKS *); + + +extern void dcc_wf_init(DCC_WF *, u_int); +extern void dcc_wf_lock(DCC_WF *); +extern void dcc_wf_unlock(DCC_WF *); + +extern void dcc_str2ck(DCC_SUM, const char *, u_int, const char *); +extern u_char dcc_get_cks(DCC_GOT_CKS *, DCC_CK_TYPES, const char *, u_char); +extern u_char dcc_ck_get_sub(DCC_GOT_CKS *, const char *, const char *); +extern u_char dcc_add_sub_hdr(DCC_EMSG, const char *); +extern void dcc_ck_ipv6(DCC_SUM, const struct in6_addr *); +extern void dcc_get_ipv6_ck(DCC_GOT_CKS *, const struct in6_addr *); +extern void dcc_unget_ip_ck(DCC_GOT_CKS *); +extern u_char dcc_get_str_ip_ck(DCC_GOT_CKS *, const char *); +extern const char *parse_received(const char *, DCC_GOT_CKS *, + char *, int, char *, int, char *, int); +extern u_char parse_return_path(const char *, char *, int); +extern u_char parse_unix_from(const char *, char *, int); +extern u_char parse_mail_host(const char *, char *, int); +extern void dcc_print_cks(LOG_WRITE_FNC, void *, u_char, DCC_TGTS, + const DCC_GOT_CKS *, DCC_CKS_WTGTS, u_char); +#define PRINT_CK_TYPE_LEN 25 +#define PRINT_CK_SUM_LEN 35 +#define PRINT_CK_PAT_CK "%25s: %-35s" +#define PRINT_CK_PAT_LIM_CK "%25.*s%c %-35.*s" +#define PRINT_CK_PAT_SRVR " %7s" +#define PRINT_CK_PAT_SRVR_LEN 8 +#define PRINT_CK_PAT_WLIST " %5s" +#define PRINT_CK_PAT_WLIST_LEN 6 +#define PRINT_CK_PAT_THOLD PRINT_CK_PAT_WLIST + +extern void dcc_cks_init(DCC_GOT_CKS *); +extern void dcc_ck_mime_hdr(DCC_GOT_CKS *, const char *, const char *); +extern u_char parse_mime_hdr(DCC_GOT_CKS *, const char *, u_int, u_char); +extern void dcc_ck_body(DCC_GOT_CKS *, const void *, u_int); +extern void dcc_cks_fin(DCC_GOT_CKS *); + +extern u_char dcc_get_white(DCC_EMSG, DCC_WHITE_INX); + +typedef int (*DCC_PARSED_CK_FNC)(DCC_EMSG, DCC_WF *, + DCC_CK_TYPES, /* type of checksum */ + DCC_SUM, /* computed checksum */ + DCC_TGTS); /* "OK2" etc */ +typedef int (*DCC_PARSED_CK_CIDR_FNC)(DCC_EMSG, DCC_WF *, + int, + const struct in6_addr *, + const struct in6_addr *, + DCC_TGTS); +extern int dcc_parse_ck(DCC_EMSG, DCC_WF *wf, + const char *, DCC_CK_TYPES, const char *, DCC_TGTS, + DCC_PARSED_CK_FNC, DCC_PARSED_CK_CIDR_FNC); +extern int dcc_parse_hex_ck(DCC_EMSG, DCC_WF *wf, + const char *, DCC_CK_TYPES, const char *, DCC_TGTS, + DCC_PARSED_CK_FNC); +extern const char *wf_fnm(const DCC_WF *, int); +extern const char *wf_fnm_lno(DCC_FNM_LNO_BUF *, const DCC_WF *); +extern DCC_TGTS dcc_str2thold(DCC_CK_TYPES, const char *); +extern int dcc_parse_whitefile(DCC_EMSG, DCC_WF *, int, + DCC_PARSED_CK_FNC, DCC_PARSED_CK_CIDR_FNC); + +typedef enum { + DCC_WHITE_USE_DCC, + DCC_WHITE_LISTED, + DCC_WHITE_UNLISTED, + DCC_WHITE_BLACK +} DCC_WHITE_LISTING; + +typedef enum { + DCC_WHITE_OK, + DCC_WHITE_NOFILE, /* no ASCII file */ + DCC_WHITE_CONTINUE, /* modest error or bad host name */ + DCC_WHITE_COMPLAIN, /* bad hash table */ + DCC_WHITE_SILENT /* no more complaints */ +} DCC_WHITE_RESULT; +#define DCC_WHITE_RESULT_FAILURE DCC_WHITE_UNLISTED + +u_char dcc_new_white_nm(DCC_EMSG, DCC_WF *, const char *); +extern DCC_WHITE_RESULT dcc_rdy_white(DCC_EMSG, DCC_WF *, DCC_WF *); +extern DCC_WHITE_RESULT dcc_white_sum(DCC_EMSG, DCC_WF *, + DCC_CK_TYPES, const DCC_SUM, + DCC_TGTS *, DCC_WHITE_LISTING *); +extern u_char dcc_white_mx(DCC_EMSG, DCC_TGTS *, const DCC_GOT_CKS *); +extern DCC_WHITE_RESULT dcc_white_cks(DCC_EMSG, DCC_WF *, DCC_GOT_CKS *, + DCC_CKS_WTGTS, DCC_WHITE_LISTING *); + + +typedef u_int32_t ASK_ST; +#define ASK_ST_INVALID_MSG 0x00000001 /* incomplete SMTP transaction */ +#define ASK_ST_QUERY 0x00000002 /* ask but do not report */ +#define ASK_ST_QUERY_GREY 0x00000004 +#define ASK_ST_SRVR_OK2 0x00000008 /* have honored DCC_TGTS_OK2 */ +#define ASK_ST_SRVR_NOTSPAM 0x00000010 /* not spam by DCC server */ +#define ASK_ST_SRVR_ISSPAM 0x00000020 /* spam by DCC server & threshold */ +#define ASK_ST_REP_ISSPAM 0x00000040 /* spam by reputation & threshold */ +#define ASK_ST_MTA_NOTSPAM 0x00000080 /* MTA says it is not spam */ +#define ASK_ST_MTA_ISSPAM 0x00000100 /* MTA says it is spam */ +#define ASK_ST_WLIST_NOTSPAM 0x00000200 /* locally whitelisted message */ +#define ASK_ST_WLIST_ISSPAM 0x00000400 /* locally blacklisted message */ +#define ASK_ST_CLNT_ISSPAM 0x00000800 /* report to DCC server as spam */ +#define ASK_ST_GREY_EMBARGO 0x00001000 /* embargo this message */ +#define ASK_ST_GREY_LOGIT 0x00002000 /* greylist logging indicated */ +#define ASK_ST_LOGIT 0x00004000 /* log message for all recipients */ +#define ASK_ST_DNSBL_HIT(n) (0x00008000*DNSBL_G2B(n)) /* DNSBL hit */ +# define ASK_ST_DNSBL_HIT_M 0x00038000 +# define ASK_ST_DNSBL_HIT_BITS(st) (((st)&ASK_ST_DNSBL_HIT_M) \ + / ASK_ST_DNSBL_HIT(0)) +#define ASK_ST_DNSBL_TIMEO(n) (0x00040000*DNSBL_G2B(n)) /* DNSBL timeout */ +# define ASK_ST_DNSBL_TIMEO_M 0x001c0000 +# define ASK_ST_DNSBL_TIMEO_BITS(st) (((st)&ASK_ST_DNSBL_TIMEO_M) \ + / ASK_ST_DNSBL_TIMEO(0)) +#define ASK_ST_DNSBL_TFAIL(n) (0x00200000*DNSBL_G2B(n)) +# define ASK_ST_DNSBL_TFAIL_M 0x00e00000 +# define ASK_ST_DNSBL_TFAIL_BITS(st) (((st)&ASK_ST_DNSBL_TFAIL_M) \ + / ASK_ST_DNSBL_TFAIL(0)) + + +extern u_char dcc_ck_grey_answer(DCC_EMSG, const DCC_OP_RESP *); +extern int ask_dcc(DCC_EMSG, DCC_CLNT_CTXT *, u_char, + DCC_HEADER_BUF *, DCC_GOT_CKS *, ASK_ST *, u_char, + DCC_TGTS); +extern u_char unthr_ask_white(DCC_EMSG, ASK_ST *, FLTR_SWS *, const char *, + DCC_GOT_CKS *, DCC_CKS_WTGTS); +extern u_char unthr_ask_dcc(DCC_EMSG, DCC_CLNT_CTXT*, DCC_HEADER_BUF*, ASK_ST *, + DCC_GOT_CKS *, u_char, DCC_TGTS); +extern void dcc_clear_tholds(void); +extern u_char dcc_merge_tholds(DCC_CKSUM_THOLDS, + const DCC_CKSUM_THOLDS, const DCC_WHITE_TBL *); +extern void dcc_parse_honor(const char *); +extern u_char dcc_parse_tholds(const char *, const char *); +extern void dcc_honor_log_cnts(ASK_ST *, const DCC_GOT_CKS *, DCC_TGTS); +extern FLTR_SWS wf2sws(FLTR_SWS, const DCC_WF *); +extern void log_ask_st(LOG_WRITE_FNC, void *, ASK_ST, FLTR_SWS, u_char, + const DCC_HEADER_BUF *); +extern u_char dcc_parse_client_grey(const char *); +extern ASK_GREY_RESULT ask_grey(DCC_EMSG, DCC_CLNT_CTXT *, DCC_OPS, + DCC_SUM, DCC_SUM, + const DCC_GOT_CKS *, const DCC_SUM, + DCC_TGTS *, DCC_TGTS *, DCC_TGTS *); + +extern u_char dcc_parse_dnsbl(DCC_EMSG, const char *, const char *, u_char); +extern const REPLY_TPLT *dnsbl_parse_reply(const char *); +extern void helper_save_arg(const char *, const char *); +extern void helper_init(int); +extern void dcc_dnsbl_init(DCC_GOT_CKS *, + DCC_CLNT_CTXT *, void *, const char *); +extern void url_dnsbl(DNSBL_WORK *); +extern void dcc_mail_host_dnsbl(DNSBL_WORK *, const char *); +extern void dcc_client_dnsbl(DNSBL_WORK *, const struct in6_addr *, + const char *); +extern void dcc_dnsbl_result(ASK_ST *, DNSBL_WORK *); +extern int PATTRIB(3,4) thr_log_print(void *, u_char, const char *, ...); +extern int PATTRIB(2,3) thr_error_msg(void *, const char *, ...); +extern void PATTRIB(2,3) thr_trace_msg(void *, const char *, ...); + +#endif /* DCC_CK_H */