diff --git a/CHANGES b/CHANGES
index aef20cce..2b58d703 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,39 @@
+28 Mar 2013 - 2.7.3
+-------------------
+
+ * Fixed IIS version race condition when module is initialized.
+
+ * Fixed IIS version failing config commands in libapr.
+
+ * Nginx version is now RC quality. The rule engine should works for all phases.
+ We fixed many issues and missing features (for more information please check jira).
+ Code is running well with latest Nginx 1.2.7 stable.
+ Thanks chaizhenhua for your help.
+
+ * Added MULTIPART_NAME and MULTIPART_FILENAME. Should be used soon by CRS
+ and will help prevent attacks using multipart data.
+
+ * Added --enable-htaccess-config configure option. It will allow the follow directives
+ to be used into .htaccess files when AllowOverride Options is set:
+
+ - SecAction
+ - SecRule
+
+ - SecRuleRemoveByMsg
+ - SecRuleRemoveByTag
+ - SecRuleRemoveById
+
+ - SecRuleUpdateActionById
+ - SecRuleUpdateTargetById
+ - SecRuleUpdateTargetByTag
+ - SecRuleUpdateTargetByMsg
+
+ * Improvements in the ID duplicate code checking. Should be faster now.
+
+ * SECURITY: Added SecXmlExternalEntity (On|Off - default it Off) that will disable
+ by default the external entity load task executed by LibXml2. This is a security issue
+ reported by Timur Yunusov, Alexey Osipov (Positive Technologies).
+
21 Jan 2013 - 2.7.2
-------------------
diff --git a/apache2/apache2_config.c b/apache2/apache2_config.c
index 830070a8..b7ae56c0 100644
--- a/apache2/apache2_config.c
+++ b/apache2/apache2_config.c
@@ -64,6 +64,7 @@ void *create_directory_config(apr_pool_t *mp, char *path)
dcfg->cookie_format = NOT_SET;
dcfg->argument_separator = NOT_SET;
+ dcfg->cookiev0_separator = NOT_SET_P;
dcfg->rule_inheritance = NOT_SET;
dcfg->rule_exceptions = apr_array_make(mp, 16, sizeof(rule_exception *));
@@ -127,6 +128,8 @@ void *create_directory_config(apr_pool_t *mp, char *path)
dcfg->cache_trans_max = NOT_SET;
dcfg->cache_trans_maxitems = NOT_SET;
+ /* Rule ids */
+ dcfg->rule_id_htab = apr_hash_make(mp);
dcfg->component_signatures = apr_array_make(mp, 16, sizeof(char *));
dcfg->request_encoding = NOT_SET_P;
@@ -153,6 +156,9 @@ void *create_directory_config(apr_pool_t *mp, char *path)
dcfg->crypto_hash_framesrc_pm = NOT_SET;
+ /* xml external entity */
+ dcfg->xml_external_entity = NOT_SET;
+
return dcfg;
}
@@ -366,6 +372,8 @@ void *merge_directory_configs(apr_pool_t *mp, void *_parent, void *_child)
? parent->cookie_format : child->cookie_format);
merged->argument_separator = (child->argument_separator == NOT_SET
? parent->argument_separator : child->argument_separator);
+ merged->cookiev0_separator = (child->cookiev0_separator == NOT_SET_P
+ ? parent->cookiev0_separator : child->cookiev0_separator);
/* rule inheritance */
@@ -586,6 +594,10 @@ void *merge_directory_configs(apr_pool_t *mp, void *_parent, void *_child)
merged->crypto_hash_framesrc_pm = (child->crypto_hash_framesrc_pm == NOT_SET
? parent->crypto_hash_framesrc_pm : child->crypto_hash_framesrc_pm);
+ /* xml external entity */
+ merged->xml_external_entity = (child->xml_external_entity == NOT_SET
+ ? parent->xml_external_entity : child->xml_external_entity);
+
return merged;
}
@@ -627,6 +639,7 @@ void init_directory_config(directory_config *dcfg)
if (dcfg->cookie_format == NOT_SET) dcfg->cookie_format = 0;
if (dcfg->argument_separator == NOT_SET) dcfg->argument_separator = '&';
+ if (dcfg->cookiev0_separator == NOT_SET_P) dcfg->cookiev0_separator = NULL;
if (dcfg->rule_inheritance == NOT_SET) dcfg->rule_inheritance = 1;
@@ -705,6 +718,9 @@ void init_directory_config(directory_config *dcfg)
if (dcfg->crypto_hash_iframesrc_pm == NOT_SET) dcfg->crypto_hash_iframesrc_pm = 0;
if (dcfg->crypto_hash_framesrc_pm == NOT_SET) dcfg->crypto_hash_framesrc_pm = 0;
+ /* xml external entity */
+ if (dcfg->xml_external_entity == NOT_SET) dcfg->xml_external_entity = 0;
+
}
/**
@@ -714,7 +730,9 @@ static const char *add_rule(cmd_parms *cmd, directory_config *dcfg, int type,
const char *p1, const char *p2, const char *p3)
{
char *my_error_msg = NULL;
- msre_rule *rule = NULL, *tmp_rule = NULL;
+ //msre_rule *rule = NULL, *tmp_rule = NULL;
+ char *rid = NULL;
+ msre_rule *rule = NULL;
extern msc_engine *modsecurity;
int offset = 0;
@@ -767,9 +785,16 @@ static const char *add_rule(cmd_parms *cmd, directory_config *dcfg, int type,
if(type != RULE_TYPE_LUA)
#endif
{
- tmp_rule = msre_ruleset_fetch_rule(dcfg->ruleset, rule->actionset->id, offset);
- if(tmp_rule != NULL)
+ rid = apr_hash_get(dcfg->rule_id_htab, rule->actionset->id, APR_HASH_KEY_STRING);
+ if(rid != NULL) {
return "ModSecurity: Found another rule with the same id";
+ } else {
+ apr_hash_set(dcfg->rule_id_htab, apr_pstrdup(dcfg->mp, rule->actionset->id), APR_HASH_KEY_STRING, apr_pstrdup(dcfg->mp, "1"));
+ }
+
+ //tmp_rule = msre_ruleset_fetch_rule(dcfg->ruleset, rule->actionset->id, offset);
+ //if(tmp_rule != NULL)
+ // return "ModSecurity: Found another rule with the same id";
}
}
@@ -1084,6 +1109,20 @@ static const char *cmd_marker(cmd_parms *cmd, void *_dcfg, const char *p1)
return add_marker(cmd, (directory_config *)_dcfg, SECMARKER_TARGETS, SECMARKER_ARGS, action);
}
+static const char *cmd_cookiev0_separator(cmd_parms *cmd, void *_dcfg,
+ const char *p1)
+{
+ directory_config *dcfg = (directory_config *)_dcfg;
+
+ if (strlen(p1) != 1) {
+ return apr_psprintf(cmd->pool, "ModSecurity: Invalid cookie v0 separator: %s", p1);
+ }
+
+ dcfg->cookiev0_separator = p1;
+
+ return NULL;
+}
+
static const char *cmd_argument_separator(cmd_parms *cmd, void *_dcfg,
const char *p1)
{
@@ -1919,6 +1958,10 @@ static const char *cmd_rule_update_target_by_id(cmd_parms *cmd, void *_dcfg,
/* TODO: Validate the range here, while we can still tell the user if it's invalid */
re->param = p1;
+ if(dcfg->ruleset == NULL) {
+ return apr_psprintf(cmd->pool, "Updating target by ID with no ruleset in this context");
+ }
+
return msre_ruleset_rule_update_target_matching_exception(NULL, dcfg->ruleset, re, p2, p3);
}
@@ -2253,9 +2296,35 @@ static const char *cmd_sensor_id(cmd_parms *cmd, void *_dcfg, const char *p1)
return NULL;
}
+/**
+* \brief Add SecXmlExternalEntity configuration option
+*
+* \param cmd Pointer to configuration data
+* \param _dcfg Pointer to directory configuration
+* \param p1 Pointer to configuration option
+*
+* \retval NULL On failure
+* \retval apr_psprintf On Success
+*/
+static const char *cmd_xml_external_entity(cmd_parms *cmd, void *_dcfg, const char *p1)
+{
+ directory_config *dcfg = (directory_config *)_dcfg;
+ if (dcfg == NULL) return NULL;
+
+ if (strcasecmp(p1, "on") == 0) {
+ dcfg->xml_external_entity = 1;
+ }
+ else if (strcasecmp(p1, "off") == 0) {
+ dcfg->xml_external_entity = 0;
+ }
+ else return apr_psprintf(cmd->pool, "ModSecurity: Invalid value for SecXmlExternalEntity: %s", p1);
+
+ return NULL;
+}
+
/**
-* \brief Add SecHash configuration option
+* \brief Add SecHashEngine configuration option
*
* \param cmd Pointer to configuration data
* \param _dcfg Pointer to directory configuration
@@ -2277,7 +2346,7 @@ static const char *cmd_hash_engine(cmd_parms *cmd, void *_dcfg, const char *p1)
dcfg->hash_is_enabled = HASH_DISABLED;
dcfg->hash_enforcement = HASH_DISABLED;
}
- else return apr_psprintf(cmd->pool, "ModSecurity: Invalid value for SecRuleEngine: %s", p1);
+ else return apr_psprintf(cmd->pool, "ModSecurity: Invalid value for SexHashEngine: %s", p1);
return NULL;
}
@@ -2767,8 +2836,21 @@ static const char *cmd_cache_transformations(cmd_parms *cmd, void *_dcfg,
#define CMD_SCOPE_MAIN (RSRC_CONF)
#define CMD_SCOPE_ANY (RSRC_CONF | ACCESS_CONF)
+#if defined(HTACCESS_CONFIG)
+#define CMD_SCOPE_HTACCESS (OR_OPTIONS)
+#endif
+
const command_rec module_directives[] = {
+#ifdef HTACCESS_CONFIG
+ AP_INIT_TAKE1 (
+ "SecAction",
+ cmd_action,
+ NULL,
+ CMD_SCOPE_HTACCESS,
+ "an action list"
+ ),
+#else
AP_INIT_TAKE1 (
"SecAction",
cmd_action,
@@ -2776,6 +2858,7 @@ const command_rec module_directives[] = {
CMD_SCOPE_ANY,
"an action list"
),
+#endif
AP_INIT_TAKE1 (
"SecArgumentSeparator",
@@ -2785,6 +2868,14 @@ const command_rec module_directives[] = {
"character that will be used as separator when parsing application/x-www-form-urlencoded content."
),
+ AP_INIT_TAKE1 (
+ "SecCookiev0Separator",
+ cmd_cookiev0_separator,
+ NULL,
+ CMD_SCOPE_ANY,
+ "character that will be used as separator when parsing cookie v0 content."
+ ),
+
AP_INIT_TAKE1 (
"SecAuditEngine",
cmd_audit_engine,
@@ -3146,6 +3237,15 @@ const command_rec module_directives[] = {
"clears the list of MIME types that will be buffered on output"
),
+#ifdef HTACCESS_CONFIG
+ AP_INIT_TAKE23 (
+ "SecRule",
+ cmd_rule,
+ NULL,
+ CMD_SCOPE_HTACCESS,
+ "rule target, operator and optional action list"
+ ),
+#else
AP_INIT_TAKE23 (
"SecRule",
cmd_rule,
@@ -3153,6 +3253,7 @@ const command_rec module_directives[] = {
CMD_SCOPE_ANY,
"rule target, operator and optional action list"
),
+#endif
AP_INIT_TAKE1 (
"SecRuleEngine",
@@ -3162,6 +3263,14 @@ const command_rec module_directives[] = {
"On or Off"
),
+ AP_INIT_TAKE1 (
+ "SecXmlExternalEntity",
+ cmd_xml_external_entity,
+ NULL,
+ CMD_SCOPE_ANY,
+ "On or Off"
+ ),
+
AP_INIT_FLAG (
"SecRuleInheritance",
cmd_rule_inheritance,
@@ -3178,6 +3287,31 @@ const command_rec module_directives[] = {
"rule script and optional actionlist"
),
+#ifdef HTACCESS_CONFIG
+ AP_INIT_ITERATE (
+ "SecRuleRemoveById",
+ cmd_rule_remove_by_id,
+ NULL,
+ CMD_SCOPE_HTACCESS,
+ "rule ID for removal"
+ ),
+
+ AP_INIT_ITERATE (
+ "SecRuleRemoveByTag",
+ cmd_rule_remove_by_tag,
+ NULL,
+ CMD_SCOPE_HTACCESS,
+ "rule tag for removal"
+ ),
+
+ AP_INIT_ITERATE (
+ "SecRuleRemoveByMsg",
+ cmd_rule_remove_by_msg,
+ NULL,
+ CMD_SCOPE_HTACCESS,
+ "rule message for removal"
+ ),
+#else
AP_INIT_ITERATE (
"SecRuleRemoveById",
cmd_rule_remove_by_id,
@@ -3201,6 +3335,7 @@ const command_rec module_directives[] = {
CMD_SCOPE_ANY,
"rule message for removal"
),
+#endif
AP_INIT_TAKE2 (
"SecHashMethodPm",
@@ -3218,6 +3353,39 @@ const command_rec module_directives[] = {
"Hash method and regex"
),
+#ifdef HTACCESS_CONFIG
+ AP_INIT_TAKE2 (
+ "SecRuleUpdateActionById",
+ cmd_rule_update_action_by_id,
+ NULL,
+ CMD_SCOPE_HTACCESS,
+ "updated action list"
+ ),
+
+ AP_INIT_TAKE23 (
+ "SecRuleUpdateTargetById",
+ cmd_rule_update_target_by_id,
+ NULL,
+ CMD_SCOPE_HTACCESS,
+ "updated target list"
+ ),
+
+ AP_INIT_TAKE23 (
+ "SecRuleUpdateTargetByTag",
+ cmd_rule_update_target_by_tag,
+ NULL,
+ CMD_SCOPE_HTACCESS,
+ "rule tag pattern and updated target list"
+ ),
+
+ AP_INIT_TAKE23 (
+ "SecRuleUpdateTargetByMsg",
+ cmd_rule_update_target_by_msg,
+ NULL,
+ CMD_SCOPE_HTACCESS,
+ "rule message pattern and updated target list"
+ ),
+#else
AP_INIT_TAKE2 (
"SecRuleUpdateActionById",
cmd_rule_update_action_by_id,
@@ -3249,7 +3417,7 @@ const command_rec module_directives[] = {
CMD_SCOPE_ANY,
"rule message pattern and updated target list"
),
-
+#endif
AP_INIT_TAKE1 (
"SecServerSignature",
diff --git a/apache2/mod_security2.c b/apache2/mod_security2.c
index 6b410881..849ca9dc 100644
--- a/apache2/mod_security2.c
+++ b/apache2/mod_security2.c
@@ -440,7 +440,11 @@ static modsec_rec *create_tx_context(request_rec *r) {
#if defined(WITH_LUA)
#ifdef CACHE_LUA
+#if LUA_VERSION_NUM > 501
+ msr->L = luaL_newstate();
+#else
msr->L = lua_open();
+#endif
luaL_openlibs(msr->L);
#endif
#endif
diff --git a/apache2/modsecurity.h b/apache2/modsecurity.h
index 8eb8af88..cb1a8d18 100644
--- a/apache2/modsecurity.h
+++ b/apache2/modsecurity.h
@@ -355,6 +355,8 @@ struct modsec_rec {
apr_size_t msc_reqbody_no_files_length;
+ char *multipart_filename;
+ char *multipart_name;
multipart_data *mpd; /* MULTIPART processor data structure */
xml_data *xml; /* XML processor data structure */
@@ -468,6 +470,7 @@ struct directory_config {
int cookie_format;
int argument_separator;
+ const char *cookiev0_separator;
int rule_inheritance;
apr_array_header_t *rule_exceptions;
@@ -571,6 +574,9 @@ struct directory_config {
/* Collection timeout */
int col_timeout;
+ /* hash of ids */
+ apr_hash_t *rule_id_htab;
+
/* Hash */
apr_array_header_t *hash_method;
const char *crypto_key;
@@ -589,6 +595,9 @@ struct directory_config {
int crypto_hash_location_pm;
int crypto_hash_iframesrc_pm;
int crypto_hash_framesrc_pm;
+
+ /* xml */
+ int xml_external_entity;
};
struct error_message_t {
diff --git a/apache2/msc_lua.c b/apache2/msc_lua.c
index 4abf7e5c..6450e778 100644
--- a/apache2/msc_lua.c
+++ b/apache2/msc_lua.c
@@ -94,7 +94,11 @@ char *lua_compile(msc_script **script, const char *filename, apr_pool_t *pool) {
msc_lua_dumpw_t dump;
/* Initialise state. */
+#if LUA_VERSION_NUM > 501
+ L = luaL_newstate();
+#else
L = lua_open();
+#endif
luaL_openlibs(L);
/* Find script. */
@@ -158,7 +162,11 @@ static apr_array_header_t *resolve_tfns(lua_State *L, int idx, modsec_rec *msr,
if (lua_isuserdata(L, idx) || lua_isnoneornil(L, idx)) { /* No second parameter */
return tfn_arr;
} else if (lua_istable(L, idx)) { /* Is the second parameter an array? */
+#if LUA_VERSION_NUM > 501
+ int i, n = lua_rawlen(L, idx);
+#else
int i, n = lua_objlen(L, idx);
+#endif
for(i = 1; i <= n; i++) {
lua_rawgeti(L, idx, i);
@@ -415,7 +423,11 @@ int lua_execute(msc_script *script, char *param, modsec_rec *msr, msre_rule *rul
lua_pop(L, rc);
#else
/* Create new state. */
+#if LUA_VERSION_NUM > 501
+ L = luaL_newstate();
+#else
L = lua_open();
+#endif
luaL_openlibs(L);
#endif
@@ -433,7 +445,12 @@ int lua_execute(msc_script *script, char *param, modsec_rec *msr, msre_rule *rul
}
/* Register functions. */
+#if LUA_VERSION_NUM > 501
+ luaL_setfuncs(L,mylib,0);
+ lua_setglobal(L,"m");
+#else
luaL_register(L, "m", mylib);
+#endif
rc = lua_restore(L, script);
if (rc) {
diff --git a/apache2/msc_multipart.c b/apache2/msc_multipart.c
index 82d4298f..d0b3242b 100644
--- a/apache2/msc_multipart.c
+++ b/apache2/msc_multipart.c
@@ -184,6 +184,8 @@ static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value)
validate_quotes(msr, value);
+ msr->multipart_name = apr_pstrdup(msr->mp, value);
+
if (msr->mpd->mpp->name != NULL) {
msr_log(msr, 4, "Multipart: Warning: Duplicate Content-Disposition name: %s",
log_escape_nq(msr->mp, value));
@@ -201,6 +203,8 @@ static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value)
validate_quotes(msr, value);
+ msr->multipart_filename = apr_pstrdup(msr->mp, value);
+
if (msr->mpd->mpp->filename != NULL) {
msr_log(msr, 4, "Multipart: Warning: Duplicate Content-Disposition filename: %s",
log_escape_nq(msr->mp, value));
diff --git a/apache2/msc_parsers.c b/apache2/msc_parsers.c
index ebbac294..ffa6d469 100644
--- a/apache2/msc_parsers.c
+++ b/apache2/msc_parsers.c
@@ -35,7 +35,11 @@ int parse_cookies_v0(modsec_rec *msr, char *_cookie_header,
cookie_header = strdup(_cookie_header);
if (cookie_header == NULL) return -1;
- p = apr_strtok(cookie_header, delim, &saveptr);
+ if(msr->txcfg->cookiev0_separator == NULL) {
+ p = apr_strtok(cookie_header, delim, &saveptr);
+ } else {
+ p = apr_strtok(cookie_header, msr->txcfg->cookiev0_separator, &saveptr);
+ }
while(p != NULL) {
attr_name = NULL;
@@ -74,7 +78,11 @@ int parse_cookies_v0(modsec_rec *msr, char *_cookie_header,
cookie_count++;
}
- p = apr_strtok(NULL, delim, &saveptr);
+ if(msr->txcfg->cookiev0_separator == NULL) {
+ p = apr_strtok(NULL, delim, &saveptr);
+ } else {
+ p = apr_strtok(NULL, msr->txcfg->cookiev0_separator, &saveptr);
+ }
}
free(cookie_header);
diff --git a/apache2/msc_pcre.c b/apache2/msc_pcre.c
index 8ca588a9..3393493b 100644
--- a/apache2/msc_pcre.c
+++ b/apache2/msc_pcre.c
@@ -21,7 +21,11 @@
static apr_status_t msc_pcre_cleanup(msc_regex_t *regex) {
if (regex != NULL) {
if (regex->pe != NULL) {
+#if defined(VERSION_NGINX)
+ pcre_free(regex->pe);
+#else
free(regex->pe);
+#endif
regex->pe = NULL;
}
if (regex->re != NULL) {
@@ -71,7 +75,11 @@ void *msc_pregcomp_ex(apr_pool_t *pool, const char *pattern, int options,
/* Setup the pcre_extra record if pcre_study did not already do it */
if (pe == NULL) {
+#if defined(VERSION_NGINX)
+ pe = pcre_malloc(sizeof(pcre_extra));
+#else
pe = malloc(sizeof(pcre_extra));
+#endif
if (pe == NULL) {
return NULL;
}
diff --git a/apache2/msc_release.h b/apache2/msc_release.h
index efefb79e..d87b185d 100644
--- a/apache2/msc_release.h
+++ b/apache2/msc_release.h
@@ -38,7 +38,7 @@
#define MODSEC_VERSION_MAJOR "2"
#define MODSEC_VERSION_MINOR "7"
-#define MODSEC_VERSION_MAINT "2"
+#define MODSEC_VERSION_MAINT "3"
#define MODSEC_VERSION_TYPE ""
#define MODSEC_VERSION_RELEASE ""
@@ -53,10 +53,10 @@
#define MODSEC_MODULE_NAME "ModSecurity for IIS (STABLE)"
#else
#ifdef VERSION_NGINX
-#define MODSEC_MODULE_NAME "ModSecurity for nginx (Beta)"
+#define MODSEC_MODULE_NAME "ModSecurity for nginx (RC)"
#else
#ifdef VERSION_STANDALONE
-#define MODSEC_MODULE_NAME "ModSecurity Standalone (Beta)"
+#define MODSEC_MODULE_NAME "ModSecurity Standalone (RC)"
#else
#define MODSEC_MODULE_NAME "ModSecurity for Apache"
#endif
diff --git a/apache2/msc_xml.c b/apache2/msc_xml.c
index d9cb09cc..87ab967e 100644
--- a/apache2/msc_xml.c
+++ b/apache2/msc_xml.c
@@ -14,17 +14,28 @@
#include "msc_xml.h"
+static xmlParserInputBufferPtr
+xml_unload_external_entity(const char *URI, xmlCharEncoding enc) {
+ return NULL;
+}
+
/**
* Initialise XML parser.
*/
int xml_init(modsec_rec *msr, char **error_msg) {
+ xmlParserInputBufferCreateFilenameFunc entity;
+
if (error_msg == NULL) return -1;
*error_msg = NULL;
msr->xml = apr_pcalloc(msr->mp, sizeof(xml_data));
if (msr->xml == NULL) return -1;
+ if(msr->txcfg->xml_external_entity == 0) {
+ entity = xmlParserInputBufferCreateFilenameDefault(xml_unload_external_entity);
+ }
+
return 1;
}
diff --git a/apache2/persist_dbm.c b/apache2/persist_dbm.c
index 4bb6a3e1..9b9536c8 100644
--- a/apache2/persist_dbm.c
+++ b/apache2/persist_dbm.c
@@ -41,9 +41,9 @@ static apr_table_t *collection_unpack(modsec_rec *msr, const unsigned char *blob
* includes the terminating NUL and should be 1 for ""
*/
if (msr->txcfg->debuglog_level >= 9) {
- msr_log(msr, 9, "BLOB[%d]: %s", blob_offset, log_escape_hex(msr->mp, blob + blob_offset, blob_size - blob_offset));
+ msr_log(msr, 9, "collection_unpack: BLOB[%d]: %s", blob_offset, log_escape_hex(msr->mp, blob + blob_offset, blob_size - blob_offset));
}
- msr_log(msr, 4, "Possibly corrupted database: var name length = 0 at blob offset %u-%u.", blob_offset, blob_offset + 1);
+ msr_log(msr, 4, "collection_unpack: Possibly corrupted database: var name length = 0 at blob offset %u-%u.", blob_offset, blob_offset + 1);
}
break;
}
@@ -52,9 +52,9 @@ static apr_table_t *collection_unpack(modsec_rec *msr, const unsigned char *blob
* to 65536.
*/
if (msr->txcfg->debuglog_level >= 9) {
- msr_log(msr, 9, "BLOB[%d]: %s", blob_offset, log_escape_hex(msr->mp, blob + blob_offset, blob_size - blob_offset));
+ msr_log(msr, 9, "collection_unpack: BLOB[%d]: %s", blob_offset, log_escape_hex(msr->mp, blob + blob_offset, blob_size - blob_offset));
}
- msr_log(msr, 4, "Possibly corrupted database: var name length > 65536 (0x%04x) at blob offset %u-%u.", var->name_len, blob_offset, blob_offset + 1);
+ msr_log(msr, 4, "collection_unpack: Possibly corrupted database: var name length > 65536 (0x%04x) at blob offset %u-%u.", var->name_len, blob_offset, blob_offset + 1);
break;
}
@@ -73,7 +73,7 @@ static apr_table_t *collection_unpack(modsec_rec *msr, const unsigned char *blob
var->value_len--;
if (log_vars && (msr->txcfg->debuglog_level >= 9)) {
- msr_log(msr, 9, "Read variable: name \"%s\", value \"%s\".",
+ msr_log(msr, 9, "collection_unpack: Read variable: name \"%s\", value \"%s\".",
log_escape_ex(msr->mp, var->name, var->name_len),
log_escape_ex(msr->mp, var->value, var->value_len));
}
@@ -102,7 +102,7 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
int i;
if (msr->txcfg->data_dir == NULL) {
- msr_log(msr, 1, "Unable to retrieve collection (name \"%s\", key \"%s\"). Use "
+ msr_log(msr, 1, "collection_retrieve_ex: Unable to retrieve collection (name \"%s\", key \"%s\"). Use "
"SecDataDir to define data directory first.", log_escape(msr->mp, col_name),
log_escape_ex(msr->mp, col_key, col_key_len));
goto cleanup;
@@ -111,7 +111,7 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
dbm_filename = apr_pstrcat(msr->mp, msr->txcfg->data_dir, "/", col_name, NULL);
if (msr->txcfg->debuglog_level >= 9) {
- msr_log(msr, 9, "collection_retrieve_ex: Retrieving collection (name \"%s\", filename \"%s\")",log_escape(msr->mp, col_name),
+ msr_log(msr, 9, "collection_retrieve_ex: collection_retrieve_ex: Retrieving collection (name \"%s\", filename \"%s\")",log_escape(msr->mp, col_name),
log_escape(msr->mp, dbm_filename));
}
@@ -133,7 +133,7 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
value = (apr_sdbm_datum_t *)apr_pcalloc(msr->mp, sizeof(apr_sdbm_datum_t));
rc = apr_sdbm_fetch(dbm, value, key);
if (rc != APR_SUCCESS) {
- msr_log(msr, 1, "Failed to read from DBM file \"%s\": %s", log_escape(msr->mp,
+ msr_log(msr, 1, "collection_retrieve_ex: Failed to read from DBM file \"%s\": %s", log_escape(msr->mp,
dbm_filename), get_apr_error(msr->mp, rc));
goto cleanup;
}
@@ -177,15 +177,15 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
}
if (msr->txcfg->debuglog_level >= 9) {
- msr_log(msr, 9, "Removing key \"%s\" from collection.", key_to_expire + 9);
- msr_log(msr, 9, "Removing key \"%s\" from collection.", key_to_expire);
+ msr_log(msr, 9, "collection_retrieve_ex: Removing key \"%s\" from collection.", key_to_expire + 9);
+ msr_log(msr, 9, "collection_retrieve_ex: Removing key \"%s\" from collection.", key_to_expire);
}
apr_table_unset(col, key_to_expire + 9);
apr_table_unset(col, key_to_expire);
if (msr->txcfg->debuglog_level >= 4) {
- msr_log(msr, 4, "Removed expired variable \"%s\".", key_to_expire + 9);
+ msr_log(msr, 4, "collection_retrieve_ex: Removed expired variable \"%s\".", key_to_expire + 9);
}
break;
@@ -205,7 +205,7 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
rc = apr_sdbm_open(&dbm, dbm_filename, APR_CREATE | APR_WRITE | APR_SHARELOCK,
CREATEMODE, msr->mp);
if (rc != APR_SUCCESS) {
- msr_log(msr, 1, "Failed to access DBM file \"%s\": %s",
+ msr_log(msr, 1, "collection_retrieve_ex: Failed to access DBM file \"%s\": %s",
log_escape(msr->mp, dbm_filename), get_apr_error(msr->mp, rc));
dbm = NULL;
goto cleanup;
@@ -217,7 +217,7 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
rc = apr_sdbm_delete(dbm, key);
if (rc != APR_SUCCESS) {
- msr_log(msr, 1, "Failed deleting collection (name \"%s\", "
+ msr_log(msr, 1, "collection_retrieve_ex: Failed deleting collection (name \"%s\", "
"key \"%s\"): %s", log_escape(msr->mp, col_name),
log_escape_ex(msr->mp, col_key, col_key_len), get_apr_error(msr->mp, rc));
goto cleanup;
@@ -230,11 +230,11 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
}
if (expired && (msr->txcfg->debuglog_level >= 9)) {
- msr_log(msr, 9, "Collection expired (name \"%s\", key \"%s\").", col_name,
+ msr_log(msr, 9, "collection_retrieve_ex: Collection expired (name \"%s\", key \"%s\").", col_name,
log_escape_ex(msr->mp, col_key, col_key_len));
}
if (msr->txcfg->debuglog_level >= 4) {
- msr_log(msr, 4, "Deleted collection (name \"%s\", key \"%s\").",
+ msr_log(msr, 4, "collection_retrieve_ex: Deleted collection (name \"%s\", key \"%s\").",
log_escape(msr->mp, col_name), log_escape_ex(msr->mp, col_key, col_key_len));
}
goto cleanup;
@@ -278,13 +278,13 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
}
if (msr->txcfg->debuglog_level >= 4) {
- msr_log(msr, 4, "Retrieved collection (name \"%s\", key \"%s\").",
+ msr_log(msr, 4, "collection_retrieve_ex: Retrieved collection (name \"%s\", key \"%s\").",
log_escape(msr->mp, col_name), log_escape_ex(msr->mp, col_key, col_key_len));
}
if ((existing_dbm == NULL) && dbm) {
/* Should not ever get here */
- msr_log(msr, 1, "Internal Error: Collection remained open (name \"%s\", key \"%s\").",
+ msr_log(msr, 1, "collection_retrieve_ex: Internal Error: Collection remained open (name \"%s\", key \"%s\").",
log_escape(msr->mp, col_name), log_escape_ex(msr->mp, col_key, col_key_len));
apr_sdbm_close(dbm);
@@ -346,7 +346,7 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
}
if (msr->txcfg->data_dir == NULL) {
- msr_log(msr, 1, "Unable to store collection (name \"%s\", key \"%s\"). Use "
+ msr_log(msr, 1, "collection_store: Unable to store collection (name \"%s\", key \"%s\"). Use "
"SecDataDir to define data directory first.", log_escape_ex(msr->mp, var_name->value, var_name->value_len),
log_escape_ex(msr->mp, var_key->value, var_key->value_len));
goto error;
@@ -416,7 +416,7 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
rc = apr_sdbm_open(&dbm, dbm_filename, APR_CREATE | APR_WRITE | APR_SHARELOCK,
CREATEMODE, msr->mp);
if (rc != APR_SUCCESS) {
- msr_log(msr, 1, "Failed to access DBM file \"%s\": %s", log_escape(msr->mp, dbm_filename),
+ msr_log(msr, 1, "collection_store: Failed to access DBM file \"%s\": %s", log_escape(msr->mp, dbm_filename),
get_apr_error(msr->mp, rc));
dbm = NULL;
goto error;
@@ -425,7 +425,7 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
/* Need to lock to pull in the stored data again and apply deltas. */
rc = apr_sdbm_lock(dbm, APR_FLOCK_EXCLUSIVE);
if (rc != APR_SUCCESS) {
- msr_log(msr, 1, "Failed to exclusivly lock DBM file \"%s\": %s", log_escape(msr->mp, dbm_filename),
+ msr_log(msr, 1, "collection_store: Failed to exclusivly lock DBM file \"%s\": %s", log_escape(msr->mp, dbm_filename),
get_apr_error(msr->mp, rc));
goto error;
}
@@ -435,7 +435,7 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
orig_col = (const apr_table_t *)apr_table_get(msr->collections_original, var_name->value);
if (orig_col != NULL) {
if (msr->txcfg->debuglog_level >= 9) {
- msr_log(msr, 9, "Re-retrieving collection prior to store: %s",
+ msr_log(msr, 9, "collection_store: Re-retrieving collection prior to store: %s",
apr_psprintf(msr->mp, "%.*s", var_name->value_len, var_name->value));
}
@@ -469,7 +469,7 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
var->value_len = strlen(var->value);
if (msr->txcfg->debuglog_level >= 9) {
- msr_log(msr, 9, "Delta applied for %s.%s %d->%d (%d): %d + (%d) = %d [%s,%d]",
+ msr_log(msr, 9, "collection_store: Delta applied for %s.%s %d->%d (%d): %d + (%d) = %d [%s,%d]",
log_escape_ex(msr->mp, var_name->value, var_name->value_len),
log_escape_ex(msr->mp, var->name, var->name_len),
origval, ourval, delta, storedval, delta, newval, var->value, var->value_len);
@@ -523,7 +523,7 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
blob_offset += 2 + len;
if (msr->txcfg->debuglog_level >= 9) {
- msr_log(msr, 9, "Wrote variable: name \"%s\", value \"%s\".",
+ msr_log(msr, 9, "collection_store: Wrote variable: name \"%s\", value \"%s\".",
log_escape_ex(msr->mp, var->name, var->name_len),
log_escape_ex(msr->mp, var->value, var->value_len));
}
@@ -541,7 +541,7 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
rc = apr_sdbm_store(dbm, key, value, APR_SDBM_REPLACE);
if (rc != APR_SUCCESS) {
- msr_log(msr, 1, "Failed to write to DBM file \"%s\": %s", dbm_filename,
+ msr_log(msr, 1, "collection_store: Failed to write to DBM file \"%s\": %s", dbm_filename,
get_apr_error(msr->mp, rc));
goto error;
}
@@ -549,7 +549,7 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
apr_sdbm_close(dbm);
if (msr->txcfg->debuglog_level >= 4) {
- msr_log(msr, 4, "Persisted collection (name \"%s\", key \"%s\").",
+ msr_log(msr, 4, "collection_store: Persisted collection (name \"%s\", key \"%s\").",
log_escape_ex(msr->mp, var_name->value, var_name->value_len),
log_escape_ex(msr->mp, var_key->value, var_key->value_len));
}
@@ -599,7 +599,7 @@ int collections_remove_stale(modsec_rec *msr, const char *col_name) {
rc = apr_sdbm_open(&dbm, dbm_filename, APR_CREATE | APR_WRITE | APR_SHARELOCK,
CREATEMODE, msr->mp);
if (rc != APR_SUCCESS) {
- msr_log(msr, 1, "Failed to access DBM file \"%s\": %s", log_escape(msr->mp, dbm_filename),
+ msr_log(msr, 1, "collections_remove_stale: Failed to access DBM file \"%s\": %s", log_escape(msr->mp, dbm_filename),
get_apr_error(msr->mp, rc));
dbm = NULL;
goto error;
@@ -609,7 +609,7 @@ int collections_remove_stale(modsec_rec *msr, const char *col_name) {
keys_arr = apr_array_make(msr->mp, 256, sizeof(char *));
rc = apr_sdbm_lock(dbm, APR_FLOCK_SHARED);
if (rc != APR_SUCCESS) {
- msr_log(msr, 1, "Failed to lock DBM file \"%s\": %s", log_escape(msr->mp, dbm_filename),
+ msr_log(msr, 1, "collections_remove_stale: Failed to lock DBM file \"%s\": %s", log_escape(msr->mp, dbm_filename),
get_apr_error(msr->mp, rc));
goto error;
}
@@ -626,7 +626,7 @@ int collections_remove_stale(modsec_rec *msr, const char *col_name) {
apr_sdbm_unlock(dbm);
if (msr->txcfg->debuglog_level >= 9) {
- msr_log(msr, 9, "Found %d record(s) in file \"%s\".", keys_arr->nelts,
+ msr_log(msr, 9, "collections_remove_stale: Found %d record(s) in file \"%s\".", keys_arr->nelts,
log_escape(msr->mp, dbm_filename));
}
@@ -638,7 +638,7 @@ int collections_remove_stale(modsec_rec *msr, const char *col_name) {
rc = apr_sdbm_fetch(dbm, &value, key);
if (rc != APR_SUCCESS) {
- msr_log(msr, 1, "Failed reading DBM file \"%s\": %s",
+ msr_log(msr, 1, "collections_remove_stale: Failed reading DBM file \"%s\": %s",
log_escape(msr->mp, dbm_filename), get_apr_error(msr->mp, rc));
goto error;
}
@@ -654,14 +654,14 @@ int collections_remove_stale(modsec_rec *msr, const char *col_name) {
var = (msc_string *)apr_table_get(col, "__expire_KEY");
if (var == NULL) {
- msr_log(msr, 1, "Collection cleanup discovered entry with no "
+ msr_log(msr, 1, "collections_remove_stale: Collection cleanup discovered entry with no "
"__expire_KEY (name \"%s\", key \"%s\").",
log_escape(msr->mp, col_name), log_escape_ex(msr->mp, key.dptr, key.dsize - 1));
} else {
unsigned int expiry_time = atoi(var->value);
if (msr->txcfg->debuglog_level >= 9) {
- msr_log(msr, 9, "Record (name \"%s\", key \"%s\") set to expire in %" APR_TIME_T_FMT " seconds.",
+ msr_log(msr, 9, "collections_remove_stale: Record (name \"%s\", key \"%s\") set to expire in %" APR_TIME_T_FMT " seconds.",
log_escape(msr->mp, col_name), log_escape_ex(msr->mp, key.dptr, key.dsize - 1),
expiry_time - now);
}
@@ -669,14 +669,14 @@ int collections_remove_stale(modsec_rec *msr, const char *col_name) {
if (expiry_time <= now) {
rc = apr_sdbm_delete(dbm, key);
if (rc != APR_SUCCESS) {
- msr_log(msr, 1, "Failed deleting collection (name \"%s\", "
+ msr_log(msr, 1, "collections_remove_stale: Failed deleting collection (name \"%s\", "
"key \"%s\"): %s", log_escape(msr->mp, col_name),
log_escape_ex(msr->mp, key.dptr, key.dsize - 1), get_apr_error(msr->mp, rc));
goto error;
}
if (msr->txcfg->debuglog_level >= 4) {
- msr_log(msr, 4, "Removed stale collection (name \"%s\", "
+ msr_log(msr, 4, "collections_remove_stale: Removed stale collection (name \"%s\", "
"key \"%s\").", log_escape(msr->mp, col_name),
log_escape_ex(msr->mp, key.dptr, key.dsize - 1));
}
diff --git a/apache2/re.c b/apache2/re.c
index 956a7eb9..70956dbb 100644
--- a/apache2/re.c
+++ b/apache2/re.c
@@ -161,7 +161,7 @@ char *msre_ruleset_rule_update_target_matching_exception(modsec_rec *msr, msre_r
char *err;
if(ruleset == NULL)
- return apr_psprintf(ruleset->mp, "No ruleset present");
+ return NULL;
if(p2 == NULL) {
return apr_psprintf(ruleset->mp, "Trying to update without a target");
@@ -353,7 +353,7 @@ char *update_rule_target_ex(modsec_rec *msr, msre_ruleset *ruleset, msre_rule *r
}
#if !defined(MSC_TEST)
else {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, " ModSecurity: Error parseing rule targets to replace variable");
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, " ModSecurity: Error parsing rule targets to replace variable");
}
#endif
goto end;
diff --git a/apache2/re_variables.c b/apache2/re_variables.c
index a4f92cbb..f1dd0744 100644
--- a/apache2/re_variables.c
+++ b/apache2/re_variables.c
@@ -1289,6 +1289,22 @@ static int var_modsec_build_generate(modsec_rec *msr, msre_var *var, msre_rule *
return var_simple_generate(var, vartab, mptmp, modsec_build(mptmp));
}
+/* MULTIPART_FILENAME */
+
+static int var_multipart_filename_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
+ apr_table_t *vartab, apr_pool_t *mptmp)
+{
+ return var_simple_generate(var, vartab, mptmp, msr->multipart_filename);
+}
+
+/* MULTIPART_NAME */
+
+static int var_multipart_name_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
+ apr_table_t *vartab, apr_pool_t *mptmp)
+{
+ return var_simple_generate(var, vartab, mptmp, msr->multipart_name);
+}
+
/* MULTIPART_BOUNDARY_QUOTED */
static int var_multipart_boundary_quoted_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
@@ -2813,6 +2829,28 @@ void msre_engine_register_default_variables(msre_engine *engine) {
PHASE_REQUEST_HEADERS
);
+ /* MULTIPART_FILENAME */
+ msre_engine_variable_register(engine,
+ "MULTIPART_FILENAME",
+ VAR_SIMPLE,
+ 0, 0,
+ NULL,
+ var_multipart_filename_generate,
+ VAR_CACHE,
+ PHASE_REQUEST_BODY
+ );
+
+ /* MULTIPART_NAME */
+ msre_engine_variable_register(engine,
+ "MULTIPART_NAME",
+ VAR_SIMPLE,
+ 0, 0,
+ NULL,
+ var_multipart_name_generate,
+ VAR_CACHE,
+ PHASE_REQUEST_BODY
+ );
+
/* MULTIPART_BOUNDARY_QUOTED */
msre_engine_variable_register(engine,
"MULTIPART_BOUNDARY_QUOTED",
diff --git a/configure.ac b/configure.ac
index d48813ca..78ca88f8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -355,6 +355,22 @@ AC_ARG_ENABLE(lua-cache,
lua_cache=
])
+# Enable phase-1 in post_read_request
+AC_ARG_ENABLE(htaccess-config,
+ AS_HELP_STRING([--enable-htaccess-config],
+ [Enable some mod_security directives into htaccess files.]),
+[
+ if test "$enableval" != "no"; then
+ htaccess_config="-DHTACCESS_CONFIG"
+ MODSEC_EXTRA_CFLAGS="$MODSEC_EXTRA_CFLAGS $htaccess_config"
+ else
+ htaccess_config=
+ fi
+],
+[
+ htaccess_config=
+])
+
# Enable phase-1 in post_read_request
AC_ARG_ENABLE(request-early,
AS_HELP_STRING([--enable-request-early],
@@ -634,7 +650,7 @@ else
fi
fi
-MODSEC_EXTRA_CFLAGS="$pcre_study $pcre_match_limit $pcre_match_limit_recursion $pcre_jit $request_early $lua_cache $debug_conf $debug_cache $debug_acmp $debug_mem $perf_meas $modsec_api $cpu_type"
+MODSEC_EXTRA_CFLAGS="$pcre_study $pcre_match_limit $pcre_match_limit_recursion $pcre_jit $request_early $htaccess_config $lua_cache $debug_conf $debug_cache $debug_acmp $debug_mem $perf_meas $modsec_api $cpu_type"
APXS_WRAPPER=build/apxs-wrapper
APXS_EXTRA_CFLAGS=""
diff --git a/iis/ModSecurityIIS/Installer/XUnzip.cpp b/iis/ModSecurityIIS/Installer/XUnzip.cpp
index d84710a7..bee1b85e 100644
--- a/iis/ModSecurityIIS/Installer/XUnzip.cpp
+++ b/iis/ModSecurityIIS/Installer/XUnzip.cpp
@@ -4132,6 +4132,8 @@ ZRESULT TUnzip::Unzip(int index,void *dst,unsigned int len,DWORD flags)
TCHAR dstfull[MAX_PATH];
_tcscpy(dstfull, rootdir);
_tcscat(dstfull, (const TCHAR *)dst);
+ SetFileAttributes( dstfull, GetFileAttributes(dstfull) & ~FILE_ATTRIBUTE_READONLY);
+ ::DeleteFile(dstfull);
h = ::CreateFile(dstfull, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
ze.attr, NULL);
}
diff --git a/iis/ModSecurityIIS/ModSecurityIIS.sln b/iis/ModSecurityIIS/ModSecurityIIS.sln
index e7961d5d..da08bb09 100644
--- a/iis/ModSecurityIIS/ModSecurityIIS.sln
+++ b/iis/ModSecurityIIS/ModSecurityIIS.sln
@@ -2,9 +2,6 @@
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "ModSecurityIIS", "ModSecurityIIS\ModSecurityIIS.vdproj", "{3352AEF1-9F2A-47CD-9F63-658553063040}"
- ProjectSection(ProjectDependencies) = postProject
- {990BB195-6716-4DE3-B5E4-DCFCB1BD7D9C} = {990BB195-6716-4DE3-B5E4-DCFCB1BD7D9C}
- EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Installer", "Installer\Installer.vcxproj", "{990BB195-6716-4DE3-B5E4-DCFCB1BD7D9C}"
EndProject
diff --git a/iis/ModSecurityIIS/ModSecurityIIS/ModSecurityIIS.vdproj b/iis/ModSecurityIIS/ModSecurityIIS/ModSecurityIIS.vdproj
index 1d834023..98b8484d 100644
--- a/iis/ModSecurityIIS/ModSecurityIIS/ModSecurityIIS.vdproj
+++ b/iis/ModSecurityIIS/ModSecurityIIS/ModSecurityIIS.vdproj
@@ -13,6 +13,12 @@
"SccProvider" = "8:"
"Hierarchy"
{
+ "Entry"
+ {
+ "MsmKey" = "8:_009A580142D04FE980ED45947D355FE7"
+ "OwnerKey" = "8:_UNDEFINED"
+ "MsmSig" = "8:_UNDEFINED"
+ }
"Entry"
{
"MsmKey" = "8:_0593BBFCC6154162A5F7E88C4967D8E8"
@@ -33,24 +39,12 @@
}
"Entry"
{
- "MsmKey" = "8:_2422B61EFBF047FFBBE92CB70714E99C"
- "OwnerKey" = "8:_UNDEFINED"
- "MsmSig" = "8:_UNDEFINED"
- }
- "Entry"
- {
"MsmKey" = "8:_2A9DB6318EE24F649FB0CDB52691122C"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
- "MsmKey" = "8:_3CE93C3FC5AC3E954253889334FBCDA8"
- "OwnerKey" = "8:_CB8446F7ADCD4E3DA3F2C6246FA844A0"
- "MsmSig" = "8:_UNDEFINED"
- }
- "Entry"
- {
"MsmKey" = "8:_51AF671FCA3544DEA3E5756B5D450275"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@@ -87,12 +81,6 @@
}
"Entry"
{
- "MsmKey" = "8:_764D5BE911464BEFBCC3BC3B25068987"
- "OwnerKey" = "8:_UNDEFINED"
- "MsmSig" = "8:_UNDEFINED"
- }
- "Entry"
- {
"MsmKey" = "8:_7C2A420982404573B53BE273BC730435"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@@ -147,12 +135,6 @@
}
"Entry"
{
- "MsmKey" = "8:_CB8446F7ADCD4E3DA3F2C6246FA844A0"
- "OwnerKey" = "8:_UNDEFINED"
- "MsmSig" = "8:_UNDEFINED"
- }
- "Entry"
- {
"MsmKey" = "8:_CEB23D021A2E4EEF9245EEDC143AFBA8"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@@ -165,13 +147,13 @@
}
"Entry"
{
- "MsmKey" = "8:_DB58E622510C458A81C3B850EDFC782C"
+ "MsmKey" = "8:_DE7847BDBDC046F29E13230DCDD4F6E3"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
- "MsmKey" = "8:_DE7847BDBDC046F29E13230DCDD4F6E3"
+ "MsmKey" = "8:_E86FB9D69F2946038E7BBDD01D619813"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
@@ -193,18 +175,6 @@
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
- "Entry"
- {
- "MsmKey" = "8:_UNDEFINED"
- "OwnerKey" = "8:_764D5BE911464BEFBCC3BC3B25068987"
- "MsmSig" = "8:_UNDEFINED"
- }
- "Entry"
- {
- "MsmKey" = "8:_UNDEFINED"
- "OwnerKey" = "8:_CB8446F7ADCD4E3DA3F2C6246FA844A0"
- "MsmSig" = "8:_UNDEFINED"
- }
}
"Configurations"
{
@@ -279,11 +249,6 @@
"ComponentsUrl" = "8:"
"Items"
{
- "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.0,Profile=Client"
- {
- "Name" = "8:Microsoft .NET Framework 4 Client Profile (x86 and x64)"
- "ProductCode" = "8:.NETFramework,Version=v4.0,Profile=Client"
- }
"{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Visual.C++.10.0.x64"
{
"Name" = "8:Visual C++ 2010 Runtime Libraries (x64)"
@@ -307,62 +272,34 @@
{
"CustomAction"
{
- "{4AA51A2D-7D85-4A59-BA75-B0809FC8B380}:_6AC6216B16A740BFBCF4DFF1FC4FB1CF"
+ "{4AA51A2D-7D85-4A59-BA75-B0809FC8B380}:_08431F489ECB46FB908D9C6006906D0E"
{
- "Name" = "8:Primary output from configure (Active)"
+ "Name" = "8:Installer.exe"
"Condition" = "8:"
- "Object" = "8:_764D5BE911464BEFBCC3BC3B25068987"
+ "Object" = "8:_009A580142D04FE980ED45947D355FE7"
"FileType" = "3:2"
"InstallAction" = "3:4"
"Arguments" = "8:uninstall"
"EntryPoint" = "8:"
"Sequence" = "3:1"
- "Identifier" = "8:_F76041EE_48F4_4DC8_9EF8_47ADAD87FEA2"
+ "Identifier" = "8:_A708DE11_BE76_4BD9_BF40_5243FE900066"
"InstallerClass" = "11:FALSE"
"CustomActionData" = "8:"
}
- "{4AA51A2D-7D85-4A59-BA75-B0809FC8B380}:_B8F3E049FAB34050978646B3CC6549F5"
+ "{4AA51A2D-7D85-4A59-BA75-B0809FC8B380}:_9C73118A4CD14A65BD57D7CC552AAD79"
{
- "Name" = "8:install.vbs"
+ "Name" = "8:Installer.exe"
"Condition" = "8:"
- "Object" = "8:_2422B61EFBF047FFBBE92CB70714E99C"
- "FileType" = "3:4"
- "InstallAction" = "3:1"
- "Arguments" = "8:"
- "EntryPoint" = "8:"
- "Sequence" = "3:2"
- "Identifier" = "8:_CB90C8D4_3928_4ACA_9263_454FD47BB545"
- "InstallerClass" = "11:FALSE"
- "CustomActionData" = "8:[TARGETDIR]"
- }
- "{4AA51A2D-7D85-4A59-BA75-B0809FC8B380}:_C6B6E1FCC7E6471F914483477DA0D4B6"
- {
- "Name" = "8:Primary output from configure (Active)"
- "Condition" = "8:"
- "Object" = "8:_764D5BE911464BEFBCC3BC3B25068987"
+ "Object" = "8:_009A580142D04FE980ED45947D355FE7"
"FileType" = "3:2"
"InstallAction" = "3:1"
"Arguments" = "8:\"[TARGETDIR]\""
"EntryPoint" = "8:"
"Sequence" = "3:1"
- "Identifier" = "8:_6EC4042E_4AC8_4584_A326_BE8E22FF087D"
+ "Identifier" = "8:_166E62F8_D2C0_4A30_A2FE_EF5B53066941"
"InstallerClass" = "11:FALSE"
"CustomActionData" = "8:"
}
- "{4AA51A2D-7D85-4A59-BA75-B0809FC8B380}:_C9D5851C213E4B928C42AC01EEF1458A"
- {
- "Name" = "8:uninstall.vbs"
- "Condition" = "8:"
- "Object" = "8:_DB58E622510C458A81C3B850EDFC782C"
- "FileType" = "3:4"
- "InstallAction" = "3:4"
- "Arguments" = "8:"
- "EntryPoint" = "8:"
- "Sequence" = "3:2"
- "Identifier" = "8:_1DC83628_1D76_474B_92FD_C7C13056C010"
- "InstallerClass" = "11:FALSE"
- "CustomActionData" = "8:[TARGETDIR]"
- }
}
"DefaultFeature"
{
@@ -374,18 +311,30 @@
{
"LaunchCondition"
{
- "{A06ECF26-33A3-4562-8140-9B0E340D4F24}:_147B76BCD529406A806B4AD361E520C1"
- {
- "Name" = "8:.NET Framework"
- "Message" = "8:[VSDNETMSG]"
- "FrameworkVersion" = "8:.NETFramework,Version=v4.0,Profile=Client"
- "AllowLaterVersions" = "11:FALSE"
- "InstallUrl" = "8:http://go.microsoft.com/fwlink/?LinkId=131000"
- }
}
}
"File"
{
+ "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_009A580142D04FE980ED45947D355FE7"
+ {
+ "SourcePath" = "8:..\\Release\\Installer.exe"
+ "TargetName" = "8:Installer.exe"
+ "Tag" = "8:"
+ "Folder" = "8:_565C3432A64049EAA7CA6E8C007B2188"
+ "Condition" = "8:"
+ "Transitive" = "11:FALSE"
+ "Vital" = "11:TRUE"
+ "ReadOnly" = "11:FALSE"
+ "Hidden" = "11:FALSE"
+ "System" = "11:FALSE"
+ "Permanent" = "11:FALSE"
+ "SharedLegacy" = "11:FALSE"
+ "PackageAs" = "3:1"
+ "Register" = "3:1"
+ "Exclude" = "11:FALSE"
+ "IsDependency" = "11:FALSE"
+ "IsolateTo" = "8:"
+ }
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0593BBFCC6154162A5F7E88C4967D8E8"
{
"SourcePath" = "8:x86\\pcre.dll"
@@ -446,26 +395,6 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
- "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2422B61EFBF047FFBBE92CB70714E99C"
- {
- "SourcePath" = "8:install.vbs"
- "TargetName" = "8:install.vbs"
- "Tag" = "8:"
- "Folder" = "8:_565C3432A64049EAA7CA6E8C007B2188"
- "Condition" = "8:"
- "Transitive" = "11:FALSE"
- "Vital" = "11:TRUE"
- "ReadOnly" = "11:FALSE"
- "Hidden" = "11:FALSE"
- "System" = "11:FALSE"
- "Permanent" = "11:FALSE"
- "SharedLegacy" = "11:FALSE"
- "PackageAs" = "3:1"
- "Register" = "3:1"
- "Exclude" = "11:TRUE"
- "IsDependency" = "11:FALSE"
- "IsolateTo" = "8:"
- }
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2A9DB6318EE24F649FB0CDB52691122C"
{
"SourcePath" = "8:ModSecurityLogo.bmp"
@@ -486,26 +415,6 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
- "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3CE93C3FC5AC3E954253889334FBCDA8"
- {
- "SourcePath" = "8:nativerd.dll"
- "TargetName" = "8:nativerd.dll"
- "Tag" = "8:"
- "Folder" = "8:_565C3432A64049EAA7CA6E8C007B2188"
- "Condition" = "8:"
- "Transitive" = "11:FALSE"
- "Vital" = "11:TRUE"
- "ReadOnly" = "11:FALSE"
- "Hidden" = "11:FALSE"
- "System" = "11:FALSE"
- "Permanent" = "11:FALSE"
- "SharedLegacy" = "11:FALSE"
- "PackageAs" = "3:1"
- "Register" = "3:1"
- "Exclude" = "11:FALSE"
- "IsDependency" = "11:TRUE"
- "IsolateTo" = "8:"
- }
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_51AF671FCA3544DEA3E5756B5D450275"
{
"SourcePath" = "8:x86\\ModSecurityIIS.dll"
@@ -806,37 +715,6 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
- "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_CB8446F7ADCD4E3DA3F2C6246FA844A0"
- {
- "AssemblyRegister" = "3:1"
- "AssemblyIsInGAC" = "11:FALSE"
- "AssemblyAsmDisplayName" = "8:Interop.AppHostAdminLibrary, Version=1.0.0.0, Culture=neutral, processorArchitecture=x86"
- "ScatterAssemblies"
- {
- "_CB8446F7ADCD4E3DA3F2C6246FA844A0"
- {
- "Name" = "8:Interop.AppHostAdminLibrary.dll"
- "Attributes" = "3:512"
- }
- }
- "SourcePath" = "8:installer project\\bin\\Release\\Interop.AppHostAdminLibrary.dll"
- "TargetName" = "8:"
- "Tag" = "8:"
- "Folder" = "8:_565C3432A64049EAA7CA6E8C007B2188"
- "Condition" = "8:"
- "Transitive" = "11:FALSE"
- "Vital" = "11:TRUE"
- "ReadOnly" = "11:FALSE"
- "Hidden" = "11:FALSE"
- "System" = "11:FALSE"
- "Permanent" = "11:FALSE"
- "SharedLegacy" = "11:FALSE"
- "PackageAs" = "3:1"
- "Register" = "3:1"
- "Exclude" = "11:FALSE"
- "IsDependency" = "11:FALSE"
- "IsolateTo" = "8:"
- }
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CEB23D021A2E4EEF9245EEDC143AFBA8"
{
"SourcePath" = "8:amd64\\ModSecurityIIS.dll"
@@ -877,12 +755,12 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
- "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DB58E622510C458A81C3B850EDFC782C"
+ "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DE7847BDBDC046F29E13230DCDD4F6E3"
{
- "SourcePath" = "8:uninstall.vbs"
- "TargetName" = "8:uninstall.vbs"
+ "SourcePath" = "8:x86\\lua5.1.dll"
+ "TargetName" = "8:lua5.1.dll"
"Tag" = "8:"
- "Folder" = "8:_565C3432A64049EAA7CA6E8C007B2188"
+ "Folder" = "8:_D7AEA61DD2D746158A1F5660E4C59AB8"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
@@ -893,16 +771,16 @@
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
- "Exclude" = "11:TRUE"
+ "Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
- "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DE7847BDBDC046F29E13230DCDD4F6E3"
+ "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E86FB9D69F2946038E7BBDD01D619813"
{
- "SourcePath" = "8:x86\\lua5.1.dll"
- "TargetName" = "8:lua5.1.dll"
+ "SourcePath" = "8:owasp_crs.zip"
+ "TargetName" = "8:owasp_crs.zip"
"Tag" = "8:"
- "Folder" = "8:_D7AEA61DD2D746158A1F5660E4C59AB8"
+ "Folder" = "8:_565C3432A64049EAA7CA6E8C007B2188"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
@@ -1056,7 +934,7 @@
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:ModSecurity IIS"
"ProductCode" = "8:{81EE8A4A-5128-4CDB-97B2-06B147E8B4B8}"
- "PackageCode" = "8:{B5E59B35-BF44-4075-B9F5-C251002DF58E}"
+ "PackageCode" = "8:{4F65AFE0-1E8A-4F79-98D5-1D7C1C39ABCC}"
"UpgradeCode" = "8:{7B32CF94-443C-47BB-91C3-0E9D3D12DF8B}"
"AspNetVersion" = "8:4.0.30319.0"
"RestartWWWService" = "11:FALSE"
@@ -1777,34 +1655,6 @@
}
"ProjectOutput"
{
- "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_764D5BE911464BEFBCC3BC3B25068987"
- {
- "SourcePath" = "8:installer project\\obj\\x86\\Release\\configure.exe"
- "TargetName" = "8:"
- "Tag" = "8:"
- "Folder" = "8:_565C3432A64049EAA7CA6E8C007B2188"
- "Condition" = "8:"
- "Transitive" = "11:FALSE"
- "Vital" = "11:TRUE"
- "ReadOnly" = "11:FALSE"
- "Hidden" = "11:FALSE"
- "System" = "11:FALSE"
- "Permanent" = "11:FALSE"
- "SharedLegacy" = "11:FALSE"
- "PackageAs" = "3:1"
- "Register" = "3:1"
- "Exclude" = "11:FALSE"
- "IsDependency" = "11:FALSE"
- "IsolateTo" = "8:"
- "ProjectOutputGroupRegister" = "3:1"
- "OutputConfiguration" = "8:"
- "OutputGroupCanonicalName" = "8:Built"
- "OutputProjectGuid" = "8:{023E10BD-4FF6-4401-9A40-AED9717073F2}"
- "ShowKeyOutput" = "11:TRUE"
- "ExcludeFilters"
- {
- }
- }
}
}
}
diff --git a/iis/ModSecurityIIS/ModSecurityIIS/readme.rtf b/iis/ModSecurityIIS/ModSecurityIIS/readme.rtf
index 39ca0234..83d46dfc 100644
--- a/iis/ModSecurityIIS/ModSecurityIIS/readme.rtf
+++ b/iis/ModSecurityIIS/ModSecurityIIS/readme.rtf
@@ -58,9 +58,9 @@
\leveltemplateid1225817962\'01\'95;}{\levelnumbers;}\f1\fbias0 \fi-360\li5760\jclisttab\tx5760\lin5760 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
\leveltemplateid1897401684\'01\'95;}{\levelnumbers;}\f1\fbias0 \fi-360\li6480\jclisttab\tx6480\lin6480 }{\listname ;}\listid652101753}}{\*\listoverridetable{\listoverride\listid625282538\listoverridecount0\ls1}{\listoverride\listid652101753
\listoverridecount0\ls2}}{\*\pgptbl {\pgp\ipgp10\itap0\li720\ri0\sb0\sa240}{\pgp\ipgp10\itap0\li720\ri0\sb0\sa240}{\pgp\ipgp10\itap0\li720\ri0\sb0\sa240}{\pgp\ipgp10\itap0\li720\ri0\sb0\sa240}{\pgp\ipgp6\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp8\itap0\li0\ri0\sb0
-\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp7\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp10\itap0\li720\ri0\sb0\sa240}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid1197496\rsid2315486\rsid3168183\rsid4593034\rsid6385683\rsid6633290\rsid6754893\rsid6967166
-\rsid9512544\rsid10098429\rsid12742482\rsid13639667\rsid16350125\rsid16593896}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author Suha Can}{\operator Greg}
-{\creatim\yr2012\mo6\dy4\hr11\min43}{\revtim\yr2013\mo1\dy17\hr16\min15}{\version9}{\edmins12}{\nofpages1}{\nofwords173}{\nofchars992}{\*\company Microsoft Corporation}{\nofcharsws1163}{\vern49275}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office
+\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp7\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp10\itap0\li720\ri0\sb0\sa240}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid1197496\rsid2315486\rsid3168183\rsid4593034\rsid6385683\rsid6633290\rsid6967166\rsid9512544
+\rsid10098429\rsid12742482\rsid13639667\rsid16350125\rsid16593896}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author Suha Can}{\operator Greg}
+{\creatim\yr2012\mo6\dy4\hr11\min43}{\revtim\yr2013\mo1\dy15\hr9\min48}{\version8}{\edmins11}{\nofpages1}{\nofwords176}{\nofchars1008}{\*\company Microsoft Corporation}{\nofcharsws1182}{\vern49275}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office
/word/2003/wordml}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect
\widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen
\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1440\dgvorigin1440\dghshow1\dgvshow1
@@ -75,44 +75,44 @@
\par }\pard\plain \ltrpar\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid16350125 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {
\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid6385683\charrsid16350125 ModSecurity home page }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid2315486 HYPERLINK "http://www.modsecurity.org"}{\rtlch\fcs1 \af0\afs24
\ltrch\fcs0 \f0\fs24\insrsid2315486\charrsid16350125 {\*\datafield
-00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b5000000068007400740070003a002f002f007700770077002e006d006f006400730065006300750072006900740079002e006f00720067002f000000795881f43b1d7f48af2c825dc485276300000000a5ab00000000}
-}}{\fldrslt {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \cs16\f0\fs24\ul\cf2\insrsid6385683\charrsid16350125 http://www.modsecurity.org}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0\afs24
+00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b5000000068007400740070003a002f002f007700770077002e006d006f006400730065006300750072006900740079002e006f00720067002f000000795881f43b1d7f48af2c825dc485276300000000a5ab000000}}
+}{\fldrslt {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \cs16\f0\fs24\ul\cf2\insrsid6385683\charrsid16350125 http://www.modsecurity.org}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0\afs24
\ltrch\fcs0 \f0\fs24\insrsid6385683\charrsid16350125 HYPERLINK "http://engineering/" }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid2315486\charrsid16350125 {\*\datafield
-00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b4000000068007400740070003a002f002f0065006e00670069006e0065006500720069006e0067002f000000795881f43b1d7f48af2c825dc485276300000000a5ab00000000}}}{\fldrslt {\rtlch\fcs1
+00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b4000000068007400740070003a002f002f0065006e00670069006e0065006500720069006e0067002f000000795881f43b1d7f48af2c825dc485276300000000a5ab000000}}}{\fldrslt {\rtlch\fcs1
\af0\afs24 \ltrch\fcs0 \cs16\f0\fs24\ul\cf2\insrsid6385683\charrsid16350125 /}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid6385683\charrsid16350125
\par OWASP Core Rule Set for ModSecurity: }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid6385683\charrsid16350125 HYPERLINK "https://www.owasp.org/index.php/Category:OWASP_ModSecurity_Core_Rule_Set_Project" }{\rtlch\fcs1
\af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid2315486\charrsid16350125 {\*\datafield
00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90bba000000680074007400700073003a002f002f007700770077002e006f0077006100730070002e006f00720067002f0069006e006400650078002e007000680070002f00430061007400650067006f00720079003a00
-4f0057004100530050005f004d006f006400530065006300750072006900740079005f0043006f00720065005f00520075006c0065005f005300650074005f00500072006f006a006500630074000000795881f43b1d7f48af2c825dc485276300000000a5ab00000016}}}{\fldrslt {\rtlch\fcs1 \af0\afs24
+4f0057004100530050005f004d006f006400530065006300750072006900740079005f0043006f00720065005f00520075006c0065005f005300650074005f00500072006f006a006500630074000000795881f43b1d7f48af2c825dc485276300000000a5ab000000}}}{\fldrslt {\rtlch\fcs1 \af0\afs24
\ltrch\fcs0 \cs16\f0\fs24\ul\cf2\insrsid6385683\charrsid16350125 https://}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid2315486
HYPERLINK "https://www.owasp.org/index.php/Category:OWASP_ModSecurity_Core_Rule_Set_Project"}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid2315486\charrsid16350125 {\*\datafield
00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90bba000000680074007400700073003a002f002f007700770077002e006f0077006100730070002e006f00720067002f0069006e006400650078002e007000680070002f00430061007400650067006f00720079003a00
-4f0057004100530050005f004d006f006400530065006300750072006900740079005f0043006f00720065005f00520075006c0065005f005300650074005f00500072006f006a006500630074000000795881f43b1d7f48af2c825dc485276300000000a5ab00000000}}}{\fldrslt {\rtlch\fcs1 \af0\afs24
+4f0057004100530050005f004d006f006400530065006300750072006900740079005f0043006f00720065005f00520075006c0065005f005300650074005f00500072006f006a006500630074000000795881f43b1d7f48af2c825dc485276300000000a5ab000000}}}{\fldrslt {\rtlch\fcs1 \af0\afs24
\ltrch\fcs0 \cs16\f0\fs24\ul\cf2\insrsid6385683\charrsid16350125 www.owasp.org/index.php/Category:OWASP_ModSecurity_Core_Rule_Set_Project}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
\f0\fs24\insrsid6385683\charrsid16350125
\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid6633290 The OWASP CRS was installed on your system drive, under }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\f0\fs24\insrsid6633290\charrsid6633290 inetpub\\wwwroot\\owasp_crs}{\rtlch\fcs1 \af0\afs24
\ltrch\fcs0 \f0\fs24\insrsid6633290
\par You can include it in your website by adding to your }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\f0\fs24\insrsid6633290\charrsid6633290 web.config}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid6633290 file, in }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
\b\f0\fs24\insrsid6633290\charrsid6633290 system.webServer}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid6633290 section:
-\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid6633290\charrsid6633290
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid6633290\charrsid6633290
\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1045\langfe1033\langnp1045\insrsid6385683\charrsid16350125 MSRC blog }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1045\langfe1033\langnp1045\insrsid6385683\charrsid16350125
HYPERLINK "http://blogs.technet.com/b/srd/" }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1045\langfe1033\langnp1045\insrsid2315486\charrsid16350125 {\*\datafield
00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b5800000068007400740070003a002f002f0062006c006f00670073002e0074006500630068006e00650074002e0063006f006d002f0062002f007300720064002f000000795881f43b1d7f48af2c825dc48527630000
-0000a5ab00000000}}}{\fldrslt {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \cs16\f0\fs24\ul\cf2\lang1045\langfe1033\langnp1045\insrsid6385683\charrsid16350125 http://blogs.technet.com/b/srd/}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {
+0000a5ab000000}}}{\fldrslt {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \cs16\f0\fs24\ul\cf2\lang1045\langfe1033\langnp1045\insrsid6385683\charrsid16350125 http://blogs.technet.com/b/srd/}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {
\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1045\langfe1033\langnp1045\insrsid6385683\charrsid16350125 }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1045\langfe1033\langnp1045\insrsid6385683\charrsid6633290
\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid6385683\charrsid16350125 Trustwave SpiderLabs blog: }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid2315486 HYPERLINK "http://blog.spiderlabs.com/"}{\rtlch\fcs1
\af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid2315486\charrsid16350125 {\*\datafield
-00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b5000000068007400740070003a002f002f0062006c006f0067002e007300700069006400650072006c006100620073002e0063006f006d002f000000795881f43b1d7f48af2c825dc485276300000000a5ab00000000}
-}}{\fldrslt {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \cs16\f0\fs24\ul\cf2\insrsid6385683\charrsid16350125 http://blog.spiderlabs.com}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0\afs24
+00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b5000000068007400740070003a002f002f0062006c006f0067002e007300700069006400650072006c006100620073002e0063006f006d002f000000795881f43b1d7f48af2c825dc485276300000000a5ab000000}}
+}{\fldrslt {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \cs16\f0\fs24\ul\cf2\insrsid6385683\charrsid16350125 http://blog.spiderlabs.com}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0\afs24
\ltrch\fcs0 \f0\fs24\insrsid6385683\charrsid16350125 HYPERLINK "http://blog.spiderlabs.com/" }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid2315486\charrsid16350125 {\*\datafield
-00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b5000000068007400740070003a002f002f0062006c006f0067002e007300700069006400650072006c006100620073002e0063006f006d002f000000795881f43b1d7f48af2c825dc485276300000000a5ab00000000}
-}}{\fldrslt {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \cs16\f0\fs24\ul\cf2\insrsid6385683\charrsid16350125 /}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid6385683\charrsid16350125
+00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b5000000068007400740070003a002f002f0062006c006f0067002e007300700069006400650072006c006100620073002e0063006f006d002f000000795881f43b1d7f48af2c825dc485276300000000a5ab000000}}
+}{\fldrslt {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \cs16\f0\fs24\ul\cf2\insrsid6385683\charrsid16350125 /}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid6385683\charrsid16350125
\par Trustwave Commercial Rule Set for ModSecurity: }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid2315486 HYPERLINK "https://www.trustwave.com/modsecurity-rules-support.php"}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
\f0\fs24\insrsid2315486\charrsid16350125 {\*\datafield
00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b88000000680074007400700073003a002f002f007700770077002e007400720075007300740077006100760065002e0063006f006d002f006d006f006400730065006300750072006900740079002d00720075006c00
-650073002d0073007500700070006f00720074002e007000680070000000795881f43b1d7f48af2c825dc485276300000000a5ab00000000}}}{\fldrslt {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \cs16\f0\fs24\ul\cf2\insrsid6385683\charrsid16350125
+650073002d0073007500700070006f00720074002e007000680070000000795881f43b1d7f48af2c825dc485276300000000a5ab000000}}}{\fldrslt {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \cs16\f0\fs24\ul\cf2\insrsid6385683\charrsid16350125
https://www.trustwave.com/modsecurity-rules-support.php}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid6385683\charrsid16350125
\par }\pard \ltrpar\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid6967166
\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a
@@ -220,8 +220,8 @@ fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e5000000000000000000000000f0d5
-16df10f5cd01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e5000000000000000000000000e065
+dc7748f3cd01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000105000000000000}}
\ No newline at end of file
diff --git a/iis/mymodulefactory.h b/iis/mymodulefactory.h
index a073a78e..9934ab61 100644
--- a/iis/mymodulefactory.h
+++ b/iis/mymodulefactory.h
@@ -20,14 +20,17 @@
// of CMyHttpModule for each request.
class CMyHttpModuleFactory : public IHttpModuleFactory
{
- CMyHttpModule * m_pModule;
+ CMyHttpModule * m_pModule;
+ CRITICAL_SECTION m_csLock;
public:
CMyHttpModuleFactory()
{
m_pModule = NULL;
+
+ InitializeCriticalSection(&m_csLock);
}
-
+
virtual
HRESULT
GetHttpModule(
@@ -43,6 +46,8 @@ public:
goto Finished;
}
+ EnterCriticalSection(&m_csLock);
+
if(m_pModule == NULL)
{
m_pModule = new CMyHttpModule();
@@ -54,6 +59,8 @@ public:
}
}
+ LeaveCriticalSection(&m_csLock);
+
*ppModule = m_pModule;
Finished:
diff --git a/nginx/modsecurity/apr_bucket_nginx.c b/nginx/modsecurity/apr_bucket_nginx.c
new file mode 100644
index 00000000..7b41b6f0
--- /dev/null
+++ b/nginx/modsecurity/apr_bucket_nginx.c
@@ -0,0 +1,239 @@
+
+#include
+
+static apr_status_t nginx_bucket_read(apr_bucket *b, const char **str,
+ apr_size_t *len, apr_read_type_e block);
+static void nginx_bucket_destroy(void *data);
+
+static const apr_bucket_type_t apr_bucket_type_nginx = {
+ "NGINX", 5, APR_BUCKET_DATA,
+ nginx_bucket_destroy,
+ nginx_bucket_read,
+ apr_bucket_setaside_noop,
+ apr_bucket_shared_split,
+ apr_bucket_shared_copy
+};
+
+
+typedef struct apr_bucket_nginx {
+ apr_bucket_refcount refcount;
+ ngx_buf_t *buf;
+} apr_bucket_nginx;
+
+/* ngx_buf_t to apr_bucket */
+apr_bucket * apr_bucket_nginx_create(ngx_buf_t *buf,
+ apr_pool_t *p,
+ apr_bucket_alloc_t *list)
+{
+
+ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+ APR_BUCKET_INIT(b); /* link */
+ b->free = apr_bucket_free;
+ b->list = list;
+ return apr_bucket_nginx_make(b, buf, p);
+}
+
+apr_bucket * apr_bucket_nginx_make(apr_bucket *b, ngx_buf_t *buf,
+ apr_pool_t *pool)
+{
+ apr_bucket_nginx *n;
+
+ n = apr_bucket_alloc(sizeof(*n), b->list);
+
+ n->buf = buf;
+
+ b = apr_bucket_shared_make(b, n, 0, ngx_buf_size(buf));
+ b->type = &apr_bucket_type_nginx;
+ return b;
+}
+
+static apr_status_t nginx_bucket_read(apr_bucket *b, const char **str,
+ apr_size_t *len, apr_read_type_e block)
+{
+ apr_bucket_nginx *n = b->data;
+ ngx_buf_t *buf = n->buf;
+ u_char *data;
+ ssize_t size;
+
+ if (buf->pos == NULL && ngx_buf_size(buf) != 0) {
+ data = apr_bucket_alloc(ngx_buf_size(buf), b->list);
+ if (data == NULL) {
+ return APR_EGENERAL;
+ }
+
+ size = ngx_read_file(buf->file, data, ngx_buf_size(buf), buf->file_pos);
+ if (size != ngx_buf_size(buf)) {
+ apr_bucket_free(data);
+ return APR_EGENERAL;
+ }
+ buf->pos = data;
+ }
+
+ *str = (char *)buf->pos + b->start;
+ *len = b->length;
+
+ return APR_SUCCESS;
+}
+
+
+static void nginx_bucket_destroy(void *data)
+{
+ apr_bucket_nginx *n = data;
+ ngx_buf_t *buf = n->buf;
+
+ if (apr_bucket_shared_destroy(n)) {
+ if (!ngx_buf_in_memory(buf) && buf->pos != NULL) {
+ apr_bucket_free(buf->pos);
+ buf->pos = NULL;
+ }
+ apr_bucket_free(n);
+ }
+}
+
+ngx_buf_t * apr_bucket_to_ngx_buf(apr_bucket *e, ngx_pool_t *pool) {
+ ngx_buf_t *buf, *b;
+ apr_bucket_nginx *n;
+ ngx_uint_t len;
+ u_char *data;
+
+ if (e->type->is_metadata) {
+ return NULL;
+ }
+
+ if (e->type == &apr_bucket_type_nginx) {
+ n = e->data;
+ b = n->buf;
+
+ /* whole buf */
+ if (e->length == (apr_size_t)ngx_buf_size(b)) {
+ b->last_buf = 0;
+ return b;
+ }
+
+ buf = ngx_palloc(pool, sizeof(ngx_buf_t));
+ if (buf == NULL) {
+ return NULL;
+ }
+ ngx_memcpy(buf, b, sizeof(ngx_buf_t));
+
+ if (ngx_buf_in_memory(buf)) {
+ buf->start = buf->pos = buf->pos + e->start;
+ buf->end = buf->last = buf->pos + e->length;
+ } else {
+ buf->pos = NULL;
+ buf->file_pos += e->start;
+ buf->file_last = buf->file_pos + e->length;
+ }
+
+ buf->last_buf = 0;
+ return buf;
+ }
+
+ if (apr_bucket_read(e, (const char **)&data,
+ &len, APR_BLOCK_READ) != APR_SUCCESS) {
+ return NULL;
+ }
+
+ buf = ngx_calloc_buf(pool);
+ if (buf == NULL) {
+ return NULL;
+ }
+
+ if (e->type == &apr_bucket_type_pool) {
+ buf->start = data;
+ } else if (len != 0) {
+ buf->start = ngx_palloc(pool, len);
+ ngx_memcpy(buf->start, data, len);
+ }
+
+ buf->pos = buf->start;
+ buf->end = buf->last = buf->start + len;
+ buf->temporary = 1;
+ return buf;
+}
+
+ngx_int_t
+move_chain_to_brigade(ngx_chain_t *chain, apr_bucket_brigade *bb, ngx_pool_t *pool, ngx_int_t last_buf) {
+ apr_bucket *e;
+ ngx_chain_t *cl;
+
+ while (chain) {
+ e = ngx_buf_to_apr_bucket(chain->buf, bb->p, bb->bucket_alloc);
+ if (e == NULL) {
+ return NGX_ERROR;
+ }
+
+ APR_BRIGADE_INSERT_TAIL(bb, e);
+ if (chain->buf->last_buf) {
+ e = apr_bucket_eos_create(bb->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, e);
+ chain->buf->last_buf = 0;
+ return NGX_OK;
+ }
+ cl = chain;
+ chain = chain->next;
+ ngx_free_chain(pool, cl);
+ }
+
+ if (last_buf) {
+ e = apr_bucket_eos_create(bb->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, e);
+ return NGX_OK;
+ }
+
+ return NGX_AGAIN;
+}
+
+ngx_int_t
+move_brigade_to_chain(apr_bucket_brigade *bb, ngx_chain_t **ll, ngx_pool_t *pool) {
+ apr_bucket *e;
+ ngx_buf_t *buf;
+ ngx_chain_t *cl;
+
+ cl = NULL;
+
+ if (APR_BRIGADE_EMPTY(bb)) {
+ *ll = NULL;
+ return NGX_OK;
+ }
+
+ for (e = APR_BRIGADE_FIRST(bb);
+ e != APR_BRIGADE_SENTINEL(bb);
+ e = APR_BUCKET_NEXT(e)) {
+
+ if (APR_BUCKET_IS_EOS(e)) {
+ if (cl == NULL) {
+ *ll = cl;
+ } else {
+ cl->buf->last_buf = 1;
+ }
+ apr_brigade_cleanup(bb);
+ return NGX_OK;
+ }
+
+ if (APR_BUCKET_IS_METADATA(e)) {
+ continue;
+ }
+
+ buf = apr_bucket_to_ngx_buf(e, pool);
+ if (buf == NULL) {
+ break;
+ }
+
+ cl = ngx_alloc_chain_link(pool);
+ if (cl == NULL) {
+ break;
+ }
+
+ cl->buf = buf;
+ cl->next = NULL;
+ *ll = cl;
+ ll = &cl->next;
+ }
+
+ apr_brigade_cleanup(bb);
+ /* no eos or error */
+ return NGX_ERROR;
+}
+
diff --git a/nginx/modsecurity/apr_bucket_nginx.h b/nginx/modsecurity/apr_bucket_nginx.h
new file mode 100644
index 00000000..e37f9f78
--- /dev/null
+++ b/nginx/modsecurity/apr_bucket_nginx.h
@@ -0,0 +1,18 @@
+#pragma once
+#include
+#include "apr_buckets.h"
+
+apr_bucket * apr_bucket_nginx_create(ngx_buf_t *buf,
+ apr_pool_t *p,
+ apr_bucket_alloc_t *list);
+
+apr_bucket * apr_bucket_nginx_make(apr_bucket *e, ngx_buf_t *buf,
+ apr_pool_t *pool);
+
+#define ngx_buf_to_apr_bucket apr_bucket_nginx_create
+
+ngx_buf_t * apr_bucket_to_ngx_buf(apr_bucket *e, ngx_pool_t *pool);
+
+ngx_int_t move_chain_to_brigade(ngx_chain_t *chain, apr_bucket_brigade *bb, ngx_pool_t *pool, ngx_int_t last_buf);
+ngx_int_t move_brigade_to_chain(apr_bucket_brigade *bb, ngx_chain_t **chain, ngx_pool_t *pool);
+
diff --git a/nginx/modsecurity/config b/nginx/modsecurity/config
index 1cf004cd..58e61efc 100644
--- a/nginx/modsecurity/config
+++ b/nginx/modsecurity/config
@@ -1,6 +1,8 @@
ngx_addon_name=ngx_http_modsecurity
-HTTP_MODULES="$HTTP_MODULES ngx_http_modsecurity"
-NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_modsecurity.c"
-NGX_ADDON_DEPS="$NGX_ADDON_DEPS"
+CORE_MODULES="$CORE_MODULES ngx_pool_context_module"
+HTTP_AUX_FILTER_MODULES="ngx_http_modsecurity $HTTP_AUX_FILTER_MODULES"
+NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_modsecurity.c $ngx_addon_dir/apr_bucket_nginx.c $ngx_addon_dir/ngx_pool_context.c"
+NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/apr_bucket_nginx.h $ngx_addon_dir/ngx_pool_context.h"
CORE_LIBS="$CORE_LIBS $ngx_addon_dir/../../standalone/.libs/standalone.a -lapr-1 -laprutil-1 -lxml2 -lm"
-CORE_INCS="$CORE_INCS /usr/include/apache2 /usr/include/apr-1.0 /usr/include/httpd /usr/include/apr-1 $ngx_addon_dir/../../standalone $ngx_addon_dir/../../apache2 /usr/include/libxml2"
+CORE_INCS="$CORE_INCS /usr/include/apache2 /usr/include/apr-1.0 /usr/include/httpd /usr/include/apr-1 $ngx_addon_dir $ngx_addon_dir/../../standalone $ngx_addon_dir/../../apache2 /usr/include/libxml2"
+
diff --git a/nginx/modsecurity/ngx_http_modsecurity.c b/nginx/modsecurity/ngx_http_modsecurity.c
index a78a1535..6eeeef05 100644
--- a/nginx/modsecurity/ngx_http_modsecurity.c
+++ b/nginx/modsecurity/ngx_http_modsecurity.c
@@ -12,14 +12,9 @@
* directly using the email address security@modsecurity.org.
*/
-#include
-#include
-#include
#include
-#include
-#include
-#include
-#include
+#include
+#include
#undef CR
#undef LF
@@ -32,17 +27,18 @@
typedef struct {
ngx_flag_t enable;
directory_config *config;
+
+ ngx_str_t *file;
+ ngx_uint_t line;
} ngx_http_modsecurity_loc_conf_t;
typedef struct {
ngx_http_request_t *r;
conn_rec *connection;
request_rec *req;
- ngx_chain_t *chain;
- ngx_buf_t buf;
- void **loc_conf;
- unsigned request_body_in_single_buf:1;
- unsigned request_body_in_file_only:1;
+
+ apr_bucket_brigade *brigade;
+ unsigned complete;
} ngx_http_modsecurity_ctx_t;
@@ -50,7 +46,9 @@ typedef struct {
** Module's registred function/handlers.
*/
static ngx_int_t ngx_http_modsecurity_handler(ngx_http_request_t *r);
-static void ngx_http_modsecurity_request_body_handler(ngx_http_request_t *r);
+static void ngx_http_modsecurity_body_handler(ngx_http_request_t *r);
+static ngx_int_t ngx_http_modsecurity_header_filter(ngx_http_request_t *r);
+static ngx_int_t ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in);
static ngx_int_t ngx_http_modsecurity_preconfiguration(ngx_conf_t *cf);
static ngx_int_t ngx_http_modsecurity_init(ngx_conf_t *cf);
static ngx_int_t ngx_http_modsecurity_init_process(ngx_cycle_t *cycle);
@@ -58,14 +56,16 @@ static void ngx_http_modsecurity_exit_process(ngx_cycle_t *cycle);
static void *ngx_http_modsecurity_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_modsecurity_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child);
static char *ngx_http_modsecurity_config(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-apr_status_t modsecurity_read_body_cb(request_rec *r, char *buf, unsigned int length,
- unsigned int *readcnt, int *is_eos);
-apr_status_t modsecurity_write_body_cb(request_rec *rec, char *buf, unsigned int length);
+static char *ngx_http_modsecurity_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_http_modsecurity_ctx_t * ngx_http_modsecurity_create_ctx(ngx_http_request_t *r);
static int ngx_http_modsecurity_drop_action(request_rec *r);
static void ngx_http_modsecurity_cleanup(void *data);
+static int ngx_http_modsecurity_save_headers_in_visitor(void *data, const char *key, const char *value);
+static int ngx_http_modsecurity_save_headers_out_visitor(void *data, const char *key, const char *value);
+
+
/* command handled by the module */
static ngx_command_t ngx_http_modsecurity_commands[] = {
{ ngx_string("ModSecurityConfig"),
@@ -77,7 +77,7 @@ static ngx_command_t ngx_http_modsecurity_commands[] = {
{ ngx_string("ModSecurityEnabled"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF
|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_flag_slot,
+ ngx_http_modsecurity_enable,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_modsecurity_loc_conf_t, enable),
NULL },
@@ -118,6 +118,656 @@ ngx_module_t ngx_http_modsecurity = {
NGX_MODULE_V1_PADDING
};
+static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
+static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
+
+static ngx_http_upstream_t ngx_http_modsecurity_upstream;
+
+static struct {
+ char *name;
+ ngx_str_t variable_name;
+} special_headers_out[] = {
+ {"Content-Type", ngx_string("sent_http_content_type") },
+ {"Content-Length", ngx_string("sent_http_content_length")},
+ {"Location", ngx_string("sent_http_location")},
+ {"Last-Modified", ngx_string("sent_http_last_modified")},
+ {"Connection", ngx_string("sent_http_connection")},
+ {"Keep-Alive", ngx_string("sent_http_keep_alive")},
+ {"Transfer-Encoding", ngx_string("sent_http_transfer_encoding")},
+ {"Cache-Control", ngx_string("sent_http_cache_control")},
+ {NULL, ngx_null_string}
+};
+
+
+static inline int ngx_http_modsecurity_method_number(unsigned int nginx)
+{
+ /*
+ * http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup
+ */
+ static const int MultiplyDeBruijnBitPosition[32] = {
+ M_INVALID, /* 1 >> 0 */
+ M_GET,
+ M_INVALID, /* 1 >> 28 */
+ M_GET, /* NGX_HTTP_HEAD */
+ M_INVALID, /* 1 >> 29 */
+ M_PATCH,
+ M_INVALID, /* 1 >> 24 */
+ M_POST,
+ M_INVALID, /* 1 >> 30 */
+ M_INVALID, /* 1 >> 22 */
+ M_INVALID, /* 1 >> 20 */
+ M_TRACE,
+ M_INVALID, /* 1 >> 25 */
+ M_INVALID, /* 1 >> 17 */
+ M_PUT,
+ M_MOVE,
+ M_INVALID, /* 1 >> 31 */
+ M_INVALID, /* 1 >> 27 */
+ M_UNLOCK,
+ M_INVALID, /* 1 >> 23 */
+ M_INVALID, /* 1 >> 21 */
+ M_INVALID, /* 1 >> 19 */
+ M_INVALID, /* 1 >> 16 */
+ M_COPY,
+ M_INVALID, /* 1 >> 26 */
+ M_LOCK,
+ M_INVALID, /* 1 >> 18 */
+ M_MKCOL,
+ M_PROPPATCH,
+ M_DELETE,
+ M_PROPFIND,
+ M_OPTIONS
+ };
+
+ return MultiplyDeBruijnBitPosition[((uint32_t)((nginx & -nginx) * 0x077CB531U)) >> 27];
+}
+
+static ngx_inline ngx_int_t
+ngx_http_modsecurity_load_request(ngx_http_request_t *r)
+{
+ ngx_http_modsecurity_ctx_t *ctx;
+ request_rec *req;
+ ngx_str_t str;
+ size_t root;
+ ngx_str_t path;
+
+ ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity);
+ req = ctx->req;
+
+ /* request line */
+ req->method = (char *)ngx_pstrdup(r->pool, &r->method_name);
+
+ /* TODO: how to use ap_method_number_of ?
+ * req->method_number = ap_method_number_of(req->method);
+ */
+
+ req->method_number = ngx_http_modsecurity_method_number(r->method);
+
+ /* ngx_http_map_uri_to_path() allocates memory for terminating '\0' */
+ if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
+ return NGX_ERROR;
+ }
+
+ req->filename = (char *) path.data;
+ req->path_info = req->filename;
+
+ req->args = (char *)ngx_pstrdup(r->pool, &r->args);
+
+ req->proto_num = r->http_major *1000 + r->http_minor;
+ req->protocol = (char *)ngx_pstrdup(r->pool, &r->http_protocol);
+ req->request_time = apr_time_make(r->start_sec, r->start_msec);
+ req->the_request = (char *)ngx_pstrdup(r->pool, &r->request_line);
+
+ req->unparsed_uri = (char *)ngx_pstrdup(r->pool, &r->unparsed_uri);
+ req->uri = (char *)ngx_pstrdup(r->pool, &r->uri);
+
+ req->parsed_uri.scheme = "http";
+
+#if (NGX_HTTP_SSL)
+ if (r->connection->ssl) {
+ req->parsed_uri.scheme = "https";
+ }
+#endif
+
+ req->parsed_uri.path = req->path_info;
+ req->parsed_uri.is_initialized = 1;
+
+ str.data = r->port_start;
+ str.len = r->port_end - r->port_start;
+ req->parsed_uri.port = ngx_atoi(str.data, str.len);
+ req->parsed_uri.port_str = (char *)ngx_pstrdup(r->pool, &str);
+
+ req->parsed_uri.query = req->args;
+ req->parsed_uri.dns_looked_up = 0;
+ req->parsed_uri.dns_resolved = 0;
+
+ // req->parsed_uri.password = (char *)ngx_pstrdup(r->pool, &r->headers_in.passwd);
+ // req->parsed_uri.user = (char *)ngx_pstrdup(r->pool, &r->headers_in.user);
+ req->parsed_uri.fragment = (char *)ngx_pstrdup(r->pool, &r->exten);
+
+ req->hostname = (char *)ngx_pstrdup(r->pool, (ngx_str_t *)&ngx_cycle->hostname);
+
+ req->header_only = r->header_only ? r->header_only : (r->method == NGX_HTTP_HEAD);
+
+ return NGX_OK;
+}
+
+
+/*
+ * TODO: deal more headers.
+ */
+
+static ngx_inline ngx_int_t
+ngx_http_modsecurity_load_headers_in(ngx_http_request_t *r)
+{
+ ngx_http_modsecurity_ctx_t *ctx;
+ const char *lang;
+ request_rec *req;
+ ngx_list_part_t *part;
+ ngx_table_elt_t *h;
+ ngx_uint_t i;
+
+
+ ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity);
+ req = ctx->req;
+
+ part = &r->headers_in.headers.part;
+ h = part->elts;
+
+ for (i = 0; ; i++) {
+ if (i >= part->nelts) {
+ if (part->next == NULL)
+ break;
+
+ part = part->next;
+ h = part->elts;
+ i = 0;
+ }
+
+ apr_table_setn(req->headers_in, (char *)h[i].key.data, (char *)h[i].value.data);
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "ModSecurity: load headers in: \"%V: %V\"",
+ &h[i].key, &h[i].value);
+ }
+
+ req->clength = r->headers_in.content_length_n;
+
+
+ req->range = apr_table_get(req->headers_in, "Range");
+ req->content_type = apr_table_get(req->headers_in, "Content-Type");
+ req->content_encoding = apr_table_get(req->headers_in, "Content-Encoding");
+
+ lang = apr_table_get(ctx->req->headers_in, "Content-Languages");
+ if(lang != NULL)
+ {
+ ctx->req->content_languages = apr_array_make(ctx->req->pool, 1, sizeof(const char *));
+
+ *(const char **)apr_array_push(ctx->req->content_languages) = lang;
+ }
+
+ req->ap_auth_type = (char *)apr_table_get(req->headers_in, "Authorization");
+
+ req->user = (char *)ngx_pstrdup(r->pool, &r->headers_in.user);
+
+
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "ModSecurity: load headers in done");
+
+ return NGX_OK;
+}
+
+static ngx_inline ngx_int_t
+ngx_http_modsecurity_save_headers_in(ngx_http_request_t *r)
+{
+ ngx_http_modsecurity_ctx_t *ctx;
+
+ ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity);
+
+ /* clean up headers_in */
+ ngx_memzero(&r->headers_in, sizeof(ngx_http_headers_in_t));
+
+ if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
+ sizeof(ngx_table_elt_t))
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+
+
+ if (ngx_array_init(&r->headers_in.cookies, r->pool, 2,
+ sizeof(ngx_table_elt_t *))
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+
+ r->headers_in.content_length_n = -1;
+ r->headers_in.keep_alive_n = -1;
+
+ r->headers_in.headers.part.nelts = 0;
+ r->headers_in.headers.part.next = NULL;
+ r->headers_in.headers.last = &r->headers_in.headers.part;
+
+ /* shadow copy */
+ if (apr_table_do(ngx_http_modsecurity_save_headers_in_visitor,
+ r, ctx->req->headers_in, NULL) == 0) {
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "ModSecurity: save headers in error");
+
+ return NGX_ERROR;
+ }
+
+ if (r->headers_in.content_length) {
+ r->headers_in.content_length_n =
+ ngx_atoof(r->headers_in.content_length->value.data,
+ r->headers_in.content_length->value.len);
+
+ if (r->headers_in.content_length_n == NGX_ERROR) {
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
+ "ModSecurity: invalid \"Content-Length\" header");
+ return NGX_ERROR;
+ }
+ }
+
+ if (r->headers_in.connection_type == NGX_HTTP_CONNECTION_KEEP_ALIVE) {
+ if (r->headers_in.keep_alive) {
+ r->headers_in.keep_alive_n =
+ ngx_atotm(r->headers_in.keep_alive->value.data,
+ r->headers_in.keep_alive->value.len);
+ }
+ }
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "ModSecurity: save headers in done");
+
+ return NGX_OK;
+}
+
+
+static int
+ngx_http_modsecurity_save_headers_in_visitor(void *data, const char *key, const char *value)
+{
+ ngx_http_request_t *r = data;
+ ngx_table_elt_t *h;
+ ngx_http_header_t *hh;
+ ngx_http_core_main_conf_t *cmcf;
+
+ h = ngx_list_push(&r->headers_in.headers);
+ if (h == NULL) {
+ return 0;
+ }
+
+ h->key.data = (u_char *)key;
+ h->key.len = ngx_strlen(key);
+
+ h->value.data = (u_char *)value;
+ h->value.len = ngx_strlen(value);
+
+ h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
+
+ if (h->lowcase_key == NULL) {
+ return 0;
+ }
+
+ ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
+
+ h->hash = ngx_hash_key(h->lowcase_key, h->key.len);
+
+ cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
+
+ hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
+ h->lowcase_key, h->key.len);
+
+ if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
+ return 0;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "ModSecurity: save headers in: \"%V: %V\"",
+ &h->key, &h->value);
+
+ return 1;
+}
+
+
+static ngx_inline ngx_int_t
+ngx_http_modsecurity_load_request_body(ngx_http_request_t *r)
+{
+ ngx_http_modsecurity_ctx_t *ctx;
+
+ ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity);
+
+ modsecSetBodyBrigade(ctx->req, ctx->brigade);
+
+ if (r->request_body == NULL || r->request_body->bufs == NULL) {
+
+ return move_chain_to_brigade(NULL, ctx->brigade, r->pool, 1);
+ }
+
+ if (move_chain_to_brigade(r->request_body->bufs, ctx->brigade, r->pool, 1) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ r->request_body = NULL;
+
+ return NGX_OK;
+}
+
+
+static ngx_inline ngx_int_t
+ngx_http_modsecurity_save_request_body(ngx_http_request_t *r)
+{
+ ngx_http_modsecurity_ctx_t *ctx;
+ apr_off_t content_length;
+ ngx_buf_t *buf;
+ ngx_http_core_srv_conf_t *cscf;
+ size_t size;
+ ngx_http_connection_t *hc;
+
+ ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity);
+
+ apr_brigade_length(ctx->brigade, 0, &content_length);
+
+ if (r->header_in->end - r->header_in->last >= content_length) {
+ /* use r->header_in */
+
+ if (ngx_buf_size(r->header_in)) {
+ /* move to the end */
+ ngx_memmove(r->header_in->pos + content_length,
+ r->header_in->pos,
+ ngx_buf_size(r->header_in));
+ }
+
+ if (apr_brigade_flatten(ctx->brigade,
+ (char *)r->header_in->pos,
+ (apr_size_t *)&content_length) != APR_SUCCESS) {
+ return NGX_ERROR;
+ }
+
+ apr_brigade_cleanup(ctx->brigade);
+
+ r->header_in->last += content_length;
+
+ return NGX_OK;
+ }
+
+ if (ngx_buf_size(r->header_in)) {
+
+ /*
+ * ngx_http_set_keepalive will reuse r->header_in if
+ * (r->header_in != c->buffer && r->header_in.last != r->header_in.end),
+ * so we need this code block.
+ * see ngx_http_set_keepalive, ngx_http_alloc_large_header_buffer
+ */
+ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
+
+ size = ngx_max(cscf->large_client_header_buffers.size,
+ (size_t)content_length + ngx_buf_size(r->header_in));
+
+ hc = r->http_connection;
+
+ if (hc->nfree && size == cscf->large_client_header_buffers.size) {
+
+ buf = hc->free[--hc->nfree];
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "ModSecurity: use http free large header buffer: %p %uz",
+ buf->pos, buf->end - buf->last);
+
+ } else if (hc->nbusy < cscf->large_client_header_buffers.num) {
+
+ if (hc->busy == NULL) {
+ hc->busy = ngx_palloc(r->connection->pool,
+ cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
+ }
+
+ if (hc->busy == NULL) {
+ return NGX_ERROR;
+ } else {
+ buf = ngx_create_temp_buf(r->connection->pool, size);
+ }
+ } else {
+ /* TODO: how to deal this case ? */
+ return NGX_ERROR;
+ }
+
+ } else {
+
+ buf = ngx_create_temp_buf(r->pool, (size_t) content_length);
+ }
+
+ if (buf == NULL) {
+ return NGX_ERROR;
+ }
+
+ if (apr_brigade_flatten(ctx->brigade, (char *)buf->pos,
+ (apr_size_t *)&content_length) != APR_SUCCESS) {
+ return NGX_ERROR;
+ }
+
+ apr_brigade_cleanup(ctx->brigade);
+ buf->last += content_length;
+
+ ngx_memcpy(buf->last, r->header_in->pos, ngx_buf_size(r->header_in));
+ buf->last += ngx_buf_size(r->header_in);
+
+ r->header_in = buf;
+
+ return NGX_OK;
+}
+
+
+static ngx_inline ngx_int_t
+ngx_http_modsecurity_load_headers_out(ngx_http_request_t *r)
+{
+
+ ngx_http_modsecurity_ctx_t *ctx;
+ char *data;
+ request_rec *req;
+ u_char *content_type;
+ ngx_uint_t content_type_len;
+ ngx_http_variable_value_t *vv;
+ ngx_list_part_t *part;
+ ngx_table_elt_t *h;
+ ngx_uint_t i;
+ char *key, *value;
+ u_char *buf = NULL;
+ size_t size = 0;
+
+ ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity);
+ req = ctx->req;
+
+ req->status = r->headers_out.status;
+ req->status_line = (char *)ngx_pstrdup(r->pool, &r->headers_out.status_line);
+
+ if (r->headers_out.charset.len) {
+
+ content_type_len = r->headers_out.content_type.len
+ + r->headers_out.charset.len
+ + ngx_strlen("; charset=") + 1;
+
+ content_type = ngx_palloc(r->pool, content_type_len);
+
+ if (content_type == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_snprintf(content_type, content_type_len,
+ "%V; charset=%V",
+ &r->headers_out.content_type,
+ &r->headers_out.charset);
+
+ r->headers_out.content_type.data = content_type;
+ r->headers_out.content_type.len = content_type_len;
+ }
+
+ /* deep copy */
+ part = &r->headers_out.headers.part;
+ h = part->elts;
+
+ for (i = 0; ; i++) {
+ if (i >= part->nelts) {
+ if (part->next == NULL)
+ break;
+
+ part = part->next;
+ h = part->elts;
+ i = 0;
+ }
+ size += h[i].key.len + h[i].value.len + 2;
+
+ buf = ngx_palloc(r->pool, size);
+
+ if (buf == NULL) {
+ return NGX_ERROR;
+ }
+
+ key = (char *)buf;
+ buf = ngx_cpymem(buf, h[i].key.data, h[i].key.len);
+ *buf++ = '\0';
+
+ value = (char *)buf;
+ buf = ngx_cpymem(buf, h[i].value.data, h[i].value.len);
+ *buf++ = '\0';
+
+ apr_table_setn(req->headers_out, key, value);
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "ModSecurity: load headers out: \"%V: %V\"",
+ &h[i].key, &h[i].value);
+
+ }
+
+ for (i = 0; special_headers_out[i].name; i++) {
+
+ vv = ngx_http_get_variable(r, &special_headers_out[i].variable_name,
+ ngx_hash_key(special_headers_out[i].variable_name.data,
+ special_headers_out[i].variable_name.len));
+
+ if (vv && !vv->not_found) {
+
+ data = ngx_palloc(r->pool, vv->len + 1);
+ if (data == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_memcpy(data,vv->data, vv->len);
+ data[vv->len] = '\0';
+
+ apr_table_setn(req->headers_out, special_headers_out[i].name, data);
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "ModSecurity: load headers out: \"%s: %s\"",
+ special_headers_out[i].name, data);
+ }
+ }
+
+ req->content_type = apr_table_get(ctx->req->headers_out, "Content-Type");
+ req->content_encoding = apr_table_get(ctx->req->headers_out, "Content-Encoding");
+
+ data = (char *)apr_table_get(ctx->req->headers_out, "Content-Languages");
+
+ if(data != NULL)
+ {
+ ctx->req->content_languages = apr_array_make(ctx->req->pool, 1, sizeof(const char *));
+ *(const char **)apr_array_push(ctx->req->content_languages) = data;
+ }
+
+ /* req->chunked = r->chunked; may be useless */
+ req->clength = r->headers_out.content_length_n;
+ req->mtime = apr_time_make(r->headers_out.last_modified_time, 0);
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "ModSecurity: load headers out done");
+
+ return NGX_OK;
+}
+
+
+static ngx_inline ngx_int_t
+ngx_http_modsecurity_save_headers_out(ngx_http_request_t *r)
+{
+ ngx_http_modsecurity_ctx_t *ctx;
+ ngx_http_upstream_t *upstream;
+
+ ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity);
+
+ /* r->chunked = ctx->req->chunked; */
+
+ ngx_http_clean_header(r);
+
+ upstream = r->upstream;
+ r->upstream = &ngx_http_modsecurity_upstream;
+
+ if (apr_table_do(ngx_http_modsecurity_save_headers_out_visitor,
+ r, ctx->req->headers_out, NULL) == 0) {
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "ModSecurity: save headers out error");
+
+ return NGX_ERROR;
+ }
+
+ r->upstream = upstream;
+
+ r->headers_out.status = ctx->req->status;
+ r->headers_out.status_line.data = (u_char *)ctx->req->status_line;
+ r->headers_out.status_line.len = ctx->req->status_line ?
+ ngx_strlen(ctx->req->status_line) : 0;
+
+ r->headers_out.content_length_n = ctx->req->clength;
+ r->headers_out.last_modified_time = apr_time_sec(ctx->req->mtime);
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "ModSecurity: save headers out done");
+
+ return NGX_OK;
+}
+
+
+static int
+ngx_http_modsecurity_save_headers_out_visitor(void *data, const char *key, const char *value)
+{
+ ngx_http_request_t *r = data;
+ ngx_table_elt_t *h, he;
+ ngx_http_upstream_header_t *hh;
+ ngx_http_upstream_main_conf_t *umcf;
+
+ umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
+
+ h = &he;
+
+ h->key.data = (u_char *)key;
+ h->key.len = ngx_strlen(key);
+
+ h->value.data = (u_char *)value;
+ h->value.len = ngx_strlen(value);
+
+ h->lowcase_key = ngx_palloc(r->pool, h->key.len);
+ if (h->lowcase_key == NULL) {
+ return 0;
+ }
+
+ ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
+
+ h->hash = ngx_hash_key(h->lowcase_key, h->key.len);
+
+ hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
+ h->lowcase_key, h->key.len);
+
+ if (hh) {
+ /* copy all */
+ if (hh->copy_handler(r, h, hh->conf) != NGX_OK) {
+ return 0;
+ }
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "ModSecurity: save headers out: \"%V: %V\"",
+ &h->key, &h->value);
+
+ return 1;
+}
/* create loc conf struct */
static void *
@@ -125,10 +775,12 @@ ngx_http_modsecurity_create_loc_conf(ngx_conf_t *cf)
{
ngx_http_modsecurity_loc_conf_t *conf;
- conf = (ngx_http_modsecurity_loc_conf_t *) ngx_pcalloc(cf->pool, sizeof(ngx_http_modsecurity_loc_conf_t));
+ conf = (ngx_http_modsecurity_loc_conf_t *)
+ ngx_palloc(cf->pool, sizeof(ngx_http_modsecurity_loc_conf_t));
if (conf == NULL)
return NULL;
+ conf->config = NGX_CONF_UNSET_PTR;
conf->enable = NGX_CONF_UNSET;
return conf;
@@ -136,22 +788,28 @@ ngx_http_modsecurity_create_loc_conf(ngx_conf_t *cf)
/* merge loc conf */
static char *
-ngx_http_modsecurity_merge_loc_conf(ngx_conf_t *cf, void *parent,
- void *child)
+ngx_http_modsecurity_merge_loc_conf(ngx_conf_t *cf, void *parent,
+ void *child)
{
ngx_http_modsecurity_loc_conf_t *prev = parent;
ngx_http_modsecurity_loc_conf_t *conf = child;
- if (conf->config == NULL) {
- conf->config = prev->config;
- }
-
ngx_conf_merge_value(conf->enable, prev->enable, 0);
+ ngx_conf_merge_ptr_value(conf->config, prev->config, NULL);
+
+ if (conf->enable && conf->config == NULL) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "\"ModSecurityEnabled\" in %V:%ui is set to \"on\""
+ " while directive \"ModSecurityConfig\" is not found"
+ " in the same location",
+ conf->file, conf->line);
+ return NGX_CONF_ERROR;
+ }
return NGX_CONF_OK;
}
-void
+static void
modsecLog(void *obj, int level, char *str)
{
if (obj != NULL) {
@@ -169,13 +827,13 @@ modsecLog(void *obj, int level, char *str)
*/
extern apr_pool_t *pool;
-void *
+static void *
modsec_pcre_malloc(size_t size)
{
return apr_palloc(pool, size);
}
-void
+static void
modsec_pcre_free(void *ptr)
{
}
@@ -183,6 +841,7 @@ modsec_pcre_free(void *ptr)
static ngx_int_t
ngx_http_modsecurity_preconfiguration(ngx_conf_t *cf)
{
+ server_rec *s;
/* XXX: temporary hack, nginx uses pcre as well and hijacks these two */
pcre_malloc = modsec_pcre_malloc;
@@ -190,16 +849,28 @@ ngx_http_modsecurity_preconfiguration(ngx_conf_t *cf)
modsecSetLogHook(cf->log, modsecLog);
modsecSetDropAction(ngx_http_modsecurity_drop_action);
- modsecSetReadBody(modsecurity_read_body_cb);
- modsecSetWriteBody(modsecurity_write_body_cb);
- modsecInit();
+ /* TODO: server_rec per server conf */
+ s = modsecInit();
+ if (s == NULL) {
+ return NGX_ERROR;
+ }
+
+ /* set host name */
+ s->server_hostname = ngx_palloc(cf->pool, ngx_cycle->hostname.len + 1);
+ if (s->server_hostname == NULL) {
+ return NGX_ERROR;
+ }
+ ngx_memcpy(s->server_hostname, ngx_cycle->hostname.data, ngx_cycle->hostname.len);
+ s->server_hostname[ ngx_cycle->hostname.len] = '\0';
+
modsecStartConfig();
-
return NGX_OK;
}
-static ngx_int_t
+
+
+static ngx_int_t
ngx_http_modsecurity_init(ngx_conf_t *cf)
{
ngx_http_handler_pt *h;
@@ -207,7 +878,7 @@ ngx_http_modsecurity_init(ngx_conf_t *cf)
modsecFinalizeConfig();
- cmcf = (ngx_http_core_main_conf_t *) ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
+ cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
if (cmcf == NULL) {
return NGX_ERROR;
}
@@ -218,20 +889,14 @@ ngx_http_modsecurity_init(ngx_conf_t *cf)
}
*h = ngx_http_modsecurity_handler;
-#ifdef PROCESS_RESPONSE
- /*
- ** This function sets up handlers for CONTENT_PHASE,
- ** XXX: not implemented yet
- */
+ ngx_http_next_header_filter = ngx_http_top_header_filter;
+ ngx_http_top_header_filter = ngx_http_modsecurity_header_filter;
- /* Register for CONTENT phase ?? */
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
- *h = ngx_http_modsecurity_content_handler;
-#endif
+ ngx_http_next_body_filter = ngx_http_top_body_filter;
+ ngx_http_top_body_filter = ngx_http_modsecurity_body_filter;
+ ngx_memzero(&ngx_http_modsecurity_upstream, sizeof(ngx_http_upstream_t));
+ ngx_http_modsecurity_upstream.cacheable = 1;
return NGX_OK;
}
@@ -251,159 +916,6 @@ ngx_http_modsecurity_exit_process(ngx_cycle_t *cycle)
}
-char *
-ConvertNgxStringToUTF8(ngx_str_t str, apr_pool_t *pool)
-{
- char *t = (char *) apr_palloc(pool, str.len + 1);
-
- ngx_memcpy(t, str.data, str.len);
- t[str.len] = 0;
-
- return t;
-}
-
-/*
-** request body callback, passing body to mod security
-*/
-apr_status_t
-modsecurity_read_body_cb(request_rec *r, char *outpos, unsigned int length,
- unsigned int *outlen, int *is_eos)
-{
- size_t len, rest;
- ssize_t size;
- ngx_http_modsecurity_ctx_t *ctx;
-
- ctx = (ngx_http_modsecurity_ctx_t *) apr_table_get(r->notes, NOTE_NGINX_REQUEST_CTX);
- if (ctx == NULL) {
- return APR_EINVAL;
- }
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->r->connection->log, 0, "modSecurity: read_body_cb");
-
- ngx_buf_t *buf = &ctx->buf;
- rest = length;
- *is_eos = 0;
-
- while (rest) {
-
- if (ngx_buf_size(buf) == 0) {
- if (ctx->chain == NULL) {
- *outlen = length - rest;
- *is_eos = 1;
- // END
- return APR_SUCCESS;
- }
-
- ngx_memcpy(buf, ctx->chain->buf, sizeof(ngx_buf_t));
- ctx->chain = ctx->chain->next;
- }
-
- len = (size_t) ngx_min((size_t)ngx_buf_size(buf), rest);
-
- if (ngx_buf_in_memory(buf)) {
-
- outpos = (char *) ngx_cpymem(outpos, buf->pos, len);
- rest -= len;
- buf->pos += len;
- } else if (buf->in_file) {
-
- size = ngx_read_file(buf->file, (u_char*)outpos, len, buf->file_pos);
-
- if (size < 0) {
- return NGX_ERROR;
- }
- outpos += size;
- rest -= size;
- buf->file_pos += size;
- } else {
- return -1;
- }
- }
-
- *outlen = length - rest;
- return APR_SUCCESS;
-}
-
-apr_status_t
-modsecurity_write_body_cb(request_rec *rec, char *buf, unsigned int length)
-{
- ngx_buf_t *b;
- ngx_http_modsecurity_ctx_t *ctx;
- ngx_http_request_t *r;
- ngx_str_t *str;
-
- ctx = (ngx_http_modsecurity_ctx_t *) apr_table_get(rec->notes, NOTE_NGINX_REQUEST_CTX);
- if (ctx == NULL) {
- return APR_EINVAL;
- }
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->r->connection->log, 0, "modSecurity: write_body_cb");
-
- r = ctx->r;
-
- /* set request body */
- b = r->header_in;
-
- if (b->end < b->pos + length) {
- b->start = ngx_palloc(ctx->r->pool, length);
- if (b->start == NULL) {
- return APR_EINVAL;
- }
- b->end = b->start + length;
- b->pos = b->start;
- }
-
- b->last = ngx_cpymem(b->pos, buf, length);
-
- /* set content_length_n */
- r->headers_in.content_length_n = length;
-
- /* set headers_in.content_length */
- str = &r->headers_in.content_length->value;
- str->data = ngx_palloc(r->pool, NGX_OFF_T_LEN);
- if (str->data == NULL) {
- return NGX_ERROR;
- }
-
- str->len = ngx_snprintf(str->data, NGX_OFF_T_LEN, "%O", length) - str->data;
-
- return APR_SUCCESS;
-}
-
-apr_sockaddr_t *CopySockAddr(apr_pool_t *pool, struct sockaddr *pAddr) {
- apr_sockaddr_t *addr = (apr_sockaddr_t *)apr_palloc(pool, sizeof(apr_sockaddr_t));
- int adrlen = 16, iplen = 4;
-
- if(pAddr->sa_family == AF_INET6) {
- adrlen = 46;
- iplen = 16;
- }
-
- addr->addr_str_len = adrlen;
- addr->family = pAddr->sa_family;
-
- addr->hostname = "unknown";
-#ifdef WIN32
- addr->ipaddr_len = sizeof(IN_ADDR);
-#else
- addr->ipaddr_len = sizeof(struct in_addr);
-#endif
- addr->ipaddr_ptr = &addr->sa.sin.sin_addr;
- addr->pool = pool;
- addr->port = 80;
-#ifdef WIN32
- memcpy(&addr->sa.sin.sin_addr.S_un.S_addr, pAddr->sa_data, iplen);
-#else
- memcpy(&addr->sa.sin.sin_addr.s_addr, pAddr->sa_data, iplen);
-#endif
- addr->sa.sin.sin_family = pAddr->sa_family;
- addr->sa.sin.sin_port = 80;
- addr->salen = sizeof(addr->sa);
- addr->servname = addr->hostname;
-
- return addr;
-}
-
-
/*
** [ENTRY POINT] does : this function called by nginx from the request handler
*/
@@ -411,181 +923,353 @@ static ngx_int_t
ngx_http_modsecurity_handler(ngx_http_request_t *r)
{
ngx_http_modsecurity_loc_conf_t *cf;
- ngx_http_core_loc_conf_t *clcf, *lcf;
ngx_http_modsecurity_ctx_t *ctx;
ngx_int_t rc;
- void **loc_conf;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "modSecurity: handler");
-
- /* Process only main request */
- if (r != r->main || r->internal) {
- return NGX_DECLINED;
- }
cf = ngx_http_get_module_loc_conf(r, ngx_http_modsecurity);
- if (!cf->enable) {
+ /* Process only main request */
+ if (r != r->main || !cf->enable) {
return NGX_DECLINED;
}
+ if (r->internal) {
+
+ ctx = ngx_http_get_module_pool_ctx(r, ngx_http_modsecurity);
+
+ if (ctx == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_http_set_ctx(r, ctx, ngx_http_modsecurity);
+
+ return NGX_DECLINED;
+ }
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "modSecurity: handler");
+
ctx = ngx_http_modsecurity_create_ctx(r);
if (ctx == NULL) {
+
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ ngx_http_set_ctx(r, ctx, ngx_http_modsecurity);
+
+ if (ngx_http_set_pool_ctx(r, ctx, ngx_http_modsecurity) != NGX_OK) {
return NGX_ERROR;
}
- ngx_http_set_ctx(r, ctx, ngx_http_modsecurity);
-
- if (r->method == NGX_HTTP_POST) {
- /* Processing POST request body, should we process PUT? */
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "modSecurity: method POST");
-
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
- if (clcf == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
+ ngx_http_modsecurity_load_request(r);
- ctx->loc_conf = r->loc_conf;
- /* hijack loc_conf so that we can receive any body length
- * TODO: nonblocking process & chuncked body
- */
- if (clcf->client_body_buffer_size < (size_t)r->headers_in.content_length_n) {
-
- loc_conf = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
- if (loc_conf == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
+ if (ngx_http_modsecurity_load_headers_in(r) != NGX_OK) {
- lcf = ngx_pcalloc(r->pool, sizeof(ngx_http_core_loc_conf_t));
- if (lcf == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_memcpy(loc_conf, r->loc_conf, sizeof(void *) * ngx_http_max_module);
- ngx_memcpy(lcf, clcf, sizeof(ngx_http_core_loc_conf_t));
-
- ctx->loc_conf = r->loc_conf;
- r->loc_conf = loc_conf;
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
- ngx_http_get_module_loc_conf(r, ngx_http_core_module) = lcf;
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
- clcf->client_body_buffer_size = r->headers_in.content_length_n;
- }
-
- ctx->request_body_in_single_buf = r->request_body_in_single_buf;
- ctx->request_body_in_file_only = r->request_body_in_file_only;
- r->request_body_in_single_buf = 1;
- r->request_body_in_file_only = 0;
+ /* processing request headers */
+ rc = modsecProcessRequestHeaders(ctx->req);
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: modsecProcessRequestHeaders %d", rc);
- rc = ngx_http_read_client_request_body(r, ngx_http_modsecurity_request_body_handler);
- if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
- return rc;
- }
+ if (rc == DECLINED) {
- return NGX_DONE;
+ if (modsecIsRequestBodyAccessEnabled(ctx->req)
+ && r->method == NGX_HTTP_POST) {
- } else {
- /* processing all the other methods */
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "modSecurity: method is not POST");
-
- rc = modsecProcessRequest(ctx->req);
-
- if (rc != DECLINED) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: status: %d, need action", rc);
-
- ngx_http_clear_accept_ranges(r);
- ngx_http_clear_last_modified(r);
- ngx_http_clear_content_length(r);
-
- /* Nginx and Apache share same response code */
+ /* Processing POST request body, should we process PUT? */
+ rc = ngx_http_read_client_request_body(r, ngx_http_modsecurity_body_handler);
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
return rc;
}
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
+
+ return NGX_DONE;
+ }
+ /* other method */
+ rc = modsecProcessRequestBody(ctx->req);
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: modsecProcessRequestBody %d", rc);
}
+ if (rc != DECLINED) {
+
+ /* Nginx and Apache share same response code */
+ if (rc < NGX_HTTP_SPECIAL_RESPONSE || rc >= 600) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+ return rc;
+ }
+
+ /*
+ if (ngx_http_modsecurity_save_headers_in(r) != NGX_OK) {
+
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+ */
+
return NGX_DECLINED;
}
+
+static void
+ngx_http_modsecurity_body_handler(ngx_http_request_t *r)
+{
+ ngx_http_modsecurity_ctx_t *ctx;
+ ngx_int_t rc;
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "modSecurity: body handler");
+
+ ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity);
+
+ if (ngx_http_modsecurity_load_request_body(r) != NGX_OK) {
+
+ return ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ }
+
+ rc = modsecProcessRequestBody(ctx->req);
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: modsecProcessRequestBody %d", rc);
+
+ if (rc != DECLINED) {
+ /* Nginx and Apache share same response code */
+ if (rc < NGX_HTTP_SPECIAL_RESPONSE || rc >= 600) {
+ rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+ return ngx_http_finalize_request(r, rc);
+ }
+
+ if (ngx_http_modsecurity_save_request_body(r) != NGX_OK
+ || ngx_http_modsecurity_save_headers_in(r) != NGX_OK ) {
+
+ return ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ }
+
+ r->phase_handler++;
+ ngx_http_core_run_phases(r);
+ ngx_http_finalize_request(r, NGX_DONE);
+}
+
+
+static ngx_int_t
+ngx_http_modsecurity_header_filter(ngx_http_request_t *r) {
+ ngx_http_modsecurity_loc_conf_t *cf;
+ ngx_http_modsecurity_ctx_t *ctx;
+ ngx_int_t rc;
+
+ cf = ngx_http_get_module_loc_conf(r, ngx_http_modsecurity);
+ ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity);
+
+ if (r != r->main || !cf->enable || ctx->complete) {
+ return ngx_http_next_header_filter(r);
+ }
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "modSecurity: header filter");
+
+ if (r->method == NGX_HTTP_HEAD || r->header_only) {
+
+ ctx->complete = 1;
+
+ // TODO: do we need reload headers_in ?
+
+ if (ngx_http_modsecurity_load_headers_in(r) != NGX_OK
+ || ngx_http_modsecurity_load_headers_out(r) != NGX_OK) {
+
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ rc = modsecProcessResponse(ctx->req);
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: modsecProcessResponse %d", rc);
+
+ if (rc == DECLINED || rc == APR_SUCCESS) {
+
+ if (ngx_http_modsecurity_save_headers_in(r) != NGX_OK
+ || ngx_http_modsecurity_save_headers_out(r) != NGX_OK) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ return ngx_http_next_header_filter(r);
+ }
+
+ if (rc < NGX_HTTP_SPECIAL_RESPONSE || rc >= 600) {
+ rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ return rc;
+ }
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
+{
+ ngx_http_modsecurity_loc_conf_t *cf;
+ ngx_http_modsecurity_ctx_t *ctx;
+ ngx_int_t rc;
+ apr_off_t content_length;
+
+ cf = ngx_http_get_module_loc_conf(r, ngx_http_modsecurity);
+ ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity);
+
+ if (r != r->main || !cf->enable || ctx->complete) {
+ return ngx_http_next_body_filter(r, in);
+ }
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "modSecurity: body filter");
+
+ if (in == NULL) {
+ return NGX_AGAIN;
+ }
+
+ rc = move_chain_to_brigade(in, ctx->brigade, r->pool, 0);
+ if (rc != NGX_OK) {
+ return rc;
+ }
+
+ /* last buf has been saved */
+
+ ctx->complete = 1;
+ modsecSetResponseBrigade(ctx->req, ctx->brigade);
+
+ // TODO: do we need reload headers_in ?
+ //
+ if (ngx_http_modsecurity_load_headers_in(r) != NGX_OK
+ || ngx_http_modsecurity_load_headers_out(r) != NGX_OK) {
+
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ rc = modsecProcessResponse(ctx->req);
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: modsecProcessResponse %d", rc);
+
+ if (rc == DECLINED || rc == APR_SUCCESS) {
+
+ in = NULL;
+
+ apr_brigade_length(ctx->brigade, 0, &content_length);
+
+ rc = move_brigade_to_chain(ctx->brigade, &in, r->pool);
+ if (rc == NGX_ERROR) {
+ return NGX_ERROR;
+ }
+
+ if (ngx_http_modsecurity_save_headers_in(r) != NGX_OK
+ ||ngx_http_modsecurity_save_headers_out(r) != NGX_OK) {
+
+ return ngx_http_filter_finalize_request(r, &ngx_http_modsecurity, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ }
+
+ if (r->headers_out.content_length_n != -1) {
+
+ r->headers_out.content_length_n = content_length;
+ r->headers_out.content_length = NULL; /* header filter will set this */
+ }
+
+ rc = ngx_http_next_header_filter(r);
+
+ if (rc == NGX_ERROR || rc > NGX_OK) {
+ return ngx_http_filter_finalize_request(r, &ngx_http_modsecurity, rc);
+ }
+
+ return ngx_http_next_body_filter(r, in);
+ }
+
+ if (rc < NGX_HTTP_SPECIAL_RESPONSE || rc >= 600) {
+ rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ return ngx_http_filter_finalize_request(r, &ngx_http_modsecurity, rc);
+}
+
+
static ngx_http_modsecurity_ctx_t *
ngx_http_modsecurity_create_ctx(ngx_http_request_t *r)
{
ngx_http_modsecurity_loc_conf_t *cf;
ngx_pool_cleanup_t *cln;
ngx_http_modsecurity_ctx_t *ctx;
- ngx_list_part_t *part;
- ngx_table_elt_t *h;
- ngx_uint_t i;
+ apr_sockaddr_t *asa;
+ struct sockaddr_in *sin;
+#if (NGX_HAVE_INET6)
+ struct sockaddr_in6 *sin6;
+#endif
+
+ ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_modsecurity_ctx_t));
+ if (ctx == NULL) {
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "modSecurity: ctx memory allocation error");
+ return NULL;
+ }
cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_modsecurity_ctx_t));
if (cln == NULL) {
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "modSecurity: ctx memory allocation error");
return NULL;
}
cln->handler = ngx_http_modsecurity_cleanup;
- ngx_memzero(cln->data, sizeof(ngx_http_modsecurity_ctx_t));
-
- ctx = cln->data;
+ cln->data = ctx;
+
ctx->r = r;
-
+
if (r->connection->requests == 0 || ctx->connection == NULL) {
+
+ /* TODO: set server_rec, why igonre return value? */
ctx->connection = modsecNewConnection();
+
+ /* fill apr_sockaddr_t */
+ asa = ngx_palloc(r->pool, sizeof(apr_sockaddr_t));
+ asa->pool = ctx->connection->pool;
+ asa->hostname = (char *)ngx_pstrdup(r->pool, &r->connection->addr_text);
+ asa->servname = asa->hostname;
+ asa->next = NULL;
+ asa->salen = r->connection->socklen;
+ ngx_memcpy(&asa->sa, r->connection->sockaddr, asa->salen);
+
+ asa->family = ((struct sockaddr *)&asa->sa)->sa_family;
+ switch ( asa->family) {
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)&asa->sa;
+ asa->ipaddr_ptr = &sin6->sin6_addr;
+ asa->ipaddr_len = sizeof(sin6->sin6_addr);
+ asa->port = ntohs(sin6->sin6_port);
+ asa->addr_str_len = NGX_INET6_ADDRSTRLEN + 1;
+ break;
+#endif
+
+ default: /* AF_INET */
+ sin = (struct sockaddr_in *) &asa->sa;
+ asa->ipaddr_ptr = &sin->sin_addr;
+ asa->ipaddr_len = sizeof(sin->sin_addr);
+ asa->port = ntohs(sin->sin_port);
+ asa->addr_str_len = NGX_INET_ADDRSTRLEN + 1;
+ break;
+ }
+
+
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER < 3
- ctx->connection->remote_addr = CopySockAddr(ctx->connection->pool, r->connection->sockaddr);
- ctx->connection->remote_ip = ConvertNgxStringToUTF8(r->connection->addr_text, ctx->connection->pool);
+ ctx->connection->remote_addr = asa;
+ ctx->connection->remote_ip = asa->hostname;
#else
- ctx->connection->client_addr = CopySockAddr(ctx->connection->pool, r->connection->sockaddr);
- ctx->connection->client_ip = ConvertNgxStringToUTF8(r->connection->addr_text, ctx->connection->pool);
+ ctx->connection->client_addr = asa;
+ ctx->connection->client_ip = asa->hostname;
#endif
ctx->connection->remote_host = NULL;
modsecProcessConnection(ctx->connection);
}
cf = ngx_http_get_module_loc_conf(r, ngx_http_modsecurity);
+
ctx->req = modsecNewRequest(ctx->connection, cf->config);
- ctx->req->request_time = apr_time_now();
- ctx->req->method = ConvertNgxStringToUTF8(r->method_name, ctx->req->pool);
- ctx->req->path_info = ConvertNgxStringToUTF8(r->unparsed_uri, ctx->req->pool);
- ctx->req->unparsed_uri = ConvertNgxStringToUTF8(r->unparsed_uri, ctx->req->pool);
- ctx->req->uri = ctx->req->unparsed_uri;
- ctx->req->the_request = ConvertNgxStringToUTF8(r->request_line, ctx->req->pool);
- ctx->req->args = ConvertNgxStringToUTF8(r->args, ctx->req->pool);
- ctx->req->filename = ctx->req->path_info;
- ctx->req->parsed_uri.scheme = "http";
- ctx->req->parsed_uri.path = ctx->req->path_info;
- ctx->req->parsed_uri.is_initialized = 1;
- ctx->req->parsed_uri.port = 80;
- ctx->req->parsed_uri.port_str = "80";
- ctx->req->parsed_uri.query = ctx->req->args;
- ctx->req->parsed_uri.dns_looked_up = 0;
- ctx->req->parsed_uri.dns_resolved = 0;
- ctx->req->parsed_uri.password = NULL;
- ctx->req->parsed_uri.user = NULL;
- ctx->req->parsed_uri.fragment = ConvertNgxStringToUTF8(r->exten, ctx->req->pool);
+ apr_table_setn(ctx->req->notes, NOTE_NGINX_REQUEST_CTX, (const char *) ctx);
+ apr_table_setn(ctx->req->subprocess_env, "UNIQUE_ID", "12345");
- part = &r->headers_in.headers.part;
- h = part->elts;
+ ctx->brigade = apr_brigade_create(ctx->req->pool, ctx->req->connection->bucket_alloc);
- for (i = 0; ; i++) {
- if (i >= part->nelts) {
- if (part->next == NULL)
- break;
-
- part = part->next;
- h = part->elts;
- i = 0;
- }
-
- apr_table_setn(ctx->req->headers_in, ConvertNgxStringToUTF8(h[i].key, ctx->req->pool),
- ConvertNgxStringToUTF8(h[i].value, ctx->req->pool));
+ if (ctx->brigade == NULL) {
+ return NULL;
}
- /* XXX: if mod_uniqid enabled - use it's value */
- apr_table_setn(ctx->req->subprocess_env, "UNIQUE_ID", "12345");
- /* actually, we need ctx only for POST request body handling - don't like this part */
- apr_table_setn(ctx->req->notes, NOTE_NGINX_REQUEST_CTX, (const char *) ctx);
return ctx;
}
@@ -593,58 +1277,12 @@ static void
ngx_http_modsecurity_cleanup(void *data)
{
ngx_http_modsecurity_ctx_t *ctx = data;
-
+
if (ctx->req != NULL) {
(void) modsecFinishRequest(ctx->req);
}
}
-
-static void
-ngx_http_modsecurity_request_body_handler(ngx_http_request_t *r)
-{
- ngx_http_modsecurity_ctx_t *ctx;
- ngx_int_t rc;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity);
-
- if (ctx == NULL
- || r->request_body->bufs == NULL
- || r->request_body->bufs->next != NULL) {
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- r->request_body_in_single_buf = ctx->request_body_in_single_buf;
- r->request_body_in_file_only = ctx->request_body_in_file_only;
- r->header_in = r->request_body->bufs->buf;
- ctx->chain = r->request_body->bufs;
- r->request_body = NULL;
- r->loc_conf = ctx->loc_conf;
-
- rc = modsecProcessRequest(ctx->req);
-
- if (rc != DECLINED) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: status: %d, need action", rc);
-
- ngx_http_clear_accept_ranges(r);
- ngx_http_clear_last_modified(r);
- ngx_http_clear_content_length(r);
-
- /* Nginx and Apache share same response code */
- if (rc < NGX_HTTP_SPECIAL_RESPONSE) {
- rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_http_finalize_request(r, rc);
- }
-
- r->phase_handler++;
- ngx_http_core_run_phases(r);
- ngx_http_finalize_request(r, NGX_DONE);
-}
-
-
static char *
ngx_http_modsecurity_config(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
@@ -652,7 +1290,7 @@ ngx_http_modsecurity_config(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_str_t *value;
const char *msg;
- if (mscf->config != NULL) {
+ if (mscf->config != NGX_CONF_UNSET_PTR) {
return "is duplicate";
}
@@ -664,15 +1302,39 @@ ngx_http_modsecurity_config(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
mscf->config = modsecGetDefaultConfig();
- msg = modsecProcessConfig(mscf->config, (const char *)value[1].data, "");
+ if (mscf->config == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ msg = modsecProcessConfig(mscf->config, (const char *)value[1].data, NULL);
if (msg != NULL) {
- ngx_conf_log_error(NGX_LOG_INFO, cf, 0, "modSecurity: modsecProcessConfig() %s", msg);
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "ModSecurityConfig in %s:%ui: %s",
+ cf->conf_file->file.name.data, cf->conf_file->line, msg);
return NGX_CONF_ERROR;
}
return NGX_CONF_OK;
}
+
+static char *
+ngx_http_modsecurity_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_modsecurity_loc_conf_t *mscf = conf;
+ char *rc;
+
+ rc = ngx_conf_set_flag_slot(cf, cmd, conf);
+ if (rc != NGX_CONF_OK) {
+ return rc;
+ }
+ if (mscf->enable) {
+ mscf->file = &cf->conf_file->file.name;
+ mscf->line = cf->conf_file->line;
+ }
+ return NGX_CONF_OK;
+}
+
+
static int
ngx_http_modsecurity_drop_action(request_rec *r)
{
@@ -685,3 +1347,4 @@ ngx_http_modsecurity_drop_action(request_rec *r)
ctx->r->connection->error = 1;
return 0;
}
+
diff --git a/nginx/modsecurity/ngx_pool_context.c b/nginx/modsecurity/ngx_pool_context.c
new file mode 100644
index 00000000..988c8933
--- /dev/null
+++ b/nginx/modsecurity/ngx_pool_context.c
@@ -0,0 +1,212 @@
+
+
+#include
+
+#define NGX_POOL_CTX_SIZE 1024
+
+typedef struct ngx_pool_context_node_s ngx_pool_context_node_t;
+struct ngx_pool_context_node_s
+{
+ ngx_pool_context_node_t *next;
+ ngx_pool_context_node_t **prev;
+ ngx_pool_t *pool;
+ ngx_uint_t index;
+ void *data;
+};
+
+static void
+ngx_pool_context_cleanup(void *data);
+
+typedef struct {
+ ngx_uint_t size;
+} ngx_pool_context_conf_t;
+
+static void * ngx_pool_context_create_conf(ngx_cycle_t *cycle);
+static char * ngx_pool_context_init_conf(ngx_cycle_t *cycle, void *conf);
+
+static ngx_core_module_t ngx_pool_context_module_ctx = {
+ ngx_string("pool_context"),
+ ngx_pool_context_create_conf,
+ ngx_pool_context_init_conf,
+};
+
+static ngx_command_t ngx_pool_context_commands[] = {
+
+ { ngx_string("pool_context_hash_size"),
+ NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_num_slot,
+ 0,
+ offsetof(ngx_pool_context_conf_t, size),
+ NULL
+ },
+ ngx_null_command
+};
+
+
+ngx_module_t ngx_pool_context_module = {
+ NGX_MODULE_V1,
+ &ngx_pool_context_module_ctx, /* module context */
+ ngx_pool_context_commands, /* module directives */
+ NGX_CORE_MODULE, /* module type */
+ NULL, /* init master */
+ NULL, /* init module */
+ NULL, /* init process */
+ NULL, /* init thread */
+ NULL, /* exit thread */
+ NULL, /* exit process */
+ NULL, /* exit master */
+ NGX_MODULE_V1_PADDING
+};
+
+
+#define ngx_pool_context_hash_key(r, ctx_index) ((ngx_uint_t) r + ctx_index)
+
+#define ngx_pool_context_unlink(node) \
+ \
+ *(node->prev) = node->next; \
+ \
+ if (node->next) { \
+ node->next->prev = node->prev; \
+ } \
+ \
+ node->prev = NULL; \
+
+
+#define ngx_pool_context_link(queue, node) \
+ \
+ if (node->prev != NULL) { \
+ ngx_pool_context_unlink(node); \
+ } \
+ node->next = (ngx_pool_context_node_t *) *queue; \
+ node->prev = (ngx_pool_context_node_t **) queue; \
+ *queue = node; \
+ \
+ if (node->next) { \
+ node->next->prev = &node->next; \
+ }
+
+
+static ngx_pool_context_node_t **ngx_pool_context_hash;
+static ngx_uint_t ngx_pool_context_hash_size;
+
+/* Nginx has removed multi-thread support, so we do not need mutex */
+
+void *
+ngx_pool_get_ctx(ngx_pool_t *pool, ngx_uint_t index)
+{
+ ngx_uint_t hash;
+ uint32_t key;
+ ngx_pool_context_node_t *node;
+
+ hash = (ngx_uint_t) pool + index;
+ key = ngx_murmur_hash2((u_char *)&hash, sizeof(hash)) % ngx_pool_context_hash_size;
+
+ node = ngx_pool_context_hash[key];
+
+ while (node) {
+
+ if (node->pool == pool && node->index == index) {
+
+ return node->data;
+ }
+ node = node->next;
+ }
+
+ return NULL;
+
+}
+
+
+ngx_int_t
+ngx_pool_set_ctx(ngx_pool_t *pool, ngx_uint_t index, void *data)
+{
+ ngx_uint_t hash;
+ uint32_t key;
+ ngx_pool_context_node_t *node;
+ ngx_pool_cleanup_t *cln;
+
+ hash = (ngx_uint_t) pool + index;
+ key = ngx_murmur_hash2((u_char *)&hash, sizeof(hash)) % ngx_pool_context_hash_size;
+
+ node = ngx_pool_context_hash[key];
+
+ while (node) {
+
+ if (node->pool == pool
+ && node->index == index) {
+
+
+ node->data = data;
+ return NGX_OK;
+ }
+ node = node->next;
+ }
+
+ cln = ngx_pool_cleanup_add(pool, sizeof(ngx_pool_context_node_t));
+
+ if (cln == NULL) {
+
+ return NGX_ERROR;
+ }
+
+ cln->handler = ngx_pool_context_cleanup;
+ node = cln->data;
+
+ node->prev = NULL;
+ node->next = NULL;
+ node->pool = pool;
+ node->index = index;
+ node->data = data;
+
+ ngx_pool_context_link(&ngx_pool_context_hash[key], node);
+
+ return NGX_OK;
+}
+
+
+static void
+ngx_pool_context_cleanup(void *data)
+{
+ ngx_pool_context_node_t *node = data;
+
+ ngx_pool_context_unlink(node);
+
+}
+
+
+static void *
+ngx_pool_context_create_conf(ngx_cycle_t *cycle)
+{
+ ngx_pool_context_conf_t *pcf;
+
+ /* create config */
+ pcf = ngx_pcalloc(cycle->pool, sizeof(ngx_pool_context_conf_t));
+ if (pcf == NULL) {
+ return NULL;
+ }
+
+ pcf->size = NGX_CONF_UNSET_UINT;
+
+ return pcf;
+}
+
+
+static char *
+ngx_pool_context_init_conf(ngx_cycle_t *cycle, void *conf)
+{
+ ngx_pool_context_conf_t *pcf = conf;
+
+ ngx_conf_init_uint_value(pcf->size, NGX_POOL_CTX_SIZE);
+
+ ngx_pool_context_hash_size = pcf->size;
+
+ ngx_pool_context_hash = ngx_palloc(cycle->pool, sizeof(ngx_pool_context_node_t *) * ngx_pool_context_hash_size);
+
+ if (ngx_pool_context_hash == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ return NGX_CONF_OK;
+}
+
+
diff --git a/nginx/modsecurity/ngx_pool_context.h b/nginx/modsecurity/ngx_pool_context.h
new file mode 100644
index 00000000..de8b2f3a
--- /dev/null
+++ b/nginx/modsecurity/ngx_pool_context.h
@@ -0,0 +1,12 @@
+
+
+#ifndef _NGX_POOL_CONTEXT_H_INCLUDE_
+#define _NGX_POOL_CONTEXT_H_INCLUDE_
+
+void* ngx_pool_get_ctx(ngx_pool_t * pool, ngx_uint_t index);
+ngx_int_t ngx_pool_set_ctx(ngx_pool_t * pool, ngx_uint_t index,void * data);
+
+#define ngx_http_get_module_pool_ctx(r, module) ngx_pool_get_ctx(r->pool, module.index)
+#define ngx_http_set_pool_ctx(r, c, module) ngx_pool_set_ctx(r->pool, module.index, c)
+
+#endif /* _NGX_POOL_CONTEXT_H_INCLUDE_ */
diff --git a/standalone/Makefile.am b/standalone/Makefile.am
index d1432bfd..d0d57530 100644
--- a/standalone/Makefile.am
+++ b/standalone/Makefile.am
@@ -73,7 +73,17 @@ standalone_la_LDFLAGS = -no-undefined -module -avoid-version \
endif
install-exec-hook: $(pkglib_LTLIBRARIES)
- @echo "Removing unused static libraries..."; \
+ @echo "Creating Nginx config file..."; \
+ rm -f ../nginx/modsecurity/config; \
+ echo "ngx_addon_name=ngx_http_modsecurity" >> ../nginx/modsecurity/config; \
+ echo "# HTTP_MODULES=\"\$$HTTP_MODULES ngx_http_modsecurity\"" >> ../nginx/modsecurity/config; \
+ echo "HTTP_HEADERS_FILTER_MODULE=\"ngx_http_modsecurity \$$HTTP_HEADERS_FILTER_MODULE\"" >> ../nginx/modsecurity/config; \
+ echo "NGX_ADDON_SRCS=\"\$$NGX_ADDON_SRCS \$$ngx_addon_dir/ngx_http_modsecurity.c \$$ngx_addon_dir/apr_bucket_nginx.c\"" >> ../nginx/modsecurity/config;\
+ echo "NGX_ADDON_DEPS=\"\$$NGX_ADDON_DEPS\"" >> ../nginx/modsecurity/config; \
+ echo "CORE_LIBS=\"\$$CORE_LIBS \$$ngx_addon_dir/../../standalone/.libs/standalone.a -lapr-1 -laprutil-1 -lxml2 -lm @LUA_LDADD@\"" >> ../nginx/modsecurity/config; \
+ echo "CORE_INCS=\"\$$CORE_INCS /usr/include/apache2 /usr/include/apr-1.0 /usr/include/httpd /usr/include/apr-1 \$$ngx_addon_dir \$$ngx_addon_dir/../../standalone \$$ngx_addon_dir/../../apache2 /usr/include/libxml2 `echo @LUA_CFLAGS@ | cut -d "I" -f3`\"" >> ../nginx/modsecurity/config; \
+ echo "have=REQUEST_EARLY . auto/have" >> ../nginx/modsecurity/config;\
+ echo "Removing unused static libraries..."; \
for m in $(pkglib_LTLIBRARIES); do \
base=`echo $$m | sed 's/\..*//'`; \
rm -f $(DESTDIR)$(pkglibdir)/$$base.*a; \
diff --git a/standalone/Makefile.in b/standalone/Makefile.in
index aa6e8acf..ca84e211 100644
--- a/standalone/Makefile.in
+++ b/standalone/Makefile.in
@@ -1,9 +1,9 @@
-# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
-# Inc.
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -16,6 +16,23 @@
@SET_MAKE@
VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
@@ -73,6 +90,12 @@ am__nobase_list = $(am__nobase_strip_setup); \
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
am__installdirs = "$(DESTDIR)$(pkglibdir)"
LTLIBRARIES = $(pkglib_LTLIBRARIES)
standalone_la_DEPENDENCIES =
@@ -112,6 +135,11 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(standalone_la_SOURCES)
DIST_SOURCES = $(standalone_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -166,6 +194,7 @@ CURL_VERSION = @CURL_VERSION@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
@@ -200,6 +229,7 @@ LUA_CFLAGS = @LUA_CFLAGS@
LUA_LDADD = @LUA_LDADD@
LUA_LDFLAGS = @LUA_LDFLAGS@
MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
MODSEC_APXS_EXTRA_CFLAGS = @MODSEC_APXS_EXTRA_CFLAGS@
MODSEC_EXTRA_CFLAGS = @MODSEC_EXTRA_CFLAGS@
@@ -230,6 +260,7 @@ PCRE_CONFIG = @PCRE_CONFIG@
PCRE_CPPFLAGS = @PCRE_CPPFLAGS@
PCRE_LDADD = @PCRE_LDADD@
PCRE_LDFLAGS = @PCRE_LDFLAGS@
+PCRE_LD_PATH = @PCRE_LD_PATH@
PCRE_VERSION = @PCRE_VERSION@
PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
@@ -246,6 +277,7 @@ abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
@@ -278,7 +310,6 @@ libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
-lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
@@ -386,7 +417,6 @@ $(ACLOCAL_M4): $(am__aclocal_m4_deps)
$(am__aclocal_m4_deps):
install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES)
@$(NORMAL_INSTALL)
- test -z "$(pkglibdir)" || $(MKDIR_P) "$(DESTDIR)$(pkglibdir)"
@list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \
list2=; for p in $$list; do \
if test -f $$p; then \
@@ -394,6 +424,8 @@ install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES)
else :; fi; \
done; \
test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \
}
@@ -415,7 +447,7 @@ clean-pkglibLTLIBRARIES:
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
-standalone.la: $(standalone_la_OBJECTS) $(standalone_la_DEPENDENCIES)
+standalone.la: $(standalone_la_OBJECTS) $(standalone_la_DEPENDENCIES) $(EXTRA_standalone_la_DEPENDENCIES)
$(standalone_la_LINK) -rpath $(pkglibdir) $(standalone_la_OBJECTS) $(standalone_la_LIBADD) $(LIBS)
mostlyclean-compile:
@@ -815,10 +847,15 @@ install-am: all-am
installcheck: installcheck-am
install-strip:
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- `test -z '$(STRIP)' || \
- echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
mostlyclean-generic:
clean-generic:
@@ -921,7 +958,17 @@ uninstall-am: uninstall-pkglibLTLIBRARIES
install-exec-hook: $(pkglib_LTLIBRARIES)
- @echo "Removing unused static libraries..."; \
+ @echo "Creating Nginx config file..."; \
+ rm -f ../nginx/modsecurity/config; \
+ echo "ngx_addon_name=ngx_http_modsecurity" >> ../nginx/modsecurity/config; \
+ echo "# HTTP_MODULES=\"\$$HTTP_MODULES ngx_http_modsecurity\"" >> ../nginx/modsecurity/config; \
+ echo "HTTP_HEADERS_FILTER_MODULE=\"ngx_http_modsecurity \$$HTTP_HEADERS_FILTER_MODULE\"" >> ../nginx/modsecurity/config; \
+ echo "NGX_ADDON_SRCS=\"\$$NGX_ADDON_SRCS \$$ngx_addon_dir/ngx_http_modsecurity.c \$$ngx_addon_dir/apr_bucket_nginx.c\"" >> ../nginx/modsecurity/config;\
+ echo "NGX_ADDON_DEPS=\"\$$NGX_ADDON_DEPS\"" >> ../nginx/modsecurity/config; \
+ echo "CORE_LIBS=\"\$$CORE_LIBS \$$ngx_addon_dir/../../standalone/.libs/standalone.a -lapr-1 -laprutil-1 -lxml2 -lm @LUA_LDADD@\"" >> ../nginx/modsecurity/config; \
+ echo "CORE_INCS=\"\$$CORE_INCS /usr/include/apache2 /usr/include/apr-1.0 /usr/include/httpd /usr/include/apr-1 \$$ngx_addon_dir \$$ngx_addon_dir/../../standalone \$$ngx_addon_dir/../../apache2 /usr/include/libxml2 `echo @LUA_CFLAGS@ | cut -d "I" -f3`\"" >> ../nginx/modsecurity/config; \
+ echo "have=REQUEST_EARLY . auto/have" >> ../nginx/modsecurity/config;\
+ echo "Removing unused static libraries..."; \
for m in $(pkglib_LTLIBRARIES); do \
base=`echo $$m | sed 's/\..*//'`; \
rm -f $(DESTDIR)$(pkglibdir)/$$base.*a; \
diff --git a/standalone/api.c b/standalone/api.c
index 10cd65f0..d656d04a 100644
--- a/standalone/api.c
+++ b/standalone/api.c
@@ -1,578 +1,662 @@
-/*
-* ModSecurity for Apache 2.x, http://www.modsecurity.org/
-* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
-*
-* You may not use this file except in compliance with
-* the License. You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* If any of the files related to licensing are missing or if you have any
-* other questions related to licensing please contact Trustwave Holdings, Inc.
-* directly using the email address security@modsecurity.org.
-*/
-
-#include
-#include
-
-#include "http_core.h"
-#include "http_request.h"
-
-#include "modsecurity.h"
-#include "apache2.h"
-#include "http_main.h"
-#include "http_connection.h"
-
-#include "apr_optional.h"
-#include "mod_log_config.h"
-
-#include "msc_logging.h"
-#include "msc_util.h"
-
-#include "ap_mpm.h"
-#include "scoreboard.h"
-
-#include "apr_version.h"
-
-#include "apr_lib.h"
-#include "ap_config.h"
-#include "http_config.h"
-
-
-extern void *modsecLogObj;
-extern void (*modsecLogHook)(void *obj, int level, char *str);
-extern int (*modsecDropAction)(request_rec *r);
-apr_status_t (*modsecReadBody)(request_rec *r, char *buf, unsigned int length, unsigned int *readcnt, int *is_eos);
-apr_status_t (*modsecReadResponse)(request_rec *r, char *buf, unsigned int length, unsigned int *readcnt, int *is_eos);
-apr_status_t (*modsecWriteBody)(request_rec *r, char *buf, unsigned int length);
-apr_status_t (*modsecWriteResponse)(request_rec *r, char *buf, unsigned int length);
-
-extern const char *process_command_config(server_rec *s,
- void *mconfig,
- apr_pool_t *p,
- apr_pool_t *ptemp,
- const char *filename);
-
-#define DECLARE_EXTERNAL_HOOK(ns,link,ret,name,args) \
-extern ns##_HOOK_##name##_t *hookfn_##name;
-
-#define DECLARE_HOOK(ret,name,args) \
- DECLARE_EXTERNAL_HOOK(ap,AP,ret,name,args)
-
-DECLARE_HOOK(int,pre_config,(apr_pool_t *pconf,apr_pool_t *plog, apr_pool_t *ptemp))
-DECLARE_HOOK(int,post_config,(apr_pool_t *pconf,apr_pool_t *plog, apr_pool_t *ptemp,server_rec *s))
-DECLARE_HOOK(void,child_init,(apr_pool_t *pchild, server_rec *s))
-DECLARE_HOOK(int,process_connection,(conn_rec *c))
-DECLARE_HOOK(int,post_read_request,(request_rec *r))
-DECLARE_HOOK(int,fixups,(request_rec *r))
-DECLARE_HOOK(void, error_log, (const char *file, int line, int level,
- apr_status_t status, const server_rec *s,
- const request_rec *r, apr_pool_t *pool,
- const char *errstr))
-DECLARE_HOOK(int,log_transaction,(request_rec *r))
-DECLARE_HOOK(void,insert_filter,(request_rec *r))
-DECLARE_HOOK(void,insert_error_filter,(request_rec *r))
-
-char *sa_name = "standalone";
-server_rec *server;
-apr_pool_t *pool = NULL;
-
-apr_status_t ap_http_in_filter(ap_filter_t *f, apr_bucket_brigade *b,
- ap_input_mode_t mode, apr_read_type_e block,
- apr_off_t readbytes);
-apr_status_t ap_http_out_filter(ap_filter_t *f, apr_bucket_brigade *b);
-
-server_rec *modsecInit() {
- apr_initialize();
-
- apr_pool_create(&pool, NULL);
-
- apr_hook_global_pool = pool;
-
- server = apr_palloc(pool, sizeof(server_rec));
-
- server->addrs = apr_palloc(pool, sizeof(server_addr_rec));
- server->addrs->host_addr = apr_palloc(pool, sizeof(apr_sockaddr_t));
- server->addrs->host_addr->addr_str_len = 16;
- server->addrs->host_addr->family = AF_INET;
- server->addrs->host_addr->hostname = sa_name;
-#ifdef WIN32
- server->addrs->host_addr->ipaddr_len = sizeof(IN_ADDR);
-#else
- server->addrs->host_addr->ipaddr_len = sizeof(struct in_addr);
-#endif
- server->addrs->host_addr->ipaddr_ptr = &server->addrs->host_addr->sa.sin.sin_addr;
- server->addrs->host_addr->pool = pool;
- server->addrs->host_addr->port = 80;
-#ifdef WIN32
- server->addrs->host_addr->sa.sin.sin_addr.S_un.S_addr = 0x0100007f;
-#else
- server->addrs->host_addr->sa.sin.sin_addr.s_addr = 0x0100007f;
-#endif
- server->addrs->host_addr->sa.sin.sin_family = AF_INET;
- server->addrs->host_addr->sa.sin.sin_port = 80;
- server->addrs->host_addr->salen = sizeof(server->addrs->host_addr->sa);
- server->addrs->host_addr->servname = sa_name;
- server->addrs->host_port = 80;
- server->error_fname = "error.log";
- server->error_log = NULL;
- server->limit_req_fields = 1024;
- server->limit_req_fieldsize = 1024;
- server->limit_req_line = 1024;
-#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER < 3
- server->loglevel = APLOG_DEBUG;
-#endif
- server->lookup_defaults = NULL;
- server->module_config = NULL;
- server->names = NULL;
-#ifdef WIN32
- server->path = "c:\\inetpub\\wwwroot";
-#else
- server->path = "/var/www";
-#endif
- server->pathlen = strlen(server->path);
- server->port = 80;
- server->process = apr_palloc(pool, sizeof(process_rec));
- server->process->argc = 1;
- server->process->argv = &sa_name;
- server->process->pconf = pool;
- server->process->pool = pool;
- server->process->short_name = sa_name;
- server->server_admin = sa_name;
- server->server_hostname = sa_name;
- server->server_scheme = "";
- server->timeout = 60 * 1000000;// 60 seconds
- server->wild_names = NULL;
- server->is_virtual = 0;
-
- ap_server_config_defines = apr_array_make(pool, 1, sizeof(char *));
-
- // here we should add scoreboard handling for multiple processes and threads
- //
- ap_scoreboard_image = (scoreboard *)apr_palloc(pool, sizeof(scoreboard));
-
- memset(ap_scoreboard_image, 0, sizeof(scoreboard));
-
- // ----------
-
- security2_module.module_index = 0;
-
- security2_module.register_hooks(pool);
-
- ap_register_input_filter("HTTP_IN", ap_http_in_filter, NULL, AP_FTYPE_RESOURCE);
- ap_register_output_filter("HTTP_OUT", ap_http_out_filter, NULL, AP_FTYPE_CONTENT_SET);
-
- return server;
-}
-
-apr_status_t ap_http_in_filter(ap_filter_t *f, apr_bucket_brigade *b,
- ap_input_mode_t mode, apr_read_type_e block,
- apr_off_t readbytes) {
- char *tmp = NULL;
- apr_bucket *e = NULL;
- unsigned int readcnt = 0;
- int is_eos = 0;
-
- if(modsecReadBody == NULL)
- return AP_NOBODY_READ;
-
- tmp = (char *)apr_palloc(f->r->pool, readbytes);
- modsecReadBody(f->r, tmp, readbytes, &readcnt, &is_eos);
-
- e = apr_bucket_pool_create(tmp, readcnt, f->r->pool, f->c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(b, e);
-
- if(is_eos) {
- e = apr_bucket_eos_create(f->c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(b, e);
- }
-
- return APR_SUCCESS;
-}
-
-apr_status_t ap_http_out_filter(ap_filter_t *f, apr_bucket_brigade *b) {
- modsec_rec *msr = (modsec_rec *)f->ctx;
- apr_status_t rc;
-
- // is there a way to tell whether the response body was modified or not?
- //
- if((msr->txcfg->content_injection_enabled || msr->content_prepend_len != 0 || msr->content_append_len != 0)
- && modsecWriteResponse != NULL && msr->txcfg->resbody_access) {
- char *data = NULL;
- apr_size_t length;
-
- rc = apr_brigade_pflatten(msr->of_brigade, &data, &length, msr->mp);
-
- if (rc != APR_SUCCESS) {
- msr_log(msr, 1, "Output filter: Failed to flatten brigade (%d): %s", rc,
- get_apr_error(msr->mp, rc));
- return -1;
- }
-
- modsecWriteResponse(msr->r, data, msr->stream_output_length);
- }
-
- return APR_SUCCESS;
-}
-
-void modsecTerminate() {
- apr_pool_destroy(pool);
- pool = NULL;
- apr_terminate();
-}
-
-void modsecStartConfig() {
- apr_pool_t *ptemp = NULL;
-
- apr_pool_create(&ptemp, pool);
-
- hookfn_pre_config(pool, pool, ptemp);
-
- apr_pool_destroy(ptemp);
-}
-
-directory_config *modsecGetDefaultConfig() {
- return (directory_config *)security2_module.create_dir_config(pool, NULL);
-}
-
-const char *modsecProcessConfig(directory_config *config, const char *file, const char *dir) {
- apr_pool_t *ptemp = NULL;
- const char *err;
- apr_status_t status;
- const char *rootpath, *incpath;
-
- if(dir == NULL || strlen(dir) == 0)
-#ifdef WIN32
- dir = "\\";
-#else
- dir = "/";
-#endif
-
- incpath = file;
-
- /* locate the start of the directories proper */
- status = apr_filepath_root(&rootpath, &incpath, APR_FILEPATH_TRUENAME | APR_FILEPATH_NATIVE, pool);
-
- /* we allow APR_SUCCESS and APR_EINCOMPLETE */
- if (APR_ERELATIVE == status) {
- int li = strlen(dir) - 1;
-
- if(dir[li] != '/' && dir[li] != '\\')
-#ifdef WIN32
- file = apr_pstrcat(pool, dir, "\\", file, NULL);
-#else
- file = apr_pstrcat(pool, dir, "/", file, NULL);
-#endif
- else
- file = apr_pstrcat(pool, dir, file, NULL);
- }
- else if (APR_EBADPATH == status) {
- return apr_pstrcat(pool, "Config file has a bad path, ", file, NULL);
- }
-
- apr_pool_create(&ptemp, pool);
-
- err = process_command_config(server, config, pool, ptemp, file);
-
- apr_pool_destroy(ptemp);
-
- return err;
-}
-
-void modsecFinalizeConfig() {
- apr_pool_t *ptemp = NULL;
-
- apr_pool_create(&ptemp, pool);
-
- hookfn_post_config(pool, pool, ptemp, server);
- hookfn_post_config(pool, pool, ptemp, server);
-
- apr_pool_destroy(ptemp);
-}
-
-void modsecInitProcess() {
- hookfn_child_init(pool, server);
-}
-
-conn_rec *modsecNewConnection() {
- conn_rec *c;
- apr_pool_t *pc = NULL;
-
- apr_pool_create(&pc, pool);
-
- c = apr_pcalloc(pc, sizeof(conn_rec));
-
- c->base_server = server;
- c->id = 1;
- c->local_addr = server->addrs->host_addr;
- c->local_host = sa_name;
- c->local_ip = "127.0.0.1";
- c->pool = pc;
- c->remote_host = sa_name;
-#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER < 3
- c->remote_ip = "127.0.0.1";
- c->remote_addr = server->addrs->host_addr;
-#else
- c->client_ip = "127.0.0.1";
- c->client_addr = server->addrs->host_addr;
-#endif
- c->input_filters = NULL;
- c->output_filters = NULL;
- c->bucket_alloc = apr_bucket_alloc_create(pc);
-
- return c;
-}
-
-void modsecProcessConnection(conn_rec *c) {
- hookfn_process_connection(c);
-}
-
-request_rec *modsecNewRequest(conn_rec *connection, directory_config *config) {
- request_rec *r;
- apr_pool_t *pr = NULL;
-
- apr_pool_create(&pr, connection->pool);
-
- r = apr_pcalloc(pr, sizeof(request_rec));
-
- r->connection = connection;
- r->server = server;
- r->pool = pr;
- r->main = NULL;
- r->next = NULL;
- r->notes = apr_table_make(pr, 10);
- r->per_dir_config = apr_palloc(pr, sizeof(void *));
- ((void **)r->per_dir_config)[0] = config;
- r->prev = NULL;
- r->subprocess_env = apr_table_make(pr, 10);
- apr_table_setn(r->subprocess_env, "UNIQUE_ID", "unique_id");
- r->user = NULL;
-
- r->headers_in = apr_table_make(pr, 10);
- r->headers_out = apr_table_make(pr, 10);
- r->err_headers_out = apr_table_make(pr, 10);
- //apr_table_setn(r->headers_in, "Host", "www.google.com");
- //apr_table_setn(r->headers_in, "", "");
-
- r->the_request = "GET /../../index.html HTTP/1.1";
- r->method = "GET";
- r->method_number = M_GET;
- r->protocol = "HTTP/1.1";
- r->uri = "http://www.google.com/../../index.html";
- r->args = "";
- r->filename = "/../../index.html";
- r->handler = "IIS";
-
- r->parsed_uri.scheme = "http";
- r->parsed_uri.path = "/../../index.html";
- r->parsed_uri.hostname = "www.google.com";
- r->parsed_uri.is_initialized = 1;
- r->parsed_uri.port = 1234;
- r->parsed_uri.port_str = "1234";
- r->parsed_uri.query = "";
- r->parsed_uri.dns_looked_up = 0;
- r->parsed_uri.dns_resolved = 0;
- r->parsed_uri.password = NULL;
- r->parsed_uri.user = NULL;
- r->parsed_uri.fragment = "";
-
- r->input_filters = NULL;
- r->output_filters = NULL;
-
- return r;
-}
-
-static modsec_rec *retrieve_msr(request_rec *r) {
- modsec_rec *msr = NULL;
- request_rec *rx = NULL;
-
- /* Look in the current request first. */
- msr = (modsec_rec *)apr_table_get(r->notes, NOTE_MSR);
- if (msr != NULL) {
- msr->r = r;
- return msr;
- }
-
- /* If this is a subrequest then look in the main request. */
- if (r->main != NULL) {
- msr = (modsec_rec *)apr_table_get(r->main->notes, NOTE_MSR);
- if (msr != NULL) {
- msr->r = r;
- return msr;
- }
- }
-
- /* If the request was redirected then look in the previous requests. */
- rx = r->prev;
- while(rx != NULL) {
- msr = (modsec_rec *)apr_table_get(rx->notes, NOTE_MSR);
- if (msr != NULL) {
- msr->r = r;
- return msr;
- }
- rx = rx->prev;
- }
-
- return NULL;
-}
-
-int modsecProcessRequest(request_rec *r) {
- int status = DECLINED;
- modsec_rec *msr = NULL;
-
- ap_filter_t *f = ap_add_input_filter("HTTP_IN", NULL, r, r->connection);
-
- status = hookfn_post_read_request(r);
- status = hookfn_fixups(r);
-
- ap_remove_input_filter(f);
-
- hookfn_insert_filter(r);
-
- /* Find the transaction context first. */
- msr = retrieve_msr(r);
-
- if (msr == NULL)
- return status;
-
- if(msr->stream_input_data != NULL && modsecWriteBody != NULL)
- {
- // target is responsible for copying the data into correctly managed buffer
- //
- modsecWriteBody(r, msr->stream_input_data, msr->stream_input_length);
-
- free(msr->stream_input_data);
-
- msr->stream_input_data = NULL;
- }
-
- // leftover code possibly for future use
- //
- //if(r->input_filters != NULL && r->input_filters->frec->filter_init_func != NULL)
- //r->input_filters->frec->filter_init_func(r->input_filters);
- //if(r->input_filters != NULL && r->input_filters->frec->filter_func.in_func != NULL)
- //r->input_filters->frec->filter_func.in_func(r->input_filters, NULL, 0, 0, 0);
-
- return status;
-}
-
-void modsecSetConfigForIISRequestBody(request_rec *r)
-{
- modsec_rec *msr = retrieve_msr(r);
-
- if(msr == NULL || msr->txcfg == NULL)
- return;
-
- if(msr->txcfg->reqbody_access)
- msr->txcfg->stream_inbody_inspection = 1;
-}
-
-int modsecIsResponseBodyAccessEnabled(request_rec *r)
-{
- modsec_rec *msr = retrieve_msr(r);
-
- if(msr == NULL || msr->txcfg == NULL)
- return 0;
-
- return msr->txcfg->resbody_access;
-}
-
-int modsecProcessResponse(request_rec *r) {
- int status = DECLINED;
-
- if(r->output_filters != NULL) {
- modsec_rec *msr = (modsec_rec *)r->output_filters->ctx;
- char buf[8192];
- char *tmp = NULL;
- apr_bucket *e = NULL;
- unsigned int readcnt = 0;
- int is_eos = 0;
- ap_filter_t *f = NULL;
- apr_bucket_brigade *bb = NULL;
-
- if (msr == NULL) {
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r->server,
- "ModSecurity: Internal Error: msr is null in output filter.");
- ap_remove_output_filter(r->output_filters);
- return send_error_bucket(msr, r->output_filters, HTTP_INTERNAL_SERVER_ERROR);
- }
-
- bb = apr_brigade_create(msr->mp, r->connection->bucket_alloc);
-
- if (bb == NULL) {
- msr_log(msr, 1, "Process response: Failed to create brigade.");
- return -1;
- }
-
- msr->r = r;
-
- if(modsecReadResponse == NULL)
- return AP_NOBODY_WROTE;
-
- f = ap_add_output_filter("HTTP_OUT", msr, r, r->connection);
-
- while(!is_eos) {
- modsecReadResponse(r, buf, 8192, &readcnt, &is_eos);
-
- if(readcnt > 0) {
- tmp = (char *)apr_palloc(r->pool, readcnt);
- memcpy(tmp, buf, readcnt);
-
- e = apr_bucket_pool_create(tmp, readcnt, r->pool, r->connection->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- }
-
- if(is_eos) {
- e = apr_bucket_eos_create(r->connection->bucket_alloc);
-
- APR_BRIGADE_INSERT_TAIL(bb, e);
- }
- }
-
- status = ap_pass_brigade(r->output_filters, bb);
-
- ap_remove_output_filter(f);
- }
-
- return status;
-}
-
-int modsecFinishRequest(request_rec *r) {
- // run output filter
- //if(r->output_filters != NULL && r->output_filters->frec->filter_init_func != NULL)
- //r->output_filters->frec->filter_init_func(r->output_filters);
-
- hookfn_log_transaction(r);
-
- // make sure you cleanup before calling apr_terminate()
- // otherwise double-free might occur, because of the request body pool cleanup function
- //
- apr_pool_destroy(r->connection->pool);
-
- return DECLINED;
-}
-
-void modsecSetLogHook(void *obj, void (*hook)(void *obj, int level, char *str)) {
- modsecLogObj = obj;
- modsecLogHook = hook;
-}
-
-void modsecSetReadBody(apr_status_t (*func)(request_rec *r, char *buf, unsigned int length, unsigned int *readcnt, int *is_eos)) {
- modsecReadBody = func;
-}
-
-void modsecSetReadResponse(apr_status_t (*func)(request_rec *r, char *buf, unsigned int length, unsigned int *readcnt, int *is_eos)) {
- modsecReadResponse = func;
-}
-
-void modsecSetWriteBody(apr_status_t (*func)(request_rec *r, char *buf, unsigned int length)) {
- modsecWriteBody = func;
-}
-
-void modsecSetWriteResponse(apr_status_t (*func)(request_rec *r, char *buf, unsigned int length)) {
- modsecWriteResponse = func;
-}
-
-void modsecSetDropAction(int (*func)(request_rec *r)) {
- modsecDropAction = func;
-}
+/*
+* ModSecurity for Apache 2.x, http://www.modsecurity.org/
+* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
+*
+* You may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* If any of the files related to licensing are missing or if you have any
+* other questions related to licensing please contact Trustwave Holdings, Inc.
+* directly using the email address security@modsecurity.org.
+*/
+
+#include
+#include
+
+#include "http_core.h"
+#include "http_request.h"
+
+#include "modsecurity.h"
+#include "apache2.h"
+#include "http_main.h"
+#include "http_connection.h"
+
+#include "apr_optional.h"
+#include "mod_log_config.h"
+
+#include "msc_logging.h"
+#include "msc_util.h"
+
+#include "ap_mpm.h"
+#include "scoreboard.h"
+
+#include "apr_version.h"
+
+#include "apr_lib.h"
+#include "ap_config.h"
+#include "http_config.h"
+
+#include "api.h"
+
+extern void *modsecLogObj;
+extern void (*modsecLogHook)(void *obj, int level, char *str);
+extern int (*modsecDropAction)(request_rec *r);
+apr_status_t (*modsecReadBody)(request_rec *r, char *buf, unsigned int length, unsigned int *readcnt, int *is_eos);
+apr_status_t (*modsecReadResponse)(request_rec *r, char *buf, unsigned int length, unsigned int *readcnt, int *is_eos);
+apr_status_t (*modsecWriteBody)(request_rec *r, char *buf, unsigned int length);
+apr_status_t (*modsecWriteResponse)(request_rec *r, char *buf, unsigned int length);
+
+extern const char *process_command_config(server_rec *s,
+ void *mconfig,
+ apr_pool_t *p,
+ apr_pool_t *ptemp,
+ const char *filename);
+
+#define DECLARE_EXTERNAL_HOOK(ns,link,ret,name,args) \
+extern ns##_HOOK_##name##_t *hookfn_##name;
+
+#define DECLARE_HOOK(ret,name,args) \
+ DECLARE_EXTERNAL_HOOK(ap,AP,ret,name,args)
+
+DECLARE_HOOK(int,pre_config,(apr_pool_t *pconf,apr_pool_t *plog, apr_pool_t *ptemp))
+DECLARE_HOOK(int,post_config,(apr_pool_t *pconf,apr_pool_t *plog, apr_pool_t *ptemp,server_rec *s))
+DECLARE_HOOK(void,child_init,(apr_pool_t *pchild, server_rec *s))
+DECLARE_HOOK(int,process_connection,(conn_rec *c))
+DECLARE_HOOK(int,post_read_request,(request_rec *r))
+DECLARE_HOOK(int,fixups,(request_rec *r))
+DECLARE_HOOK(void, error_log, (const char *file, int line, int level,
+ apr_status_t status, const server_rec *s,
+ const request_rec *r, apr_pool_t *pool,
+ const char *errstr))
+DECLARE_HOOK(int,log_transaction,(request_rec *r))
+DECLARE_HOOK(void,insert_filter,(request_rec *r))
+DECLARE_HOOK(void,insert_error_filter,(request_rec *r))
+
+char *sa_name = "standalone";
+server_rec *server;
+apr_pool_t *pool = NULL;
+
+apr_status_t ap_http_in_filter(ap_filter_t *f, apr_bucket_brigade *b,
+ ap_input_mode_t mode, apr_read_type_e block,
+ apr_off_t readbytes);
+apr_status_t ap_http_out_filter(ap_filter_t *f, apr_bucket_brigade *b);
+
+server_rec *modsecInit() {
+ apr_initialize();
+
+ apr_pool_create(&pool, NULL);
+
+ apr_hook_global_pool = pool;
+
+ server = apr_palloc(pool, sizeof(server_rec));
+
+ server->addrs = apr_palloc(pool, sizeof(server_addr_rec));
+ server->addrs->host_addr = apr_palloc(pool, sizeof(apr_sockaddr_t));
+ server->addrs->host_addr->addr_str_len = 16;
+ server->addrs->host_addr->family = AF_INET;
+ server->addrs->host_addr->hostname = sa_name;
+#ifdef WIN32
+ server->addrs->host_addr->ipaddr_len = sizeof(IN_ADDR);
+#else
+ server->addrs->host_addr->ipaddr_len = sizeof(struct in_addr);
+#endif
+ server->addrs->host_addr->ipaddr_ptr = &server->addrs->host_addr->sa.sin.sin_addr;
+ server->addrs->host_addr->pool = pool;
+ server->addrs->host_addr->port = 80;
+#ifdef WIN32
+ server->addrs->host_addr->sa.sin.sin_addr.S_un.S_addr = 0x0100007f;
+#else
+ server->addrs->host_addr->sa.sin.sin_addr.s_addr = 0x0100007f;
+#endif
+ server->addrs->host_addr->sa.sin.sin_family = AF_INET;
+ server->addrs->host_addr->sa.sin.sin_port = 80;
+ server->addrs->host_addr->salen = sizeof(server->addrs->host_addr->sa);
+ server->addrs->host_addr->servname = sa_name;
+ server->addrs->host_port = 80;
+ server->error_fname = "error.log";
+ server->error_log = NULL;
+ server->limit_req_fields = 1024;
+ server->limit_req_fieldsize = 1024;
+ server->limit_req_line = 1024;
+#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER < 3
+ server->loglevel = APLOG_DEBUG;
+#endif
+ server->lookup_defaults = NULL;
+ server->module_config = NULL;
+ server->names = NULL;
+#ifdef WIN32
+ server->path = "c:\\inetpub\\wwwroot";
+#else
+ server->path = "/var/www";
+#endif
+ server->pathlen = strlen(server->path);
+ server->port = 80;
+ server->process = apr_palloc(pool, sizeof(process_rec));
+ server->process->argc = 1;
+ server->process->argv = &sa_name;
+ server->process->pconf = pool;
+ server->process->pool = pool;
+ server->process->short_name = sa_name;
+ server->server_admin = sa_name;
+ server->server_hostname = sa_name;
+ server->server_scheme = "";
+ server->timeout = 60 * 1000000;// 60 seconds
+ server->wild_names = NULL;
+ server->is_virtual = 0;
+
+ ap_server_config_defines = apr_array_make(pool, 1, sizeof(char *));
+
+ // here we should add scoreboard handling for multiple processes and threads
+ //
+ ap_scoreboard_image = (scoreboard *)apr_palloc(pool, sizeof(scoreboard));
+
+ memset(ap_scoreboard_image, 0, sizeof(scoreboard));
+
+ // ----------
+
+ security2_module.module_index = 0;
+
+ security2_module.register_hooks(pool);
+
+ ap_register_input_filter("HTTP_IN", ap_http_in_filter, NULL, AP_FTYPE_RESOURCE);
+ ap_register_output_filter("HTTP_OUT", ap_http_out_filter, NULL, AP_FTYPE_CONTENT_SET);
+
+ return server;
+}
+
+apr_status_t ap_http_in_filter(ap_filter_t *f, apr_bucket_brigade *bb_out,
+ ap_input_mode_t mode, apr_read_type_e block,
+ apr_off_t readbytes) {
+ char *tmp = NULL;
+ apr_bucket *e = NULL;
+ unsigned int readcnt = 0;
+ int is_eos = 0;
+ apr_bucket_brigade *bb_in;
+ apr_bucket *after;
+ apr_status_t rv;
+
+ bb_in = modsecGetBodyBrigade(f->r);
+
+ /* use request brigade */
+ if (bb_in != NULL) {
+ if (!APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb_in))) {
+ e = apr_bucket_eos_create(f->c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb_in, e);
+ }
+
+ rv = apr_brigade_partition(bb_in, readbytes, &after);
+ if (rv != APR_SUCCESS && rv != APR_INCOMPLETE) {
+ return rv;
+ }
+
+ for (e = APR_BRIGADE_FIRST(bb_in); e != after; e = APR_BRIGADE_FIRST(bb_in)) {
+ APR_BUCKET_REMOVE(e);
+ APR_BRIGADE_INSERT_TAIL(bb_out, e);
+ }
+
+ return APR_SUCCESS;
+ }
+
+ /* call the callback */
+ if(modsecReadBody != NULL) {
+
+ tmp = (char *)apr_palloc(f->r->pool, readbytes);
+ modsecReadBody(f->r, tmp, readbytes, &readcnt, &is_eos);
+
+ e = apr_bucket_pool_create(tmp, readcnt, f->r->pool, f->c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb_out, e);
+
+ if(is_eos) {
+ e = apr_bucket_eos_create(f->c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb_out, e);
+ }
+ return APR_SUCCESS;
+ }
+
+ /* cannot read request body */
+ e = apr_bucket_eos_create(f->c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb_out, e);
+
+ return APR_SUCCESS;
+}
+
+apr_status_t ap_http_out_filter(ap_filter_t *f, apr_bucket_brigade *b) {
+ modsec_rec *msr = (modsec_rec *)f->ctx;
+ apr_status_t rc;
+ apr_bucket_brigade *bb_out;
+
+ bb_out = modsecGetResponseBrigade(f->r);
+
+
+ if (bb_out) {
+ APR_BRIGADE_CONCAT(bb_out, b);
+ return APR_SUCCESS;
+ }
+
+ // is there a way to tell whether the response body was modified or not?
+ //
+ if((msr->txcfg->content_injection_enabled || msr->content_prepend_len != 0 || msr->content_append_len != 0)
+ && msr->txcfg->resbody_access) {
+
+ if (modsecWriteResponse != NULL) {
+ char *data = NULL;
+ apr_size_t length;
+
+ rc = apr_brigade_pflatten(msr->of_brigade, &data, &length, msr->mp);
+
+ if (rc != APR_SUCCESS) {
+ msr_log(msr, 1, "Output filter: Failed to flatten brigade (%d): %s", rc,
+ get_apr_error(msr->mp, rc));
+ return -1;
+ }
+
+ /* TODO: return ?*/
+ modsecWriteResponse(msr->r, data, msr->stream_output_length);
+ }
+ }
+
+ return APR_SUCCESS;
+}
+
+void modsecTerminate() {
+ apr_pool_destroy(pool);
+ pool = NULL;
+ apr_terminate();
+}
+
+void modsecStartConfig() {
+ apr_pool_t *ptemp = NULL;
+
+ apr_pool_create(&ptemp, pool);
+
+ hookfn_pre_config(pool, pool, ptemp);
+
+ apr_pool_destroy(ptemp);
+}
+
+directory_config *modsecGetDefaultConfig() {
+ return (directory_config *)security2_module.create_dir_config(pool, NULL);
+}
+
+const char *modsecProcessConfig(directory_config *config, const char *file, const char *dir) {
+ apr_pool_t *ptemp = NULL;
+ const char *err;
+ apr_status_t status;
+ const char *rootpath, *incpath;
+
+ if(dir == NULL || strlen(dir) == 0)
+#ifdef WIN32
+ dir = "\\";
+#else
+ dir = "/";
+#endif
+
+ incpath = file;
+
+ /* locate the start of the directories proper */
+ status = apr_filepath_root(&rootpath, &incpath, APR_FILEPATH_TRUENAME | APR_FILEPATH_NATIVE, pool);
+
+ /* we allow APR_SUCCESS and APR_EINCOMPLETE */
+ if (APR_ERELATIVE == status) {
+ int li = strlen(dir) - 1;
+
+ if(dir[li] != '/' && dir[li] != '\\')
+#ifdef WIN32
+ file = apr_pstrcat(pool, dir, "\\", file, NULL);
+#else
+ file = apr_pstrcat(pool, dir, "/", file, NULL);
+#endif
+ else
+ file = apr_pstrcat(pool, dir, file, NULL);
+ }
+ else if (APR_EBADPATH == status) {
+ return apr_pstrcat(pool, "Config file has a bad path, ", file, NULL);
+ }
+
+ apr_pool_create(&ptemp, pool);
+
+ err = process_command_config(server, config, pool, ptemp, file);
+
+ apr_pool_destroy(ptemp);
+
+ return err;
+}
+
+void modsecFinalizeConfig() {
+ apr_pool_t *ptemp = NULL;
+
+ apr_pool_create(&ptemp, pool);
+
+ hookfn_post_config(pool, pool, ptemp, server);
+ hookfn_post_config(pool, pool, ptemp, server);
+
+ apr_pool_destroy(ptemp);
+}
+
+void modsecInitProcess() {
+ hookfn_child_init(pool, server);
+}
+
+conn_rec *modsecNewConnection() {
+ conn_rec *c;
+ apr_pool_t *pc = NULL;
+
+ apr_pool_create(&pc, pool);
+
+ c = apr_pcalloc(pc, sizeof(conn_rec));
+
+ c->base_server = server;
+ c->id = 1;
+ c->local_addr = server->addrs->host_addr;
+ c->local_host = sa_name;
+ c->local_ip = "127.0.0.1";
+ c->pool = pc;
+ c->remote_host = sa_name;
+#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER < 3
+ c->remote_ip = "127.0.0.1";
+ c->remote_addr = server->addrs->host_addr;
+#else
+ c->client_ip = "127.0.0.1";
+ c->client_addr = server->addrs->host_addr;
+#endif
+ c->input_filters = NULL;
+ c->output_filters = NULL;
+ c->bucket_alloc = apr_bucket_alloc_create(pc);
+
+ return c;
+}
+
+void modsecProcessConnection(conn_rec *c) {
+ hookfn_process_connection(c);
+}
+
+request_rec *modsecNewRequest(conn_rec *connection, directory_config *config) {
+ request_rec *r;
+ apr_pool_t *pr = NULL;
+
+ apr_pool_create(&pr, connection->pool);
+
+ r = apr_pcalloc(pr, sizeof(request_rec));
+
+ r->connection = connection;
+ r->server = server;
+ r->pool = pr;
+ r->main = NULL;
+ r->next = NULL;
+ r->notes = apr_table_make(pr, 10);
+ r->per_dir_config = apr_palloc(pr, sizeof(void *));
+ ((void **)r->per_dir_config)[0] = config;
+ r->prev = NULL;
+ r->subprocess_env = apr_table_make(pr, 10);
+ apr_table_setn(r->subprocess_env, "UNIQUE_ID", "unique_id");
+ r->user = NULL;
+
+ r->headers_in = apr_table_make(pr, 10);
+ r->headers_out = apr_table_make(pr, 10);
+ r->err_headers_out = apr_table_make(pr, 10);
+ //apr_table_setn(r->headers_in, "Host", "www.google.com");
+ //apr_table_setn(r->headers_in, "", "");
+
+ r->the_request = "GET /../../index.html HTTP/1.1";
+ r->method = "GET";
+ r->method_number = M_GET;
+ r->protocol = "HTTP/1.1";
+ r->uri = "http://www.google.com/../../index.html";
+ r->args = "";
+ r->filename = "/../../index.html";
+ r->handler = "IIS";
+
+ r->parsed_uri.scheme = "http";
+ r->parsed_uri.path = "/../../index.html";
+ r->parsed_uri.hostname = "www.google.com";
+ r->parsed_uri.is_initialized = 1;
+ r->parsed_uri.port = 1234;
+ r->parsed_uri.port_str = "1234";
+ r->parsed_uri.query = "";
+ r->parsed_uri.dns_looked_up = 0;
+ r->parsed_uri.dns_resolved = 0;
+ r->parsed_uri.password = NULL;
+ r->parsed_uri.user = NULL;
+ r->parsed_uri.fragment = "";
+
+ r->input_filters = NULL;
+ r->output_filters = NULL;
+
+ return r;
+}
+
+static modsec_rec *retrieve_msr(request_rec *r) {
+ modsec_rec *msr = NULL;
+ request_rec *rx = NULL;
+
+ /* Look in the current request first. */
+ msr = (modsec_rec *)apr_table_get(r->notes, NOTE_MSR);
+ if (msr != NULL) {
+ msr->r = r;
+ return msr;
+ }
+
+ /* If this is a subrequest then look in the main request. */
+ if (r->main != NULL) {
+ msr = (modsec_rec *)apr_table_get(r->main->notes, NOTE_MSR);
+ if (msr != NULL) {
+ msr->r = r;
+ return msr;
+ }
+ }
+
+ /* If the request was redirected then look in the previous requests. */
+ rx = r->prev;
+ while(rx != NULL) {
+ msr = (modsec_rec *)apr_table_get(rx->notes, NOTE_MSR);
+ if (msr != NULL) {
+ msr->r = r;
+ return msr;
+ }
+ rx = rx->prev;
+ }
+
+ return NULL;
+}
+
+int modsecProcessRequestHeaders(request_rec *r) {
+ return hookfn_post_read_request(r);
+}
+
+int modsecProcessRequestBody(request_rec *r) {
+ int status = DECLINED;
+ modsec_rec *msr = NULL;
+
+ ap_filter_t *f = ap_add_input_filter("HTTP_IN", NULL, r, r->connection);
+ apr_bucket_brigade* bb_out;
+
+ status = hookfn_fixups(r);
+
+ ap_remove_input_filter(f);
+
+ if (status != DECLINED) {
+ return status;
+ }
+
+ hookfn_insert_filter(r);
+
+ /* Find the transaction context first. */
+ msr = retrieve_msr(r);
+
+ if (msr == NULL)
+ return status;
+
+ bb_out = modsecGetBodyBrigade(r);
+ if (bb_out) {
+ (void) apr_brigade_cleanup(bb_out);
+ status = ap_get_brigade(r->input_filters, bb_out, AP_MODE_READBYTES, APR_BLOCK_READ, -1);
+ if (status == APR_SUCCESS) {
+ return DECLINED;
+ }
+ return status;
+ }
+
+ if(msr->stream_input_data != NULL && modsecWriteBody != NULL)
+ {
+ // target is responsible for copying the data into correctly managed buffer
+ //
+ modsecWriteBody(r, msr->stream_input_data, msr->stream_input_length);
+
+ free(msr->stream_input_data);
+
+ msr->stream_input_data = NULL;
+ }
+
+ // leftover code possibly for future use
+ //
+ //if(r->input_filters != NULL && r->input_filters->frec->filter_init_func != NULL)
+ //r->input_filters->frec->filter_init_func(r->input_filters);
+ //if(r->input_filters != NULL && r->input_filters->frec->filter_func.in_func != NULL)
+ //r->input_filters->frec->filter_func.in_func(r->input_filters, NULL, 0, 0, 0);
+
+ return status;
+}
+
+void modsecSetConfigForIISRequestBody(request_rec *r)
+{
+ modsec_rec *msr = retrieve_msr(r);
+
+ if(msr == NULL || msr->txcfg == NULL)
+ return;
+
+ if(msr->txcfg->reqbody_access)
+ msr->txcfg->stream_inbody_inspection = 1;
+}
+
+int modsecIsRequestBodyAccessEnabled(request_rec *r)
+{
+ modsec_rec *msr = retrieve_msr(r);
+
+ if(msr == NULL || msr->txcfg == NULL)
+ return 0;
+
+ return msr->txcfg->reqbody_access;
+}
+
+int modsecIsResponseBodyAccessEnabled(request_rec *r)
+{
+ modsec_rec *msr = retrieve_msr(r);
+
+ if(msr == NULL || msr->txcfg == NULL)
+ return 0;
+
+ return msr->txcfg->resbody_access;
+}
+
+int modsecProcessResponse(request_rec *r) {
+ int status = DECLINED;
+
+ if(r->output_filters != NULL) {
+ modsec_rec *msr = (modsec_rec *)r->output_filters->ctx;
+ char buf[8192];
+ char *tmp = NULL;
+ apr_bucket *e = NULL;
+ unsigned int readcnt = 0;
+ int is_eos = 0;
+ ap_filter_t *f = NULL;
+ apr_bucket_brigade *bb_in, *bb = NULL;
+
+ if (msr == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r->server,
+ "ModSecurity: Internal Error: msr is null in output filter.");
+ ap_remove_output_filter(r->output_filters);
+ return send_error_bucket(msr, r->output_filters, HTTP_INTERNAL_SERVER_ERROR);
+ }
+
+ bb = apr_brigade_create(msr->mp, r->connection->bucket_alloc);
+
+ if (bb == NULL) {
+ msr_log(msr, 1, "Process response: Failed to create brigade.");
+ return APR_EGENERAL;
+ }
+
+ msr->r = r;
+
+ bb_in = modsecGetResponseBrigade(r);
+
+ if (bb_in != NULL) {
+ APR_BRIGADE_CONCAT(bb, bb_in);
+ if (!APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
+ e = apr_bucket_eos_create(bb->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, e);
+ }
+ } else if (modsecReadResponse != NULL) {
+ while(!is_eos) {
+ modsecReadResponse(r, buf, 8192, &readcnt, &is_eos);
+
+ if(readcnt > 0) {
+ tmp = (char *)apr_palloc(r->pool, readcnt);
+ memcpy(tmp, buf, readcnt);
+ e = apr_bucket_pool_create(tmp, readcnt, r->pool, r->connection->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, e);
+ }
+ }
+
+ e = apr_bucket_eos_create(r->connection->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, e);
+ } else {
+ /* cannot read response body process header only */
+
+ e = apr_bucket_eos_create(r->connection->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, e);
+ }
+
+ f = ap_add_output_filter("HTTP_OUT", msr, r, r->connection);
+ status = ap_pass_brigade(r->output_filters, bb);
+ ap_remove_output_filter(f);
+ if(status > 0
+ && msr->intercept_actionset->intercept_status != 0) {
+ status = msr->intercept_actionset->intercept_status;
+ }
+ return status;
+ }
+
+ return status;
+}
+
+int modsecFinishRequest(request_rec *r) {
+ // run output filter
+ //if(r->output_filters != NULL && r->output_filters->frec->filter_init_func != NULL)
+ //r->output_filters->frec->filter_init_func(r->output_filters);
+
+ hookfn_log_transaction(r);
+
+ // make sure you cleanup before calling apr_terminate()
+ // otherwise double-free might occur, because of the request body pool cleanup function
+ //
+ apr_pool_destroy(r->connection->pool);
+
+ return DECLINED;
+}
+
+void modsecSetLogHook(void *obj, void (*hook)(void *obj, int level, char *str)) {
+ modsecLogObj = obj;
+ modsecLogHook = hook;
+}
+
+void modsecSetReadBody(apr_status_t (*func)(request_rec *r, char *buf, unsigned int length, unsigned int *readcnt, int *is_eos)) {
+ modsecReadBody = func;
+}
+
+void modsecSetReadResponse(apr_status_t (*func)(request_rec *r, char *buf, unsigned int length, unsigned int *readcnt, int *is_eos)) {
+ modsecReadResponse = func;
+}
+
+void modsecSetWriteBody(apr_status_t (*func)(request_rec *r, char *buf, unsigned int length)) {
+ modsecWriteBody = func;
+}
+
+void modsecSetWriteResponse(apr_status_t (*func)(request_rec *r, char *buf, unsigned int length)) {
+ modsecWriteResponse = func;
+}
+
+void modsecSetDropAction(int (*func)(request_rec *r)) {
+ modsecDropAction = func;
+}
diff --git a/standalone/api.h b/standalone/api.h
index 7ba998d5..15c326c6 100644
--- a/standalone/api.h
+++ b/standalone/api.h
@@ -60,12 +60,49 @@ conn_rec *modsecNewConnection();
void modsecProcessConnection(conn_rec *c);
request_rec *modsecNewRequest(conn_rec *connection, directory_config *config);
-int modsecProcessRequest(request_rec *r);
+
+int modsecProcessRequestBody(request_rec *r);
+int modsecProcessRequestHeaders(request_rec *r);
+
+static inline int modsecProcessRequest(request_rec *r) {
+ int status;
+ status = modsecProcessRequestHeaders(r);
+ if (status != DECLINED) {
+ return status;
+ }
+
+ return modsecProcessRequestBody(r);
+}
+
+
int modsecProcessResponse(request_rec *r);
int modsecFinishRequest(request_rec *r);
void modsecSetLogHook(void *obj, void (*hook)(void *obj, int level, char *str));
+#define NOTE_MSR_BRIGADE_REQUEST "modsecurity-brigade-request"
+#define NOTE_MSR_BRIGADE_RESPONSE "modsecurity-brigade-response"
+
+static inline void
+modsecSetBodyBrigade(request_rec *r, apr_bucket_brigade *b) {
+ apr_table_setn(r->notes, NOTE_MSR_BRIGADE_REQUEST, (char *)b);
+};
+
+static inline apr_bucket_brigade *
+modsecGetBodyBrigade(request_rec *r) {
+ return (apr_bucket_brigade *)apr_table_get(r->notes, NOTE_MSR_BRIGADE_REQUEST);
+};
+
+static inline void
+modsecSetResponseBrigade(request_rec *r, apr_bucket_brigade *b) {
+ apr_table_setn(r->notes, NOTE_MSR_BRIGADE_RESPONSE, (char *)b);
+};
+
+static inline apr_bucket_brigade *
+modsecGetResponseBrigade(request_rec *r) {
+ return (apr_bucket_brigade *)apr_table_get(r->notes, NOTE_MSR_BRIGADE_RESPONSE);
+};
+
void modsecSetReadBody(apr_status_t (*func)(request_rec *r, char *buf, unsigned int length, unsigned int *readcnt, int *is_eos));
void modsecSetReadResponse(apr_status_t (*func)(request_rec *r, char *buf, unsigned int length, unsigned int *readcnt, int *is_eos));
void modsecSetWriteBody(apr_status_t (*func)(request_rec *r, char *buf, unsigned int length));
@@ -73,6 +110,7 @@ void modsecSetWriteResponse(apr_status_t (*func)(request_rec *r, char *buf, unsi
void modsecSetDropAction(int (*func)(request_rec *r));
int modsecIsResponseBodyAccessEnabled(request_rec *r);
+int modsecIsRequestBodyAccessEnabled(request_rec *r);
void modsecSetConfigForIISRequestBody(request_rec *r);
diff --git a/standalone/config.c b/standalone/config.c
index b1a57dad..ec1c40f4 100644
--- a/standalone/config.c
+++ b/standalone/config.c
@@ -1153,7 +1153,14 @@ ProcessInclude:
parms->directive = newdir;
- errmsg = invoke_cmd(cmd, parms, mconfig, args);
+ __try
+ {
+ errmsg = invoke_cmd(cmd, parms, mconfig, args);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ errmsg = "Command failed to execute (check file/folder permissions, syntax, etc.).";
+ }
if(errmsg != NULL)
break;
diff --git a/standalone/main.cpp b/standalone/main.cpp
index 73265b1a..912b96f9 100644
--- a/standalone/main.cpp
+++ b/standalone/main.cpp
@@ -21,6 +21,7 @@
char *config_file = NULL;
+char *url_file = NULL;
char *event_files[1024];
int event_file_cnt;
char *event_file = NULL;
@@ -31,6 +32,11 @@ int event_file_blocks[256];
#define EVENT_FILE_MAX_SIZE (16*1024*1024)
+#define MAX_URLS 4096
+
+char urls[MAX_URLS][4096];
+int url_cnt = 0;
+
void readeventfile(char *name)
{
if(event_file == NULL)
@@ -119,6 +125,12 @@ void parseargs(int argc, char *argv[])
i += 2;
continue;
}
+ if(argv[i][1] == 'u' && i < argc - 1)
+ {
+ url_file = argv[i + 1];
+ i += 2;
+ continue;
+ }
i++;
continue;
}
@@ -224,7 +236,7 @@ void main(int argc, char *argv[])
if(config_file == NULL || argc < 3)
{
printf("Usage:\n");
- printf("standalone.exe -c [ ...]\n");
+ printf("standalone.exe -c [-u ] [ ...]\n");
return;
}
@@ -250,133 +262,171 @@ void main(int argc, char *argv[])
modsecInitProcess();
+ if(url_file != NULL)
+ {
+ FILE *fr = fopen(url_file, "rb");
+ int i = 0;
+
+ while(fgets(urls[i],4096,fr) != NULL)
+ {
+ urls[i][4095] = 0;
+
+ int l = strlen(urls[i]) - 1;
+
+ if(l < 8)
+ continue;
+
+ while(urls[i][l] == 10 || urls[i][l] == 13)
+ l--;
+
+ urls[i++][l + 1] = 0;
+ }
+
+ url_cnt = i;
+ fclose(fr);
+ }
+
for(int i = 0; i < event_file_cnt; i++)
{
- readeventfile(event_files[i]);
- parseeventfile();
+ if(url_cnt == 0)
+ {
+ urls[0][0] = 0;
+ url_cnt = 1;
+ }
- bodypos = 0;
- responsepos = 0;
+ for(int ui = 0; ui < url_cnt; ui++)
+ {
+ readeventfile(event_files[i]);
+ parseeventfile();
- c = modsecNewConnection();
+ bodypos = 0;
+ responsepos = 0;
- modsecProcessConnection(c);
+ c = modsecNewConnection();
- r = modsecNewRequest(c, config);
+ modsecProcessConnection(c);
- int j = event_file_blocks['B'];
+ r = modsecNewRequest(c, config);
- if(j < 0)
- continue;
+ int j = event_file_blocks['B'];
- j++;
+ if(j < 0)
+ continue;
- if(event_file_lines[j][0] == 0)
- continue;
+ j++;
- char *method = event_file_lines[j];
- char *url = strchr(method, 32);
- char *proto = strchr(url + 1, 32);
+ if(event_file_lines[j][0] == 0)
+ continue;
- if(url == NULL || proto == NULL)
- continue;
+ char *method = event_file_lines[j];
+ char *url = strchr(method, 32);
+ char *proto = strchr(url + 1, 32);
- *url++=0;
- *proto++=0;
+ if(url == NULL || proto == NULL)
+ continue;
+
+ *url++=0;
+ *proto++=0;
+
+ if(urls[ui][0] != 0)
+ {
+ url = urls[ui];
+ }
#define SETMETHOD(m) if(strcmp(method,#m) == 0){ r->method = method; r->method_number = M_##m; }
- r->method = "INVALID";
- r->method_number = M_INVALID;
+ r->method = "INVALID";
+ r->method_number = M_INVALID;
- SETMETHOD(OPTIONS)
- SETMETHOD(GET)
- SETMETHOD(POST)
- SETMETHOD(PUT)
- SETMETHOD(DELETE)
- SETMETHOD(TRACE)
- SETMETHOD(CONNECT)
- SETMETHOD(MOVE)
- SETMETHOD(COPY)
- SETMETHOD(PROPFIND)
- SETMETHOD(PROPPATCH)
- SETMETHOD(MKCOL)
- SETMETHOD(LOCK)
- SETMETHOD(UNLOCK)
+ SETMETHOD(OPTIONS)
+ SETMETHOD(GET)
+ SETMETHOD(POST)
+ SETMETHOD(PUT)
+ SETMETHOD(DELETE)
+ SETMETHOD(TRACE)
+ SETMETHOD(CONNECT)
+ SETMETHOD(MOVE)
+ SETMETHOD(COPY)
+ SETMETHOD(PROPFIND)
+ SETMETHOD(PROPPATCH)
+ SETMETHOD(MKCOL)
+ SETMETHOD(LOCK)
+ SETMETHOD(UNLOCK)
- r->protocol = proto;
+ r->protocol = proto;
- while(event_file_lines[++j][0] != 0)
- {
- char *value = strchr(event_file_lines[j], ':');
+ while(event_file_lines[++j][0] != 0)
+ {
+ char *value = strchr(event_file_lines[j], ':');
- if(value == NULL)
- break;
+ if(value == NULL)
+ break;
- *value++ = 0;
+ *value++ = 0;
- while(*value <=32 && *value != 0)
- value++;
+ while(*value <=32 && *value != 0)
+ value++;
- apr_table_setn(r->headers_in, event_file_lines[j], value);
- }
+ apr_table_setn(r->headers_in, event_file_lines[j], value);
+ }
- r->content_encoding = apr_table_get(r->headers_in, "Content-Encoding");
- r->content_type = apr_table_get(r->headers_in, "Content-Type");
- r->hostname = apr_table_get(r->headers_in, "Host");
- r->path_info = url;
+ r->content_encoding = apr_table_get(r->headers_in, "Content-Encoding");
+ r->content_type = apr_table_get(r->headers_in, "Content-Type");
+ r->hostname = apr_table_get(r->headers_in, "Host");
+ r->path_info = url;
- char *query = strchr(url, '?');
- char *rawurl = url;
+ char *query = strchr(url, '?');
+ char *rawurl = url;
- if(query != NULL)
- {
- rawurl = (char *)apr_palloc(r->pool, strlen(url) + 1);
- strcpy(rawurl, url);
- *query++ = 0;
- r->args = query;
+ if(query != NULL)
+ {
+ rawurl = (char *)apr_palloc(r->pool, strlen(url) + 1);
+ strcpy(rawurl, url);
+ *query++ = 0;
+ r->args = query;
+ }
+
+ const char *lng = apr_table_get(r->headers_in, "Content-Languages");
+
+ if(lng != NULL)
+ {
+ r->content_languages = apr_array_make(r->pool, 1, sizeof(const char *));
+
+ *(const char **)apr_array_push(r->content_languages) = lng;
+ }
+
+ r->request_time = apr_time_now();
+
+ r->parsed_uri.scheme = "http";
+ r->parsed_uri.path = r->path_info;
+ r->parsed_uri.hostname = (char *)r->hostname;
+ r->parsed_uri.is_initialized = 1;
+ r->parsed_uri.port = 80;
+ r->parsed_uri.port_str = "80";
+ r->parsed_uri.query = r->args;
+ r->parsed_uri.dns_looked_up = 0;
+ r->parsed_uri.dns_resolved = 0;
+ r->parsed_uri.password = NULL;
+ r->parsed_uri.user = NULL;
+ r->parsed_uri.fragment = NULL;
+
+ r->unparsed_uri = rawurl;
+ r->uri = r->unparsed_uri;
+
+ r->the_request = (char *)apr_palloc(r->pool, strlen(r->method) + 1 + strlen(r->uri) + 1 + strlen(r->protocol) + 1);
+
+ strcpy(r->the_request, r->method);
+ strcat(r->the_request, " ");
+ strcat(r->the_request, r->uri);
+ strcat(r->the_request, " ");
+ strcat(r->the_request, r->protocol);
+
+ apr_table_setn(r->subprocess_env, "UNIQUE_ID", "1");
+
+ modsecProcessRequest(r);
+ modsecProcessResponse(r);
+ modsecFinishRequest(r);
}
-
- const char *lng = apr_table_get(r->headers_in, "Content-Languages");
-
- if(lng != NULL)
- {
- r->content_languages = apr_array_make(r->pool, 1, sizeof(const char *));
-
- *(const char **)apr_array_push(r->content_languages) = lng;
- }
-
- r->request_time = apr_time_now();
-
- r->parsed_uri.scheme = "http";
- r->parsed_uri.path = r->path_info;
- r->parsed_uri.hostname = (char *)r->hostname;
- r->parsed_uri.is_initialized = 1;
- r->parsed_uri.port = 80;
- r->parsed_uri.port_str = "80";
- r->parsed_uri.query = r->args;
- r->parsed_uri.dns_looked_up = 0;
- r->parsed_uri.dns_resolved = 0;
- r->parsed_uri.password = NULL;
- r->parsed_uri.user = NULL;
- r->parsed_uri.fragment = NULL;
-
- r->unparsed_uri = rawurl;
- r->uri = r->unparsed_uri;
-
- r->the_request = (char *)apr_palloc(r->pool, strlen(r->method) + 1 + strlen(r->uri) + 1 + strlen(r->protocol) + 1);
-
- strcpy(r->the_request, r->method);
- strcat(r->the_request, " ");
- strcat(r->the_request, r->uri);
- strcat(r->the_request, " ");
- strcat(r->the_request, r->protocol);
-
- apr_table_setn(r->subprocess_env, "UNIQUE_ID", "1");
-
- modsecProcessRequest(r);
- modsecProcessResponse(r);
- modsecFinishRequest(r);
}
modsecTerminate();
diff --git a/standalone/standalone.vcxproj.user b/standalone/standalone.vcxproj.user
index 0be15d4d..deb3e354 100644
--- a/standalone/standalone.vcxproj.user
+++ b/standalone/standalone.vcxproj.user
@@ -1,7 +1,7 @@
- -c owasp_crs\modsecurity_iis.conf d:\test.dat
+ -c d:\temp\antixss.conf -u d:\temp\modsec_urls.txt d:\temp\test1.dat
WindowsLocalDebugger
$(TargetPath)
false