Mercurial > dnsbl
view src/context.h @ 435:afd10321eb70
Added tag stable-6-0-63 for changeset a83ed5615403
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Tue, 24 Oct 2017 09:17:10 -0700 |
parents | 6f2db3d19a34 |
children | 7b072e16bd69 |
line wrap: on
line source
/* Copyright (c) 2007 Carl Byington - 510 Software Group, released under the GPL version 3 or any later version at your choice available at http://www.gnu.org/licenses/gpl-3.0.txt */ #ifndef context_include #define context_include #ifdef NS_PACKETSZ #define maxdnslength (NS_PACKETSZ*8) #else #define maxdnslength 1000 #endif enum status {oksofar, // not rejected yet white, // whitelisted black, // blacklisted reject}; // rejected by a dns list class DKIM; class DNSBL; class DNSWL; class CONTEXT; class VERIFY; class SMTP; class WHITELISTER; class DELAYWHITE; class recorder; class mlfiPriv; typedef map<const char *, const char *, ltstr> string_map; typedef set<int> int_set; typedef set<int32_t> int32_t_set; typedef int32_t_set * int32_t_set_p; typedef set<uint32_t> uint32_t_set; typedef uint32_t_set * uint32_t_set_p; typedef list<SMTP *> smtp_list; typedef DKIM * DKIMP; typedef DNSBL * DNSBLP; typedef DNSWL * DNSWLP; typedef VERIFY * VERIFYP; typedef WHITELISTER * WHITELISTERP; typedef DELAYWHITE * DELAYWHITEP; typedef map<const char *, DKIMP, ltstr> dkimp_map; typedef list<DNSBLP> dnsblp_list; typedef map<const char *, DNSBLP, ltstr> dnsblp_map; typedef list<DNSWLP> dnswlp_list; typedef map<const char *, DNSWLP, ltstr> dnswlp_map; typedef CONTEXT * CONTEXTP; typedef list<CONTEXTP> context_list; typedef map<const char *, CONTEXTP, ltstr> context_map; typedef map<const char *, uint32_t, ltstr> ns_mapper; // name to ipv4 address typedef map<const char *, int, ltstr> rates; typedef map<const char *, uint32_t_set_p, ltstr> auth_addresses; typedef map<const char *, time_t, ltstr> autowhite_sent; typedef map<const char *, VERIFYP, ltstr> verify_map; typedef map<const char *, WHITELISTERP, ltstr> whitelister_map; typedef list<DELAYWHITEP> delay_whitelist; class SMTP { static const int maxlen = 1000; static const int qlen = 20; int fd; bool error; time_t stamp; char efrom[maxlen]; // last envelope from sent on this socket int pending; // unread bytes in buffer, not including the null terminator char buffer[maxlen]; char queueid[qlen]; // last queueid for logging public: SMTP(int f) {fd = f; error = false; now(); efrom[0] = '\0'; queueid[0] = '\0'; init();}; ~SMTP() {if (!error) quit(); closefd();}; void init() {pending = 0; buffer[0] = '\0';}; void append(const char *c) {strncat(buffer, c, max(0, maxlen-1-(int)strlen(c)));}; bool err() {return error;}; void now() {stamp = time(NULL);}; time_t get_stamp() {return stamp;}; int get_fd() {return fd;}; void set_id(const char *id) {strncpy(queueid, id, qlen); queueid[qlen-1] = '\0';}; int writer(); int reader(); int read_line(); int read_response(); void flush_line(int r); int cmd(const char *c); int helo(); int rset(); int from(const char *f); int rcpt(const char *t); int quit(); void closefd(); void log(const char *m, int v); void log(const char *m, const char *v); }; class VERIFY { const char *host; // host to be used to verify recipient addresses time_t last_err; // time of last socket error pthread_mutex_t mutex; // protect the lists of sockets and timestamps smtp_list connections;// open sockets, ready to be used public: VERIFY(const char *h); void log(const char *m, const char *q, const char *v); void closer(); // if the oldest socket is ancient, close it SMTP *get_connection(const char *queueid); void put_connection(SMTP *conn); bool ok(const char *queueid, const char *from, const char *to); }; class WHITELISTER { const char *fn; // file to use int days; // how long do we keep entries pthread_mutex_t mutex; // protect the flag and map time_t loaded; // when we loaded this file bool need; // force writing on new entries autowhite_sent rcpts; // recipient map to remember when we sent them mail public: WHITELISTER(const char *f, int d); void merge(); void writer(); // dump any changes back to the file void sent(const char *to); bool is_white(const char *from); // should we white list this sender (did we send them anything recently) int get_days() {return days;}; void set_days(int d) {days = d;}; }; class DELAYWHITE { const char *loto; WHITELISTERP w; CONTEXTP con; public: DELAYWHITE(const char *loto_, WHITELISTERP w_, CONTEXTP con_); const char *get_loto() {return loto;}; WHITELISTERP get_w() {return w;}; CONTEXTP get_con() {return con;}; }; struct DKIM { const char *action; const char *signer; public: DKIM(const char *action_, const char *signer_); }; struct DNSBL { const char *name; // nickname for this dns based list const char *suffix; // blacklist suffix like blackholes.five-ten-sg.com const char *message; // error message with one or two %s operators for the ip address replacement DNSBL(const char *n, const char *s, const char *m); bool operator==(const DNSBL &rhs); }; struct DNSWL { const char *name; // nickname for this dns based list const char *suffix; // whitelist suffix like list.dnswl.org int level; // matches 127.0.x.y where y >= level DNSWL(const char *n, const char *s, const int l); bool operator==(const DNSWL &rhs); }; class CONTEXT { CONTEXTP parent; const char * name; context_map children; // map child context names to their contexts string_set env_to; // this context applies to these envelope recipients const char * verify_host; // use this smtp host to verify email addresses VERIFYP verifier; // pointer to the verifier structure const char * generic_regx; // pointer to generic regular expression const char * generic_message; // pointer to generic message with one %s regex_t generic_pattern; // compiled regex pattern const char * white_regx; // pointer to whitelist regular expression regex_t white_pattern; // compiled regex pattern const char * autowhite_file; // file to use for automatic whitelisting WHITELISTERP whitelister; // pointer to the auto whitelister structure string_map env_from; // map senders to white/black/unknown context_map env_from_context; // map senders to a child context const char * env_from_default; // default value for senders that are not found in the map white/black/unknown/inherit bool content_filtering; // const char * content_suffix; // for url body filtering based on ip addresses of hostnames in the body const char * content_message; // "" const char * uribl_suffix; // for uribl body filtering based on hostnames in the body const char * uribl_message; // "" string_set content_host_ignore; // hosts to ignore for content sbl checking string_set content_tlds; // names that are tlds string_set content_tldwilds; // *.names that are tlds string_set content_tldnots; // names that are not tlds string_set html_tags; // set of valid html tags int host_limit; // limit on host names const char * host_limit_message; // error message for excessive host names bool host_random; // pick a random selection of host names rather than error for excessive hosts int tag_limit; // limit on bad html tags const char * tag_limit_message; // error message for excessive bad html tags int spamassassin_limit; // max score from spamassassin bool require_match; // require matching context filtering context bool require_rdns; // require proper rdns on client ip bool dcc_greylist; // should we do dcc greylisting? int dcc_bulk_threshold; // off = 0, many = 1000 dkimp_map dkim_from_names; // map header from domains to dkim constraints string_map dkim_signer_names; // map dkim signers to actions dnsblp_map dnsbl_names; // name to dnsbl mapping for lists that are available in this context and children dnsblp_list dnsbl_list; // list of dnsbls to be used in this context bool dnsbl_list_parsed; // true iff we have actually parsed a dnsbl_list dnswlp_map dnswl_names; // name to dnswl mapping for lists that are available in this context and children dnswlp_list dnswl_list; // list of dnswls to be used in this context bool dnswl_list_parsed; // true iff we have actually parsed a dnswl_list int default_rate_limit; // if not specified per user int default_address_limit; // if not specified per user int daily_rate_multiple; // daily multiplier applied to hourly rate int daily_address_multiple; // daily multiplier applied to hourly rate rates rcpt_per_hour; // per user limits on number of recipients per hour rates addresses_per_hour; // per user limits on number of unique ip address connections per hour public: CONTEXT(CONTEXTP parent_, const char *name_); ~CONTEXT(); CONTEXTP get_parent() {return parent;}; bool is_parent(CONTEXTP p); // is p a parent of this? const char* get_full_name(char *buffer, int size); void add_context(CONTEXTP child) {children[child->name] = child;}; bool allow_env_to(const char *to) {return (parent) ? parent->cover_env_to(to) : true;}; bool cover_env_to(const char *to); void set_verifier(VERIFYP v) {verifier = v;}; void set_verify(const char *host) {verify_host = host;}; const char* get_verify() {return verify_host;}; VERIFYP find_verify(const char *to); void set_whitelister(WHITELISTERP v) {whitelister = v;}; void set_autowhite(const char *fn) {autowhite_file = fn;}; const char* get_autowhite() {return autowhite_file;}; WHITELISTERP find_autowhite(const char *from, const char *to); void set_default_rate_limit(int limit) {default_rate_limit = limit;}; void set_default_address_limit(int limit) {default_address_limit = limit;}; void set_daily_rate_multiple(int multiple) {daily_rate_multiple = multiple;}; void set_daily_address_multiple(int multiple) {daily_address_multiple = multiple;}; void add_rate_limit(const char *user, int limit) {rcpt_per_hour[user] = limit;}; void add_address_limit(const char *user, int limit) {addresses_per_hour[user] = limit;}; int find_rate_limit(const char *user); // recipients per hour/day int find_address_limit(const char *user); // unique ip address connections per hour/day bool is_unauthenticated_limited(const char *user); int get_daily_rate_multiple() {return daily_rate_multiple;}; int get_daily_address_multiple() {return daily_address_multiple;}; void add_to(const char *to) {env_to.insert(to);}; void add_from(const char *from, const char *status) {env_from[from] = status;}; void add_from_context(const char *from, CONTEXTP con) {env_from_context[from] = con;}; void set_from_default(const char *status) {env_from_default = status;}; const char* find_from(const char *from, bool update_white = false, const char *queueid = NULL); CONTEXTP find_context(const char *from); CONTEXTP find_from_context_name(const char *name); void set_content_filtering(bool filter) {content_filtering = filter; }; void set_content_suffix(const char *suffix) {content_suffix = suffix; }; void set_content_message(const char *message) {content_message = message; }; void set_uribl_suffix(const char *suffix) {uribl_suffix = suffix; }; void set_uribl_message(const char *message) {uribl_message = message; }; void add_ignore(const char *host) {content_host_ignore.insert(host);}; void add_tld(const char *tld) {content_tlds.insert(tld); }; void add_tldwild(const char *tld) {content_tldwilds.insert(tld); }; void add_tldnot(const char *tld) {content_tldnots.insert(tld); }; void set_host_limit(int limit) {host_limit = limit; }; void set_host_message(const char *message) {host_limit_message = message;}; void set_host_random(bool random) {host_random = random; }; void set_spamassassin_limit(int limit) {spamassassin_limit = limit; }; void set_tag_limit(int limit) {tag_limit = limit; }; void set_tag_message(const char *message) {tag_limit_message = message;}; void add_tag(const char *tag) {html_tags.insert(tag); }; const char *find_dkim_signer(const char *name); void add_dkim_signer(const char *signer, const char *action) {dkim_signer_names[signer] = action;}; DKIMP find_dkim_from(const char *name); void add_dkim_from(const char *from, const char *action, const char *signer) {dkim_from_names[from] = new DKIM(action,signer);}; void add_dnsbl(const char *name, DNSBLP dns) {dnsbl_names[name] = dns; }; void add_dnsbl(DNSBLP dns) {dnsbl_list.push_back(dns);}; DNSBLP find_dnsbl(const char *name); void set_dnsbll_parsed() {dnsbl_list_parsed = true;}; void add_dnswl(const char *name, DNSWLP dns) {dnswl_names[name] = dns; }; void add_dnswl(DNSWLP dns) {dnswl_list.push_back(dns);}; DNSWLP find_dnswl(const char *name); void set_dnswll_parsed() {dnswl_list_parsed = true;}; bool set_white(const char *regx); bool white_match(const char *from); bool set_generic(const char *regx, const char *msg); const char* generic_match(const char *client); void set_require(bool r) {require_match = r; }; void set_requirerdns(bool r) {require_rdns = r; }; void set_grey(bool g) {dcc_greylist = g; }; void set_bulk(int b) {dcc_bulk_threshold = b; }; bool get_content_filtering() {return content_filtering; }; bool get_require() {return content_filtering && require_match; }; bool get_requirerdns() {return require_rdns; }; bool get_grey() {return content_filtering && dcc_greylist; }; int get_bulk() {return (content_filtering) ? dcc_bulk_threshold : 0;}; int get_host_limit() {return (content_filtering) ? host_limit : 0;}; bool get_host_random() {return (content_filtering) ? host_random : 0;}; int get_spamassassin_limit() {return (content_filtering) ? spamassassin_limit : 0;}; const char* get_content_suffix(); const char* get_content_message(); const char* get_uribl_suffix(); const char* get_uribl_message(); string_set& get_content_host_ignore(); string_set& get_content_tlds(); string_set& get_content_tldwilds(); string_set& get_content_tldnots(); string_set& get_html_tags(); dnsblp_list& get_dnsbl_list(); dnswlp_list& get_dnswl_list(); void log(const char *queueid, const char *msg, const char *v); bool in_signing_set(const char *s, const char *signers); void replace(char *buf, char *p, const char *what); bool resolve_spf(const char *from, uint32_t ip, mlfiPriv *priv); bool resolve_one_spf(const char *from, uint32_t ip, mlfiPriv *priv, int level = 0); const char *acceptable_content(recorder &memory, int score, int bulk, const char *queueid, string_set &signers, const char *from, mlfiPriv *priv, string& msg); bool ignore_host(const char *host); void dump(bool isdefault, bool &spamass, int level = 0); }; struct CONFIG { // the only mutable stuff once it has been loaded from the config file int reference_count; // protected by the global config_mutex // all the rest is constant after loading from the config file int generation; time_t load_time; string_set config_files; context_list contexts; // owns all the contexts, not just top level contexts context_map env_to; // map recipient to a filtering context CONTEXTP default_context;// for env_to values that don't have their own specific filtering context // the default context is also used for some of the content filtering values CONFIG(); ~CONFIG(); void add_context(CONTEXTP con); void add_to(const char *to, CONTEXTP con); CONTEXTP find_context(const char *to); void dump(); }; extern const char *token_asterisk; extern const char *token_autowhite; extern const char *token_bang; extern const char *token_black; extern const char *token_content; extern const char *token_context; extern const char *token_dccbulk; extern const char *token_dccfrom; extern const char *token_dccgrey; extern const char *token_dccto; extern const char *token_default; extern const char *token_dnsbl; extern const char *token_dnsbll; extern const char *token_dnswl; extern const char *token_dnswll; extern const char *token_envfrom; extern const char *token_envto; extern const char *token_filter; extern const char *token_generic; extern const char *token_host_limit; extern const char *token_html_limit; extern const char *token_html_tags; extern const char *token_ignore; extern const char *token_include; extern const char *token_inherit; extern const char *token_lbrace; extern const char *token_mailhost; extern const char *token_many; extern const char *token_no; extern const char *token_off; extern const char *token_ok; extern const char *token_ok2; extern const char *token_on; extern const char *token_period; extern const char *token_rate; extern const char *token_rbrace; extern const char *token_require; extern const char *token_requirerdns; extern const char *token_semi; extern const char *token_soft; extern const char *token_spamassassin; extern const char *token_substitute; extern const char *token_tld; extern const char *token_unknown; extern const char *token_uribl; extern const char *token_verify; extern const char *token_white; extern const char *token_white_regex; extern const char *token_yes; extern const char *token_dkim_signer; extern const char *token_dkim_from; extern const char *token_signed_white; extern const char *token_signed_black; extern const char *token_require_signed; extern const char *token_myhostname; extern pthread_mutex_t verifier_mutex; // protect the verifier map extern pthread_mutex_t whitelister_mutex; // protect the void discard(string_set &s); const char* register_string(string_set &s, const char *name); const char* register_string(const char *name); void clear_strings(); bool load_conf(CONFIG &dc, const char *fn); void* verify_closer(void *arg); void* whitelister_writer(void *arg); void token_init(); #endif