Mercurial > dnsbl
changeset 268:f941563c2a95 stable-6-0-34
Add require_rdns checking
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Wed, 22 May 2013 11:29:44 -0700 |
parents | db12f6028f8b |
children | 6d2a11f0ae41 |
files | ChangeLog NEWS configure.in dnsbl.conf dnsbl.spec.in src/context.cpp src/context.h src/dnsbl.cpp src/dnsbl.h xml/dnsbl.in |
diffstat | 10 files changed, 70 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Sat Jul 21 13:13:07 2012 -0700 +++ b/ChangeLog Wed May 22 11:29:44 2013 -0700 @@ -1,3 +1,6 @@ +6.34 2013-05-22 + Add require_rdns checking. + 6.33 2012-07-21 Fix unauthenticated rate limit bug for empty mail from. Move unauthenticated rate limit checks after spam filtering.
--- a/NEWS Sat Jul 21 13:13:07 2012 -0700 +++ b/NEWS Wed May 22 11:29:44 2013 -0700 @@ -1,3 +1,4 @@ +6.34 2013-05-22 Add require_rdns checking. 6.33 2012-07-21 Fix unauthenticated rate limit bug for empty mail from. Move unauthenticated rate limit checks after spam filtering. 6.32 2012-07-21 Allow rate limiting for unauthentication connections by mail from address or domain. 6.31 2012-07-01 Fix uribl lookups on client dns name.
--- a/configure.in Sat Jul 21 13:13:07 2012 -0700 +++ b/configure.in Wed May 22 11:29:44 2013 -0700 @@ -1,6 +1,6 @@ AC_PREREQ(2.59) -AC_INIT(dnsbl,6.33,carl@five-ten-sg.com) +AC_INIT(dnsbl,6.34,carl@five-ten-sg.com) AC_CONFIG_SRCDIR([config.h.in]) AC_CONFIG_HEADER([config.h])
--- a/dnsbl.conf Sat Jul 21 13:13:07 2012 -0700 +++ b/dnsbl.conf Wed May 22 11:29:44 2013 -0700 @@ -48,6 +48,7 @@ dnswl dnswl.org list.dnswl.org 2; dnsbl_list local sbl; dnswl_list dnswl.org; + require_rdns yes; content on { filter sbl-xbl.spamhaus.org "Mail containing %s rejected - sbl; see http://www.spamhaus.org/query/bl?ip=%s";
--- a/dnsbl.spec.in Sat Jul 21 13:13:07 2012 -0700 +++ b/dnsbl.spec.in Wed May 22 11:29:44 2013 -0700 @@ -103,6 +103,9 @@ %changelog +* Wed May 22 2013 Carl Byington <carl@five-ten-sg.com> - 6.34-1 +- Add require_rdns checking. + * Sat Jul 21 2012 Carl Byington <carl@five-ten-sg.com> - 6.33-1 - Fix unauthenticated rate limit bug for empty mail from. Move unauthenticated rate limit checks after spam filtering.
--- a/src/context.cpp Sat Jul 21 13:13:07 2012 -0700 +++ b/src/context.cpp Wed May 22 11:29:44 2013 -0700 @@ -55,6 +55,7 @@ const char *token_rate; const char *token_rbrace; const char *token_require; +const char *token_requirerdns; const char *token_semi; const char *token_soft; const char *token_spamassassin; @@ -725,6 +726,7 @@ tag_limit_message = NULL; spamassassin_limit = (parent) ? parent->spamassassin_limit : 0; require_match = (parent) ? parent->require_match : false; + require_rdns = (parent) ? parent->require_rdns : false; dcc_greylist = (parent) ? parent->dcc_greylist : false; dcc_bulk_threshold = (parent) ? parent->dcc_bulk_threshold : 0; dnsbl_list_parsed = false; @@ -1074,6 +1076,7 @@ printf(" %s", d.name); } printf("; \n"); + printf("%s require_rdns %s; \n", indent, (require_rdns) ? "yes" : "no"); } { @@ -1350,6 +1353,22 @@ //////////////////////////////////////////////// // +bool parse_requirerdns(TOKEN &tok, CONFIG &dc, CONTEXT &me); +bool parse_requirerdns(TOKEN &tok, CONFIG &dc, CONTEXT &me) { + const char *have = tok.next(); + if (have == token_yes) me.set_requirerdns(true); + else if (have == token_no) me.set_requirerdns(false); + else { + tok.token_error("yes/no", have); + return false; + } + if (!tsa(tok, token_semi)) return false; + return true; +} + + +//////////////////////////////////////////////// +// bool parse_content(TOKEN &tok, CONFIG &dc, CONTEXT &me); bool parse_content(TOKEN &tok, CONFIG &dc, CONTEXT &me) { const char *setting = tok.next(); @@ -1768,6 +1787,9 @@ else if (have == token_dnswll) { if (!parse_dnswll(tok, dc, *con)) return false; } + else if (have == token_requirerdns) { + if (!parse_requirerdns(tok, dc, *con)) return false; + } else if (have == token_content) { if (!parse_content(tok, dc, *con)) return false; } @@ -1877,6 +1899,7 @@ token_rate = register_string("rate_limit"); token_rbrace = register_string("}"); token_require = register_string("require_match"); + token_requirerdns = register_string("require_rdns"); token_semi = register_string(";"); token_soft = register_string("soft"); token_spamassassin = register_string("spamassassin");
--- a/src/context.h Sat Jul 21 13:13:07 2012 -0700 +++ b/src/context.h Wed May 22 11:29:44 2013 -0700 @@ -171,6 +171,7 @@ 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 dnsblp_map dnsbl_names; // name to dnsbl mapping for lists that are available in this context and children @@ -254,11 +255,13 @@ 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;}; @@ -338,6 +341,7 @@ 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;
--- a/src/dnsbl.cpp Sat Jul 21 13:13:07 2012 -0700 +++ b/src/dnsbl.cpp Wed May 22 11:29:44 2013 -0700 @@ -488,6 +488,7 @@ authenticated = NULL; client_name = NULL; client_dns_name = NULL; + client_dns_forged = false; host_uribl = NULL; helo_uribl = false; client_uribl = false; @@ -1149,6 +1150,15 @@ //snprintf(text, sizeof(text), "found simple dns client name %s", priv.client_dns_name); //my_syslog(text); } + p = strstr(priv.client_name, "] (may be forged)"); + if (p) { + priv.client_dns_forged = true; + if (priv.client_dns_name) { + char text[500]; + snprintf(text, sizeof(text), "forged dns client name %s", priv.client_dns_name); + my_syslog(text); + } + } } if (spamc != spamc_empty) { priv.assassin = new SpamAssassin(&priv, priv.ip, priv.helo, priv.mailaddr, priv.queueid); @@ -1247,6 +1257,15 @@ return SMFIS_REJECT; } if (st == oksofar) { + // check forged rdns + if (con.get_requirerdns() && (!priv.client_dns_name || priv.client_dns_forged)) { + // reject the recipient based on forged reverse dns + char buf[maxlen]; + snprintf(buf, sizeof(buf), "%s is not acceptable", priv.client_name); + smfi_setreply(ctx, (char*)"550", (char*)"5.7.1", buf); + return SMFIS_REJECT; + } + // check generic rdns const char *msg = con.generic_match(priv.client_name); if (msg) { // reject the recipient based on generic reverse dns @@ -1323,12 +1342,12 @@ snprintf(bu, sizeof(bu), "(helo %s)", priv.host_uribl); uri = true; } - // content filterint implies also checking client reverse dns name on uribl (if enabled) + // content filtering implies also checking client reverse dns name on uribl (if enabled) if (priv.client_uribl) { snprintf(bu, sizeof(bu), "(rdns %s)", priv.host_uribl); uri = true; } - // content filterint implies also checking mail from domain name on uribl (if enabled) + // content filtering implies also checking mail from domain name on uribl (if enabled) if (priv.from_uribl) { snprintf(bu, sizeof(bu), "(from %s)", priv.host_uribl); uri = true;
--- a/src/dnsbl.h Sat Jul 21 13:13:07 2012 -0700 +++ b/src/dnsbl.h Wed May 22 11:29:44 2013 -0700 @@ -42,6 +42,7 @@ const char *authenticated; // client authenticated? if so, suppress all dnsbl checks, but check rate limits const char *client_name; // fully qualified host name of the smtp client xxx [ip.ad.dr.es] (may be forged) char *client_dns_name; // fully qualified host name of the smtp client xxx + bool client_dns_forged; // rdns mismatch const char *host_uribl; // pointer to helo/client/from host name if found on uribl string_set hosts_uribl; // string set to hold the helo/client/from host name if found on uribl bool helo_uribl; // helo value on uribl
--- a/xml/dnsbl.in Sat Jul 21 13:13:07 2012 -0700 +++ b/xml/dnsbl.in Wed May 22 11:29:44 2013 -0700 @@ -335,8 +335,8 @@ </para> <para> If the client has authenticated with sendmail, the rate limits are - checked. If the authenticated user has not exceeded the hourly rate - limit, then the mail is accepted, the filtering contexts are not used, + checked. If the authenticated user has not exceeded the hourly or daily rate + limits, then the mail is accepted, the filtering contexts are not used, the dns lists are not checked, and the body content is not scanned. If the client has not authenticated with sendmail, we follow these steps for each recipient. @@ -405,6 +405,11 @@ </para></listitem> <listitem><para> If the mail has not been accepted or rejected yet, and the filtering + context (or any ancestor context) requires matching reverse dns client + name, the mail is rejected if the client name is empty or forged. + </para></listitem> + <listitem><para> + If the mail has not been accepted or rejected yet, and the filtering context (or any ancestor context) specifies a non-empty generic regular expression, then we check the fully qualified client name (obtained via the sendmail macro "_"). The mail is rejected if the client name @@ -597,10 +602,6 @@ Add the ability to use the DBL for content filtering. We need to avoid checking bare ip addresses against that list. </para> - <para> - Add daily recipient limits based on some fixed multiple (perhaps 3?) - of the hourly limit. - </para> </refsect1> <refsect1 id='copyright.1'> @@ -672,7 +673,7 @@ CONTEXT = "context" NAME "{" {STATEMENT}+ "}" STATEMENT = (DNSBL | DNSBLLIST | DNSWL | DNSWLLIST | CONTENT | ENV-TO | VERIFY | GENERIC | W_REGEX | AUTOWHITE | CONTEXT | ENV-FROM - | RATE-LIMIT) ";" + | RATE-LIMIT | REQUIRERDNS) ";" DNSBL = "dnsbl" NAME DNSPREFIX ERROR-MSG1 DNSBLLIST = "dnsbl_list" {NAME}* @@ -681,6 +682,8 @@ DNSWLLIST = "dnswl_list" {NAME}* LEVEL = INTEGER +REQUIRERDNS = "require_rdns" ("yes" | "no") + CONTENT = "content" ("on" | "off") "{" {CONTENT-ST}+ "}" CONTENT-ST = (FILTER | URIBL | IGNORE | TLD | CCTLD | HTML-TAGS | HTML-LIMIT | HOST-LIMIT | SPAMASS | REQUIRE | DCCGREY | @@ -787,6 +790,7 @@ dnswl dnswl.org list.dnswl.org 2; dnsbl_list local sbl; dnswl_list dnswl.org; + require_rdns yes; content on { filter sbl-xbl.spamhaus.org "Mail containing %s rejected - sbl; see http://www.spamhaus.org/query/bl?ip=%s";