Mercurial > dnsbl
view src/context.h @ 225:8e1cbf3d96fc stable-6-0-20
simple dns lookup failure need not kill the resolver process
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Mon, 29 Dec 2008 18:12:22 -0800 |
parents | 82886d4dd71f |
children | 5c3e9bf45bb5 |
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 enum status {oksofar, // not rejected yet white, // whitelisted black, // blacklisted reject}; // rejected by a dns list class DNSBL; class CONTEXT; class VERIFY; class SMTP; class WHITELISTER; class DELAYWHITE; class recorder; typedef map<const char *, const char *, ltstr> string_map; typedef set<int> int_set; typedef list<SMTP *> smtp_list; typedef DNSBL * DNSBLP; typedef VERIFY * VERIFYP; typedef WHITELISTER * WHITELISTERP; typedef DELAYWHITE * DELAYWHITEP; typedef list<DNSBLP> dnsblp_list; typedef map<const char *, DNSBLP, ltstr> dnsblp_map; typedef CONTEXT * CONTEXTP; typedef list<CONTEXTP> context_list; typedef map<const char *, CONTEXTP, ltstr> context_map; typedef map<const char *, int, ltstr> ns_mapper; typedef map<const char *, int, ltstr> rcpt_rates; 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; 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]; public: SMTP(int f) {fd = f; error = false; now(); efrom[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;}; 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(); #ifdef VERIFY_DEBUG static void log(const char *m, int v); static void log(const char *m, const char *v); #endif }; 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 closer(); // if the oldest socket is ancient, close it SMTP *get_connection(); void put_connection(SMTP *conn); bool ok(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 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); }; 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 * 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; // string_set content_cctlds; // 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 dcc_greylist; // should we do dcc greylisting? int dcc_bulk_threshold; // off = 0, many = 1000 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 int default_rcpt_rate; // if not specified per user rcpt_rates rcpt_per_hour; // per user limits on number of recipients 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(int limit) {default_rcpt_rate = limit;}; void add_rate(const char *user, int limit) {rcpt_per_hour[user] = limit;}; int find_rate(const char *user); 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); 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_cctld(const char *cctld) {content_cctlds.insert(cctld); }; 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); }; 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); 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_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_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_cctlds(); string_set& get_html_tags(); dnsblp_list& get_dnsbl_list(); bool acceptable_content(recorder &memory, int score, int bulk, 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_autowhite; extern const char *token_black; extern const char *token_cctld; 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_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_rate; extern const char *token_rbrace; extern const char *token_require; 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_yes; 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