From 5303c003b4f68674ba2bd9f1a58a4de7ffa6d3f0 Mon Sep 17 00:00:00 2001 From: Breno Silva Date: Fri, 22 Mar 2013 18:52:42 -0400 Subject: [PATCH] Update master to 2.7.3 --- CHANGES | 36 + apache2/apache2_config.c | 180 ++- apache2/mod_security2.c | 4 + apache2/modsecurity.h | 9 + apache2/msc_lua.c | 17 + apache2/msc_multipart.c | 4 + apache2/msc_parsers.c | 12 +- apache2/msc_pcre.c | 8 + apache2/msc_release.h | 6 +- apache2/msc_xml.c | 11 + apache2/persist_dbm.c | 66 +- apache2/re.c | 4 +- apache2/re_variables.c | 38 + configure.ac | 18 +- iis/ModSecurityIIS/Installer/XUnzip.cpp | 2 + iis/ModSecurityIIS/ModSecurityIIS.sln | 3 - .../ModSecurityIIS/ModSecurityIIS.vdproj | 242 +-- iis/ModSecurityIIS/ModSecurityIIS/readme.rtf | 36 +- iis/mymodulefactory.h | 11 +- nginx/modsecurity/apr_bucket_nginx.c | 239 +++ nginx/modsecurity/apr_bucket_nginx.h | 18 + nginx/modsecurity/config | 10 +- nginx/modsecurity/ngx_http_modsecurity.c | 1395 ++++++++++++----- nginx/modsecurity/ngx_pool_context.c | 212 +++ nginx/modsecurity/ngx_pool_context.h | 12 + standalone/Makefile.am | 12 +- standalone/Makefile.in | 69 +- standalone/api.c | 1240 ++++++++------- standalone/api.h | 40 +- standalone/config.c | 9 +- standalone/main.cpp | 252 +-- standalone/standalone.vcxproj.user | 2 +- 32 files changed, 2887 insertions(+), 1330 deletions(-) create mode 100644 nginx/modsecurity/apr_bucket_nginx.c create mode 100644 nginx/modsecurity/apr_bucket_nginx.h create mode 100644 nginx/modsecurity/ngx_pool_context.c create mode 100644 nginx/modsecurity/ngx_pool_context.h 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