|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
|
|
Packit Service |
384592 |
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* You may not use this file except in compliance with
|
|
Packit Service |
384592 |
* the License. You may obtain a copy of the License at
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* If any of the files related to licensing are missing or if you have any
|
|
Packit Service |
384592 |
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
|
Packit Service |
384592 |
* directly using the email address security@modsecurity.org.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#include <limits.h>
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#include "http_core.h"
|
|
Packit Service |
384592 |
#include "http_request.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#include "modsecurity.h"
|
|
Packit Service |
384592 |
#include "apache2.h"
|
|
Packit Service |
384592 |
#include "http_main.h"
|
|
Packit Service |
384592 |
#include "http_connection.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#include "apr_optional.h"
|
|
Packit Service |
384592 |
#include "mod_log_config.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* #ifdef APLOG_USE_MODULE
|
|
Packit Service |
384592 |
* APLOG_USE_MODULE(security2);
|
|
Packit Service |
384592 |
* #endif
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#include "msc_logging.h"
|
|
Packit Service |
384592 |
#include "msc_util.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#include "ap_mpm.h"
|
|
Packit Service |
384592 |
#include "scoreboard.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#include "apr_version.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#include "msc_remote_rules.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#if defined(WITH_LUA)
|
|
Packit Service |
384592 |
#include "msc_lua.h"
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#include "msc_status_engine.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#ifdef WITH_YAJL
|
|
Packit Service |
384592 |
#include <yajl/yajl_version.h>
|
|
Packit Service |
384592 |
#endif /* WITH_YAJL */
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* ModSecurity structure */
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
msc_engine DSOLOCAL *modsecurity = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Global module variables; these are used for the Apache-specific functionality */
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
char DSOLOCAL *chroot_dir = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
char DSOLOCAL *new_server_signature = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
char DSOLOCAL *real_server_signature = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
char DSOLOCAL *guardianlog_name = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
apr_file_t DSOLOCAL *guardianlog_fd = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
char DSOLOCAL *guardianlog_condition = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
unsigned long int DSOLOCAL msc_pcre_match_limit = 0;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
unsigned long int DSOLOCAL msc_pcre_match_limit_recursion = 0;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#ifdef WITH_REMOTE_RULES
|
|
Packit Service |
384592 |
msc_remote_rules_server DSOLOCAL *remote_rules_server = NULL;
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
int DSOLOCAL remote_rules_fail_action = REMOTE_RULES_ABORT_ON_FAIL;
|
|
Packit Service |
384592 |
char DSOLOCAL *remote_rules_fail_message = NULL;
|
|
Packit Service |
34f31f |
unsigned long int DSOLOCAL remote_rules_timeout = NOT_SET;
|
|
Packit Service |
34f31f |
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
int DSOLOCAL status_engine_state = STATUS_ENGINE_DISABLED;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
int DSOLOCAL conn_limits_filter_state = MODSEC_DISABLED;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
unsigned long int DSOLOCAL conn_read_state_limit = 0;
|
|
Packit Service |
384592 |
TreeRoot DSOLOCAL *conn_read_state_whitelist = 0;
|
|
Packit Service |
384592 |
TreeRoot DSOLOCAL *conn_read_state_suspicious_list = 0;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
unsigned long int DSOLOCAL conn_write_state_limit = 0;
|
|
Packit Service |
384592 |
TreeRoot DSOLOCAL *conn_write_state_whitelist = 0;
|
|
Packit Service |
384592 |
TreeRoot DSOLOCAL *conn_write_state_suspicious_list = 0;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#if defined(WIN32) || defined(VERSION_NGINX)
|
|
Packit Service |
384592 |
int (*modsecDropAction)(request_rec *r) = NULL;
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
static int server_limit, thread_limit;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* -- Miscellaneous functions -- */
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* \brief Print informations from used libraries
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* \param mp Pointer to memory pool
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static void version(apr_pool_t *mp) {
|
|
Packit Service |
384592 |
char *pcre_vrs = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
|
|
Packit Service |
384592 |
"ModSecurity: APR compiled version=\"%s\"; "
|
|
Packit Service |
384592 |
"loaded version=\"%s\"", APR_VERSION_STRING, apr_version_string());
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (strstr(apr_version_string(), APR_VERSION_STRING) == NULL) {
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, "ModSecurity: Loaded APR do not match with compiled!");
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
pcre_vrs = apr_psprintf(mp,"%d.%d ", PCRE_MAJOR, PCRE_MINOR);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
|
|
Packit Service |
384592 |
"ModSecurity: PCRE compiled version=\"%s\"; "
|
|
Packit Service |
384592 |
"loaded version=\"%s\"", pcre_vrs, pcre_version());
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (strstr(pcre_version(),pcre_vrs) == NULL) {
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, "ModSecurity: Loaded PCRE do not match with compiled!");
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Lua version function was removed in current 5.1. Need to check in future versions if it's back */
|
|
Packit Service |
384592 |
#if defined(WITH_LUA)
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
|
|
Packit Service |
384592 |
"ModSecurity: LUA compiled version=\"%s\"", LUA_VERSION);
|
|
Packit Service |
384592 |
#endif /* WITH_LUA */
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#ifdef WITH_YAJL
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
|
|
Packit Service |
384592 |
"ModSecurity: YAJL compiled version=\"%d.%d.%d\"", YAJL_MAJOR, YAJL_MINOR, YAJL_MICRO);
|
|
Packit Service |
384592 |
#endif /* WITH_YAJL */
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
|
|
Packit Service |
384592 |
"ModSecurity: LIBXML compiled version=\"%s\"", LIBXML_DOTTED_VERSION);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Intercepts transaction, using the method specified
|
|
Packit Service |
384592 |
* in the structure itself. MUST return an HTTP status code,
|
|
Packit Service |
384592 |
* which will be used to terminate the transaction.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
int perform_interception(modsec_rec *msr) {
|
|
Packit Service |
384592 |
msre_actionset *actionset = NULL;
|
|
Packit Service |
384592 |
const char *message = NULL;
|
|
Packit Service |
384592 |
const char *phase_text = "";
|
|
Packit Service |
384592 |
unsigned int pause = 0;
|
|
Packit Service |
384592 |
int status = DECLINED;
|
|
Packit Service |
384592 |
int log_level = 1;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Sanity checks first. */
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (msr->was_intercepted == 0) {
|
|
Packit Service |
384592 |
msr_log(msr, 1, "Internal Error: Asked to intercept request but was_intercepted is zero");
|
|
Packit Service |
384592 |
return DECLINED;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (msr->phase > 4) {
|
|
Packit Service |
384592 |
msr_log(msr, 1, "Internal Error: Asked to intercept request in phase %d.", msr->phase);
|
|
Packit Service |
384592 |
msr->was_intercepted = 0;
|
|
Packit Service |
384592 |
return DECLINED;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* OK, we're good to go. */
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
actionset = msr->intercept_actionset;
|
|
Packit Service |
384592 |
phase_text = apr_psprintf(msr->mp, " (phase %d)", msr->phase);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* By default we log at level 1 but we switch to 4
|
|
Packit Service |
384592 |
* if a nolog action was used or this is not the initial request
|
|
Packit Service |
384592 |
* to hide the message.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
log_level = (actionset->log != 1) ? 4 : 1;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Pause the request first (if configured and the initial request). */
|
|
Packit Service |
384592 |
if (actionset->intercept_pause != NULL) {
|
|
Packit Service |
384592 |
if(strstr(actionset->intercept_pause,"%{") != NULL) {
|
|
Packit Service |
384592 |
msc_string *var = (msc_string *)apr_pcalloc(msr->mp, sizeof(msc_string));
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
var->value = (char *)actionset->intercept_pause;
|
|
Packit Service |
384592 |
var->value_len = strlen(actionset->intercept_pause);
|
|
Packit Service |
384592 |
expand_macros(msr, var, NULL, msr->mp);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
pause = atoi(var->value);
|
|
Packit Service |
384592 |
if ((pause == LONG_MAX)||(pause == LONG_MIN)||(pause <= 0))
|
|
Packit Service |
384592 |
pause = 0;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
msr_log(msr, (log_level > 3 ? log_level : log_level + 1), "Pausing transaction for "
|
|
Packit Service |
384592 |
"%d msec.", pause);
|
|
Packit Service |
384592 |
/* apr_sleep accepts microseconds */
|
|
Packit Service |
384592 |
apr_sleep((apr_interval_time_t)(pause * 1000));
|
|
Packit Service |
384592 |
} else {
|
|
Packit Service |
384592 |
pause = atoi(actionset->intercept_pause);
|
|
Packit Service |
384592 |
if ((pause == LONG_MAX)||(pause == LONG_MIN)||(pause <= 0))
|
|
Packit Service |
384592 |
pause = 0;
|
|
Packit Service |
384592 |
msr_log(msr, (log_level > 3 ? log_level : log_level + 1), "Pausing transaction for "
|
|
Packit Service |
384592 |
"%d msec.", pause);
|
|
Packit Service |
384592 |
/* apr_sleep accepts microseconds */
|
|
Packit Service |
384592 |
apr_sleep((apr_interval_time_t)(pause * 1000));
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Determine how to respond and prepare the log message. */
|
|
Packit Service |
384592 |
switch(actionset->intercept_action) {
|
|
Packit Service |
384592 |
case ACTION_DENY :
|
|
Packit Service |
384592 |
if (actionset->intercept_status != 0) {
|
|
Packit Service |
384592 |
status = actionset->intercept_status;
|
|
Packit Service |
384592 |
message = apr_psprintf(msr->mp, "Access denied with code %d%s.",
|
|
Packit Service |
384592 |
status, phase_text);
|
|
Packit Service |
384592 |
} else {
|
|
Packit Service |
384592 |
log_level = 1;
|
|
Packit Service |
384592 |
status = HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit Service |
384592 |
message = apr_psprintf(msr->mp, "Access denied with code 500%s "
|
|
Packit Service |
384592 |
"(Internal Error: Invalid status code requested %d).",
|
|
Packit Service |
384592 |
phase_text, actionset->intercept_status);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
case ACTION_PROXY :
|
|
Packit Service |
384592 |
#if !(defined(VERSION_IIS)) && !(defined(VERSION_NGINX)) && !(defined(VERSION_STANDALONE))
|
|
Packit Service |
384592 |
if (msr->phase < 3) {
|
|
Packit Service |
384592 |
if (ap_find_linked_module("mod_proxy.c") == NULL) {
|
|
Packit Service |
384592 |
log_level = 1;
|
|
Packit Service |
384592 |
status = HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit Service |
384592 |
message = apr_psprintf(msr->mp, "Access denied with code 500%s "
|
|
Packit Service |
384592 |
"(Configuration Error: Proxy action to %s requested but mod_proxy not found).",
|
|
Packit Service |
384592 |
phase_text,
|
|
Packit Service |
384592 |
log_escape_nq(msr->mp, actionset->intercept_uri));
|
|
Packit Service |
384592 |
} else {
|
|
Packit Service |
384592 |
msr->r->filename = apr_psprintf(msr->mp, "proxy:%s", actionset->intercept_uri);
|
|
Packit Service |
384592 |
msr->r->proxyreq = PROXYREQ_REVERSE;
|
|
Packit Service |
384592 |
msr->r->handler = "proxy-server";
|
|
Packit Service |
384592 |
status = OK;
|
|
Packit Service |
384592 |
message = apr_psprintf(msr->mp, "Access denied using proxy to%s %s.",
|
|
Packit Service |
384592 |
phase_text,
|
|
Packit Service |
384592 |
log_escape_nq(msr->mp, actionset->intercept_uri));
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
} else {
|
|
Packit Service |
384592 |
log_level = 1;
|
|
Packit Service |
384592 |
status = HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit Service |
384592 |
message = apr_psprintf(msr->mp, "Access denied with code 500%s "
|
|
Packit Service |
384592 |
"(Configuration Error: Proxy action requested but it does not work in output phases).",
|
|
Packit Service |
384592 |
phase_text);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
#else
|
|
Packit Service |
384592 |
log_level = 1;
|
|
Packit Service |
384592 |
status = HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit Service |
384592 |
message = apr_psprintf(msr->mp, "Access denied with code 500%s "
|
|
Packit Service |
384592 |
"(Configuration Error: Proxy action to %s requested but "
|
|
Packit Service |
384592 |
"proxy is only available in Apache version).",
|
|
Packit Service |
384592 |
phase_text,
|
|
Packit Service |
384592 |
log_escape_nq(msr->mp, actionset->intercept_uri));
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
case ACTION_DROP :
|
|
Packit Service |
384592 |
/* ENH This does not seem to work on Windows. Is there a
|
|
Packit Service |
384592 |
* better way to drop a connection anyway?
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
#if !defined(WIN32) && !defined(VERSION_NGINX)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
extern module core_module;
|
|
Packit Service |
384592 |
apr_socket_t *csd;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2 && AP_SERVER_PATCHLEVEL_NUMBER > 17
|
|
Packit Service |
384592 |
/* For mod_http2 used by HTTP/2 there is a virtual connection so must go through
|
|
Packit Service |
384592 |
* master to get the main connection or the drop request doesn't seem to do anything.
|
|
Packit Service |
384592 |
* For HTTP/1.1 master will not be defined so just go through normal connection.
|
|
Packit Service |
384592 |
* More details here: https://github.com/icing/mod_h2/issues/127
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
if (msr->r->connection->master) {
|
|
Packit Service |
384592 |
csd = ap_get_module_config(msr->r->connection->master->conn_config, &core_module);
|
|
Packit Service |
384592 |
} else {
|
|
Packit Service |
384592 |
csd = ap_get_module_config(msr->r->connection->conn_config, &core_module);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
#else
|
|
Packit Service |
384592 |
csd = ap_get_module_config(msr->r->connection->conn_config, &core_module);
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
if (csd) {
|
|
Packit Service |
384592 |
if (apr_socket_close(csd) == APR_SUCCESS) {
|
|
Packit Service |
384592 |
status = HTTP_FORBIDDEN;
|
|
Packit Service |
384592 |
message = apr_psprintf(msr->mp, "Access denied with connection close%s.",
|
|
Packit Service |
384592 |
phase_text);
|
|
Packit Service |
384592 |
} else {
|
|
Packit Service |
384592 |
log_level = 1;
|
|
Packit Service |
384592 |
status = HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit Service |
384592 |
message = apr_psprintf(msr->mp, "Access denied with code 500%s "
|
|
Packit Service |
384592 |
"(Error: Connection drop requested but failed to close the "
|
|
Packit Service |
384592 |
" socket).",
|
|
Packit Service |
384592 |
phase_text);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
} else {
|
|
Packit Service |
384592 |
log_level = 1;
|
|
Packit Service |
384592 |
status = HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit Service |
384592 |
message = apr_psprintf(msr->mp, "Access denied with code 500%s "
|
|
Packit Service |
384592 |
"(Error: Connection drop requested but socket not found.",
|
|
Packit Service |
384592 |
phase_text);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
#else
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
if (modsecDropAction == NULL) {
|
|
Packit Service |
384592 |
log_level = 1;
|
|
Packit Service |
384592 |
status = HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit Service |
384592 |
message = apr_psprintf(msr->mp, "Access denied with code 500%s "
|
|
Packit Service |
384592 |
"(Error: Connection drop not implemented on this platform.",
|
|
Packit Service |
384592 |
phase_text);
|
|
Packit Service |
384592 |
} else if (modsecDropAction(msr->r) == 0) {
|
|
Packit Service |
384592 |
status = HTTP_FORBIDDEN;
|
|
Packit Service |
384592 |
message = apr_psprintf(msr->mp, "Access denied with connection close%s.",
|
|
Packit Service |
384592 |
phase_text);
|
|
Packit Service |
384592 |
} else {
|
|
Packit Service |
384592 |
log_level = 1;
|
|
Packit Service |
384592 |
status = HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit Service |
384592 |
message = apr_psprintf(msr->mp, "Access denied with code 500%s "
|
|
Packit Service |
384592 |
"(Error: Connection drop request failed.",
|
|
Packit Service |
384592 |
phase_text);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
case ACTION_REDIRECT :
|
|
Packit Service |
384592 |
if(strstr(actionset->intercept_uri,"%{") != NULL) {
|
|
Packit Service |
384592 |
msc_string *var = (msc_string *)apr_pcalloc(msr->mp, sizeof(msc_string));
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
var->value = (char *)actionset->intercept_uri;
|
|
Packit Service |
384592 |
var->value_len = strlen(actionset->intercept_uri);
|
|
Packit Service |
384592 |
expand_macros(msr, var, NULL, msr->mp);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
apr_table_setn(msr->r->headers_out, "Location", var->value);
|
|
Packit Service |
384592 |
if ((actionset->intercept_status == 301)||(actionset->intercept_status == 302)
|
|
Packit Service |
384592 |
||(actionset->intercept_status == 303)||(actionset->intercept_status == 307))
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
status = actionset->intercept_status;
|
|
Packit Service |
384592 |
} else {
|
|
Packit Service |
384592 |
status = HTTP_MOVED_TEMPORARILY;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
message = apr_psprintf(msr->mp, "Access denied with redirection to %s using "
|
|
Packit Service |
384592 |
"status %d%s.",
|
|
Packit Service |
384592 |
log_escape_nq(msr->mp, var->value), status,
|
|
Packit Service |
384592 |
phase_text);
|
|
Packit Service |
384592 |
} else {
|
|
Packit Service |
384592 |
apr_table_setn(msr->r->headers_out, "Location", actionset->intercept_uri);
|
|
Packit Service |
384592 |
if ((actionset->intercept_status == 301)||(actionset->intercept_status == 302)
|
|
Packit Service |
384592 |
||(actionset->intercept_status == 303)||(actionset->intercept_status == 307))
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
status = actionset->intercept_status;
|
|
Packit Service |
384592 |
} else {
|
|
Packit Service |
384592 |
status = HTTP_MOVED_TEMPORARILY;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
message = apr_psprintf(msr->mp, "Access denied with redirection to %s using "
|
|
Packit Service |
384592 |
"status %d%s.",
|
|
Packit Service |
384592 |
log_escape_nq(msr->mp, actionset->intercept_uri), status,
|
|
Packit Service |
384592 |
phase_text);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
case ACTION_ALLOW :
|
|
Packit Service |
384592 |
status = DECLINED;
|
|
Packit Service |
384592 |
message = apr_psprintf(msr->mp, "Access allowed%s.", phase_text);
|
|
Packit Service |
384592 |
msr->was_intercepted = 0;
|
|
Packit Service |
384592 |
msr->allow_scope = ACTION_ALLOW;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
case ACTION_PAUSE :
|
|
Packit Service |
384592 |
status = DECLINED;
|
|
Packit Service |
384592 |
message = apr_psprintf(msr->mp, "Paused Access%s.", phase_text);
|
|
Packit Service |
384592 |
msr->was_intercepted = 0;
|
|
Packit Service |
384592 |
msr->allow_scope = ACTION_ALLOW;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
case ACTION_ALLOW_PHASE :
|
|
Packit Service |
384592 |
status = DECLINED;
|
|
Packit Service |
384592 |
message = apr_psprintf(msr->mp, "Access to phase allowed%s.", phase_text);
|
|
Packit Service |
384592 |
msr->was_intercepted = 0;
|
|
Packit Service |
384592 |
msr->allow_scope = ACTION_ALLOW_PHASE;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
case ACTION_ALLOW_REQUEST :
|
|
Packit Service |
384592 |
status = DECLINED;
|
|
Packit Service |
384592 |
message = apr_psprintf(msr->mp, "Access to request allowed%s.", phase_text);
|
|
Packit Service |
384592 |
msr->was_intercepted = 0;
|
|
Packit Service |
384592 |
msr->allow_scope = ACTION_ALLOW_REQUEST;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
default :
|
|
Packit Service |
384592 |
log_level = 1;
|
|
Packit Service |
384592 |
status = HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit Service |
384592 |
message = apr_psprintf(msr->mp, "Access denied with code 500%s "
|
|
Packit Service |
384592 |
"(Internal Error: invalid interception action %d).",
|
|
Packit Service |
384592 |
phase_text, actionset->intercept_action);
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* If the level is not high enough to add an alert message, but "auditlog"
|
|
Packit Service |
384592 |
* is enabled, then still add the message. */
|
|
Packit Service |
384592 |
if ((log_level > 3) && (actionset->auditlog != 0)) {
|
|
Packit Service |
384592 |
*(const char **)apr_array_push(msr->alerts) = msc_alert_message(msr, actionset, NULL, message);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Log the message now. */
|
|
Packit Service |
384592 |
msc_alert(msr, log_level, actionset, message, msr->intercept_message);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* However, this will mark the txn relevant again if it is <= 3,
|
|
Packit Service |
384592 |
* which will mess up noauditlog. We need to compensate for this
|
|
Packit Service |
384592 |
* so that we do not increment twice when auditlog is enabled and
|
|
Packit Service |
384592 |
* prevent incrementing when auditlog is disabled.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
if ((actionset->auditlog == 0) && (log_level <= 3)) {
|
|
Packit Service |
384592 |
msr->is_relevant--;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return status;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Retrieves a previously stored transaction context by
|
|
Packit Service |
384592 |
* looking at the main request, and the previous requests.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static modsec_rec *retrieve_tx_context(request_rec *r) {
|
|
Packit Service |
384592 |
modsec_rec *msr = NULL;
|
|
Packit Service |
384592 |
request_rec *rx = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Look in the current request first. */
|
|
Packit Service |
384592 |
msr = (modsec_rec *)apr_table_get(r->notes, NOTE_MSR);
|
|
Packit Service |
384592 |
if (msr != NULL) {
|
|
Packit Service |
384592 |
msr->r = r;
|
|
Packit Service |
384592 |
return msr;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* If this is a subrequest then look in the main request. */
|
|
Packit Service |
384592 |
if (r->main != NULL) {
|
|
Packit Service |
384592 |
msr = (modsec_rec *)apr_table_get(r->main->notes, NOTE_MSR);
|
|
Packit Service |
384592 |
if (msr != NULL) {
|
|
Packit Service |
384592 |
msr->r = r;
|
|
Packit Service |
384592 |
return msr;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* If the request was redirected then look in the previous requests. */
|
|
Packit Service |
384592 |
rx = r->prev;
|
|
Packit Service |
384592 |
while(rx != NULL) {
|
|
Packit Service |
384592 |
msr = (modsec_rec *)apr_table_get(rx->notes, NOTE_MSR);
|
|
Packit Service |
384592 |
if (msr != NULL) {
|
|
Packit Service |
384592 |
msr->r = r;
|
|
Packit Service |
384592 |
return msr;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
rx = rx->prev;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return NULL;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Stores transaction context where it can be found in subsequent
|
|
Packit Service |
384592 |
* phases, redirections, or subrequests.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static void store_tx_context(modsec_rec *msr, request_rec *r) {
|
|
Packit Service |
384592 |
apr_table_setn(r->notes, NOTE_MSR, (void *)msr);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Creates a new transaction context.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static modsec_rec *create_tx_context(request_rec *r) {
|
|
Packit Service |
384592 |
apr_allocator_t *allocator = NULL;
|
|
Packit Service |
384592 |
modsec_rec *msr = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
msr = (modsec_rec *)apr_pcalloc(r->pool, sizeof(modsec_rec));
|
|
Packit Service |
384592 |
if (msr == NULL) return NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
apr_allocator_create(&allocator);
|
|
Packit Service |
384592 |
apr_allocator_max_free_set(allocator, 1024);
|
|
Packit Service |
384592 |
apr_pool_create_ex(&msr->mp, r->pool, NULL, allocator);
|
|
Packit Service |
384592 |
if (msr->mp == NULL) return NULL;
|
|
Packit Service |
384592 |
apr_allocator_owner_set(allocator, msr->mp);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
msr->modsecurity = modsecurity;
|
|
Packit Service |
384592 |
msr->r = r;
|
|
Packit Service |
384592 |
msr->r_early = r;
|
|
Packit Service |
384592 |
msr->request_time = r->request_time;
|
|
Packit Service |
384592 |
msr->dcfg1 = (directory_config *)ap_get_module_config(r->per_dir_config,
|
|
Packit Service |
384592 |
&security2_module);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#if defined(WITH_LUA)
|
|
Packit Service |
384592 |
#ifdef CACHE_LUA
|
|
Packit Service |
384592 |
#if LUA_VERSION_NUM > 501
|
|
Packit Service |
384592 |
msr->L = luaL_newstate();
|
|
Packit Service |
384592 |
#else
|
|
Packit Service |
384592 |
msr->L = lua_open();
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
luaL_openlibs(msr->L);
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Create a special user configuration. This is where
|
|
Packit Service |
384592 |
* explicit instructions will be stored. This will be used
|
|
Packit Service |
384592 |
* to override the default settings (and to override the
|
|
Packit Service |
384592 |
* configuration in the second phase, dcfg2, with the user
|
|
Packit Service |
384592 |
* setting executed in the first phase.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
msr->usercfg = create_directory_config(msr->mp, NULL);
|
|
Packit Service |
384592 |
if (msr->usercfg == NULL) return NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Create a transaction context and populate
|
|
Packit Service |
384592 |
* it using the directory config we just
|
|
Packit Service |
384592 |
* got from Apache.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
msr->txcfg = create_directory_config(msr->mp, NULL);
|
|
Packit Service |
384592 |
if (msr->txcfg == NULL) return NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (msr->dcfg1 != NULL) {
|
|
Packit Service |
384592 |
msr->txcfg = merge_directory_configs(msr->mp, msr->txcfg, msr->dcfg1);
|
|
Packit Service |
384592 |
if (msr->txcfg == NULL) return NULL;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
init_directory_config(msr->txcfg);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
msr->txid = get_env_var(r, "UNIQUE_ID");
|
|
Packit Service |
384592 |
if (msr->txid == NULL) {
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r->server,
|
|
Packit Service |
384592 |
"ModSecurity: ModSecurity requires mod_unique_id to be installed.");
|
|
Packit Service |
384592 |
return NULL;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (msr->txcfg->debuglog_level >= 4) {
|
|
Packit Service |
384592 |
msr_log(msr, 4, "Initialising transaction (txid %s).", msr->txid);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Populate tx fields */
|
|
Packit Service |
384592 |
msr->error_messages = apr_array_make(msr->mp, 5, sizeof(error_message_t *));
|
|
Packit Service |
384592 |
msr->alerts = apr_array_make(msr->mp, 5, sizeof(char *));
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
msr->server_software = real_server_signature;
|
|
Packit Service |
384592 |
msr->local_addr = r->connection->local_ip;
|
|
Packit Service |
384592 |
msr->local_port = r->connection->local_addr->port;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER < 3
|
|
Packit Service |
384592 |
msr->remote_addr = r->connection->remote_ip;
|
|
Packit Service |
384592 |
msr->remote_port = r->connection->remote_addr->port;
|
|
Packit Service |
384592 |
#else
|
|
Packit Service |
384592 |
msr->remote_addr = r->connection->client_ip;
|
|
Packit Service |
384592 |
msr->remote_port = r->connection->client_addr->port;
|
|
Packit Service |
384592 |
msr->useragent_ip = r->useragent_ip;
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
msr->request_line = r->the_request;
|
|
Packit Service |
384592 |
msr->request_uri = r->uri;
|
|
Packit Service |
384592 |
msr->request_method = r->method;
|
|
Packit Service |
384592 |
msr->query_string = r->args;
|
|
Packit Service |
384592 |
msr->request_protocol = r->protocol;
|
|
Packit Service |
384592 |
msr->request_headers = apr_table_copy(msr->mp, r->headers_in);
|
|
Packit Service |
384592 |
msr->hostname = ap_get_server_name(r);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
msr->msc_full_request_buffer = NULL;
|
|
Packit Service |
384592 |
msr->msc_full_request_length = 0;
|
|
Packit Service |
384592 |
msr->msc_rule_mptmp = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Invoke the engine to continue with initialisation */
|
|
Packit Service |
384592 |
if (modsecurity_tx_init(msr) < 0) {
|
|
Packit Service |
384592 |
msr_log(msr, 1, "Failed to initialise transaction (txid %s).", msr->txid);
|
|
Packit Service |
384592 |
return NULL;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
store_tx_context(msr, r);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (msr->txcfg->debuglog_level >= 4) {
|
|
Packit Service |
384592 |
msr_log(msr, 4, "Transaction context created (dcfg %pp).", msr->dcfg1);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return msr;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* -- Hooks -- */
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* Change the signature of the server if change was requested in
|
|
Packit Service |
384592 |
* configuration. We do this by locating the signature in server
|
|
Packit Service |
384592 |
* memory and writing over it.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static apr_status_t change_server_signature(server_rec *s) {
|
|
Packit Service |
384592 |
char *server_version = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* This is a very particular way to handle the server banner. It is Apache
|
|
Packit Service |
384592 |
* only. Stanalone and descendants should address that in its specifics
|
|
Packit Service |
384592 |
* implementations, e.g. Nginx module.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
#if !(defined(VERSION_IIS)) && !(defined(VERSION_NGINX)) && !(defined(VERSION_STANDALONE))
|
|
Packit Service |
384592 |
if (new_server_signature == NULL) return 0;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
server_version = (char *)apache_get_server_version();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (server_version == NULL) {
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, s,
|
|
Packit Service |
384592 |
"SecServerSignature: Apache returned null as signature.");
|
|
Packit Service |
384592 |
return -1;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (strlen(server_version) >= strlen(new_server_signature)) {
|
|
Packit Service |
384592 |
strcpy(server_version, new_server_signature);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
else {
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, s,
|
|
Packit Service |
384592 |
"SecServerSignature: original signature too short. Please set "
|
|
Packit Service |
384592 |
"ServerTokens to Full.");
|
|
Packit Service |
384592 |
return -1;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Check that it really changed. This assumes that what we got was
|
|
Packit Service |
384592 |
* not a copy and this could change in future versions of Apache.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
server_version = (char *)apache_get_server_version();
|
|
Packit Service |
384592 |
if ((server_version == NULL) || (strcmp(server_version, new_server_signature) != 0)) {
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, s, "SecServerSignature: Failed to change server signature to \"%s\".", new_server_signature);
|
|
Packit Service |
384592 |
return 0;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
else {
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, s, "SecServerSignature: Changed server signature to \"%s\".", server_version);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
return 1;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Executed at the end of server lifetime to cleanup the allocated resources.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static apr_status_t module_cleanup(void *data) {
|
|
Packit Service |
384592 |
modsecurity_shutdown(modsecurity);
|
|
Packit Service |
384592 |
return APR_SUCCESS;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Generate a single variable for use with mod_log_config.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static const char *modsec_var_log_handler(request_rec *r, char *name) {
|
|
Packit Service |
384592 |
modsec_rec *msr = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (name == NULL) return NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
msr = retrieve_tx_context(r);
|
|
Packit Service |
384592 |
if (msr == NULL) return NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return construct_single_var(msr, name);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Pre-configuration initialisation hook.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static int hook_pre_config(apr_pool_t *mp, apr_pool_t *mp_log, apr_pool_t *mp_temp) {
|
|
Packit Service |
384592 |
static APR_OPTIONAL_FN_TYPE(ap_register_log_handler) *log_pfn_register;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Initialise ModSecurity engine */
|
|
Packit Service |
384592 |
modsecurity = modsecurity_create(mp, MODSEC_ONLINE);
|
|
Packit Service |
384592 |
if (modsecurity == NULL) {
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
|
|
Packit Service |
384592 |
"ModSecurity: Failed to initialise engine.");
|
|
Packit Service |
384592 |
return HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
log_pfn_register = APR_RETRIEVE_OPTIONAL_FN(ap_register_log_handler);
|
|
Packit Service |
384592 |
if (log_pfn_register) {
|
|
Packit Service |
384592 |
log_pfn_register(mp, "M", modsec_var_log_handler, 0);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return OK;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Main (post-configuration) module initialisation.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static int hook_post_config(apr_pool_t *mp, apr_pool_t *mp_log, apr_pool_t *mp_temp, server_rec *s) {
|
|
Packit Service |
384592 |
void *init_flag = NULL;
|
|
Packit Service |
384592 |
int first_time = 0;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* ENH Figure out a way to validate config before we start
|
|
Packit Service |
384592 |
* - skipafter: need to make sure we found all of our targets
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Figure out if we are here for the first time */
|
|
Packit Service |
384592 |
apr_pool_userdata_get(&init_flag, "modsecurity-init-flag", s->process->pool);
|
|
Packit Service |
384592 |
if (init_flag == NULL) {
|
|
Packit Service |
384592 |
first_time = 1;
|
|
Packit Service |
384592 |
apr_pool_userdata_set((const void *)1, "modsecurity-init-flag",
|
|
Packit Service |
384592 |
apr_pool_cleanup_null, s->process->pool);
|
|
Packit Service |
384592 |
} else {
|
|
Packit Service |
384592 |
modsecurity_init(modsecurity, mp);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Store the original server signature */
|
|
Packit Service |
384592 |
real_server_signature = apr_pstrdup(mp, apache_get_server_version());
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Make some space in the server signature for later */
|
|
Packit Service |
384592 |
if (new_server_signature != NULL) {
|
|
Packit Service |
384592 |
ap_add_version_component(mp, new_server_signature);
|
|
Packit Service |
384592 |
change_server_signature(s);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* For connection level hook */
|
|
Packit Service |
384592 |
ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
|
|
Packit Service |
384592 |
ap_mpm_query(AP_MPMQ_HARD_LIMIT_DAEMONS, &server_limit);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#if (!(defined(WIN32) || defined(NETWARE)))
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Internal chroot functionality */
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (chroot_dir != NULL) {
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* ENH Is it safe to simply return with an error, instead
|
|
Packit Service |
384592 |
* of using exit()?
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (first_time == 0) {
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_NOTICE | APLOG_NOERRNO, 0, s,
|
|
Packit Service |
384592 |
"ModSecurity: chroot checkpoint #2 (pid=%ld ppid=%ld)", (long)getpid(), (long)getppid());
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (chdir(chroot_dir) < 0) {
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, s,
|
|
Packit Service |
384592 |
"ModSecurity: chroot failed, unable to chdir to %s, errno=%d (%s)",
|
|
Packit Service |
384592 |
chroot_dir, errno, strerror(errno));
|
|
Packit Service |
384592 |
exit(1);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (chroot(chroot_dir) < 0) {
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, s,
|
|
Packit Service |
384592 |
"ModSecurity: chroot failed, path=%s, errno=%d(%s)",
|
|
Packit Service |
384592 |
chroot_dir, errno, strerror(errno));
|
|
Packit Service |
384592 |
exit(1);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (chdir("/") < 0) {
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, s,
|
|
Packit Service |
384592 |
"ModSecurity: chdoot failed, unable to chdir to /, errno=%d (%s)",
|
|
Packit Service |
384592 |
errno, strerror(errno));
|
|
Packit Service |
384592 |
exit(1);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_NOTICE | APLOG_NOERRNO, 0, s,
|
|
Packit Service |
384592 |
"ModSecurity: chroot successful, path=%s", chroot_dir);
|
|
Packit Service |
384592 |
} else {
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_NOTICE | APLOG_NOERRNO, 0, s,
|
|
Packit Service |
384592 |
"ModSecurity: chroot checkpoint #1 (pid=%ld ppid=%ld)", (long)getpid(), (long)getppid());
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Schedule main cleanup for later, when the main pool is destroyed. */
|
|
Packit Service |
384592 |
apr_pool_cleanup_register(mp, (void *)s, module_cleanup, apr_pool_cleanup_null);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Log our presence to the error log. */
|
|
Packit Service |
384592 |
if (first_time) {
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_NOTICE | APLOG_NOERRNO, 0, s,
|
|
Packit Service |
384592 |
"%s configured.", MODSEC_MODULE_NAME_FULL);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
version(mp);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* If we've changed the server signature make note of the original. */
|
|
Packit Service |
384592 |
if (new_server_signature != NULL) {
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_NOTICE | APLOG_NOERRNO, 0, s,
|
|
Packit Service |
384592 |
"ModSecurity: Original server signature: %s",
|
|
Packit Service |
384592 |
real_server_signature);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#ifndef VERSION_IIS
|
|
Packit Service |
384592 |
if (status_engine_state != STATUS_ENGINE_DISABLED) {
|
|
Packit Service |
384592 |
msc_status_engine_call();
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
else {
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
|
|
Packit Service |
384592 |
"ModSecurity: Status engine is currently disabled, enable " \
|
|
Packit Service |
384592 |
"it by set SecStatusEngine to On.");
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Checking if it is not the first time that we are in this very function.
|
|
Packit Service |
384592 |
* We want to show the messages below during the start and the reload.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
#ifndef VERSION_IIS
|
|
Packit Service |
384592 |
if (first_time != 1)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
#ifdef WITH_REMOTE_RULES
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (remote_rules_server != NULL)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
if (remote_rules_server->amount_of_rules == 1)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
|
|
Packit Service |
384592 |
"ModSecurity: Loaded %d rule from: '%s'.",
|
|
Packit Service |
384592 |
remote_rules_server->amount_of_rules,
|
|
Packit Service |
384592 |
remote_rules_server->uri);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
else
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
|
|
Packit Service |
384592 |
"ModSecurity: Loaded %d rules from: '%s'.",
|
|
Packit Service |
384592 |
remote_rules_server->amount_of_rules,
|
|
Packit Service |
384592 |
remote_rules_server->uri);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
if (remote_rules_fail_message != NULL)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL, "ModSecurity: " \
|
|
Packit Service |
384592 |
"Problems loading external resources: %s",
|
|
Packit Service |
384592 |
remote_rules_fail_message);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
srand((unsigned int)(time(NULL) * getpid()));
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return OK;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Initialisation performed for every new child process.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static void hook_child_init(apr_pool_t *mp, server_rec *s) {
|
|
Packit Service |
384592 |
modsecurity_child_init(modsecurity);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Initial request processing, executed immediatelly after
|
|
Packit Service |
384592 |
* Apache receives the request headers. This function wil create
|
|
Packit Service |
384592 |
* a transaction context.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static int hook_request_early(request_rec *r) {
|
|
Packit Service |
384592 |
modsec_rec *msr = NULL;
|
|
Packit Service |
384592 |
int rc = DECLINED;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* This function needs to run only once per transaction
|
|
Packit Service |
384592 |
* (i.e. subrequests and redirects are excluded).
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
if ((r->main != NULL)||(r->prev != NULL)) {
|
|
Packit Service |
384592 |
return DECLINED;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Initialise transaction context and
|
|
Packit Service |
384592 |
* create the initial configuration.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
msr = create_tx_context(r);
|
|
Packit Service |
384592 |
if (msr == NULL) return DECLINED;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#ifdef REQUEST_EARLY
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Are we allowed to continue? */
|
|
Packit Service |
384592 |
if (msr->txcfg->is_enabled == MODSEC_DISABLED) {
|
|
Packit Service |
384592 |
if (msr->txcfg->debuglog_level >= 4) {
|
|
Packit Service |
384592 |
msr_log(msr, 4, "Processing disabled, skipping (hook request_early).");
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
return DECLINED;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Process phase REQUEST_HEADERS */
|
|
Packit Service |
384592 |
if (modsecurity_process_phase(msr, PHASE_REQUEST_HEADERS) > 0) {
|
|
Packit Service |
384592 |
rc = perform_interception(msr);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if ( (msr->txcfg->is_enabled != MODSEC_DISABLED)
|
|
Packit Service |
384592 |
&& (msr->txcfg->reqbody_access == 1)
|
|
Packit Service |
384592 |
&& (rc == DECLINED))
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
/* Check request body limit (non-chunked requests only). */
|
|
Packit Service |
384592 |
if (msr->request_content_length > msr->txcfg->reqbody_limit) {
|
|
Packit Service |
384592 |
msr_log(msr, 1, "Request body (Content-Length) is larger than the "
|
|
Packit Service |
384592 |
"configured limit (%ld).", msr->txcfg->reqbody_limit);
|
|
Packit Service |
384592 |
if(msr->txcfg->is_enabled != MODSEC_DETECTION_ONLY && msr->txcfg->if_limit_action != REQUEST_BODY_LIMIT_ACTION_PARTIAL)
|
|
Packit Service |
384592 |
return HTTP_REQUEST_ENTITY_TOO_LARGE;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
return rc;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Invoked as the first hook in the handler chain, this function
|
|
Packit Service |
384592 |
* executes the second phase of ModSecurity request processing.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static int hook_request_late(request_rec *r) {
|
|
Packit Service |
384592 |
char *my_error_msg = NULL;
|
|
Packit Service |
384592 |
modsec_rec *msr = NULL;
|
|
Packit Service |
384592 |
int rc;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* This function needs to run only once per transaction
|
|
Packit Service |
384592 |
* (i.e. subrequests and redirects are excluded).
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
if ((r->main != NULL)||(r->prev != NULL)) {
|
|
Packit Service |
384592 |
return DECLINED;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Find the transaction context and make sure
|
|
Packit Service |
384592 |
* we are supposed to proceed.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
msr = retrieve_tx_context(r);
|
|
Packit Service |
384592 |
if (msr == NULL) {
|
|
Packit Service |
384592 |
/* If we can't find the context that probably means it's
|
|
Packit Service |
384592 |
* a subrequest that was not initiated from the outside.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
return DECLINED;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Has this phase been completed already? */
|
|
Packit Service |
384592 |
if (msr->phase_request_body_complete) {
|
|
Packit Service |
384592 |
msr_log(msr, 1, "Internal Error: Attempted to process the request body more than once.");
|
|
Packit Service |
384592 |
return DECLINED;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
msr->phase_request_body_complete = 1;
|
|
Packit Service |
384592 |
msr->remote_user = r->user;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Get the second configuration context. */
|
|
Packit Service |
384592 |
msr->dcfg2 = (directory_config *)ap_get_module_config(r->per_dir_config,
|
|
Packit Service |
384592 |
&security2_module);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Create a transaction context. */
|
|
Packit Service |
384592 |
msr->txcfg = create_directory_config(msr->mp, NULL);
|
|
Packit Service |
384592 |
if (msr->txcfg == NULL) return DECLINED;
|
|
Packit Service |
384592 |
if (msr->dcfg2 != NULL) {
|
|
Packit Service |
384592 |
msr->txcfg = merge_directory_configs(msr->mp, msr->txcfg, msr->dcfg2);
|
|
Packit Service |
384592 |
if (msr->txcfg == NULL) return DECLINED;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Update with the explicit user settings. */
|
|
Packit Service |
384592 |
msr->txcfg = merge_directory_configs(msr->mp, msr->txcfg, msr->usercfg);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
init_directory_config(msr->txcfg);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (msr->txcfg->is_enabled == 0) {
|
|
Packit Service |
384592 |
if (msr->txcfg->debuglog_level >= 4) {
|
|
Packit Service |
384592 |
msr_log(msr, 4, "Processing disabled, skipping (hook request_late).");
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
return DECLINED;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#ifndef REQUEST_EARLY
|
|
Packit Service |
384592 |
/* Phase 1 */
|
|
Packit Service |
384592 |
if (msr->txcfg->debuglog_level >= 4) {
|
|
Packit Service |
384592 |
msr_log(msr, 4, "First phase starting (dcfg %pp).", msr->dcfg2);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Process phase REQUEST_HEADERS */
|
|
Packit Service |
384592 |
if (modsecurity_process_phase(msr, PHASE_REQUEST_HEADERS) > 0) {
|
|
Packit Service |
384592 |
/* There was a match; see if we need to intercept. */
|
|
Packit Service |
384592 |
rc = perform_interception(msr);
|
|
Packit Service |
384592 |
if (rc != DECLINED) {
|
|
Packit Service |
384592 |
/* Intercepted */
|
|
Packit Service |
384592 |
return rc;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* The rule engine could have been disabled in phase 1. */
|
|
Packit Service |
384592 |
if (msr->txcfg->is_enabled == MODSEC_DISABLED) {
|
|
Packit Service |
384592 |
if (msr->txcfg->debuglog_level >= 4) {
|
|
Packit Service |
384592 |
msr_log(msr, 4, "Skipping phase 2 as the rule engine was disabled by a rule in phase 1.");
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return DECLINED;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Phase 2 */
|
|
Packit Service |
384592 |
if (msr->txcfg->debuglog_level >= 4) {
|
|
Packit Service |
384592 |
msr_log(msr, 4, "Second phase starting (dcfg %pp).", msr->dcfg2);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Check that the request body is not too long, but only
|
|
Packit Service |
384592 |
* if configuration allows for request body access.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
msr->inbound_error = 0;
|
|
Packit Service |
384592 |
if (msr->txcfg->reqbody_access == 1) {
|
|
Packit Service |
384592 |
/* Check request body limit (non-chunked requests only). */
|
|
Packit Service |
384592 |
if (msr->request_content_length > msr->txcfg->reqbody_limit) {
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if((msr->txcfg->is_enabled == MODSEC_ENABLED) && (msr->txcfg->if_limit_action == REQUEST_BODY_LIMIT_ACTION_REJECT)) {
|
|
Packit Service |
384592 |
msr->inbound_error = 1;
|
|
Packit Service |
384592 |
msr_log(msr, 1, "Request body (Content-Length) is larger than the "
|
|
Packit Service |
384592 |
"configured limit (%ld). Deny with status (%d)", msr->txcfg->reqbody_limit, HTTP_REQUEST_ENTITY_TOO_LARGE);
|
|
Packit Service |
384592 |
return HTTP_REQUEST_ENTITY_TOO_LARGE;
|
|
Packit Service |
384592 |
} else if ((msr->txcfg->is_enabled == MODSEC_ENABLED) && (msr->txcfg->if_limit_action == REQUEST_BODY_LIMIT_ACTION_PARTIAL)){
|
|
Packit Service |
384592 |
msr->inbound_error = 1;
|
|
Packit Service |
384592 |
msr_log(msr, 1, "Request body (Content-Length) is larger than the "
|
|
Packit Service |
384592 |
"configured limit (%ld).", msr->txcfg->reqbody_limit);
|
|
Packit Service |
384592 |
} else if ((msr->txcfg->is_enabled == MODSEC_DETECTION_ONLY) && (msr->txcfg->if_limit_action == REQUEST_BODY_LIMIT_ACTION_PARTIAL)){
|
|
Packit Service |
384592 |
msr_log(msr, 1, "Request body (Content-Length) is larger than the "
|
|
Packit Service |
384592 |
"configured limit (%ld).", msr->txcfg->reqbody_limit);
|
|
Packit Service |
384592 |
msr->inbound_error = 1;
|
|
Packit Service |
384592 |
} else {
|
|
Packit Service |
384592 |
msr_log(msr, 1, "Request body (Content-Length) is larger than the "
|
|
Packit Service |
384592 |
"configured limit (%ld).", msr->txcfg->reqbody_limit);
|
|
Packit Service |
384592 |
msr->inbound_error = 1;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Figure out whether to extract multipart files. */
|
|
Packit Service |
384592 |
if ((msr->txcfg->upload_keep_files != KEEP_FILES_OFF) /* user might want to keep them */
|
|
Packit Service |
384592 |
|| (msr->txcfg->upload_validates_files)) /* user might want to validate them */
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
msr->upload_extract_files = 1;
|
|
Packit Service |
384592 |
msr->upload_remove_files = 1;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
rc = read_request_body(msr, &my_error_msg);
|
|
Packit Service |
384592 |
if (rc < 0) {
|
|
Packit Service |
384592 |
switch(rc) {
|
|
Packit Service |
384592 |
case -1 :
|
|
Packit Service |
384592 |
if (my_error_msg != NULL) {
|
|
Packit Service |
384592 |
msr_log(msr, 1, "%s", my_error_msg);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
return HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case -4 : /* Timeout. */
|
|
Packit Service |
384592 |
if (my_error_msg != NULL) {
|
|
Packit Service |
384592 |
msr_log(msr, 4, "%s", my_error_msg);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
r->connection->keepalive = AP_CONN_CLOSE;
|
|
Packit Service |
384592 |
return HTTP_REQUEST_TIME_OUT;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case -5 : /* Request body limit reached. */
|
|
Packit Service |
384592 |
msr->inbound_error = 1;
|
|
Packit Service |
384592 |
if((msr->txcfg->is_enabled == MODSEC_ENABLED) && (msr->txcfg->if_limit_action == REQUEST_BODY_LIMIT_ACTION_REJECT)) {
|
|
Packit Service |
384592 |
r->connection->keepalive = AP_CONN_CLOSE;
|
|
Packit Service |
384592 |
if (my_error_msg != NULL) {
|
|
Packit Service |
384592 |
msr_log(msr, 1, "%s. Deny with code (%d)", my_error_msg, HTTP_REQUEST_ENTITY_TOO_LARGE);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
return HTTP_REQUEST_ENTITY_TOO_LARGE;
|
|
Packit Service |
384592 |
} else {
|
|
Packit Service |
384592 |
if (my_error_msg != NULL) {
|
|
Packit Service |
384592 |
msr_log(msr, 1, "%s", my_error_msg);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case -6 : /* EOF when reading request body. */
|
|
Packit Service |
384592 |
if (my_error_msg != NULL) {
|
|
Packit Service |
384592 |
msr_log(msr, 4, "%s", my_error_msg);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
r->connection->keepalive = AP_CONN_CLOSE;
|
|
Packit Service |
384592 |
return HTTP_BAD_REQUEST;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case -7 : /* Partial recieved */
|
|
Packit Service |
384592 |
if (my_error_msg != NULL) {
|
|
Packit Service |
384592 |
msr_log(msr, 4, "%s", my_error_msg);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
r->connection->keepalive = AP_CONN_CLOSE;
|
|
Packit Service |
384592 |
return HTTP_BAD_REQUEST;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
default :
|
|
Packit Service |
384592 |
/* allow through */
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
msr->msc_reqbody_error = 1;
|
|
Packit Service |
384592 |
msr->msc_reqbody_error_msg = my_error_msg;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Update the request headers. They might have changed after
|
|
Packit Service |
384592 |
* the body was read (trailers).
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* TODO We might still want to hold onto the original headers
|
|
Packit Service |
384592 |
* so that we can log them. Keeping them is probably not
|
|
Packit Service |
384592 |
* going to increase our memory requirements (because all
|
|
Packit Service |
384592 |
* headers are allocated from the request memory pool
|
|
Packit Service |
384592 |
* anyway).
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
msr->request_headers = apr_table_copy(msr->mp, r->headers_in);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Process phase REQUEST_BODY */
|
|
Packit Service |
384592 |
rc = DECLINED;
|
|
Packit Service |
384592 |
if (modsecurity_process_phase(msr, PHASE_REQUEST_BODY) > 0) {
|
|
Packit Service |
384592 |
rc = perform_interception(msr);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(msr->txcfg->stream_inbody_inspection && msr->msc_reqbody_read) {
|
|
Packit Service |
384592 |
const char *clen = NULL;
|
|
Packit Service |
384592 |
clen = apr_psprintf(msr->mp,"%"APR_SIZE_T_FMT,msr->stream_input_length);
|
|
Packit Service |
384592 |
if(clen)
|
|
Packit Service |
384592 |
apr_table_setn(r->headers_in, "Content-Length",clen);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Remove the compression ability indications the client set,
|
|
Packit Service |
384592 |
* but only if we need to disable backend compression.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
if (msr->txcfg->disable_backend_compression) {
|
|
Packit Service |
384592 |
apr_table_unset(r->headers_in, "Accept-Encoding");
|
|
Packit Service |
384592 |
apr_table_unset(r->headers_in, "TE");
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return rc;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Invoked every time Apache has something to write to the error log.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
|
|
Packit Service |
384592 |
static void hook_error_log(const ap_errorlog_info *info, const char *errstr)
|
|
Packit Service |
384592 |
#else
|
|
Packit Service |
384592 |
static void hook_error_log(const char *file, int line, int level, apr_status_t status,
|
|
Packit Service |
384592 |
const server_rec *s, const request_rec *r, apr_pool_t *mp, const char *fmt)
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
modsec_rec *msr = NULL;
|
|
Packit Service |
384592 |
error_message_t *em = NULL;
|
|
Packit Service |
384592 |
int msr_ap_server;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
|
|
Packit Service |
384592 |
if (info == NULL) return;
|
|
Packit Service |
384592 |
if (info->r == NULL) return;
|
|
Packit Service |
384592 |
#else
|
|
Packit Service |
384592 |
if (r == NULL) return;
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
|
|
Packit Service |
384592 |
msr = retrieve_tx_context((request_rec *)info->r);
|
|
Packit Service |
384592 |
#else
|
|
Packit Service |
384592 |
msr = retrieve_tx_context((request_rec *)r);
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Create a context for requests we never had the chance to process */
|
|
Packit Service |
384592 |
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
|
|
Packit Service |
384592 |
msr_ap_server = ((msr == NULL)
|
|
Packit Service |
384592 |
&& ((info->level & APLOG_LEVELMASK) < APLOG_DEBUG)
|
|
Packit Service |
384592 |
&& apr_table_get(info->r->subprocess_env, "UNIQUE_ID"));
|
|
Packit Service |
384592 |
#else
|
|
Packit Service |
384592 |
msr_ap_server = ((msr == NULL)
|
|
Packit Service |
384592 |
&& ((level & APLOG_LEVELMASK) < APLOG_DEBUG)
|
|
Packit Service |
384592 |
&& apr_table_get(r->subprocess_env, "UNIQUE_ID"));
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
if (msr_ap_server) {
|
|
Packit Service |
384592 |
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
|
|
Packit Service |
384592 |
msr = create_tx_context((request_rec *)info->r);
|
|
Packit Service |
384592 |
#else
|
|
Packit Service |
384592 |
msr = create_tx_context((request_rec *)r);
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
if (msr != NULL && msr->txcfg->debuglog_level >= 9) {
|
|
Packit Service |
384592 |
if (msr == NULL) {
|
|
Packit Service |
384592 |
msr_log(msr, 9, "Failed to create context after request failure.");
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
else {
|
|
Packit Service |
384592 |
msr_log(msr, 9, "Context created after request failure.");
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
if (msr == NULL) return;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Store the error message for later */
|
|
Packit Service |
384592 |
em = (error_message_t *)apr_pcalloc(msr->mp, sizeof(error_message_t));
|
|
Packit Service |
384592 |
if (em == NULL) return;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
|
|
Packit Service |
384592 |
if (info->file != NULL) em->file = apr_pstrdup(msr->mp, info->file);
|
|
Packit Service |
384592 |
em->line = info->line;
|
|
Packit Service |
384592 |
em->level = info->level;
|
|
Packit Service |
384592 |
em->status = info->status;
|
|
Packit Service |
384592 |
em->message = apr_pstrdup(msr->mp, errstr);
|
|
Packit Service |
384592 |
#else
|
|
Packit Service |
384592 |
if (file != NULL) em->file = apr_pstrdup(msr->mp, file);
|
|
Packit Service |
384592 |
em->line = line;
|
|
Packit Service |
384592 |
em->level = level;
|
|
Packit Service |
384592 |
em->status = status;
|
|
Packit Service |
384592 |
if (fmt != NULL) em->message = apr_pstrdup(msr->mp, fmt);
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
/* Remove \n from the end of the message */
|
|
Packit Service |
384592 |
if (em->message != NULL) {
|
|
Packit Service |
384592 |
char *p = (char *)em->message;
|
|
Packit Service |
384592 |
while(*p != '\0') {
|
|
Packit Service |
384592 |
if ((*(p + 1) == '\0')&&(*p == '\n')) {
|
|
Packit Service |
384592 |
*p = '\0';
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
p++;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
*(const error_message_t **)apr_array_push(msr->error_messages) = em;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Guardian logger is used to interface to the external
|
|
Packit Service |
384592 |
* script for web server protection - httpd_guardian.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static void sec_guardian_logger(request_rec *r, request_rec *origr, modsec_rec *msr) {
|
|
Packit Service |
384592 |
char *str1, *str2, *text;
|
|
Packit Service |
384592 |
char *modsec_message = "-";
|
|
Packit Service |
384592 |
int modsec_rating = 0; /* not used yet */
|
|
Packit Service |
384592 |
apr_size_t nbytes, nbytes_written;
|
|
Packit Service |
384592 |
apr_time_t duration = (apr_time_now() - origr->request_time);
|
|
Packit Service |
384592 |
int limit, was_limited;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* bail out if we do not have where to write */
|
|
Packit Service |
384592 |
if ((guardianlog_name == NULL)||(guardianlog_fd == NULL)) return;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* process the condition, if we have one */
|
|
Packit Service |
384592 |
if (guardianlog_condition != NULL) {
|
|
Packit Service |
384592 |
if (*guardianlog_condition == '!') {
|
|
Packit Service |
384592 |
if (apr_table_get(r->subprocess_env, guardianlog_condition + 1) != NULL) {
|
|
Packit Service |
384592 |
return;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
else {
|
|
Packit Service |
384592 |
if (apr_table_get(r->subprocess_env, guardianlog_condition) == NULL) {
|
|
Packit Service |
384592 |
return;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* Log format is as follows:
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* %V %h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-agent}i" %{UNIQUE_ID}e
|
|
Packit Service |
384592 |
* "SESSION_ID" %T %D "MODSEC_MESSAGE" MODSEC_RATING
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* The fields SESSION_ID, MODSEC_MESSAGE, and MODSEC_RATING are not used at the moment.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
str2 = apr_psprintf(msr->mp, "%" APR_TIME_T_FMT " %" APR_TIME_T_FMT " \"%s\" %d",
|
|
Packit Service |
384592 |
duration, apr_time_sec(duration), log_escape(msr->mp, modsec_message), modsec_rating);
|
|
Packit Service |
384592 |
if (str2 == NULL) return;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* We do not want the index line to be longer than 3980 bytes. */
|
|
Packit Service |
384592 |
limit = 3980;
|
|
Packit Service |
384592 |
was_limited = 0;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* If we are logging to a pipe we need to observe and
|
|
Packit Service |
384592 |
* obey the pipe atomic write limit - PIPE_BUF. For
|
|
Packit Service |
384592 |
* more details see the discussion in sec_guardian_logger,
|
|
Packit Service |
384592 |
* above.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
if (msr->txcfg->auditlog_name[0] == '|') {
|
|
Packit Service |
384592 |
if (PIPE_BUF < limit) {
|
|
Packit Service |
384592 |
limit = PIPE_BUF;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
limit = limit - strlen(str2) - 5;
|
|
Packit Service |
384592 |
if (limit <= 0) {
|
|
Packit Service |
384592 |
msr_log(msr, 1, "Audit Log: Atomic PIPE write buffer too small: %d", PIPE_BUF);
|
|
Packit Service |
384592 |
return;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
str1 = construct_log_vcombinedus_limited(msr, limit, &was_limited);
|
|
Packit Service |
384592 |
if (str1 == NULL) return;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (was_limited == 0) {
|
|
Packit Service |
384592 |
text = apr_psprintf(msr->mp, "%s %s \n", str1, str2);
|
|
Packit Service |
384592 |
} else {
|
|
Packit Service |
384592 |
text = apr_psprintf(msr->mp, "%s %s L\n", str1, str2);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
if (text == NULL) return;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
nbytes = strlen(text);
|
|
Packit Service |
384592 |
apr_file_write_full(guardianlog_fd, text, nbytes, &nbytes_written);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Invoked at the end of each transaction.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static int hook_log_transaction(request_rec *r) {
|
|
Packit Service |
384592 |
const apr_array_header_t *arr = NULL;
|
|
Packit Service |
384592 |
request_rec *origr = NULL;
|
|
Packit Service |
384592 |
modsec_rec *msr = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
msr = retrieve_tx_context(r);
|
|
Packit Service |
384592 |
if (msr == NULL) {
|
|
Packit Service |
384592 |
return DECLINED;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (msr->txcfg->debuglog_level >= 4) {
|
|
Packit Service |
384592 |
msr_log(msr, 4, "Initialising logging.");
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Find the first (origr) and the last (r) request */
|
|
Packit Service |
384592 |
origr = r;
|
|
Packit Service |
384592 |
while(origr->prev) {
|
|
Packit Service |
384592 |
origr = origr->prev;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
while(r->next) {
|
|
Packit Service |
384592 |
r = r->next;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* At this point r is the last request in the
|
|
Packit Service |
384592 |
* chain. However, we now need to detect a case when
|
|
Packit Service |
384592 |
* a bad ErrorDocument was used and back out of it. That's
|
|
Packit Service |
384592 |
* how Apache does it internally. Except where Apache knows
|
|
Packit Service |
384592 |
* exactly what is happening we will have to rely on the missing
|
|
Packit Service |
384592 |
* headers in the final request to detect this condition.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
arr = apr_table_elts(r->headers_out);
|
|
Packit Service |
384592 |
while ((arr->nelts == 0)&&(r->prev != NULL)) {
|
|
Packit Service |
384592 |
r = r->prev;
|
|
Packit Service |
384592 |
arr = apr_table_elts(r->headers_out);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
msr->r = r;
|
|
Packit Service |
384592 |
msr->response_status = r->status;
|
|
Packit Service |
384592 |
msr->status_line = ((r->status_line != NULL)
|
|
Packit Service |
384592 |
? r->status_line : ap_get_status_line(r->status));
|
|
Packit Service |
384592 |
msr->response_protocol = get_response_protocol(origr);
|
|
Packit Service |
384592 |
msr->response_headers = apr_table_copy(msr->mp, r->headers_out);
|
|
Packit Service |
384592 |
if (!r->assbackwards) msr->response_headers_sent = 1;
|
|
Packit Service |
384592 |
msr->bytes_sent = r->bytes_sent;
|
|
Packit Service |
384592 |
msr->local_user = r->user;
|
|
Packit Service |
384592 |
msr->remote_user = r->connection->remote_logname;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* -- Guardian -- */
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
sec_guardian_logger(r, origr, msr);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Invoke the engine to do the rest of the work now. */
|
|
Packit Service |
384592 |
modsecurity_process_phase(msr, PHASE_LOGGING);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return DECLINED;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Invoked right before request processing begins. This is
|
|
Packit Service |
384592 |
* when we need to decide if we want to hook into the output
|
|
Packit Service |
384592 |
* filter chain.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static void hook_insert_filter(request_rec *r) {
|
|
Packit Service |
384592 |
modsec_rec *msr = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Find the transaction context first. */
|
|
Packit Service |
384592 |
msr = retrieve_tx_context(r);
|
|
Packit Service |
384592 |
if (msr == NULL) return;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Add the input filter, but only if we need it to run. */
|
|
Packit Service |
384592 |
if (msr->if_status == IF_STATUS_WANTS_TO_RUN) {
|
|
Packit Service |
384592 |
if (msr->txcfg->debuglog_level >= 4) {
|
|
Packit Service |
384592 |
msr_log(msr, 4, "Hook insert_filter: Adding input forwarding filter %s(r %pp).",
|
|
Packit Service |
384592 |
(((r->main != NULL)||(r->prev != NULL)) ? "for subrequest " : ""), r);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ap_add_input_filter("MODSECURITY_IN", msr, r, r->connection);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* The output filters only need to be added only once per transaction
|
|
Packit Service |
384592 |
* (i.e. subrequests and redirects are excluded).
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
if ((r->main != NULL)||(r->prev != NULL)) {
|
|
Packit Service |
384592 |
return;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Only proceed to add the second filter if the engine is enabled. */
|
|
Packit Service |
384592 |
if (msr->txcfg->is_enabled == 0) {
|
|
Packit Service |
384592 |
if (msr->txcfg->debuglog_level >= 4) {
|
|
Packit Service |
384592 |
msr_log(msr, 4, "Hook insert_filter: Processing disabled, skipping.");
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* We always add the output filter because that's where we need to
|
|
Packit Service |
384592 |
* initiate our 3rd and 4th processing phases from. The filter is
|
|
Packit Service |
384592 |
* smart enough not to buffer the data if it is not supposed to.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
if (msr->of_status != OF_STATUS_COMPLETE) {
|
|
Packit Service |
384592 |
if (msr->txcfg->debuglog_level >= 4) {
|
|
Packit Service |
384592 |
msr_log(msr, 4, "Hook insert_filter: Adding output filter (r %pp).", r);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ap_add_output_filter("MODSECURITY_OUT", msr, r, r->connection);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
// TODO: Holding off on this for now (needs more testing)
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Invoked whenever Apache starts processing an error. A chance
|
|
Packit Service |
384592 |
* to insert ourselves into the output filter chain.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static void hook_insert_error_filter(request_rec *r) {
|
|
Packit Service |
384592 |
modsec_rec *msr = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Find the transaction context and make sure we are
|
|
Packit Service |
384592 |
* supposed to proceed.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
msr = retrieve_tx_context(r);
|
|
Packit Service |
384592 |
if (msr == NULL) return;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Do not run if not enabled. */
|
|
Packit Service |
384592 |
if (msr->txcfg->is_enabled == 0) {
|
|
Packit Service |
384592 |
if (msr->txcfg->debuglog_level >= 4) {
|
|
Packit Service |
384592 |
msr_log(msr, 4, "Hook insert_error_filter: Processing disabled, skipping.");
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
return;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Do not run if the output filter already completed. This will
|
|
Packit Service |
384592 |
* happen if we intercept in phase 4.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
if (msr->of_status != OF_STATUS_COMPLETE) {
|
|
Packit Service |
384592 |
if (msr->txcfg->debuglog_level >= 4) {
|
|
Packit Service |
384592 |
msr_log(msr, 4, "Hook insert_error_filter: Adding output filter (r %pp).", r);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Make a note that the output we will be receiving is a
|
|
Packit Service |
384592 |
* result of error processing.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
msr->of_is_error = 1;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ap_add_output_filter("MODSECURITY_OUT", msr, r, r->connection);
|
|
Packit Service |
384592 |
} else {
|
|
Packit Service |
384592 |
if (msr->txcfg->debuglog_level >= 4) {
|
|
Packit Service |
384592 |
msr_log(msr, 4, "Hook insert_error_filter: Output buffering already complete.");
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#if (!defined(NO_MODSEC_API))
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* This function is exported for other Apache modules to
|
|
Packit Service |
384592 |
* register new transformation functions.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static void modsec_register_tfn(const char *name, void *fn) {
|
|
Packit Service |
384592 |
if (modsecurity != NULL) {
|
|
Packit Service |
384592 |
msre_engine_tfn_register(modsecurity->msre, name, (fn_tfn_execute_t)fn);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* This function is exported for other Apache modules to
|
|
Packit Service |
384592 |
* register new operators.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static void modsec_register_operator(const char *name, void *fn_init, void *fn_exec) {
|
|
Packit Service |
384592 |
if (modsecurity != NULL) {
|
|
Packit Service |
384592 |
msre_engine_op_register(modsecurity->msre, name, (fn_op_param_init_t)fn_init, (fn_op_execute_t)fn_exec);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
|
|
Packit Service |
384592 |
#else
|
|
Packit Service |
384592 |
typedef struct {
|
|
Packit Service |
384592 |
int child_num;
|
|
Packit Service |
384592 |
int thread_num;
|
|
Packit Service |
384592 |
} sb_handle;
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* \brief Connetion hook to limit the number of
|
|
Packit Service |
384592 |
* connections in BUSY state
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* \param conn Pointer to connection struct
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* \retval DECLINED On failure
|
|
Packit Service |
384592 |
* \retval OK On Success
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static int hook_connection_early(conn_rec *conn)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
|
|
Packit Service |
384592 |
ap_sb_handle_t *sbh = conn->sbh;
|
|
Packit Service |
384592 |
char *client_ip = conn->client_ip;
|
|
Packit Service |
384592 |
#else
|
|
Packit Service |
384592 |
sb_handle *sbh = conn->sbh;
|
|
Packit Service |
384592 |
char *client_ip = conn->remote_ip;
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
int i, j;
|
|
Packit Service |
384592 |
unsigned long int ip_count_r = 0, ip_count_w = 0;
|
|
Packit Service |
384592 |
char *error_msg;
|
|
Packit Service |
384592 |
worker_score *ws_record = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (sbh != NULL && (conn_read_state_limit > 0 || conn_write_state_limit > 0)) {
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
|
|
Packit Service |
384592 |
ws_record = ap_get_scoreboard_worker(sbh);
|
|
Packit Service |
384592 |
#else
|
|
Packit Service |
384592 |
ws_record = ap_get_scoreboard_worker(sbh->child_num, sbh->thread_num);
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
if (ws_record == NULL)
|
|
Packit Service |
384592 |
return DECLINED;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* If ws_record does not have correct ip yet, we count it already */
|
|
Packit Service |
384592 |
if (strcmp(client_ip, ws_record->client) != 0) {
|
|
Packit Service |
384592 |
switch (ws_record->status) {
|
|
Packit Service |
384592 |
case SERVER_BUSY_READ:
|
|
Packit Service |
384592 |
ip_count_r++;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case SERVER_BUSY_WRITE:
|
|
Packit Service |
384592 |
ip_count_w++;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
default:
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, conn,
|
|
Packit Service |
384592 |
"ModSecurity: going to loop through %d servers with %d threads",
|
|
Packit Service |
384592 |
server_limit, thread_limit);
|
|
Packit Service |
384592 |
for (i = 0; i < server_limit; ++i) {
|
|
Packit Service |
384592 |
for (j = 0; j < thread_limit; ++j) {
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
|
|
Packit Service |
384592 |
ws_record = ap_get_scoreboard_worker_from_indexes(i, j);
|
|
Packit Service |
384592 |
#else
|
|
Packit Service |
384592 |
ws_record = ap_get_scoreboard_worker(i, j);
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (ws_record == NULL)
|
|
Packit Service |
384592 |
return DECLINED;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
switch (ws_record->status) {
|
|
Packit Service |
384592 |
case SERVER_BUSY_READ:
|
|
Packit Service |
384592 |
if (strcmp(client_ip, ws_record->client) == 0)
|
|
Packit Service |
384592 |
ip_count_r++;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
case SERVER_BUSY_WRITE:
|
|
Packit Service |
384592 |
if (strcmp(client_ip, ws_record->client) == 0)
|
|
Packit Service |
384592 |
ip_count_w++;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
default:
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, conn,
|
|
Packit Service |
384592 |
"ModSecurity: threads in READ: %ld of %ld, WRITE: %ld of %ld, IP: %s",
|
|
Packit Service |
384592 |
ip_count_r, conn_read_state_limit, ip_count_w, conn_write_state_limit, client_ip);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (conn_read_state_limit > 0 && ip_count_r > conn_read_state_limit)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
if (conn_read_state_suspicious_list &&
|
|
Packit Service |
384592 |
(tree_contains_ip(conn->pool,
|
|
Packit Service |
384592 |
conn_read_state_suspicious_list, client_ip, NULL, &error_msg) <= 0))
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
if (conn_limits_filter_state == MODSEC_DETECTION_ONLY)
|
|
Packit Service |
384592 |
ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, conn,
|
|
Packit Service |
384592 |
"ModSecurity: Too many threads [%ld] of %ld allowed " \
|
|
Packit Service |
384592 |
"in READ state from %s - There is a suspission list " \
|
|
Packit Service |
384592 |
"but that IP is not part of it, access granted",
|
|
Packit Service |
384592 |
ip_count_r, conn_read_state_limit, client_ip);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
else if (tree_contains_ip(conn->pool,
|
|
Packit Service |
384592 |
conn_read_state_whitelist, client_ip, NULL, &error_msg) > 0)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
if (conn_limits_filter_state == MODSEC_DETECTION_ONLY)
|
|
Packit Service |
384592 |
ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, conn,
|
|
Packit Service |
384592 |
"ModSecurity: Too many threads [%ld] of %ld allowed " \
|
|
Packit Service |
384592 |
"in READ state from %s - Ip is on whitelist, access " \
|
|
Packit Service |
384592 |
"granted", ip_count_r, conn_read_state_limit,
|
|
Packit Service |
384592 |
client_ip);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
else
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, conn,
|
|
Packit Service |
384592 |
"ModSecurity: Access denied with code 400. Too many " \
|
|
Packit Service |
384592 |
"threads [%ld] of %ld allowed in READ state from %s - " \
|
|
Packit Service |
384592 |
"Possible DoS Consumption Attack [Rejected]", ip_count_r,
|
|
Packit Service |
384592 |
conn_read_state_limit, client_ip);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (conn_limits_filter_state == MODSEC_ENABLED)
|
|
Packit Service |
384592 |
return OK;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (conn_write_state_limit > 0 && ip_count_w > conn_write_state_limit)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
if (conn_write_state_suspicious_list &&
|
|
Packit Service |
384592 |
(tree_contains_ip(conn->pool,
|
|
Packit Service |
384592 |
conn_write_state_suspicious_list, client_ip, NULL, &error_msg) <= 0))
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
if (conn_limits_filter_state == MODSEC_DETECTION_ONLY)
|
|
Packit Service |
384592 |
ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, conn,
|
|
Packit Service |
384592 |
"ModSecurity: Too many threads [%ld] of %ld allowed " \
|
|
Packit Service |
384592 |
"in WRITE state from %s - There is a suspission list " \
|
|
Packit Service |
384592 |
"but that IP is not part of it, access granted",
|
|
Packit Service |
384592 |
ip_count_w, conn_read_state_limit, client_ip);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
else if (tree_contains_ip(conn->pool,
|
|
Packit Service |
384592 |
conn_write_state_whitelist, client_ip, NULL, &error_msg) > 0)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
if (conn_limits_filter_state == MODSEC_DETECTION_ONLY)
|
|
Packit Service |
384592 |
ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, conn,
|
|
Packit Service |
384592 |
"ModSecurity: Too many threads [%ld] of %ld allowed " \
|
|
Packit Service |
384592 |
"in WRITE state from %s - Ip is on whitelist, " \
|
|
Packit Service |
384592 |
"access granted", ip_count_w, conn_read_state_limit,
|
|
Packit Service |
384592 |
client_ip);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
else
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, conn,
|
|
Packit Service |
384592 |
"ModSecurity: Access denied with code 400. Too many " \
|
|
Packit Service |
384592 |
"threads [%ld] of %ld allowed in WRITE state from %s - " \
|
|
Packit Service |
384592 |
"Possible DoS Consumption Attack [Rejected]", ip_count_w,
|
|
Packit Service |
384592 |
conn_write_state_limit, client_ip);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (!conn_limits_filter_state == MODSEC_ENABLED)
|
|
Packit Service |
384592 |
return OK;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return DECLINED;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* This function is exported for other Apache modules to
|
|
Packit Service |
384592 |
* register new variables.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static void modsec_register_variable(const char *name, unsigned int type,
|
|
Packit Service |
384592 |
unsigned int argc_min, unsigned int argc_max,
|
|
Packit Service |
384592 |
void *fn_validate, void *fn_generate,
|
|
Packit Service |
384592 |
unsigned int is_cacheable, unsigned int availability) {
|
|
Packit Service |
384592 |
if (modsecurity != NULL) {
|
|
Packit Service |
384592 |
msre_engine_variable_register(modsecurity->msre, name, type, argc_min, argc_max, (fn_var_validate_t)fn_validate, (fn_var_generate_t)fn_generate, is_cacheable, availability);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
else {
|
|
Packit Service |
384592 |
fprintf(stderr,"modsecurity is NULL\n");
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* This function is exported for other Apache modules to
|
|
Packit Service |
384592 |
* register new request body processors.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static void modsec_register_reqbody_processor(const char *name,
|
|
Packit Service |
384592 |
void *fn_init,
|
|
Packit Service |
384592 |
void *fn_process,
|
|
Packit Service |
384592 |
void *fn_complete)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
if (modsecurity != NULL) {
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
msre_engine_reqbody_processor_register(modsecurity->msre, name,
|
|
Packit Service |
384592 |
(fn_reqbody_processor_init_t)fn_init,
|
|
Packit Service |
384592 |
(fn_reqbody_processor_init_t)fn_process,
|
|
Packit Service |
384592 |
(fn_reqbody_processor_init_t)fn_complete);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Registers module hooks with Apache.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
static void register_hooks(apr_pool_t *mp) {
|
|
Packit Service |
384592 |
static const char *const postconfig_beforeme_list[] = {
|
|
Packit Service |
384592 |
"mod_unique_id.c",
|
|
Packit Service |
384592 |
"mod_ssl.c",
|
|
Packit Service |
384592 |
NULL
|
|
Packit Service |
384592 |
};
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
static const char *const postconfig_afterme_list[] = {
|
|
Packit Service |
384592 |
"mod_fcgid.c",
|
|
Packit Service |
384592 |
"mod_cgid.c",
|
|
Packit Service |
384592 |
NULL
|
|
Packit Service |
384592 |
};
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
static const char *const postread_beforeme_list[] = {
|
|
Packit Service |
384592 |
"mod_rpaf.c",
|
|
Packit Service |
384592 |
"mod_rpaf-2.0.c",
|
|
Packit Service |
384592 |
"mod_extract_forwarded.c",
|
|
Packit Service |
384592 |
"mod_extract_forwarded2.c",
|
|
Packit Service |
384592 |
"mod_remoteip.c",
|
|
Packit Service |
384592 |
"mod_custom_header.c",
|
|
Packit Service |
384592 |
"mod_breach_realip.c",
|
|
Packit Service |
384592 |
"mod_breach_trans.c",
|
|
Packit Service |
384592 |
"mod_unique_id.c",
|
|
Packit Service |
384592 |
NULL
|
|
Packit Service |
384592 |
};
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
static const char *const postread_afterme_list[] = {
|
|
Packit Service |
384592 |
"mod_log_forensic.c",
|
|
Packit Service |
384592 |
NULL
|
|
Packit Service |
384592 |
};
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
static const char *const transaction_afterme_list[] = {
|
|
Packit Service |
384592 |
"mod_log_config.c",
|
|
Packit Service |
384592 |
NULL
|
|
Packit Service |
384592 |
};
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
static const char *const fixups_beforeme_list[] = {
|
|
Packit Service |
384592 |
"mod_env.c",
|
|
Packit Service |
384592 |
NULL
|
|
Packit Service |
384592 |
};
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Add the MODSEC_2.x compatibility defines */
|
|
Packit Service |
384592 |
*(char **)apr_array_push(ap_server_config_defines) = apr_pstrdup(mp, "MODSEC_2.5");
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Add the MODSEC_a.b define */
|
|
Packit Service |
384592 |
*(char **)apr_array_push(ap_server_config_defines) = apr_psprintf(mp, "MODSEC_%s.%s", MODSEC_VERSION_MAJOR, MODSEC_VERSION_MINOR);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#if (!defined(NO_MODSEC_API))
|
|
Packit Service |
384592 |
/* Export optional functions. */
|
|
Packit Service |
384592 |
APR_REGISTER_OPTIONAL_FN(modsec_register_tfn);
|
|
Packit Service |
384592 |
APR_REGISTER_OPTIONAL_FN(modsec_register_operator);
|
|
Packit Service |
384592 |
APR_REGISTER_OPTIONAL_FN(modsec_register_variable);
|
|
Packit Service |
384592 |
APR_REGISTER_OPTIONAL_FN(modsec_register_reqbody_processor);
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Main hooks */
|
|
Packit Service |
384592 |
ap_hook_pre_config(hook_pre_config, NULL, NULL, APR_HOOK_FIRST);
|
|
Packit Service |
384592 |
ap_hook_post_config(hook_post_config, postconfig_beforeme_list,
|
|
Packit Service |
384592 |
postconfig_afterme_list, APR_HOOK_REALLY_LAST);
|
|
Packit Service |
384592 |
ap_hook_child_init(hook_child_init, NULL, NULL, APR_HOOK_MIDDLE);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Our own hook to handle RPC transactions (not used at the moment).
|
|
Packit Service |
384592 |
* // ap_hook_handler(hook_handler, NULL, NULL, APR_HOOK_MIDDLE);
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Connection processing hooks */
|
|
Packit Service |
384592 |
ap_hook_process_connection(hook_connection_early, NULL, NULL, APR_HOOK_FIRST);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Transaction processing hooks */
|
|
Packit Service |
384592 |
ap_hook_post_read_request(hook_request_early,
|
|
Packit Service |
384592 |
postread_beforeme_list, postread_afterme_list, APR_HOOK_REALLY_FIRST);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ap_hook_fixups(hook_request_late, fixups_beforeme_list, NULL, APR_HOOK_REALLY_FIRST);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Logging */
|
|
Packit Service |
384592 |
ap_hook_error_log(hook_error_log, NULL, NULL, APR_HOOK_MIDDLE);
|
|
Packit Service |
384592 |
ap_hook_log_transaction(hook_log_transaction, NULL, transaction_afterme_list, APR_HOOK_MIDDLE);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Filter hooks */
|
|
Packit Service |
384592 |
ap_hook_insert_filter(hook_insert_filter, NULL, NULL, APR_HOOK_FIRST);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ap_hook_insert_error_filter(hook_insert_error_filter, NULL, NULL, APR_HOOK_FIRST);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ap_register_input_filter("MODSECURITY_IN", input_filter,
|
|
Packit Service |
384592 |
NULL, AP_FTYPE_CONTENT_SET);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Ensure that the output filter runs before other modules so that
|
|
Packit Service |
384592 |
* we get a request that has a better chance of not being modified:
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* Currently:
|
|
Packit Service |
384592 |
* mod_expires = -2
|
|
Packit Service |
384592 |
* mod_cache = -1
|
|
Packit Service |
384592 |
* mod_deflate = -1
|
|
Packit Service |
384592 |
* mod_headers = 0
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ap_register_output_filter("MODSECURITY_OUT", output_filter,
|
|
Packit Service |
384592 |
NULL, AP_FTYPE_CONTENT_SET - 3);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Defined in apache2_config.c */
|
|
Packit Service |
384592 |
extern const command_rec module_directives[];
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Module entry points */
|
|
Packit Service |
384592 |
module AP_MODULE_DECLARE_DATA security2_module = {
|
|
Packit Service |
384592 |
STANDARD20_MODULE_STUFF,
|
|
Packit Service |
384592 |
create_directory_config,
|
|
Packit Service |
384592 |
merge_directory_configs,
|
|
Packit Service |
384592 |
NULL, /* create_server_config */
|
|
Packit Service |
384592 |
NULL, /* merge_server_configs */
|
|
Packit Service |
384592 |
module_directives,
|
|
Packit Service |
384592 |
register_hooks
|
|
Packit Service |
384592 |
};
|