Merge branch 'v2/master' of https://github.com/marcstern/ModSecurity into v2/master

This commit is contained in:
Marc Stern 2024-05-16 16:51:48 +02:00
commit ca7b4b49bf
37 changed files with 3372 additions and 2170 deletions

6
.github/security2.conf vendored Normal file
View File

@ -0,0 +1,6 @@
LoadModule security2_module /usr/lib/apache2/modules/mod_security2.so
<IfModule security2_module>
SecDataDir /var/cache/modsecurity
Include /etc/apache2/modsecurity.conf
</IfModule>

View File

@ -10,22 +10,42 @@ jobs:
strategy:
matrix:
os: [ubuntu-22.04]
platform: [x64]
compiler: [gcc]
platform: [x32, x64]
compiler: [gcc, clang]
configure:
- {label: "with pcre2", opt: "--with-pcre2" }
- {label: "with lua", opt: "--with-lua" }
- {label: "wo lua", opt: "--without-lua" }
- {label: "with pcre, no study, no jit", opt: "--enable-pcre-study=no" }
- {label: "with pcre, with study, no jit", opt: "--enable-pcre-study=yes" }
- {label: "with pcre, no study, with jit", opt: "--enable-pcre-study=no --enable-pcre-jit" }
- {label: "with pcre, with study, with jit", opt: "--enable-pcre-study=yes --enable-pcre-jit" }
- {label: "with pcre2", opt: "--with-pcre2 --enable-pcre-study=no" }
- {label: "with pcre2, with study, no jit", opt: "--with-pcre2 --enable-pcre-study=yes" }
- {label: "with pcre2, no study, with jit", opt: "--with-pcre2 --enable-pcre-study=no --enable-pcre-jit" }
- {label: "with pcre2, with study, with jit", opt: "--with-pcre2 --enable-pcre-study=yes --enable-pcre-jit" }
- {label: "with lua", opt: "--with-lua" }
- {label: "wo lua", opt: "--without-lua" }
steps:
- name: Setup Dependencies
run: |
sudo apt-get update -y -qq
sudo apt-get install -y apache2-dev libxml2-dev liblua5.1-0-dev libcurl4-gnutls-dev libpcre2-dev pkg-config libyajl-dev
sudo apt-get install -y apache2-dev libxml2-dev liblua5.1-0-dev libcurl4-gnutls-dev libpcre2-dev pkg-config libyajl-dev apache2 apache2-bin apache2-data
- uses: actions/checkout@v2
- name: autogen.sh
run: ./autogen.sh
- name: configure ${{ matrix.configure.label }}
run: ./configure ${{ matrix.configure.opt }}
run: ./configure --enable-assertions ${{ matrix.configure.opt }}
- uses: ammaraskar/gcc-problem-matcher@master
- name: make
run: make -j `nproc`
- name: install module
run: sudo make install
- name: prepare config
run: |
sudo cp .github/security2.conf /etc/apache2/mods-enabled/
sudo cp modsecurity.conf-recommended /etc/apache2/modsecurity.conf
sudo cp unicode.mapping /etc/apache2/
sudo mkdir -p /var/cache/modsecurity
sudo chown -R www-data:www-data /var/cache/modsecurity
- name: start apache with module
run: |
sudo systemctl restart apache2.service

View File

@ -1,6 +1,8 @@
DD mmm YYYY - 2.9.x (to be released)
-------------------
* Fix possible segfault in collection_unpack
[Issue #3072 - @twouters]
* Set the minimum security protocol version for SecRemoteRules
[Issue security/code-scanning/2 - @airween]
* Allow lua version 5.4

View File

@ -30,6 +30,15 @@
APLOG_USE_MODULE(security2);
#endif
// Returns the rule id if existing, otherwise the file name & line number
const char* id_log(msre_rule* rule) {
assert(rule != NULL);
assert(rule->actionset != NULL);
const char* id = rule->actionset->id;
if (!id || !*id || id == NOT_SET_P) id = apr_psprintf(rule->ruleset->mp, "%s (%d)", rule->filename, rule->line_num);
return id;
}
/* -- Directory context creation and initialisation -- */
/**
@ -239,19 +248,19 @@ static void copy_rules_phase(apr_pool_t *mp,
if (copy > 0) {
#ifdef DEBUG_CONF
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_NOERRNO, 0, mp, "Copy rule %pp [id \"%s\"]", rule, rule->actionset->id);
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_NOERRNO, 0, mp, "Copy rule %pp [id \"%s\"]", rule, id_log(rule));
#endif
/* Copy the rule. */
*(msre_rule **)apr_array_push(child_phase_arr) = rule;
if (rule->actionset && rule->actionset->is_chained) mode = 2;
if (rule->actionset->is_chained) mode = 2;
} else {
if (rule->actionset && rule->actionset->is_chained) mode = 1;
if (rule->actionset->is_chained) mode = 1;
}
} else {
if (mode == 2) {
#ifdef DEBUG_CONF
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_NOERRNO, 0, mp, "Copy chain %pp for rule %pp [id \"%s\"]", rule, rule->chain_starter, rule->chain_starter->actionset->id);
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_NOERRNO, 0, mp, "Copy chain %pp for rule %pp [id \"%s\"]", rule, rule->chain_starter, id_log(rule->chain_starter));
#endif
/* Copy the rule (it belongs to the chain we want to include. */
@ -906,16 +915,14 @@ static const char *add_rule(cmd_parms *cmd, directory_config *dcfg, int type,
*/
rule->actionset = msre_actionset_merge(modsecurity->msre, cmd->pool, dcfg->tmp_default_actionset,
rule->actionset, 1);
if (rule->actionset == NULL) return apr_psprintf(cmd->pool, "ModSecurity: cannot merge actionset (memory full?).");
/* Keep track of the parent action for "block" */
if (rule->actionset) {
rule->actionset->parent_intercept_action_rec = dcfg->tmp_default_actionset->intercept_action_rec;
rule->actionset->parent_intercept_action = dcfg->tmp_default_actionset->intercept_action;
}
rule->actionset->parent_intercept_action_rec = dcfg->tmp_default_actionset->intercept_action_rec;
rule->actionset->parent_intercept_action = dcfg->tmp_default_actionset->intercept_action;
/* Must NOT specify a disruptive action in logging phase. */
if ((rule->actionset != NULL)
&& (rule->actionset->phase == PHASE_LOGGING)
if ( (rule->actionset->phase == PHASE_LOGGING)
&& (rule->actionset->intercept_action != ACTION_ALLOW)
&& (rule->actionset->intercept_action != ACTION_ALLOW_REQUEST)
&& (rule->actionset->intercept_action != ACTION_NONE)
@ -926,9 +933,7 @@ static const char *add_rule(cmd_parms *cmd, directory_config *dcfg, int type,
if (dcfg->tmp_chain_starter != NULL) {
rule->chain_starter = dcfg->tmp_chain_starter;
if (rule->actionset) {
rule->actionset->phase = rule->chain_starter->actionset->phase;
}
rule->actionset->phase = rule->chain_starter->actionset->phase;
}
if (rule->actionset->is_chained != 1) {
@ -967,8 +972,7 @@ static const char *add_rule(cmd_parms *cmd, directory_config *dcfg, int type,
#ifdef DEBUG_CONF
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_NOERRNO, 0, cmd->pool,
"Adding rule %pp phase=%d id=\"%s\".", rule, rule->actionset->phase, (rule->actionset->id == NOT_SET_P
? "(none)" : rule->actionset->id));
"Adding rule %pp phase=%d id=\"%s\".", rule, rule->actionset->phase, id_log(rule));
#endif
/* Add rule to the recipe. */
@ -1042,8 +1046,7 @@ static const char *add_marker(cmd_parms *cmd, directory_config *dcfg,
for (p = PHASE_FIRST; p <= PHASE_LAST; p++) {
#ifdef DEBUG_CONF
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_NOERRNO, 0, cmd->pool,
"Adding marker %pp phase=%d id=\"%s\".", rule, p, (rule->actionset->id == NOT_SET_P
? "(none)" : rule->actionset->id));
"Adding marker %pp phase=%d id=\"%s\".", rule, p, id_log(rule));
#endif
if (msre_ruleset_rule_add(dcfg->ruleset, rule, p) < 0) {
@ -1091,11 +1094,7 @@ static const char *update_rule_action(cmd_parms *cmd, directory_config *dcfg,
return NULL;
}
/* Check the rule actionset */
/* ENH: Can this happen? */
if (rule->actionset == NULL) {
return apr_psprintf(cmd->pool, "ModSecurity: Attempt to update action for rule \"%s\" failed: Rule does not have an actionset.", p1);
}
assert(rule->actionset != NULL);
/* Create a new actionset */
new_actionset = msre_actionset_create(modsecurity->msre, cmd->pool, p2, &my_error_msg);
@ -1117,9 +1116,7 @@ static const char *update_rule_action(cmd_parms *cmd, directory_config *dcfg,
char *actions = msre_actionset_generate_action_string(ruleset->mp, rule->actionset);
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_NOERRNO, 0, cmd->pool,
"Update rule %pp id=\"%s\" old action: \"%s\"",
rule,
(rule->actionset->id == NOT_SET_P ? "(none)" : rule->actionset->id),
actions);
rule, id_log(rule), actions);
}
#endif
@ -1127,6 +1124,7 @@ static const char *update_rule_action(cmd_parms *cmd, directory_config *dcfg,
/* ENH: Will this leak the old actionset? */
rule->actionset = msre_actionset_merge(modsecurity->msre, cmd->pool, rule->actionset,
new_actionset, 1);
if (rule->actionset == NULL) return apr_psprintf(cmd->pool, "ModSecurity: cannot merge actionset (memory full?).");
msre_actionset_set_defaults(rule->actionset);
/* Update the unparsed rule */
@ -1137,9 +1135,7 @@ static const char *update_rule_action(cmd_parms *cmd, directory_config *dcfg,
char *actions = msre_actionset_generate_action_string(ruleset->mp, rule->actionset);
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_NOERRNO, 0, cmd->pool,
"Update rule %pp id=\"%s\" new action: \"%s\"",
rule,
(rule->actionset->id == NOT_SET_P ? "(none)" : rule->actionset->id),
actions);
rule, id_log(rule), actions);
}
#endif
@ -1746,6 +1742,9 @@ char *parser_conn_limits_operator(apr_pool_t *mp, const char *p2,
config_orig_path = apr_pstrndup(mp, filename,
strlen(filename) - strlen(apr_filepath_name_get(filename)));
if (config_orig_path == NULL) {
return apr_psprintf(mp, "ModSecurity: failed to duplicate filename in parser_conn_limits_operator");
}
apr_filepath_merge(&file, config_orig_path, param, APR_FILEPATH_TRUENAME,
mp);
@ -2452,8 +2451,12 @@ static const char *cmd_rule_remove_by_id(cmd_parms *cmd, void *_dcfg,
const char *p1)
{
directory_config *dcfg = (directory_config *)_dcfg;
rule_exception *re = apr_pcalloc(cmd->pool, sizeof(rule_exception));
if (dcfg == NULL) return NULL;
rule_exception* re = apr_pcalloc(cmd->pool, sizeof(rule_exception));
if (re == NULL) {
ap_log_perror(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, cmd->pool, "cmd_rule_remove_by_id: Cannot allocate memory");
return NULL;
}
re->type = RULE_EXCEPTION_REMOVE_ID;
re->param = p1;

View File

@ -179,12 +179,13 @@ apr_status_t input_filter(ap_filter_t *f, apr_bucket_brigade *bb_out,
* Reads request body from a client.
*/
apr_status_t read_request_body(modsec_rec *msr, char **error_msg) {
assert(msr != NULL);
assert(error_msg!= NULL);
request_rec *r = msr->r;
unsigned int finished_reading;
apr_bucket_brigade *bb_in;
apr_bucket *bucket;
if (error_msg == NULL) return -1;
*error_msg = NULL;
if (msr->reqbody_should_exist != 1) {
@ -368,6 +369,8 @@ apr_status_t read_request_body(modsec_rec *msr, char **error_msg) {
* run or not.
*/
static int output_filter_should_run(modsec_rec *msr, request_rec *r) {
assert(msr != NULL);
assert(r != NULL);
char *content_type = NULL;
/* Check configuration. */
@ -429,10 +432,13 @@ static int output_filter_should_run(modsec_rec *msr, request_rec *r) {
static apr_status_t output_filter_init(modsec_rec *msr, ap_filter_t *f,
apr_bucket_brigade *bb_in)
{
assert(msr != NULL);
assert(f != NULL);
request_rec *r = f->r;
const char *s_content_length = NULL;
apr_status_t rc;
assert(msr != NULL);
msr->of_brigade = apr_brigade_create(msr->mp, f->c->bucket_alloc);
if (msr->of_brigade == NULL) {
msr_log(msr, 1, "Output filter: Failed to create brigade.");
@ -496,6 +502,8 @@ static apr_status_t output_filter_init(modsec_rec *msr, ap_filter_t *f,
* and to the client.
*/
static apr_status_t send_of_brigade(modsec_rec *msr, ap_filter_t *f) {
assert(msr != NULL);
assert(f != NULL);
apr_status_t rc;
rc = ap_pass_brigade(f->next, msr->of_brigade);
@ -537,6 +545,8 @@ static apr_status_t send_of_brigade(modsec_rec *msr, ap_filter_t *f) {
*
*/
static void inject_content_to_of_brigade(modsec_rec *msr, ap_filter_t *f) {
assert(msr != NULL);
assert(f != NULL);
apr_bucket *b;
if (msr->txcfg->content_injection_enabled && msr->stream_output_data != NULL) {
@ -563,6 +573,8 @@ static void inject_content_to_of_brigade(modsec_rec *msr, ap_filter_t *f) {
*
*/
static void prepend_content_to_of_brigade(modsec_rec *msr, ap_filter_t *f) {
assert(msr != NULL);
assert(f != NULL);
if ((msr->txcfg->content_injection_enabled) && (msr->content_prepend) && (!msr->of_skipping)) {
apr_bucket *bucket_ci = NULL;
@ -1008,6 +1020,12 @@ apr_status_t output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
/* Now send data down the filter stream
* (full-buffering only).
*/
if (!eos_bucket) {
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, f->r->server,
"ModSecurity: Internal Error: eos_bucket is NULL.");
return APR_EGENERAL;
}
if ((msr->of_skipping == 0)&&(!msr->of_partial)) {
if(msr->of_stream_changed == 1) {
inject_content_to_of_brigade(msr,f);

View File

@ -25,6 +25,8 @@
* Sends a brigade with an error bucket down the filter chain.
*/
apr_status_t send_error_bucket(modsec_rec *msr, ap_filter_t *f, int status) {
assert(msr != NULL);
assert(f != NULL);
apr_bucket_brigade *brigade = NULL;
apr_bucket *bucket = NULL;
@ -61,6 +63,9 @@ apr_status_t send_error_bucket(modsec_rec *msr, ap_filter_t *f, int status) {
* the "output" parameter.
*/
int apache2_exec(modsec_rec *msr, const char *command, const char **argv, char **output) {
assert(msr != NULL);
assert(command != NULL);
apr_procattr_t *procattr = NULL;
apr_proc_t *procnew = NULL;
apr_status_t rc = APR_SUCCESS;
@ -204,6 +209,9 @@ char *get_env_var(request_rec *r, char *name) {
static void internal_log_ex(request_rec *r, directory_config *dcfg, modsec_rec *msr,
int level, int fixup, const char *text, va_list ap)
{
assert(r != NULL);
assert(msr != NULL);
assert(text != NULL);
apr_size_t nbytes, nbytes_written;
apr_file_t *debuglog_fd = NULL;
int filter_debug_level = 0;
@ -303,6 +311,8 @@ static void internal_log_ex(request_rec *r, directory_config *dcfg, modsec_rec *
* Apache error log if the message is important enough.
*/
void msr_log(modsec_rec *msr, int level, const char *text, ...) {
assert(msr != NULL);
assert(text != NULL);
va_list ap;
va_start(ap, text);
@ -316,6 +326,8 @@ void msr_log(modsec_rec *msr, int level, const char *text, ...) {
* Apache error log. This is intended for error callbacks.
*/
void msr_log_error(modsec_rec *msr, const char *text, ...) {
assert(msr != NULL);
assert(text != NULL);
va_list ap;
va_start(ap, text);
@ -330,6 +342,8 @@ void msr_log_error(modsec_rec *msr, const char *text, ...) {
* The 'text' will first be escaped.
*/
void msr_log_warn(modsec_rec *msr, const char *text, ...) {
assert(msr != NULL);
assert(text != NULL);
va_list ap;
va_start(ap, text);

View File

@ -475,6 +475,8 @@ static modsec_rec *retrieve_tx_context(request_rec *r) {
* phases, redirections, or subrequests.
*/
static void store_tx_context(modsec_rec *msr, request_rec *r) {
assert(msr != NULL);
assert(r != NULL);
apr_table_setn(r->notes, NOTE_MSR, (void *)msr);
}
@ -491,7 +493,10 @@ static modsec_rec *create_tx_context(request_rec *r) {
apr_allocator_create(&allocator);
apr_allocator_max_free_set(allocator, 1024);
apr_pool_create_ex(&msr->mp, r->pool, NULL, allocator);
if (msr->mp == NULL) return NULL;
if (msr->mp == NULL) {
apr_allocator_destroy(allocator);
return NULL;
}
apr_allocator_owner_set(allocator, msr->mp);
msr->modsecurity = modsecurity;
@ -863,6 +868,9 @@ static int hook_request_early(request_rec *r) {
*/
msr = create_tx_context(r);
if (msr == NULL) return DECLINED;
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "Context created after request failure.");
}
#ifdef REQUEST_EARLY
@ -1150,17 +1158,12 @@ static void hook_error_log(const char *file, int line, int level, apr_status_t s
#endif
if (msr_ap_server) {
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
msr = create_tx_context((request_rec *)info->r);
msr = create_tx_context((request_rec*)info->r);
#else
msr = create_tx_context((request_rec *)r);
msr = create_tx_context((request_rec*)r);
#endif
if (msr != NULL && msr->txcfg->debuglog_level >= 9) {
if (msr == NULL) {
msr_log(msr, 9, "Failed to create context after request failure.");
}
else {
msr_log(msr, 9, "Context created after request failure.");
}
if (msr && msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "Context created after request failure.");
}
}
if (msr == NULL) return;

View File

@ -41,6 +41,8 @@ int DSOLOCAL *unicode_map_table = NULL;
const char * msc_alert_message(modsec_rec *msr, msre_actionset *actionset, const char *action_message,
const char *rule_message)
{
assert(msr != NULL);
assert(actionset != NULL);
const char *message = NULL;
if (rule_message == NULL) rule_message = "Unknown error.";
@ -63,6 +65,8 @@ const char * msc_alert_message(modsec_rec *msr, msre_actionset *actionset, const
void msc_alert(modsec_rec *msr, int level, msre_actionset *actionset, const char *action_message,
const char *rule_message)
{
assert(msr != NULL);
assert(actionset != NULL);
const char *message = msc_alert_message(msr, actionset, action_message, rule_message);
msr_log(msr, level, "%s", message);
@ -126,6 +130,11 @@ msc_engine *modsecurity_create(apr_pool_t *mp, int processing_mode) {
int modsecurity_init(msc_engine *msce, apr_pool_t *mp) {
apr_status_t rc;
msce->auditlog_lock = msce->geo_lock = NULL;
#ifdef GLOBAL_COLLECTION_LOCK
msce->geo_lock = NULL;
#endif
/**
* Notice that curl is initialized here but never cleaned up. First version
* of this implementation curl was initialized and cleaned for every
@ -547,6 +556,7 @@ apr_status_t modsecurity_tx_init(modsec_rec *msr) {
*
*/
static int is_response_status_relevant(modsec_rec *msr, int status) {
assert(msr != NULL);
char *my_error_msg = NULL;
apr_status_t rc;
char buf[32];
@ -780,6 +790,7 @@ static apr_status_t modsecurity_process_phase_logging(modsec_rec *msr) {
* in the modsec_rec structure.
*/
apr_status_t modsecurity_process_phase(modsec_rec *msr, unsigned int phase) {
assert(msr != NULL);
/* Check if we should run. */
if ((msr->was_intercepted)&&(phase != PHASE_LOGGING)) {
if (msr->txcfg->debuglog_level >= 4) {

View File

@ -32,14 +32,12 @@
* \retval NULL on fail
*/
char *normalize_path(modsec_rec *msr, char *input) {
assert(msr != NULL);
assert(input != NULL);
xmlURI *uri = NULL;
char *parsed_content = NULL;
char *content = NULL;
if(msr == NULL) return NULL;
if(input == NULL) return NULL;
uri = xmlParseURI(input);
if(uri != NULL && uri->path) {
@ -195,6 +193,8 @@ char *mschmac(modsec_rec *msr, const char *key, int key_len,
char *hmac(modsec_rec *msr, const char *key, int key_len,
unsigned char *msg, int msglen) {
#endif
assert(msr != NULL);
assert(msg != NULL);
apr_sha1_ctx_t ctx;
unsigned char digest[APR_SHA1_DIGESTSIZE];
unsigned char hmac_ipad[HMAC_PAD_SIZE], hmac_opad[HMAC_PAD_SIZE];
@ -346,6 +346,8 @@ int init_response_body_html_parser(modsec_rec *msr) {
* \retval -1 on fail
*/
int do_hash_method(modsec_rec *msr, char *link, int type) {
assert(msr != NULL);
assert(link != NULL);
hash_method **em = NULL;
int i = 0;
char *error_msg = NULL;
@ -1051,6 +1053,7 @@ ctx_error:
* \retval -1 On fail
*/
int inject_hashed_response_body(modsec_rec *msr, int elts) {
assert(msr != NULL);
xmlOutputBufferPtr output_buf = NULL;
xmlCharEncodingHandlerPtr handler = NULL;
char *p = NULL;
@ -1290,13 +1293,13 @@ int inject_hashed_response_body(modsec_rec *msr, int elts) {
* \retval NULL on fail
*/
char *do_hash_link(modsec_rec *msr, char *link, int type) {
assert(msr != NULL);
assert(link != NULL);
char *mac_link = NULL;
char *path_chunk = NULL;
char *hash_value = NULL;
char *qm = NULL;
if(msr == NULL) return NULL;
if(strlen(link) > 7 && strncmp("http:",(char*)link,5)==0){
path_chunk = strchr(link+7,'/');
if(path_chunk != NULL) {

View File

@ -263,6 +263,10 @@ int geo_init(directory_config *dcfg, const char *dbfn, char **error_msg)
*/
int geo_lookup(modsec_rec *msr, geo_rec *georec, const char *target, char **error_msg)
{
assert(msr != NULL);
assert(georec != NULL);
assert(target != NULL);
assert(error_msg != NULL);
apr_sockaddr_t *addr;
long ipnum = 0;
char *targetip = NULL;

View File

@ -20,6 +20,7 @@ const char *base_offset=NULL;
int json_add_argument(modsec_rec *msr, const char *value, unsigned length)
{
assert(msr != NULL);
msc_arg *arg = (msc_arg *) NULL;
/**
@ -86,6 +87,7 @@ int json_add_argument(modsec_rec *msr, const char *value, unsigned length)
static int yajl_map_key(void *ctx, const unsigned char *key, size_t length)
{
modsec_rec *msr = (modsec_rec *) ctx;
assert(msr != NULL);
unsigned char *safe_key = (unsigned char *) NULL;
/**
@ -117,6 +119,7 @@ static int yajl_map_key(void *ctx, const unsigned char *key, size_t length)
static int yajl_null(void *ctx)
{
modsec_rec *msr = (modsec_rec *) ctx;
assert(msr != NULL);
return json_add_argument(msr, "", 0);
}
@ -127,6 +130,7 @@ static int yajl_null(void *ctx)
static int yajl_boolean(void *ctx, int value)
{
modsec_rec *msr = (modsec_rec *) ctx;
assert(msr != NULL);
if (value) {
return json_add_argument(msr, "true", strlen("true"));
@ -142,6 +146,7 @@ static int yajl_boolean(void *ctx, int value)
static int yajl_string(void *ctx, const unsigned char *value, size_t length)
{
modsec_rec *msr = (modsec_rec *) ctx;
assert(msr != NULL);
return json_add_argument(msr, value, length);
}
@ -154,12 +159,14 @@ static int yajl_string(void *ctx, const unsigned char *value, size_t length)
static int yajl_number(void *ctx, const char *value, size_t length)
{
modsec_rec *msr = (modsec_rec *) ctx;
assert(msr != NULL);
return json_add_argument(msr, value, length);
}
static int yajl_start_array(void *ctx) {
modsec_rec *msr = (modsec_rec *) ctx;
assert(msr != NULL);
if (!msr->json->current_key && !msr->json->prefix) {
msr->json->prefix = apr_pstrdup(msr->mp, "array");
@ -189,6 +196,7 @@ static int yajl_start_array(void *ctx) {
static int yajl_end_array(void *ctx) {
modsec_rec *msr = (modsec_rec *) ctx;
assert(msr != NULL);
unsigned char *separator = (unsigned char *) NULL;
/**
@ -225,6 +233,7 @@ static int yajl_end_array(void *ctx) {
static int yajl_start_map(void *ctx)
{
modsec_rec *msr = (modsec_rec *) ctx;
assert(msr != NULL);
/**
* If we do not have a current_key, this is a top-level hash, so we do not
@ -263,6 +272,7 @@ static int yajl_start_map(void *ctx)
static int yajl_end_map(void *ctx)
{
modsec_rec *msr = (modsec_rec *) ctx;
assert(msr != NULL);
unsigned char *separator = (unsigned char *) NULL;
/**
@ -298,6 +308,8 @@ static int yajl_end_map(void *ctx)
* Initialise JSON parser.
*/
int json_init(modsec_rec *msr, char **error_msg) {
assert(msr != NULL);
assert(error_msg != NULL);
/**
* yajl configuration and callbacks
*/
@ -315,7 +327,6 @@ int json_init(modsec_rec *msr, char **error_msg) {
yajl_end_array
};
if (error_msg == NULL) return -1;
*error_msg = NULL;
msr_log(msr, 4, "JSON parser initialization");
@ -352,7 +363,8 @@ int json_init(modsec_rec *msr, char **error_msg) {
* Feed one chunk of data to the JSON parser.
*/
int json_process_chunk(modsec_rec *msr, const char *buf, unsigned int size, char **error_msg) {
if (error_msg == NULL) return -1;
assert(msr != NULL);
assert(error_msg != NULL);
*error_msg = NULL;
base_offset=buf;
@ -376,9 +388,10 @@ int json_process_chunk(modsec_rec *msr, const char *buf, unsigned int size, char
* Finalise JSON parsing.
*/
int json_complete(modsec_rec *msr, char **error_msg) {
assert(msr != NULL);
assert(error_msg != NULL);
char *json_data = (char *) NULL;
if (error_msg == NULL) return -1;
*error_msg = NULL;
/* Wrap up the parsing process */

View File

@ -35,6 +35,7 @@
* the size counters, update the hash context.
*/
static int sec_auditlog_write(modsec_rec *msr, const char *data, unsigned int len) {
assert(msr != NULL);
apr_size_t nbytes_written, nbytes = len;
apr_status_t rc;
@ -86,6 +87,8 @@ static int sec_auditlog_write(modsec_rec *msr, const char *data, unsigned int le
* some of the fields to make the log line shorter than _limit bytes.
*/
char *construct_log_vcombinedus_limited(modsec_rec *msr, int _limit, int *was_limited) {
assert(msr != NULL);
assert(was_limited != NULL);
char *hostname;
char *local_user, *remote_user;
char *referer, *user_agent, *uniqueid;
@ -405,6 +408,7 @@ static void sec_auditlog_write_producer_header(modsec_rec *msr) {
* Ouput the Producer header into a JSON generator
*/
static void sec_auditlog_write_producer_header_json(modsec_rec *msr, yajl_gen g) {
assert(msr != NULL);
char **signatures = NULL;
int i;
@ -520,6 +524,7 @@ static msre_rule *return_chained_rule(const msre_rule *current, modsec_rec *msr)
* \retval 1 On Success
*/
static int chained_is_matched(modsec_rec *msr, const msre_rule *next_rule) {
assert(msr != NULL);
int i = 0;
const msre_rule *rule = NULL;
@ -538,6 +543,7 @@ static int chained_is_matched(modsec_rec *msr, const msre_rule *next_rule) {
* Write detailed information about performance metrics into a JSON generator
*/
static void format_performance_variables_json(modsec_rec *msr, yajl_gen g) {
assert(msr != NULL);
yajl_string(g, "stopwatch");
yajl_gen_map_open(g);
@ -558,6 +564,8 @@ static void format_performance_variables_json(modsec_rec *msr, yajl_gen g) {
* Write detailed information about a rule and its actionset into a JSON generator
*/
static void write_rule_json(modsec_rec *msr, const msre_rule *rule, yajl_gen g) {
assert(msr != NULL);
assert(rule != NULL);
const apr_array_header_t *tarr;
const apr_table_entry_t *telts;
int been_opened = 0;
@ -748,10 +756,13 @@ void sec_audit_logger_json(modsec_rec *msr) {
/* Lock the mutex, but only if we are using serial format. */
if (msr->txcfg->auditlog_type != AUDITLOG_CONCURRENT) {
rc = apr_global_mutex_lock(msr->modsecurity->auditlog_lock);
if (rc != APR_SUCCESS) {
msr_log(msr, 1, "Audit log: Failed to lock global mutex: %s",
get_apr_error(msr->mp, rc));
if (!msr->modsecurity->auditlog_lock) msr_log(msr, 1, "Audit log: Global mutex was not created");
else {
rc = apr_global_mutex_lock(msr->modsecurity->auditlog_lock);
if (rc != APR_SUCCESS) {
msr_log(msr, 1, "Audit log: Failed to lock global mutex: %s",
get_apr_error(msr->mp, rc));
}
}
}

View File

@ -154,6 +154,8 @@ static int l_log(lua_State *L) {
*
*/
static apr_array_header_t *resolve_tfns(lua_State *L, int idx, modsec_rec *msr, apr_pool_t *mp) {
assert(msr != NULL);
assert(mp != NULL);
apr_array_header_t *tfn_arr = NULL;
msre_tfn_metadata *tfn = NULL;
char *name = NULL;
@ -406,11 +408,13 @@ static const struct luaL_Reg mylib[] = {
*
*/
int lua_execute(msc_script *script, char *param, modsec_rec *msr, msre_rule *rule, char **error_msg) {
assert(script != NULL);
assert(msr != NULL);
assert(error_msg != NULL);
apr_time_t time_before;
lua_State *L = NULL;
int rc = 0;
if (error_msg == NULL) return -1;
*error_msg = NULL;
if (msr->txcfg->debuglog_level >= 8) {

View File

@ -21,11 +21,9 @@
#include "msc_parsers.h"
void validate_quotes(modsec_rec *msr, char *data, char quote) {
assert(msr != NULL);
int i, len;
if(msr == NULL)
return;
if(msr->mpd == NULL)
return;
@ -84,6 +82,8 @@ static char *multipart_construct_filename(modsec_rec *msr) {
*
*/
static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value) {
assert(msr != NULL);
assert(c_d_value != NULL);
char *p = NULL, *t = NULL;
/* accept only what we understand */
@ -255,9 +255,10 @@ static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value)
*
*/
static int multipart_process_part_header(modsec_rec *msr, char **error_msg) {
assert(msr != NULL);
assert(error_msg != NULL);
int i, len, rc;
if (error_msg == NULL) return -1;
*error_msg = NULL;
/* Check for nul bytes. */
@ -454,11 +455,12 @@ static int multipart_process_part_header(modsec_rec *msr, char **error_msg) {
*
*/
static int multipart_process_part_data(modsec_rec *msr, char **error_msg) {
assert(msr != NULL);
assert(error_msg != NULL);
char *p = msr->mpd->buf + (MULTIPART_BUF_SIZE - msr->mpd->bufleft);
char localreserve[2] = { '\0', '\0' }; /* initialized to quiet warning */
int bytes_reserved = 0;
if (error_msg == NULL) return -1;
*error_msg = NULL;
msr->mpd->mpp_substate_part_data_read = 1;
@ -628,6 +630,8 @@ static int multipart_process_part_data(modsec_rec *msr, char **error_msg) {
*
*/
static char *multipart_combine_value_parts(modsec_rec *msr, apr_array_header_t *value_parts) {
assert(msr != NULL);
assert(value_parts != NULL);
value_part_t **parts = NULL;
char *rval = apr_palloc(msr->mp, msr->mpd->mpp->length + 1);
unsigned long int offset;
@ -652,6 +656,7 @@ static char *multipart_combine_value_parts(modsec_rec *msr, apr_array_header_t *
*
*/
static int multipart_process_boundary(modsec_rec *msr, int last_part, char **error_log) {
assert(msr != NULL);
/* if there was a part being built finish it */
if (msr->mpd->mpp != NULL) {
/* close the temp file */
@ -788,7 +793,8 @@ static int multipart_count_boundary_params(apr_pool_t *mp, const char *header_va
*
*/
int multipart_init(modsec_rec *msr, char **error_msg) {
if (error_msg == NULL) return -1;
assert(msr != NULL);
assert(error_msg != NULL);
*error_msg = NULL;
msr->mpd = (multipart_data *)apr_pcalloc(msr->mp, sizeof(multipart_data));
@ -952,6 +958,8 @@ int multipart_init(modsec_rec *msr, char **error_msg) {
* is clear that there is no more data to be processed.
*/
int multipart_complete(modsec_rec *msr, char **error_msg) {
assert(msr != NULL);
assert(error_msg != NULL);
if (msr->mpd == NULL) return 1;
if (msr->txcfg->debuglog_level >= 4) {
@ -1055,10 +1063,12 @@ int multipart_complete(modsec_rec *msr, char **error_msg) {
int multipart_process_chunk(modsec_rec *msr, const char *buf,
unsigned int size, char **error_msg)
{
assert(msr != NULL);
assert(buf != NULL);
assert(error_msg != NULL);
char *inptr = (char *)buf;
unsigned int inleft = size;
if (error_msg == NULL) return -1;
*error_msg = NULL;
if (size == 0) return 1;
@ -1433,6 +1443,7 @@ apr_status_t multipart_cleanup(modsec_rec *msr) {
*
*/
int multipart_get_arguments(modsec_rec *msr, char *origin, apr_table_t *arguments) {
assert(msr != NULL);
multipart_part **parts;
int i;

View File

@ -21,6 +21,9 @@
int parse_cookies_v0(modsec_rec *msr, char *_cookie_header,
apr_table_t *cookies, const char *delim)
{
assert(msr != NULL);
assert(cookies != NULL);
assert(delim != NULL);
char *attr_name = NULL, *attr_value = NULL;
char *cookie_header;
char *saveptr = NULL;
@ -95,6 +98,8 @@ int parse_cookies_v0(modsec_rec *msr, char *_cookie_header,
int parse_cookies_v1(modsec_rec *msr, char *_cookie_header,
apr_table_t *cookies)
{
assert(msr != NULL);
assert(cookies != NULL);
char *attr_name = NULL, *attr_value = NULL, *p = NULL;
char *prev_attr_name = NULL;
char *cookie_header = NULL;
@ -239,6 +244,7 @@ int parse_arguments(modsec_rec *msr, const char *s, apr_size_t inputlength,
int argument_separator, const char *origin,
apr_table_t *arguments, int *invalid_count)
{
assert(msr != NULL);
msc_arg *arg;
apr_size_t i, j;
char *value = NULL;
@ -340,6 +346,9 @@ int parse_arguments(modsec_rec *msr, const char *s, apr_size_t inputlength,
*/
void add_argument(modsec_rec *msr, apr_table_t *arguments, msc_arg *arg)
{
assert(msr != NULL);
assert(arguments != NULL);
assert(arg != NULL);
if (msr->txcfg->debuglog_level >= 5) {
msr_log(msr, 5, "Adding request argument (%s): name \"%s\", value \"%s\"",
arg->origin, log_escape_ex(msr->mp, arg->name, arg->name_len),

View File

@ -41,6 +41,8 @@ void msre_engine_reqbody_processor_register(msre_engine *engine,
* Prepare to accept the request body (part 2).
*/
static apr_status_t modsecurity_request_body_start_init(modsec_rec *msr, char **error_msg) {
assert(msr != NULL);
assert(error_msg != NULL);
*error_msg = NULL;
if(msr->msc_reqbody_storage == MSC_REQBODY_MEMORY) {
@ -80,6 +82,8 @@ static apr_status_t modsecurity_request_body_start_init(modsec_rec *msr, char **
* Prepare to accept the request body (part 1).
*/
apr_status_t modsecurity_request_body_start(modsec_rec *msr, char **error_msg) {
assert(msr != NULL);
assert(error_msg != NULL);
*error_msg = NULL;
msr->msc_reqbody_length = 0;
msr->stream_input_length = 0;
@ -161,6 +165,8 @@ apr_status_t modsecurity_request_body_start(modsec_rec *msr, char **error_msg) {
static apr_status_t modsecurity_request_body_store_disk(modsec_rec *msr,
const char *data, apr_size_t length, char **error_msg)
{
assert(msr != NULL);
assert(error_msg != NULL);
apr_size_t i;
*error_msg = NULL;
@ -181,6 +187,8 @@ static apr_status_t modsecurity_request_body_store_disk(modsec_rec *msr,
static apr_status_t modsecurity_request_body_store_memory(modsec_rec *msr,
const char *data, apr_size_t length, char **error_msg)
{
assert(msr != NULL);
assert(error_msg != NULL);
*error_msg = NULL;
/* Would storing this chunk mean going over the limit? */
@ -309,6 +317,8 @@ static apr_status_t modsecurity_request_body_store_memory(modsec_rec *msr,
apr_status_t modsecurity_request_body_store(modsec_rec *msr,
const char *data, apr_size_t length, char **error_msg)
{
assert(msr != NULL);
assert(error_msg != NULL);
*error_msg = NULL;
/* If we have a processor for this request body send
@ -428,6 +438,8 @@ apr_status_t modsecurity_request_body_store(modsec_rec *msr,
}
apr_status_t modsecurity_request_body_to_stream(modsec_rec *msr, const char *buffer, int buflen, char **error_msg) {
assert(msr != NULL);
assert(error_msg != NULL);
#ifndef MSC_LARGE_STREAM_INPUT
char *stream_input_body = NULL;
char *data = NULL;
@ -541,6 +553,8 @@ apr_status_t modsecurity_request_body_to_stream(modsec_rec *msr, const char *buf
* Replace a bunch of chunks holding a request body with a single large chunk.
*/
static apr_status_t modsecurity_request_body_end_raw(modsec_rec *msr, char **error_msg) {
assert(msr != NULL);
assert(error_msg != NULL);
msc_data_chunk **chunks, *one_chunk;
char *d;
int i, sofar;
@ -614,6 +628,8 @@ static apr_status_t modsecurity_request_body_end_raw(modsec_rec *msr, char **err
*
*/
static apr_status_t modsecurity_request_body_end_urlencoded(modsec_rec *msr, char **error_msg) {
assert(msr != NULL);
assert(error_msg != NULL);
int invalid_count = 0;
*error_msg = NULL;
@ -643,6 +659,8 @@ static apr_status_t modsecurity_request_body_end_urlencoded(modsec_rec *msr, cha
* Stops receiving the request body.
*/
apr_status_t modsecurity_request_body_end(modsec_rec *msr, char **error_msg) {
assert(msr != NULL);
assert(error_msg != NULL);
*error_msg = NULL;
/* Close open file descriptors, if any. */
@ -753,6 +771,8 @@ apr_status_t modsecurity_request_body_end(modsec_rec *msr, char **error_msg) {
* Prepares to forward the request body.
*/
apr_status_t modsecurity_request_body_retrieve_start(modsec_rec *msr, char **error_msg) {
assert(msr != NULL);
assert(error_msg != NULL);
*error_msg = NULL;
if (msr->msc_reqbody_storage == MSC_REQBODY_MEMORY) {
@ -821,6 +841,8 @@ apr_status_t modsecurity_request_body_retrieve_end(modsec_rec *msr) {
apr_status_t modsecurity_request_body_retrieve(modsec_rec *msr,
msc_data_chunk **chunk, long int nbytes, char **error_msg)
{
assert(msr != NULL);
assert(error_msg != NULL);
msc_data_chunk **chunks;
*error_msg = NULL;
@ -922,6 +944,8 @@ apr_status_t modsecurity_request_body_retrieve(modsec_rec *msr,
*
*/
apr_status_t modsecurity_request_body_clear(modsec_rec *msr, char **error_msg) {
assert(msr != NULL);
assert(error_msg != NULL);
*error_msg = NULL;
/* Release memory we used to store request body data. */

View File

@ -535,6 +535,8 @@ int TreeCheckData(TreePrefix *prefix, CPTData *prefix_data, unsigned int netmask
}
int TreePrefixNetmask(modsec_rec *msr, TreePrefix *prefix, unsigned int netmask, int flag) {
// msr can be NULL;
assert(!msr || msr->txcfg != NULL);
CPTData *prefix_data = NULL;
int ret = 0;
@ -574,6 +576,8 @@ int TreePrefixNetmask(modsec_rec *msr, TreePrefix *prefix, unsigned int netmask,
}
TreeNode *CPTRetriveNode(modsec_rec *msr, unsigned char *buffer, unsigned int ip_bitmask, TreeNode *node) {
// msr can be NULL;
assert(!msr || msr->txcfg != NULL);
unsigned int x, y;
if(node == NULL) {
@ -620,6 +624,8 @@ TreeNode *CPTRetriveParentNode(TreeNode *node) {
}
TreeNode *CPTFindElementIPNetblock(modsec_rec *msr, unsigned char *ipdata, unsigned char ip_bitmask, TreeNode *node) {
// msr can be NULL;
assert(!msr || msr->txcfg != NULL);
TreeNode *netmask_node = NULL;
int mask = 0, bytes = 0;
int i = 0, j = 0;
@ -656,15 +662,22 @@ TreeNode *CPTFindElementIPNetblock(modsec_rec *msr, unsigned char *ipdata, unsig
}
node = CPTRetriveNode(msr, ipdata, ip_bitmask, node);
if (!node) {
if (msr && msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "CPTFindElementIPNetblock: No tree node found.");
}
return NULL;
}
if (node && node->bit != ip_bitmask) {
if (node->bit != ip_bitmask) {
if (msr && msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "CPTFindElementIPNetblock: Found a tree node but netmask is different.");
}
return NULL;
}
if (node && node->prefix == NULL) {
if (node->prefix == NULL) {
if (msr && msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "CPTFindElementIPNetblock: Found a tree node but prefix is NULL.");
}
@ -700,6 +713,8 @@ TreeNode *CPTFindElementIPNetblock(modsec_rec *msr, unsigned char *ipdata, unsig
}
TreeNode *CPTFindElement(modsec_rec *msr, unsigned char *ipdata, unsigned int ip_bitmask, CPTTree *tree) {
// msr can be NULL;
assert(!msr || msr->txcfg != NULL);
TreeNode *node = NULL;
int mask = 0, bytes = 0;
unsigned char temp_data[NETMASK_256-1];
@ -781,6 +796,8 @@ TreeNode *CPTFindElement(modsec_rec *msr, unsigned char *ipdata, unsigned int ip
}
TreeNode *CPTIpMatch(modsec_rec *msr, unsigned char *ipdata, CPTTree *tree, int type) {
// msr can be NULL;
assert(!msr || msr->txcfg != NULL);
if(tree == NULL) {
if (msr && msr->txcfg->debuglog_level >= 9) {
@ -839,6 +856,7 @@ TreeNode *TreeAddIP(const char *buffer, CPTTree *tree, int type) {
*(ip_strv4 + (sizeof(ip_strv4) - 1)) = '\0';
ptr = strdup(ip_strv4);
if (ptr == NULL) return NULL; // No way to return a clean error message
netmask_v4 = is_netmask_v4(ptr);
if (netmask_v4 > NETMASK_32) {
@ -875,6 +893,7 @@ TreeNode *TreeAddIP(const char *buffer, CPTTree *tree, int type) {
*(ip_strv6 + sizeof(ip_strv6) - 1) = '\0';
ptr = strdup(ip_strv6);
if (ptr == NULL) return NULL; // No way to return a clean error message
netmask_v6 = is_netmask_v6(ptr);
if (netmask_v6 > NETMASK_128) {
@ -911,4 +930,3 @@ TreeNode *TreeAddIP(const char *buffer, CPTTree *tree, int type) {
return NULL;
}

View File

@ -667,6 +667,7 @@ int convert_to_int(const char c)
* \retval 0 On Sucess|Fail
*/
int set_match_to_tx(modsec_rec *msr, int capture, const char *match, int tx_n) {
assert(msr != NULL);
if (capture) {
msc_string *s = (msc_string *)apr_pcalloc(msr->mp, sizeof(msc_string));
@ -2378,6 +2379,7 @@ apr_fileperms_t mode2fileperms(int mode) {
* Generate a single variable.
*/
char *construct_single_var(modsec_rec *msr, char *name) {
assert(msr != NULL);
char *varname = NULL;
char *param = NULL;
msre_var *var = NULL;
@ -2386,6 +2388,7 @@ char *construct_single_var(modsec_rec *msr, char *name) {
/* Extract variable name and its parameter from the script. */
varname = apr_pstrdup(msr->mp, name);
if (varname == NULL) return NULL;
param = strchr(varname, '.');
if (param != NULL) {
*param = '\0';
@ -2703,6 +2706,10 @@ int ip_tree_from_uri(TreeRoot **rtree, char *uri,
int tree_contains_ip(apr_pool_t *mp, TreeRoot *rtree,
const char *value, modsec_rec *msr, char **error_msg)
{
assert(mp != NULL);
assert(value != NULL);
// msr can be NULL;
assert(error_msg != NULL);
struct in_addr in;
#if APR_HAVE_IPV6
struct in6_addr in6;
@ -2843,3 +2850,14 @@ char* strtok_r(
}
#endif
// we cannot log an error message as this happens much too often
char* get_username(apr_pool_t* mp) {
char* username;
apr_uid_t uid;
apr_gid_t gid;
int rc = apr_uid_current(&uid, &gid, mp);
if (rc != APR_SUCCESS) return "apache";
rc = apr_uid_name_get(&username, uid, mp);
if (rc != APR_SUCCESS) return "apache";
return username;
}

View File

@ -15,6 +15,7 @@
#ifndef _UTIL_H_
#define _UTIL_H_
#include <assert.h>
#include <sys/types.h>
#include <apr_file_info.h>
@ -164,6 +165,9 @@ int ip_tree_from_uri(TreeRoot **rtree, char *uri,
apr_pool_t *mp, char **error_msg);
#endif
char DSOLOCAL *get_username(apr_pool_t* mp);
const char* id_log(msre_rule* rule);
int read_line(char *buff, int size, FILE *fp);
size_t msc_curl_write_memory_cb(void *contents, size_t size,

View File

@ -24,9 +24,10 @@ xml_unload_external_entity(const char *URI, xmlCharEncoding enc) {
* Initialise XML parser.
*/
int xml_init(modsec_rec *msr, char **error_msg) {
assert(msr != NULL);
assert(error_msg != NULL);
xmlParserInputBufferCreateFilenameFunc entity;
if (error_msg == NULL) return -1;
*error_msg = NULL;
msr->xml = apr_pcalloc(msr->mp, sizeof(xml_data));
@ -59,7 +60,8 @@ static void xml_receive_sax_error(void *data, const char *msg, ...) {
* Feed one chunk of data to the XML parser.
*/
int xml_process_chunk(modsec_rec *msr, const char *buf, unsigned int size, char **error_msg) {
if (error_msg == NULL) return -1;
assert(msr != NULL);
assert(error_msg != NULL);
*error_msg = NULL;
/* We want to initialise our parsing context here, to
@ -107,7 +109,8 @@ int xml_process_chunk(modsec_rec *msr, const char *buf, unsigned int size, char
* Finalise XML parsing.
*/
int xml_complete(modsec_rec *msr, char **error_msg) {
if (error_msg == NULL) return -1;
assert(msr != NULL);
assert(error_msg != NULL);
*error_msg = NULL;
/* Only if we have a context, meaning we've done some work. */

File diff suppressed because it is too large Load Diff

View File

@ -57,6 +57,7 @@ static apr_status_t msre_rule_process(msre_rule *rule, modsec_rec *msr);
* \param targets Exception list.
*/
static int fetch_target_exception(msre_rule *rule, modsec_rec *msr, msre_var *var, const char *exceptions) {
assert(msr != NULL);
const char *targets = NULL;
char *savedptr = NULL, *target = NULL;
char *c = NULL, *name = NULL, *value = NULL;
@ -64,9 +65,6 @@ static int fetch_target_exception(msre_rule *rule, modsec_rec *msr, msre_var *va
char *myvalue = NULL, *myname = NULL;
int match = 0;
if(msr == NULL)
return 0;
if(var == NULL)
return 0;
@ -76,8 +74,9 @@ static int fetch_target_exception(msre_rule *rule, modsec_rec *msr, msre_var *va
if(rule->actionset == NULL)
return 0;
if(rule->actionset->id !=NULL) {
assert(exceptions != NULL);
{
myvar = apr_pstrdup(msr->mp, var->name);
c = strchr(myvar,':');
@ -94,7 +93,7 @@ static int fetch_target_exception(msre_rule *rule, modsec_rec *msr, msre_var *va
if(targets != NULL) {
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "fetch_target_exception: Found exception target list [%s] for rule id %s", targets, rule->actionset->id);
msr_log(msr, 9, "fetch_target_exception: Found exception target list [%s] for rule id %s", targets, id_log(rule));
}
target = apr_strtok((char *)targets, ",", &savedptr);
@ -139,7 +138,7 @@ static int fetch_target_exception(msre_rule *rule, modsec_rec *msr, msre_var *va
}
} else {
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "fetch_target_exception: No exception target found for rule id %s.", rule->actionset->id);
msr_log(msr, 9, "fetch_target_exception: No exception target found for rule id %s.", id_log(rule));
}
}
@ -203,6 +202,7 @@ char *msre_ruleset_phase_rule_update_target_matching_exception(modsec_rec *msr,
apr_array_header_t *phase_arr, const char *p2,
const char *p3)
{
assert(ruleset != NULL);
msre_rule **rules;
int i, j, mode;
char *err;
@ -212,11 +212,9 @@ char *msre_ruleset_phase_rule_update_target_matching_exception(modsec_rec *msr,
rules = (msre_rule **)phase_arr->elts;
for (i = 0; i < phase_arr->nelts; i++) {
msre_rule *rule = (msre_rule *)rules[i];
if (mode == 0) { /* Looking for next rule. */
if (msre_ruleset_rule_matches_exception(rule, re)) {
err = update_rule_target_ex(NULL, ruleset, rule, p2, p3);
err = update_rule_target_ex(msr, ruleset, rule, p2, p3);
if (err) return err;
if (rule->actionset->is_chained) mode = 2; /* Match all rules in this chain. */
} else {
@ -238,6 +236,7 @@ char *msre_ruleset_phase_rule_update_target_matching_exception(modsec_rec *msr,
char *update_rule_target_ex(modsec_rec *msr, msre_ruleset *ruleset, msre_rule *rule, const char *p2,
const char *p3) {
assert(ruleset != NULL);
msre_var **targets = NULL;
const char *current_targets = NULL;
@ -637,7 +636,10 @@ static char *msre_generate_target_string(apr_pool_t *pool, msre_rule *rule) {
/**
* Generate an action string from an actionset.
*/
static char *msre_actionset_generate_action_string(apr_pool_t *pool, const msre_actionset *actionset) {
#ifndef DEBUG_CONF
static
#endif
char *msre_actionset_generate_action_string(apr_pool_t *pool, const msre_actionset *actionset) {
const apr_array_header_t *tarr = NULL;
const apr_table_entry_t *telts = NULL;
char *actions = NULL;
@ -864,6 +866,7 @@ static msre_action_metadata *msre_resolve_action(msre_engine *engine, const char
msre_var *msre_create_var_ex(apr_pool_t *pool, msre_engine *engine, const char *name, const char *param,
modsec_rec *msr, char **error_msg)
{
// msr can be NULL
const char *varparam = param;
msre_var *var = apr_pcalloc(pool, sizeof(msre_var));
if (var == NULL) return NULL;
@ -944,6 +947,9 @@ msre_var *msre_create_var_ex(apr_pool_t *pool, msre_engine *engine, const char *
static msre_var *msre_create_var(msre_ruleset *ruleset, const char *name, const char *param,
modsec_rec *msr, char **error_msg)
{
// msr can be NULL
assert(ruleset != NULL);
assert(error_msg != NULL);
msre_var *var = msre_create_var_ex(ruleset->mp, ruleset->engine, name, param, msr, error_msg);
if (var == NULL) return NULL;
@ -1539,6 +1545,7 @@ static apr_status_t msre_ruleset_process_phase_(msre_ruleset *ruleset, modsec_re
#if defined(PERFORMANCE_MEASUREMENT)
apr_time_t time1 = 0;
#endif
assert(rule->actionset != NULL);
/* Reset the rule interception flag */
msr->rule_was_intercepted = 0;
@ -1566,7 +1573,7 @@ static apr_status_t msre_ruleset_process_phase_(msre_ruleset *ruleset, modsec_re
saw_starter = 0;
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "Current rule is id=\"%s\" [chained %d] is trying to find the SecMarker=\"%s\" [stater %d]",rule->actionset->id,last_rule->actionset->is_chained,skip_after,saw_starter);
msr_log(msr, 9, "Current rule is id=\"%s\" [chained %d] is trying to find the SecMarker=\"%s\" [stater %d]", id_log(rule),last_rule->actionset->is_chained,skip_after,saw_starter);
}
}
@ -1723,7 +1730,7 @@ static apr_status_t msre_ruleset_process_phase_(msre_ruleset *ruleset, modsec_re
msr_log(msr, 5, "Not processing %srule id=\"%s\": "
"removed by ctl action",
rule->actionset->is_chained ? "chained " : "",
rule->actionset->id);
id_log(rule));
}
/* Skip the whole chain, if this is a chained rule */
@ -1757,11 +1764,11 @@ static apr_status_t msre_ruleset_process_phase_(msre_ruleset *ruleset, modsec_re
fn = apr_psprintf(p, " [file \"%s\"] [line \"%d\"]", rule->filename, rule->line_num);
}
if (rule->actionset != NULL && rule->actionset->id != NULL) {
if (rule->actionset->id != NULL) {
id = apr_psprintf(p, " [id \"%s\"]", rule->actionset->id);
}
if (rule->actionset != NULL && rule->actionset->rev != NULL) {
if (rule->actionset->rev != NULL) {
rev = apr_psprintf(p, " [rev \"%s\"]", rule->actionset->rev);
}
@ -1893,23 +1900,17 @@ static apr_status_t msre_ruleset_process_phase_(msre_ruleset *ruleset, modsec_re
}
}
else if (rc < 0) {
const char *id = "";
const char *msg = "";
if (rule->actionset) {
if (rule->actionset->id) {
id = rule->actionset->id;
}
if (rule->actionset->msg) {
msg = rule->actionset->msg;
}
if (rule->actionset->msg) {
msg = rule->actionset->msg;
}
msr_log(msr, 1, "Rule processing failed (id=%s, msg=%s).", id, msg);
msr_log(msr, 1, "Rule processing failed (id=%s, msg=%s).", id_log(rule), msg);
if (msr->txcfg->reqintercept_oe == 1) {
apr_table_clear(msr->matched_vars);
return -1;
} else {
if (rule->actionset && rule->actionset->is_chained) {
if (rule->actionset->is_chained) {
/* If the current rule is part of a chain then
* we need to skip over all the rules in the chain.
*/
@ -1933,17 +1934,11 @@ static apr_status_t msre_ruleset_process_phase_(msre_ruleset *ruleset, modsec_re
}
}
else {
const char *id = "";
const char *msg = "";
if (rule->actionset) {
if (rule->actionset->id) {
id = rule->actionset->id;
}
if (rule->actionset->msg) {
msg = rule->actionset->msg;
}
if (rule->actionset->msg) {
msg = rule->actionset->msg;
}
msr_log(msr, 1, "Rule processing failed with unknown return code: %d (id=%s, msg=%s).", rc, id, msg);
msr_log(msr, 1, "Rule processing failed with unknown return code: %d (id=%s, msg=%s).", rc, id_log(rule), msg);
apr_table_clear(msr->matched_vars);
return -1;
}
@ -2081,6 +2076,8 @@ static int msre_ruleset_phase_rule_remove_with_exception(msre_ruleset *ruleset,
rules = (msre_rule **)phase_arr->elts;
for (i = 0; i < phase_arr->nelts; i++) {
msre_rule *rule = (msre_rule *)rules[i];
assert(rule != NULL);
assert(rule->actionset != NULL);
if (mode == 0) { /* Looking for next rule. */
int remove_rule = 0;
@ -2089,7 +2086,7 @@ static int msre_ruleset_phase_rule_remove_with_exception(msre_ruleset *ruleset,
if (rule->placeholder == RULE_PH_NONE) {
switch(re->type) {
case RULE_EXCEPTION_REMOVE_ID :
if ((rule->actionset != NULL)&&(rule->actionset->id != NULL)) {
if (rule->actionset->id != NULL) {
int ruleid = atoi(rule->actionset->id);
if (rule_id_in_range(ruleid, re->param)) {
@ -2142,9 +2139,9 @@ static int msre_ruleset_phase_rule_remove_with_exception(msre_ruleset *ruleset,
if (remove_rule) {
/* Do not increment j. */
removed_count++;
if (rule->actionset && rule->actionset->is_chained) mode = 2; /* Remove rules in this chain. */
if (rule->actionset->is_chained) mode = 2; /* Remove rules in this chain. */
} else {
if (rule->actionset && rule->actionset->is_chained) mode = 1; /* Keep rules in this chain. */
if (rule->actionset->is_chained) mode = 1; /* Keep rules in this chain. */
rules[j++] = rules[i];
}
} else { /* Handling rule that is part of a chain. */
@ -2201,6 +2198,7 @@ static const char *msre_format_severity(int severity) {
* Creates a string containing the metadata of the supplied rule.
*/
char *msre_format_metadata(modsec_rec *msr, msre_actionset *actionset) {
assert(msr != NULL);
const apr_array_header_t *tarr;
const apr_table_entry_t *telts;
char *id = "";
@ -2497,6 +2495,8 @@ msre_rule *msre_rule_lua_create(msre_ruleset *ruleset,
static void msre_perform_nondisruptive_actions(modsec_rec *msr, msre_rule *rule,
msre_actionset *actionset, apr_pool_t *mptmp)
{
assert(msr != NULL);
assert(actionset != NULL);
const apr_array_header_t *tarr;
const apr_table_entry_t *telts;
int i;
@ -2519,6 +2519,8 @@ static void msre_perform_nondisruptive_actions(modsec_rec *msr, msre_rule *rule,
static void msre_perform_disruptive_actions(modsec_rec *msr, msre_rule *rule,
msre_actionset *actionset, apr_pool_t *mptmp, const char *message)
{
assert(msr != NULL);
assert(actionset != NULL);
const apr_array_header_t *tarr;
const apr_table_entry_t *telts;
int i;
@ -2603,6 +2605,14 @@ static void msre_perform_disruptive_actions(modsec_rec *msr, msre_rule *rule,
static int execute_operator(msre_var *var, msre_rule *rule, modsec_rec *msr,
msre_actionset *acting_actionset, apr_pool_t *mptmp)
{
assert(var != NULL);
assert(rule != NULL);
assert(rule->actionset != NULL);
assert(rule->op_metadata != NULL);
assert(rule->op_metadata->execute != NULL);
assert(msr != NULL);
assert(acting_actionset != NULL);
assert(mptmp != NULL);
apr_time_t time_before_op = 0;
char *my_error_msg = NULL;
const char *full_varname = NULL;
@ -3111,6 +3121,8 @@ static apr_status_t msre_rule_process_normal(msre_rule *rule, modsec_rec *msr) {
/* Perform transformations. */
tarr = apr_table_elts(normtab);
/* if no transformation, multi_match makes no sense and breaks the logic */
if (tarr->nelts == 0) multi_match = 0;
/* Execute transformations in a loop. */

View File

@ -75,6 +75,10 @@ int DSOLOCAL rule_id_in_range(int ruleid, const char *range);
msre_var DSOLOCAL *generate_single_var(modsec_rec *msr, msre_var *var, apr_array_header_t *tfn_arr,
msre_rule *rule, apr_pool_t *mptmp);
#ifdef DEBUG_CONF
char DSOLOCAL* msre_actionset_generate_action_string(apr_pool_t* pool, const msre_actionset* actionset);
#endif
#if defined(WITH_LUA)
apr_table_t DSOLOCAL *generate_multi_var(modsec_rec *msr, msre_var *var, apr_array_header_t *tfn_arr,
msre_rule *rule, apr_pool_t *mptmp);

View File

@ -51,6 +51,7 @@ static void msre_engine_action_register(msre_engine *engine, const char *name,
msre_var *generate_single_var(modsec_rec *msr, msre_var *var, apr_array_header_t *tfn_arr,
msre_rule *rule, apr_pool_t *mptmp)
{
assert(msr != NULL);
apr_table_t *vartab = NULL;
const apr_table_entry_t *te = NULL;
const apr_array_header_t *arr = NULL;
@ -108,6 +109,7 @@ msre_var *generate_single_var(modsec_rec *msr, msre_var *var, apr_array_header_t
apr_table_t *generate_multi_var(modsec_rec *msr, msre_var *var, apr_array_header_t *tfn_arr,
msre_rule *rule, apr_pool_t *mptmp)
{
assert(msr != NULL);
const apr_array_header_t *tarr;
const apr_table_entry_t *telts;
apr_table_t *vartab = NULL, *tvartab = NULL;
@ -169,6 +171,8 @@ apr_table_t *generate_multi_var(modsec_rec *msr, msre_var *var, apr_array_header
* in the given variable.
*/
int expand_macros(modsec_rec *msr, msc_string *var, msre_rule *rule, apr_pool_t *mptmp) {
assert(msr != NULL);
assert(var != NULL);
char *data = NULL;
apr_array_header_t *arr = NULL;
char *p = NULL, *q = NULL, *t = NULL;
@ -316,6 +320,7 @@ int expand_macros(modsec_rec *msr, msc_string *var, msre_rule *rule, apr_pool_t
* value that is set.
*/
apr_status_t collection_original_setvar(modsec_rec *msr, const char *col_name, const msc_string *orig_var) {
assert(msr != NULL);
apr_table_t *table = NULL;
msc_string *var = NULL;
const char *var_name = NULL;
@ -628,6 +633,8 @@ static apr_status_t msre_action_redirect_init(msre_engine *engine, apr_pool_t *m
static apr_status_t msre_action_redirect_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
assert(msr != NULL);
assert(action != NULL);
msc_string *var = NULL;
var = apr_pcalloc(mptmp, sizeof(msc_string));
@ -660,6 +667,8 @@ static apr_status_t msre_action_proxy_init(msre_engine *engine, apr_pool_t *mp,
static apr_status_t msre_action_proxy_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
assert(msr != NULL);
assert(action != NULL);
msc_string *var = NULL;
var = apr_pcalloc(mptmp, sizeof(msc_string));
@ -968,6 +977,8 @@ static apr_status_t msre_action_ctl_init(msre_engine *engine, apr_pool_t *mp, ms
static apr_status_t msre_action_ctl_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
assert(msr != NULL);
assert(action != NULL);
char *name = NULL;
char *value = NULL;
@ -1236,13 +1247,21 @@ static apr_status_t msre_action_ctl_execute(modsec_rec *msr, apr_pool_t *mptmp,
msr_log(msr, 4, "Ctl: ruleRemoveTargetById id=%s targets=%s", p1, p2);
}
if (p2 == NULL) {
msr_log(msr, 1, "ModSecurity: Missing target for id \"%s\"", p1);
msr_log(msr, 1, "Ctl: ruleRemoveTargetById: Missing target for id \"%s\"", p1);
return -1;
}
re = apr_pcalloc(msr->mp, sizeof(rule_exception));
if (re == NULL) {
msr_log(msr, 1, "Ctl: Memory allocation error");
return -1;
}
re->type = RULE_EXCEPTION_REMOVE_ID;
re->param = (const char *)apr_pstrdup(msr->mp, p1);
if (re->param == NULL) {
msr_log(msr, 1, "Ctl: Memory allocation error");
return -1;
}
apr_table_addn(msr->removed_targets, apr_pstrdup(msr->mp, p2), (void *)re);
return 1;
} else
@ -1336,6 +1355,8 @@ static char *msre_action_xmlns_validate(msre_engine *engine, apr_pool_t *mp, msr
static apr_status_t msre_action_sanitizeArg_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
assert(msr != NULL);
assert(action != NULL);
const char *sargname = NULL;
const apr_array_header_t *tarr;
const apr_table_entry_t *telts;
@ -1364,6 +1385,8 @@ static apr_status_t msre_action_sanitizeArg_execute(modsec_rec *msr, apr_pool_t
static apr_status_t msre_action_sanitizeMatched_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
assert(msr != NULL);
assert(action != NULL);
const char *sargname = NULL;
const apr_array_header_t *tarr;
const apr_table_entry_t *telts;
@ -1439,6 +1462,8 @@ static apr_status_t msre_action_sanitizeMatched_execute(modsec_rec *msr, apr_poo
static apr_status_t msre_action_sanitizeRequestHeader_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
assert(msr != NULL);
assert(action != NULL);
apr_table_set(msr->request_headers_to_sanitize, action->param, "1");
return 1;
}
@ -1447,6 +1472,8 @@ static apr_status_t msre_action_sanitizeRequestHeader_execute(modsec_rec *msr, a
static apr_status_t msre_action_sanitizeResponseHeader_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
assert(msr != NULL);
assert(action != NULL);
apr_table_set(msr->response_headers_to_sanitize, action->param, "1");
return 1;
}
@ -1455,6 +1482,8 @@ static apr_status_t msre_action_sanitizeResponseHeader_execute(modsec_rec *msr,
static apr_status_t msre_action_setenv_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
assert(msr != NULL);
assert(action != NULL);
char *data = apr_pstrdup(mptmp, action->param);
char *env_name = NULL, *env_value = NULL;
char *s = NULL;
@ -1528,6 +1557,9 @@ static apr_status_t msre_action_setenv_execute(modsec_rec *msr, apr_pool_t *mptm
apr_status_t msre_action_setvar_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, char *var_name, char *var_value)
{
assert(msr != NULL);
assert(var_name != NULL);
assert(var_value != NULL);
char *col_name = NULL;
char *s = NULL;
apr_table_t *target_col = NULL;
@ -1549,9 +1581,13 @@ apr_status_t msre_action_setvar_execute(modsec_rec *msr, apr_pool_t *mptmp,
var->value_len = strlen(var->value);
expand_macros(msr, var, rule, mptmp);
var_name = log_escape_nq_ex(msr->mp, var->value, var->value_len);
if (var_name == NULL) {
msr_log(msr, 1, "Failed to allocate space to expand name macros");
return -1;
}
/* Handle the exclamation mark. */
if (var_name != NULL && var_name[0] == '!') {
if (var_name[0] == '!') {
var_name = var_name + 1;
is_negated = 1;
}
@ -1711,6 +1747,8 @@ apr_status_t msre_action_setvar_execute(modsec_rec *msr, apr_pool_t *mptmp,
static apr_status_t msre_action_setvar_parse(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
assert(msr != NULL);
assert(action != NULL);
char *data = apr_pstrdup(mptmp, action->param);
char *var_name = NULL, *var_value = NULL;
char *s = NULL;
@ -1736,6 +1774,8 @@ static apr_status_t msre_action_setvar_parse(modsec_rec *msr, apr_pool_t *mptmp,
static apr_status_t msre_action_expirevar_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
assert(msr != NULL);
assert(action != NULL);
char *data = apr_pstrdup(mptmp, action->param);
char *col_name = NULL, *var_name = NULL, *var_value = NULL;
char *s = NULL;
@ -1833,6 +1873,8 @@ static apr_status_t msre_action_expirevar_execute(modsec_rec *msr, apr_pool_t *m
static apr_status_t msre_action_deprecatevar_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
assert(msr != NULL);
assert(action != NULL);
char *data = apr_pstrdup(mptmp, action->param);
char *col_name = NULL, *var_name = NULL, *var_value = NULL;
char *s = NULL;
@ -1967,6 +2009,8 @@ static apr_status_t msre_action_deprecatevar_execute(modsec_rec *msr, apr_pool_t
static apr_status_t init_collection(modsec_rec *msr, const char *real_col_name,
const char *col_name, const char *col_key, unsigned int col_key_len)
{
assert(msr != NULL);
assert(real_col_name != NULL);
apr_table_t *table = NULL;
msc_string *var = NULL;
@ -1980,7 +2024,6 @@ static apr_status_t init_collection(modsec_rec *msr, const char *real_col_name,
/* Init collection from storage. */
table = collection_retrieve(msr, real_col_name, col_key, col_key_len);
if (table == NULL) {
/* Does not exist yet - create new. */
@ -2101,6 +2144,8 @@ static apr_status_t init_collection(modsec_rec *msr, const char *real_col_name,
static apr_status_t msre_action_initcol_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
assert(msr != NULL);
assert(action != NULL);
char *data = apr_pstrdup(msr->mp, action->param);
char *col_name = NULL, *col_key = NULL;
unsigned int col_key_len;
@ -2132,6 +2177,8 @@ static apr_status_t msre_action_initcol_execute(modsec_rec *msr, apr_pool_t *mpt
static apr_status_t msre_action_setsid_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
assert(msr != NULL);
assert(action != NULL);
msc_string *var = NULL;
char *real_col_name = NULL, *col_key = NULL;
unsigned int col_key_len;
@ -2156,6 +2203,8 @@ static apr_status_t msre_action_setsid_execute(modsec_rec *msr, apr_pool_t *mptm
static apr_status_t msre_action_setuid_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
assert(msr != NULL);
assert(action != NULL);
msc_string *var = NULL;
char *real_col_name = NULL, *col_key = NULL;
unsigned int col_key_len;
@ -2180,6 +2229,8 @@ static apr_status_t msre_action_setuid_execute(modsec_rec *msr, apr_pool_t *mptm
static apr_status_t msre_action_setrsc_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
assert(msr != NULL);
assert(action != NULL);
msc_string *var = NULL;
char *real_col_name = NULL, *col_key = NULL;
unsigned int col_key_len;
@ -2228,7 +2279,9 @@ static char *msre_action_exec_validate(msre_engine *engine, apr_pool_t *mp, msre
static apr_status_t msre_action_exec_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
#if defined(WITH_LUA)
assert(msr != NULL);
assert(action != NULL);
#if defined(WITH_LUA)
if (action->param_data != NULL) { /* Lua */
msc_script *script = (msc_script *)action->param_data;
char *my_error_msg = NULL;
@ -2256,6 +2309,8 @@ static apr_status_t msre_action_exec_execute(modsec_rec *msr, apr_pool_t *mptmp,
static apr_status_t msre_action_prepend_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
assert(msr != NULL);
assert(action != NULL);
msc_string *var = NULL;
/* Expand any macros in the text */
@ -2276,6 +2331,8 @@ static apr_status_t msre_action_prepend_execute(modsec_rec *msr, apr_pool_t *mpt
static apr_status_t msre_action_append_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
assert(msr != NULL);
assert(action != NULL);
msc_string *var = NULL;
/* Expand any macros in the text */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,9 @@
#! /bin/sh
# Wrapper for compilers which do not understand `-c -o'.
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2005-05-14.22
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
@ -17,8 +17,7 @@ scriptversion=2005-05-14.22
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@ -29,21 +28,224 @@ scriptversion=2005-05-14.22
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
nl='
'
# We need space, tab and new line, in precisely that order. Quoting is
# there to prevent tools from complaining about whitespace usage.
IFS=" "" $nl"
file_conv=
# func_file_conv build_file lazy
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts. If the determined conversion
# type is listed in (the comma separated) LAZY, no conversion will
# take place.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
file_conv=mingw
;;
CYGWIN* | MSYS*)
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv/,$2, in
*,$file_conv,*)
;;
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin/* | msys/*)
file=`cygpath -m "$file" || echo "$file"`
;;
wine/*)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_cl_dashL linkdir
# Make cl look for libraries in LINKDIR
func_cl_dashL ()
{
func_file_conv "$1"
if test -z "$lib_path"; then
lib_path=$file
else
lib_path="$lib_path;$file"
fi
linker_opts="$linker_opts -LIBPATH:$file"
}
# func_cl_dashl library
# Do a library search-path lookup for cl
func_cl_dashl ()
{
lib=$1
found=no
save_IFS=$IFS
IFS=';'
for dir in $lib_path $LIB
do
IFS=$save_IFS
if $shared && test -f "$dir/$lib.dll.lib"; then
found=yes
lib=$dir/$lib.dll.lib
break
fi
if test -f "$dir/$lib.lib"; then
found=yes
lib=$dir/$lib.lib
break
fi
if test -f "$dir/lib$lib.a"; then
found=yes
lib=$dir/lib$lib.a
break
fi
done
IFS=$save_IFS
if test "$found" != yes; then
lib=$lib.lib
fi
}
# func_cl_wrapper cl arg...
# Adjust compile command to suit cl
func_cl_wrapper ()
{
# Assume a capable shell
lib_path=
shared=:
linker_opts=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
eat=1
case $2 in
*.o | *.[oO][bB][jJ])
func_file_conv "$2"
set x "$@" -Fo"$file"
shift
;;
*)
func_file_conv "$2"
set x "$@" -Fe"$file"
shift
;;
esac
;;
-I)
eat=1
func_file_conv "$2" mingw
set x "$@" -I"$file"
shift
;;
-I*)
func_file_conv "${1#-I}" mingw
set x "$@" -I"$file"
shift
;;
-l)
eat=1
func_cl_dashl "$2"
set x "$@" "$lib"
shift
;;
-l*)
func_cl_dashl "${1#-l}"
set x "$@" "$lib"
shift
;;
-L)
eat=1
func_cl_dashL "$2"
;;
-L*)
func_cl_dashL "${1#-L}"
;;
-static)
shared=false
;;
-Wl,*)
arg=${1#-Wl,}
save_ifs="$IFS"; IFS=','
for flag in $arg; do
IFS="$save_ifs"
linker_opts="$linker_opts $flag"
done
IFS="$save_ifs"
;;
-Xlinker)
eat=1
linker_opts="$linker_opts $2"
;;
-*)
set x "$@" "$1"
shift
;;
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
func_file_conv "$1"
set x "$@" -Tp"$file"
shift
;;
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
func_file_conv "$1" mingw
set x "$@" "$file"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -n "$linker_opts"; then
linker_opts="-link$linker_opts"
fi
exec "$@" $linker_opts
exit 1
}
eat=
case $1 in
'')
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand `-c -o'.
Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
Wrapper for compilers which do not understand '-c -o'.
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file `INSTALL'.
right script to run: please start by reading the file 'INSTALL'.
Report bugs to <bug-automake@gnu.org>.
EOF
@ -53,11 +255,14 @@ EOF
echo "compile $scriptversion"
exit $?
;;
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
func_cl_wrapper "$@" # Doesn't return...
;;
esac
ofile=
cfile=
eat=
for arg
do
@ -66,8 +271,8 @@ do
else
case $1 in
-o)
# configure might choose to run compile as `compile cc -o foo foo.c'.
# So we strip `-o arg' only if arg is an object.
# configure might choose to run compile as 'compile cc -o foo foo.c'.
# So we strip '-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
@ -94,22 +299,22 @@ do
done
if test -z "$ofile" || test -z "$cfile"; then
# If no `-o' option was seen then we might have been invoked from a
# If no '-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# `.c' file was seen then we are probably linking. That is also
# '.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
# Create the lock directory.
# Note: use `[/.-]' here to ensure that we don't use the same name
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
@ -124,9 +329,9 @@ trap "rmdir '$lockdir'; exit 1" 1 2 15
ret=$?
if test -f "$cofile"; then
mv "$cofile" "$ofile"
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
mv "${cofile}bj" "$ofile"
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
@ -135,8 +340,9 @@ exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

View File

@ -18,7 +18,7 @@ AC_DEFUN([CHECK_APR],
AC_ARG_WITH(
apr,
[AC_HELP_STRING([--with-apr=PATH],[Path to apr prefix or config script])],
[AS_HELP_STRING([--with-apr=PATH],[Path to apr prefix or config script])],
[test_paths="${with_apr}"],
[test_paths="/usr/local/libapr /usr/local/apr /usr/local /opt/libapr /opt/apr /opt /usr"])

View File

@ -18,7 +18,7 @@ AC_DEFUN([CHECK_APU],
AC_ARG_WITH(
apu,
[AC_HELP_STRING([--with-apu=PATH],[Path to apu prefix or config script])],
[AS_HELP_STRING([--with-apu=PATH],[Path to apu prefix or config script])],
[test_paths="${with_apu}"],
[test_paths="/usr/local/libapr-util /usr/local/apr-util /usr/local/libapu /usr/local/apu /usr/local/apr /usr/local /opt/libapr-util /opt/apr-util /opt/libapu /opt/apu /opt /usr"])

View File

@ -18,7 +18,7 @@ AC_DEFUN([CHECK_CURL],
AC_ARG_WITH(
curl,
[AC_HELP_STRING([--with-curl=PATH],[Path to curl prefix or config script])],
[AS_HELP_STRING([--with-curl=PATH],[Path to curl prefix or config script])],
[test_paths="${with_curl}"],
[test_paths="/usr/local/libcurl /usr/local/curl /usr/local /opt/libcurl /opt/curl /opt /usr"])

View File

@ -21,7 +21,7 @@ LUA_SONAMES="so la sl dll dylib a"
AC_ARG_WITH(
lua,
[AC_HELP_STRING([--with-lua=PATH],[Path to lua prefix or config script])]
[AS_HELP_STRING([--with-lua=PATH],[Path to lua prefix or config script])]
,, with_lua=yes)
AS_CASE(["${with_lua}"],

View File

@ -17,7 +17,7 @@ AC_DEFUN([CHECK_PCRE],
AC_ARG_WITH(
pcre,
[AC_HELP_STRING([--with-pcre=PATH],[Path to pcre prefix or config script])],
[AS_HELP_STRING([--with-pcre=PATH],[Path to pcre prefix or config script])],
[test_paths="${with_pcre}"],
[test_paths="/usr/local/libpcre /usr/local/pcre /usr/local /opt/libpcre /opt/pcre /opt /usr"])

View File

@ -17,7 +17,7 @@ AC_DEFUN([CHECK_PCRE2],
AC_ARG_WITH(
pcre2,
[AC_HELP_STRING([--with-pcre2=PATH],[Path to pcre2 prefix or config script])],
[AS_HELP_STRING([--with-pcre2=PATH],[Path to pcre2 prefix or config script])],
, with_pcre2=no)
AS_CASE(["${with_pcre2}"],

View File

@ -13,7 +13,7 @@ SSDEEP_LDADD=""
AC_ARG_WITH(
ssdeep,
[AC_HELP_STRING([--with-ssdeep=PATH],[Path to ssdeep prefix])]
[AS_HELP_STRING([--with-ssdeep=PATH],[Path to ssdeep prefix])]
,, with_ssdeep=yes)
AS_CASE(["${with_ssdeep}"],

View File

@ -23,7 +23,7 @@ YAJL_SONAMES="so la sl dll dylib"
AC_ARG_WITH(
yajl,
[AC_HELP_STRING([--with-yajl=PATH],[Path to yajl prefix or config script])]
[AS_HELP_STRING([--with-yajl=PATH],[Path to yajl prefix or config script])]
,, with_yajl=yes)
AS_CASE(["${with_yajl}"],

View File

@ -33,7 +33,6 @@ AC_PATH_PROGS(ENV_CMD, [env printenv], )
PKG_PROG_PKG_CONFIG
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([fcntl.h limits.h stdlib.h string.h unistd.h sys/types.h sys/stat.h sys/utsname.h])
# Checks for typedefs, structures, and compiler characteristics.
@ -306,6 +305,22 @@ if test "$build_docs" -eq 1; then
fi
# Add assert() usage
AC_ARG_ENABLE(assertions,
AS_HELP_STRING([--enable-assertions],
[Turn on assertions checks (undefine NDEBUG)]),
[
if test "${enableval}" = "yes"; then
assertions='-UNDEBUG'
else
assertions='-DNDEBUG'
fi
],
[
assertions='-DNDEBUG'
])
# Add PCRE Studying
AC_ARG_ENABLE(pcre-study,
@ -829,7 +844,7 @@ else
fi
fi
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 $unique_id $log_filename $log_server $log_collection_delete_problem $log_dechunk $log_stopwatch $log_handler $log_server_context $collection_global_lock $large_stream_input"
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 $unique_id $log_filename $log_server $log_collection_delete_problem $log_dechunk $log_stopwatch $log_handler $log_server_context $collection_global_lock $large_stream_input $assertions"
APXS_WRAPPER=build/apxs-wrapper
APXS_EXTRA_CFLAGS=""
@ -889,13 +904,13 @@ ORIG_CFLAGS="$CFLAGS $APU_CFLAGS"
ORIG_CPPFLAGS="$CPPFLAGS"
CFLAGS="$CFLAGS $APR_CFLAGS"
CPPFLAGS="$CPPFLAGS $APR_CPPFLAGS"
AC_TRY_COMPILE(
[#include <apr_crypto.h>],
[
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[ #include <apr_crypto.h> ]],
[[
#if APU_HAVE_CRYPTO == 0
#error APR util was not compiled with crypto support.
#endif
],
]])],
[ AC_DEFINE([WITH_APU_CRYPTO], [1], [APR util was compiled with crypto support])
MODSEC_EXTRA_CFLAGS="$MODSEC_EXTRA_CFLAGS -DWITH_APU_CRYPTO"
],
@ -906,7 +921,7 @@ AC_TRY_COMPILE(
CFLAGS="$ORIG_CFLAGS"
CPPFLAGS="$ORIG_CPPFLAGS"
# Current our unique download backend is curl, furhter we can support more.
# Currently our unique download backend is curl, further we can support more.
if test ! -z "${CURL_VERSION}"; then
AC_DEFINE([WITH_REMOTE_RULES], [1], [Enables SecRemoteRules support])
MODSEC_EXTRA_CFLAGS="$MODSEC_EXTRA_CFLAGS -DWITH_REMOTE_RULES"

29
design.md Normal file
View File

@ -0,0 +1,29 @@
Design notes for source code
==
This file give some explanations and guidelines regarding ModSecurity v2 source code.
The goal is to discuss topics that are not related to a specific location in the code, so that cannot be best explained by comments.
The goal is not to replace comments where it is probably better.
It's quite short for the moment, but the goal is to extend it from time to time.
## Null pointer check
The default behaviour is to check for null pointer dereference everywhere it may be needed.
In case a pointer cannot be null, it has to be explained with a comment at the beginning of the function of when dereferencing the pointer.
On top of that, an explicit check should be done when compiling in debug mode with the following code:
```
assert(mypointer);
```
In case a pointer that cannot be null is used at several locations (say more than 3 times),
the explanation could be given globally in this file.
### Pointers never null
The following pointers can never be null:
#### msr
msr is assigned at the following places:
- mod_security2.c (14 x): initialization
In all the above calls, and all calling functions, it immediately returns (with an error code) in case msr is null, up to a place where no mod_security2 processing at all occurs.
In subsequent calls, there's thus no possibility to have msr null.
- apache2_io.c (2 x): assign a previously initialized msr
- msc_json (9 x): assign a previously initialized msr
- msc_lua.c (4 x): assign a previously initialized msr