diff --git a/CHANGES b/CHANGES index e5164c0c..cee23824 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +11 Jul 2011 - trunk +------------------- + + * Add HttpBl support to rbl operator. + 30 Jun 2011 - 2.6.1-rc1 ------------------- diff --git a/apache2/apache2_config.c b/apache2/apache2_config.c index 99ac9305..ebc55e64 100644 --- a/apache2/apache2_config.c +++ b/apache2/apache2_config.c @@ -96,6 +96,7 @@ void *create_directory_config(apr_pool_t *mp, char *path) /* Misc */ dcfg->data_dir = NOT_SET_P; dcfg->webappid = NOT_SET_P; + dcfg->httpBlkey = NOT_SET_P; /* Content injection. */ dcfg->content_injection_enabled = NOT_SET; @@ -467,6 +468,8 @@ void *merge_directory_configs(apr_pool_t *mp, void *_parent, void *_child) ? parent->data_dir : child->data_dir); merged->webappid = (child->webappid == NOT_SET_P ? parent->webappid : child->webappid); + merged->httpBlkey = (child->httpBlkey == NOT_SET_P + ? parent->httpBlkey : child->httpBlkey); /* Content injection. */ merged->content_injection_enabled = (child->content_injection_enabled == NOT_SET @@ -580,6 +583,7 @@ void init_directory_config(directory_config *dcfg) /* Misc */ if (dcfg->data_dir == NOT_SET_P) dcfg->data_dir = NULL; if (dcfg->webappid == NOT_SET_P) dcfg->webappid = "default"; + if (dcfg->httpBlkey == NOT_SET_P) dcfg->httpBlkey = NULL; /* Content injection. */ if (dcfg->content_injection_enabled == NOT_SET) dcfg->content_injection_enabled = 0; @@ -1941,6 +1945,18 @@ static const char *cmd_web_app_id(cmd_parms *cmd, void *_dcfg, const char *p1) return NULL; } +static const char *cmd_httpBl_key(cmd_parms *cmd, void *_dcfg, const char *p1) +{ + directory_config *dcfg = (directory_config *)_dcfg; + + if (dcfg == NULL) return NULL; + + if (p1 == NULL) return NULL; + dcfg->httpBlkey = p1; + + return NULL; +} + /* PCRE Limits */ static const char *cmd_pcre_match_limit(cmd_parms *cmd, @@ -2652,5 +2668,13 @@ const command_rec module_directives[] = { "id" ), + AP_INIT_TAKE1 ( + "SecHttpBlKey", + cmd_httpBl_key, + NULL, + CMD_SCOPE_ANY, + "httpBl access key" + ), + { NULL } }; diff --git a/apache2/modsecurity.h b/apache2/modsecurity.h index 06015487..6db74202 100644 --- a/apache2/modsecurity.h +++ b/apache2/modsecurity.h @@ -486,6 +486,7 @@ struct directory_config { /* Misc */ const char *data_dir; const char *webappid; + const char *httpBlkey; /* Content injection. */ int content_injection_enabled; diff --git a/apache2/re_operators.c b/apache2/re_operators.c index d159e226..ea4c591f 100644 --- a/apache2/re_operators.c +++ b/apache2/re_operators.c @@ -2932,6 +2932,7 @@ static int msre_op_rbl_execute(modsec_rec *msr, msre_rule *rule, msre_var *var, unsigned int high8bits = 0; char *name_to_check = NULL; char *target = NULL; + char *target2 = NULL; apr_sockaddr_t *sa = NULL; apr_status_t rc; int capture = 0; @@ -2949,7 +2950,20 @@ static int msre_op_rbl_execute(modsec_rec *msr, msre_rule *rule, msre_var *var, /* Construct the host name we want to resolve. */ if (sscanf(target, "%d.%d.%d.%d", &h0, &h1, &h2, &h3) == 4) { /* IPv4 address */ - name_to_check = apr_psprintf(msr->mp, "%d.%d.%d.%d.%s", h3, h2, h1, h0, rule->op_param); + /* If we're using the httpBl blocklist, we need to add the key */ + if(strstr(rule->op_param,"httpbl.org")) { + if (msr->txcfg->httpBlkey == NULL) { + if (msr->txcfg->debuglog_level >= 4) { + msr_log(msr, 4, "RBL httpBl called but no key defined: set SecHttpBlKey"); + } + *error_msg = "RBL httpBl called but no key defined: set SecHttpBlKey"; + } else { + name_to_check = apr_psprintf(msr->mp, "%s.%d.%d.%d.%d.%s", msr->txcfg->httpBlkey, h3, h2, h1, h0, rule->op_param); + } + } else { + /* regular IPv4 RBLs */ + name_to_check = apr_psprintf(msr->mp, "%d.%d.%d.%d.%s", h3, h2, h1, h0, rule->op_param); + } } else { /* Assume the input is a domain name. */ name_to_check = apr_psprintf(msr->mp, "%s.%s", target, rule->op_param); @@ -3025,6 +3039,55 @@ static int msre_op_rbl_execute(modsec_rec *msr, msre_rule *rule, msre_var *var, set_match_to_tx(msr, capture, *error_msg, 0); + } else + if(strstr(rule->op_param,"httpbl.org")) { + char *respBl; + int first, days, score, type; + + respBl = inet_ntoa(sa->sa.sin.sin_addr); + if (sscanf(respBl, "%d.%d.%d.%d", &first, &days, &score, &type) != 4) { + *error_msg = apr_psprintf(msr->r->pool, "RBL lookup of %s failed: bad response", log_escape_nq(msr->mp, name_to_check)); + } else { + if (first != 127) { + *error_msg = apr_psprintf(msr->r->pool, "RBL lookup of %s failed: bad response", log_escape_nq(msr->mp, name_to_check)); + } + else { + char *ptype; + switch(type) { + case 0: + ptype = "Search Engine"; + break; + case 1: + ptype = "Suspicious IP"; + break; + case 2: + ptype = "Harvester IP"; + break; + case 3: + ptype = "Suspicious harvester IP"; + break; + case 4: + ptype = "Comment spammer IP"; + break; + case 5: + ptype = "Suspicious comment spammer IP"; + break; + case 6: + ptype = "Harvester and comment spammer IP"; + break; + case 7: + ptype = "Suspicious harvester comment spammer IP"; + break; + default: + ptype = " "; + } + *error_msg = apr_psprintf(msr->r->pool, "RBL lookup of %s succeeded at %s. %s: %d days since last activity, threat score %d", + log_escape_nq(msr->mp, name_to_check), var->name, + ptype, days, score); + } + } + set_match_to_tx(msr, capture, *error_msg, 0); + /* end of httpBl code */ } else { *error_msg = apr_psprintf(msr->r->pool, "RBL lookup of %s succeeded at %s.", log_escape_nq(msr->mp, name_to_check), var->name);