Merge pull request #93 from SpiderLabs/remotes/trunk

Remotes/trunk
This commit is contained in:
Breno Silva 2013-05-10 05:23:04 -07:00
commit f31724e20f
96 changed files with 6207 additions and 356 deletions

29
CHANGES
View File

@ -1,3 +1,28 @@
10 May 2013 - 2.7.4
-------------------
Improvements:
* Added Libinjection project http://www.client9.com/projects/libinjection/ as a new operator @detectSQLi. (Thanks Nick Galbreath).
* Added new variable SDBM_DELETE_ERROR that will be set to 1 when sdbm engine fails to delete entries.
* Nginx module is set as STABLE.
Bug Fixes:
* Fixed SecRulePerfTime storing unnecessary rules performance times.
* Fixed Possible SDBM deadlock condition.
* Fixed Possible @rsub memory leak.
* Fixed REMOTE_ADDR content will receive the client ip address when mod_remoteip.c is present.
Security Issues:
* Fixed Remote Null Pointer DeReference (CVE-2013-2765). When forceRequestBodyVariable action is triggered and a unknown Content-Type is used,
mod_security will crash trying to manipulate msr->msc_reqbody_chunks->elts however msr->msc_reqbody_chunks is NULL. (Thanks Younes JAAIDI).
28 Mar 2013 - 2.7.3
-------------------
@ -32,7 +57,7 @@
* SECURITY: Added SecXmlExternalEntity (On|Off - default it Off) that will disable
by default the external entity load task executed by LibXml2. This is a security issue
reported by Timur Yunusov, Alexey Osipov (Positive Technologies).
[CVE-2013-1915] reported by Timur Yunusov, Alexey Osipov (Positive Technologies).
21 Jan 2013 - 2.7.2
-------------------
@ -130,7 +155,7 @@
support Include directive like Apache2.
* Added MULTIPART_INVALID_PART flag. Also used in rule id 200002 for multipart strict
validation.
validation. https://www.sec-consult.com/fxdata/seccons/prod/temedia/advisories_txt/20121017-0_mod_security_ruleset_bypass.txt).
* Updated Reference Manual.

2
NOTICE
View File

@ -1,5 +1,5 @@
ModSecurity (www.modsecurity.org)
    Copyright [2004-2011] Trustwave Holdings, Inc
    Copyright [2004-2013] Trustwave Holdings, Inc
    This product includes software developed at
    Trustwave Holdings, Inc (http://www.trustwave.com/).

View File

@ -1,5 +1,5 @@
ModSecurity for Apache 2.x, http://www.modsecurity.org/
Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
You may not use this file except in compliance with
the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -11,7 +11,7 @@ mod_security2_la_SOURCES = mod_security2.c \
re_variables.c msc_logging.c msc_xml.c \
msc_multipart.c modsecurity.c msc_parsers.c \
msc_util.c msc_pcre.c persist_dbm.c msc_reqbody.c \
msc_geo.c msc_gsb.c msc_crypt.c msc_tree.c msc_unicode.c acmp.c msc_lua.c msc_release.c
msc_geo.c msc_gsb.c msc_crypt.c msc_tree.c msc_unicode.c acmp.c msc_lua.c msc_release.c libinjection/sqlparse.c
mod_security2_la_CFLAGS = @APXS_CFLAGS@ @APR_CFLAGS@ @APU_CFLAGS@ \
@PCRE_CFLAGS@ @LIBXML2_CFLAGS@ @LUA_CFLAGS@ @MODSEC_EXTRA_CFLAGS@ @CURL_CFLAGS@

View File

@ -46,7 +46,7 @@ OBJS = mod_security2.obj apache2_config.obj apache2_io.obj apache2_util.obj \
msc_logging.obj msc_xml.obj msc_multipart.obj modsecurity.obj \
msc_parsers.obj msc_util.obj msc_pcre.obj persist_dbm.obj \
msc_reqbody.obj msc_geo.obj msc_gsb.obj msc_crypt.obj msc_tree.obj msc_unicode.obj acmp.obj msc_lua.obj \
msc_release.obj
msc_release.obj libinjection\sqlparse.obj
all: $(DLL)

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
@ -2346,7 +2346,7 @@ static const char *cmd_hash_engine(cmd_parms *cmd, void *_dcfg, const char *p1)
dcfg->hash_is_enabled = HASH_DISABLED;
dcfg->hash_enforcement = HASH_DISABLED;
}
else return apr_psprintf(cmd->pool, "ModSecurity: Invalid value for SexHashEngine: %s", p1);
else return apr_psprintf(cmd->pool, "ModSecurity: Invalid value for SecHashEngine: %s", p1);
return NULL;
}

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
@ -198,6 +198,10 @@ static void internal_log_ex(request_rec *r, directory_config *dcfg, modsec_rec *
apr_size_t nbytes, nbytes_written;
apr_file_t *debuglog_fd = NULL;
int filter_debug_level = 0;
char *remote = NULL;
char *parse_remote = NULL;
char *saved = NULL;
char *str = NULL;
char str1[1024] = "";
char str2[1256] = "";
@ -269,8 +273,8 @@ static void internal_log_ex(request_rec *r, directory_config *dcfg, modsec_rec *
hostname, log_escape(msr->mp, r->uri), unique_id);
#else
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r->server,
"[client %s] ModSecurity: %s%s [uri \"%s\"]%s", r->connection->remote_ip, str1,
hostname, log_escape(msr->mp, r->uri), unique_id);
"[client %s] ModSecurity: %s%s [uri \"%s\"]%s", msr->remote_addr ? msr->remote_addr : r->connection->remote_ip, str1,
hostname, log_escape(msr->mp, r->uri), unique_id);
#endif
/* Add this message to the list. */

View File

@ -0,0 +1,37 @@
/*
* Copyright 2012, 2013
* Nick Galbreath -- nickg [at] client9 [dot] com
* http://www.client9.com/projects/libinjection/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of libinjection nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This is the standard "new" BSD license:
* http://www.opensource.org/licenses/bsd-license.php
*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,113 @@
/**
* Copyright 2012, 2013 Nick Galbreath
* nickg@client9.com
* BSD License -- see COPYING.txt for details
*
*
* HOW TO USE:
*
* // Normalize query or postvar value
* // If it comes in urlencoded, then it's up to you
* // to urldecode it. If it's in correct form already
* // then nothing to do!
*
* sfilter s;
* int sqli = is_sqli(&s, user_string, new_len);
*
* // 0 = not sqli
* // 1 = is sqli
*
* // That's it! sfilter s has some data on how it matched or not
* // details to come!
*
*/
#ifndef _SQLPARSE_H
#define _SQLPARSE_H
#ifdef __cplusplus
extern "C" {
#endif
/*
* Version info.
* See python's normalized version
* http://www.python.org/dev/peps/pep-0386/#normalizedversion
*/
#define LIBINJECTION_VERSION "1.2.0"
#define ST_MAX_SIZE 32
#define MAX_TOKENS 5
#define CHAR_NULL '\0'
#define CHAR_SINGLE '\''
#define CHAR_DOUBLE '"'
typedef struct {
char type;
char str_open;
char str_close;
char val[ST_MAX_SIZE];
} stoken_t;
typedef struct {
/* input */
const char *s;
size_t slen;
/* current tokenize state */
size_t pos;
int in_comment;
/* syntax fixups state */
stoken_t syntax_current;
stoken_t syntax_last;
stoken_t syntax_comment;
/* constant folding state */
stoken_t fold_current;
stoken_t fold_last;
int fold_state;
/* final sqli data */
stoken_t tokenvec[MAX_TOKENS];
/* +1 for ending null */
char pat[MAX_TOKENS + 1];
char delim;
int reason;
} sfilter;
/**
* Pointer to function, takes cstr input, return true/false
*/
typedef int (*ptr_fingerprints_fn)(const char*);
/**
* Main API: tests for SQLi in three possible contexts, no quotes,
* single quote and double quote
*
* \return 1 (true) if SQLi, 0 (false) if benign
*/
int is_sqli(sfilter * sql_state, const char *s, size_t slen,
ptr_fingerprints_fn fn);
/**
* This detects SQLi in a single context, mostly useful for custom
* logic and debugging.
*
* \param delim must be "NULL" (no context), single quote or double quote.
* Other values will likely be ignored.
*
* \return 1 (true) if SQLi, 0 (false) if not SQLi **in this context**
*
*/
int is_string_sqli(sfilter * sql_state, const char *s, size_t slen,
const char delim,
ptr_fingerprints_fn fn);
#ifdef __cplusplus
}
#endif
#endif /* _SQLPARSE_H */

View File

@ -0,0 +1,983 @@
#ifndef _SQLPARSE_DATA_H
#define _SQLPARSE_DATA_H
#include "sqlparse.h"
static const char* operators2[] = {
"!!",
"!<",
"!=",
"!>",
"!~",
"%=",
"&&",
"&=",
"*=",
"+=",
"-=",
"/=",
":=",
"<<",
"<=",
"<>",
"<@",
">=",
">>",
"@>",
"^=",
"|/",
"|=",
"||",
"~*",
};
static const size_t operators2_sz = 25;
static const keyword_t sql_keywords[] = {
{"ABS", 'f'},
{"ACCESSIBLE", 'k'},
{"ACOS", 'f'},
{"ADD", 'k'},
{"ADDDATE", 'f'},
{"ADDTIME", 'f'},
{"AES_DECRYPT", 'f'},
{"AES_ENCRYPT", 'f'},
{"AGAINST", 'k'},
{"AGE", 'f'},
{"ALL_USERS", 'k'},
{"ALTER", 'k'},
{"ANALYZE", 'k'},
{"AND", '&'},
{"APPLOCK_MODE", 'f'},
{"APPLOCK_TEST", 'f'},
{"APP_NAME", 'f'},
{"ARRAY_AGG", 'f'},
{"ARRAY_CAT", 'f'},
{"ARRAY_DIM", 'f'},
{"ARRAY_FILL", 'f'},
{"ARRAY_LENGTH", 'f'},
{"ARRAY_LOWER", 'f'},
{"ARRAY_NDIMS", 'f'},
{"ARRAY_PREPEND", 'f'},
{"ARRAY_TO_JSON", 'f'},
{"ARRAY_TO_STRING", 'f'},
{"ARRAY_UPPER", 'f'},
{"AS", 'k'},
{"ASC", 'k'},
{"ASCII", 'f'},
{"ASENSITIVE", 'k'},
{"ASIN", 'f'},
{"ASSEMBLYPROPERTY", 'f'},
{"ASYMKEY_ID", 'f'},
{"ATAN", 'f'},
{"ATAN2", 'f'},
{"AVG", 'f'},
{"BEFORE", 'k'},
{"BEGIN", 'k'},
{"BENCHMARK", 'f'},
{"BETWEEN", 'k'},
{"BIGINT", 'k'},
{"BIN", 'f'},
{"BINARY", 'k'},
{"BINARY_DOUBLE_INFINITY", '1'},
{"BINARY_DOUBLE_NAN", '1'},
{"BINARY_FLOAT_INFINITY", '1'},
{"BINARY_FLOAT_NAN", '1'},
{"BINBINARY", 'f'},
{"BIT_AND", 'f'},
{"BIT_COUNT", 'f'},
{"BIT_LENGTH", 'f'},
{"BIT_OR", 'f'},
{"BIT_XOR", 'f'},
{"BLOB", 'k'},
{"BOOLEAN", 'k'},
{"BOOL_AND", 'f'},
{"BOOL_OR", 'f'},
{"BOTH", 'k'},
{"BTRIM", 'f'},
{"BY", 'n'},
{"CALL", 'k'},
{"CASCADE", 'k'},
{"CASE", 'o'},
{"CAST", 'f'},
{"CBOOL", 'f'},
{"CBRT", 'f'},
{"CBYTE", 'f'},
{"CCUR", 'f'},
{"CDATE", 'f'},
{"CDBL", 'f'},
{"CEIL", 'f'},
{"CEILING", 'f'},
{"CERTENCODED", 'f'},
{"CERTPRIVATEKEY", 'f'},
{"CERT_ID", 'f'},
{"CERT_PROPERTY", 'f'},
{"CHANGE", 'k'},
{"CHAR", 'f'},
{"CHARACTER", 'k'},
{"CHARACTER_LENGTH", 'f'},
{"CHARINDEX", 'f'},
{"CHARSET", 'f'},
{"CHAR_LENGTH", 'f'},
{"CHDIR", 'f'},
{"CHDRIVE", 'f'},
{"CHECK", 'k'},
{"CHECKSUM_AGG", 'f'},
{"CHOOSE", 'f'},
{"CHR", 'f'},
{"CINT", 'f'},
{"CLNG", 'f'},
{"CLOCK_TIMESTAMP", 'f'},
{"COALESCE", 'k'},
{"COERCIBILITY", 'f'},
{"COLLATE", 'k'},
{"COLLATION", 'f'},
{"COLLATIONPROPERTY", 'f'},
{"COLUMN", 'k'},
{"COLUMNPROPERTY", 'f'},
{"COLUMNS_UPDATED", 'f'},
{"COL_LENGTH", 'f'},
{"COL_NAME", 'f'},
{"COMPRESS", 'f'},
{"CONCAT", 'f'},
{"CONCAT_WS", 'f'},
{"CONDITION", 'k'},
{"CONNECTION_ID", 'f'},
{"CONSTRAINT", 'k'},
{"CONTINUE", 'k'},
{"CONV", 'f'},
{"CONVERT", 'f'},
{"CONVERT_FROM", 'f'},
{"CONVERT_TO", 'f'},
{"CONVERT_TZ", 'f'},
{"COS", 'f'},
{"COT", 'f'},
{"COUNT", 'f'},
{"COUNT_BIG", 'k'},
{"CRC32", 'f'},
{"CREATE", 'k'},
{"CSNG", 'f'},
{"CTXSYS.DRITHSX.SN", 'f'},
{"CUME_DIST", 'f'},
{"CURDATE", 'f'},
{"CURDIR", 'f'},
{"CURRENTUSER", 'f'},
{"CURRENT_DATABASE", 'f'},
{"CURRENT_DATE", 'k'},
{"CURRENT_QUERY", 'f'},
{"CURRENT_SCHEMA", 'f'},
{"CURRENT_SCHEMAS", 'f'},
{"CURRENT_SETTING", 'p'},
{"CURRENT_TIME", 'k'},
{"CURRENT_TIMESTAMP", 'k'},
{"CURRENT_USER", 'k'},
{"CURRVAL", 'f'},
{"CURSOR", 'k'},
{"CURSOR_STATUS", 'f'},
{"CURTIME", 'f'},
{"CVAR", 'f'},
{"DATABASE", 'k'},
{"DATABASEPROPERTYEX", 'f'},
{"DATABASES", 'k'},
{"DATABASE_PRINCIPAL_ID", 'f'},
{"DATALENGTH", 'f'},
{"DATE", 'f'},
{"DATEADD", 'f'},
{"DATEDIFF", 'f'},
{"DATEFROMPARTS", 'f'},
{"DATENAME", 'f'},
{"DATEPART", 'f'},
{"DATESERIAL", 'f'},
{"DATETIME2FROMPARTS", 'f'},
{"DATETIMEFROMPARTS", 'f'},
{"DATETIMEOFFSETFROMPARTS", 'f'},
{"DATEVALUE", 'f'},
{"DATE_ADD", 'f'},
{"DATE_FORMAT", 'f'},
{"DATE_PART", 'f'},
{"DATE_SUB", 'f'},
{"DATE_TRUNC", 'f'},
{"DAVG", 'f'},
{"DAY", 'f'},
{"DAYNAME", 'f'},
{"DAYOFMONTH", 'f'},
{"DAYOFWEEK", 'f'},
{"DAYOFYEAR", 'f'},
{"DAY_HOUR", 'k'},
{"DAY_MICROSECOND", 'k'},
{"DAY_MINUTE", 'k'},
{"DAY_SECOND", 'k'},
{"DBMS_PIPE.RECEIVE_MESSAGE", 'f'},
{"DB_ID", 'f'},
{"DB_NAME", 'f'},
{"DCOUNT", 'f'},
{"DEC", 'k'},
{"DECIMAL", 'k'},
{"DECLARE", 'k'},
{"DECODE", 'f'},
{"DECRYPTBYASMKEY", 'f'},
{"DECRYPTBYCERT", 'f'},
{"DECRYPTBYKEY", 'f'},
{"DECRYPTBYKEYAUTOCERT", 'f'},
{"DECRYPTBYPASSPHRASE", 'f'},
{"DEFAULT", 'k'},
{"DEGREES", 'f'},
{"DELAY", 'k'},
{"DELAYED", 'k'},
{"DELETE", 'k'},
{"DENSE_RANK", 'f'},
{"DESC", 'k'},
{"DESCRIBE", 'k'},
{"DES_DECRYPT", 'f'},
{"DES_ENCRYPT", 'f'},
{"DETERMINISTIC", 'k'},
{"DFIRST", 'f'},
{"DIFFERENCE", 'f'},
{"DISTINCROW", 'k'},
{"DISTINCT", 'k'},
{"DIV", 'o'},
{"DLAST", 'f'},
{"DLOOKUP", 'f'},
{"DMAX", 'f'},
{"DMIN", 'f'},
{"DROP", 'k'},
{"DSUM", 'f'},
{"DUAL", 'k'},
{"EACH", 'k'},
{"ELSE", 'k'},
{"ELSEIF", 'k'},
{"ELT", 'f'},
{"ENCLOSED", 'k'},
{"ENCODE", 'f'},
{"ENCRYPT", 'f'},
{"ENCRYPTBYASMKEY", 'f'},
{"ENCRYPTBYCERT", 'f'},
{"ENCRYPTBYKEY", 'f'},
{"ENCRYPTBYPASSPHRASE", 'f'},
{"ENUM_FIRST", 'f'},
{"ENUM_LAST", 'f'},
{"ENUM_RANGE", 'f'},
{"EOMONTH", 'f'},
{"ESCAPED", 'k'},
{"EVENTDATA", 'f'},
{"EXEC", 'k'},
{"EXECUTE", 'k'},
{"EXISTS", 'k'},
{"EXIT", 'k'},
{"EXP", 'f'},
{"EXPLAIN", 'k'},
{"EXPORT_SET", 'f'},
{"EXTRACT", 'f'},
{"EXTRACTVALUE", 'f'},
{"EXTRACT_VALUE", 'f'},
{"FALSE", '1'},
{"FETCH", 'k'},
{"FIELD", 'f'},
{"FILEDATETIME", 'f'},
{"FILEGROUPPROPERTY", 'f'},
{"FILEGROUP_ID", 'f'},
{"FILEGROUP_NAME", 'f'},
{"FILELEN", 'f'},
{"FILEPROPERTY", 'f'},
{"FILE_ID", 'f'},
{"FILE_IDEX", 'f'},
{"FILE_NAME", 'f'},
{"FIND_IN_SET", 'f'},
{"FIRST_VALUE", 'f'},
{"FLOOR", 'f'},
{"FN_VIRTUALFILESTATS", 'f'},
{"FOR", 'n'},
{"FORCE", 'k'},
{"FOREIGN", 'k'},
{"FORMAT", 'f'},
{"FOUND_ROWS", 'f'},
{"FROM", 'k'},
{"FROM_DAYS", 'f'},
{"FROM_UNIXTIME", 'f'},
{"FULLTEXT", 'k'},
{"FULLTEXTCATALOGPROPERTY", 'f'},
{"FULLTEXTSERVICEPROPERTY", 'f'},
{"GENERATE_SERIES", 'f'},
{"GENERATE_SUBSCRIPTS", 'f'},
{"GETATTR", 'f'},
{"GETDATE", 'f'},
{"GETUTCDATE", 'f'},
{"GET_BIT", 'f'},
{"GET_BYTE", 'f'},
{"GET_FORMAT", 'f'},
{"GET_LOCK", 'f'},
{"GOTO", 'k'},
{"GRANT", 'k'},
{"GREATEST", 'f'},
{"GROUP", 'n'},
{"GROUPING", 'f'},
{"GROUPING_ID", 'f'},
{"GROUP_CONCAT", 'f'},
{"HASHBYTES", 'f'},
{"HAS_PERMS_BY_NAME", 'f'},
{"HAVING", 'k'},
{"HEX", 'f'},
{"HIGH_PRIORITY", 'k'},
{"HOST_NAME", 'f'},
{"HOUR", 'f'},
{"HOUR_MICROSECOND", 'k'},
{"HOUR_MINUTE", 'k'},
{"HOUR_SECOND", 'k'},
{"IDENTIFY", 'f'},
{"IDENT_CURRENT", 'f'},
{"IDENT_INCR", 'f'},
{"IDENT_SEED", 'f'},
{"IF", 'k'},
{"IFF", 'f'},
{"IFNULL", 'f'},
{"IGNORE", 'k'},
{"IIF", 'f'},
{"IN", 'n'},
{"INDEX", 'k'},
{"INDEXKEY_PROPERTY", 'f'},
{"INDEXPROPERTY", 'f'},
{"INDEX_COL", 'f'},
{"INET_ATON", 'f'},
{"INET_NTOA", 'f'},
{"INFILE", 'k'},
{"INITCAP", 'f'},
{"INNER", 'k'},
{"INOUT", 'k'},
{"INSENSITIVE", 'k'},
{"INSERT", 'k'},
{"INSTR", 'f'},
{"INSTRREV", 'f'},
{"INT", 'k'},
{"INT1", 'k'},
{"INT2", 'k'},
{"INT3", 'k'},
{"INT4", 'k'},
{"INT8", 'k'},
{"INTEGER", 'k'},
{"INTERVAL", 'k'},
{"INTO", 'k'},
{"IS", 'o'},
{"ISDATE", 'f'},
{"ISEMPTY", 'f'},
{"ISFINITE", 'f'},
{"ISNULL", 'f'},
{"ISNUMERIC", 'f'},
{"IS_FREE_LOCK", 'f'},
{"IS_MEMBER", 'f'},
{"IS_OBJECTSIGNED", 'f'},
{"IS_ROLEMEMBER", 'f'},
{"IS_SRVROLEMEMBER", 'f'},
{"IS_USED_LOCK", 'f'},
{"ITERATE", 'k'},
{"JOIN", 'k'},
{"JUSTIFY_DAYS", 'f'},
{"JUSTIFY_HOURS", 'f'},
{"JUSTIFY_INTERVAL", 'f'},
{"KEYS", 'k'},
{"KEY_GUID", 'f'},
{"KEY_ID", 'f'},
{"KILL", 'k'},
{"LAG", 'f'},
{"LASTVAL", 'f'},
{"LAST_INSERT_ID", 'f'},
{"LAST_VALUE", 'f'},
{"LCASE", 'f'},
{"LEAD", 'f'},
{"LEADING", 'k'},
{"LEAST", 'f'},
{"LEAVE", 'k'},
{"LEFT", 'n'},
{"LENGTH", 'f'},
{"LIKE", 'o'},
{"LIMIT", 'k'},
{"LINEAR", 'k'},
{"LINES", 'k'},
{"LN", 'f'},
{"LOAD", 'k'},
{"LOAD_FILE", 'f'},
{"LOCALTIME", 'k'},
{"LOCALTIMESTAMP", 'k'},
{"LOCATE", 'f'},
{"LOCK", 'n'},
{"LOG", 'f'},
{"LOG10", 'f'},
{"LOG2", 'f'},
{"LONGBLOB", 'k'},
{"LONGTEXT", 'k'},
{"LOOP", 'k'},
{"LOWER", 'f'},
{"LOWER_INC", 'f'},
{"LOWER_INF", 'f'},
{"LOW_PRIORITY", 'k'},
{"LPAD", 'f'},
{"LTRIM", 'f'},
{"MAKEDATE", 'f'},
{"MAKE_SET", 'f'},
{"MASKLEN", 'f'},
{"MASTER_BIND", 'k'},
{"MASTER_POS_WAIT", 'f'},
{"MASTER_SSL_VERIFY_SERVER_CERT", 'k'},
{"MATCH", 'k'},
{"MAX", 'f'},
{"MAXVALUE", 'k'},
{"MD5", 'f'},
{"MEDIUMBLOB", 'k'},
{"MEDIUMINT", 'k'},
{"MEDIUMTEXT", 'k'},
{"MERGE", 'k'},
{"MICROSECOND", 'f'},
{"MID", 'f'},
{"MIDDLEINT", 'k'},
{"MIN", 'f'},
{"MINUTE", 'f'},
{"MINUTE_MICROSECOND", 'k'},
{"MINUTE_SECOND", 'k'},
{"MKDIR", 'f'},
{"MOD", 'o'},
{"MODE", 'n'},
{"MODIFIES", 'k'},
{"MONTH", 'f'},
{"MONTHNAME", 'f'},
{"NAME_CONST", 'f'},
{"NETMASK", 'f'},
{"NEXTVAL", 'f'},
{"NOT", 'o'},
{"NOW", 'f'},
{"NO_WRITE_TO_BINLOG", 'k'},
{"NTH_VALUE", 'f'},
{"NTILE", 'f'},
{"NULL", '1'},
{"NULLIF", 'f'},
{"NUMERIC", 'k'},
{"NZ", 'f'},
{"OBJECTPROPERTY", 'f'},
{"OBJECTPROPERTYEX", 'f'},
{"OBJECT_DEFINITION", 'f'},
{"OBJECT_ID", 'f'},
{"OBJECT_NAME", 'f'},
{"OBJECT_SCHEMA_NAME", 'f'},
{"OCT", 'f'},
{"OCTET_LENGTH", 'f'},
{"OFFSET", 'k'},
{"OLD_PASSWORD", 'f'},
{"ONE_SHOT", 'k'},
{"OPEN", 'k'},
{"OPENDATASOURCE", 'f'},
{"OPENQUERY", 'f'},
{"OPENROWSET", 'f'},
{"OPENXML", 'f'},
{"OPTIMIZE", 'k'},
{"OPTION", 'k'},
{"OPTIONALLY", 'k'},
{"OR", '&'},
{"ORD", 'f'},
{"ORDER", 'n'},
{"ORIGINAL_DB_NAME", 'f'},
{"ORIGINAL_LOGIN", 'f'},
{"OUT", 'k'},
{"OUTFILE", 'k'},
{"OVERLAPS", 'f'},
{"OVERLAY", 'f'},
{"OWN3D", 'k'},
{"PARSENAME", 'f'},
{"PARTITION", 'k'},
{"PASSWORD", 'k'},
{"PATHINDEX", 'f'},
{"PATINDEX", 'f'},
{"PERCENTILE_COUNT", 'f'},
{"PERCENTILE_DISC", 'f'},
{"PERCENTILE_RANK", 'f'},
{"PERCENT_RANK", 'f'},
{"PERIOD_ADD", 'f'},
{"PERIOD_DIFF", 'f'},
{"PERMISSIONS", 'f'},
{"PG_ADVISORY_LOCK", 'f'},
{"PG_BACKEND_PID", 'f'},
{"PG_CANCEL_BACKEND", 'f'},
{"PG_CLIENT_ENCODING", 'f'},
{"PG_CONF_LOAD_TIME", 'f'},
{"PG_CREATE_RESTORE_POINT", 'f'},
{"PG_HAS_ROLE", 'f'},
{"PG_IS_IN_RECOVERY", 'f'},
{"PG_IS_OTHER_TEMP_SCHEMA", 'f'},
{"PG_LISTENING_CHANNELS", 'f'},
{"PG_LS_DIR", 'f'},
{"PG_MY_TEMP_SCHEMA", 'f'},
{"PG_POSTMASTER_START_TIME", 'f'},
{"PG_READ_BINARY_FILE", 'f'},
{"PG_READ_FILE", 'f'},
{"PG_RELOAD_CONF", 'f'},
{"PG_ROTATE_LOGFILE", 'f'},
{"PG_SLEEP", 'f'},
{"PG_START_BACKUP", 'f'},
{"PG_STAT_FILE", 'f'},
{"PG_STOP_BACKUP", 'f'},
{"PG_SWITCH_XLOG", 'f'},
{"PG_TERMINATE_BACKEND", 'f'},
{"PG_TRIGGER_DEPTH", 'f'},
{"PI", 'f'},
{"POSITION", 'f'},
{"POW", 'f'},
{"POWER", 'f'},
{"PRECISION", 'k'},
{"PRIMARY", 'k'},
{"PROCEDURE", 'k'},
{"PUBLISHINGSERVERNAME", 'f'},
{"PURGE", 'k'},
{"PWDCOMPARE", 'f'},
{"PWDENCRYPT", 'f'},
{"QUARTER", 'f'},
{"QUOTE", 'f'},
{"QUOTENAME", 'f'},
{"QUOTE_IDENT", 'f'},
{"QUOTE_LITERAL", 'f'},
{"QUOTE_NULLABLE", 'f'},
{"RADIANS", 'f'},
{"RAND", 'f'},
{"RANDOM", 'f'},
{"RANDOMBLOB", 'f'},
{"RANGE", 'k'},
{"RANK", 'f'},
{"READ", 'k'},
{"READS", 'k'},
{"READ_WRITE", 'k'},
{"REAL", 'n'},
{"REFERENCES", 'k'},
{"REGEXP", 'o'},
{"REGEXP_MATCHES", 'f'},
{"REGEXP_REPLACE", 'f'},
{"REGEXP_SPLIT_TO_ARRAY", 'f'},
{"REGEXP_SPLIT_TO_TABLE", 'f'},
{"RELEASE", 'k'},
{"RELEASE_LOCK", 'f'},
{"RENAME", 'k'},
{"REPEAT", 'k'},
{"REPLACE", 'k'},
{"REPLICATE", 'f'},
{"REQUIRE", 'k'},
{"RESIGNAL", 'k'},
{"RESTRICT", 'k'},
{"RETURN", 'k'},
{"REVERSE", 'f'},
{"REVOKE", 'k'},
{"RIGHT", 'n'},
{"RLIKE", 'o'},
{"ROUND", 'f'},
{"ROW", 'f'},
{"ROW_COUNT", 'f'},
{"ROW_NUMBER", 'f'},
{"ROW_TO_JSON", 'f'},
{"RPAD", 'f'},
{"RTRIM", 'f'},
{"SCHAMA_NAME", 'f'},
{"SCHEMA", 'k'},
{"SCHEMAS", 'k'},
{"SCHEMA_ID", 'f'},
{"SCOPE_IDENTITY", 'f'},
{"SECOND_MICROSECOND", 'k'},
{"SEC_TO_TIME", 'f'},
{"SELECT", 'k'},
{"SENSITIVE", 'k'},
{"SEPARATOR", 'k'},
{"SESSION_USER", 'f'},
{"SET", 'k'},
{"SETATTR", 'f'},
{"SETSEED", 'f'},
{"SETVAL", 'f'},
{"SET_BIT", 'f'},
{"SET_BYTE", 'f'},
{"SET_CONFIG", 'f'},
{"SET_MASKLEN", 'f'},
{"SHA", 'f'},
{"SHA1", 'f'},
{"SHA2", 'f'},
{"SHOW", 'n'},
{"SHUTDOWN", 'k'},
{"SIGN", 'f'},
{"SIGNAL", 'k'},
{"SIGNBYASMKEY", 'f'},
{"SIGNBYCERT", 'f'},
{"SIMILAR", 'k'},
{"SIN", 'f'},
{"SLEEP", 'f'},
{"SMALLDATETIMEFROMPARTS", 'f'},
{"SMALLINT", 'k'},
{"SOUNDEX", 'f'},
{"SOUNDS", 'o'},
{"SPACE", 'f'},
{"SPATIAL", 'k'},
{"SPECIFIC", 'k'},
{"SPLIT_PART", 'f'},
{"SQL", 'k'},
{"SQLEXCEPTION", 'k'},
{"SQLSTATE", 'k'},
{"SQLWARNING", 'k'},
{"SQL_BIG_RESULT", 'k'},
{"SQL_CALC_FOUND_ROWS", 'k'},
{"SQL_SMALL_RESULT", 'k'},
{"SQL_VARIANT_PROPERTY", 'f'},
{"SQRT", 'f'},
{"SSL", 'k'},
{"STARTING", 'k'},
{"STATEMENT_TIMESTAMP", 'f'},
{"STATS_DATE", 'f'},
{"STDDEV", 'p'},
{"STDDEV_POP", 'f'},
{"STDDEV_SAMP", 'f'},
{"STRAIGHT_JOIN", 'k'},
{"STRCMP", 'f'},
{"STRCONV", 'f'},
{"STRING_AGG", 'f'},
{"STRING_TO_ARRAY", 'f'},
{"STRPOS", 'f'},
{"STR_TO_DATE", 'f'},
{"STUFF", 'f'},
{"SUBDATE", 'f'},
{"SUBSTR", 'f'},
{"SUBSTRING", 'f'},
{"SUBSTRING_INDEX", 'f'},
{"SUBTIME", 'f'},
{"SUM", 'f'},
{"SUSER_ID", 'f'},
{"SUSER_NAME", 'f'},
{"SUSER_SID", 'f'},
{"SUSER_SNAME", 'f'},
{"SWITCHOFFET", 'f'},
{"SYS.FN_BUILTIN_PERMISSIONS", 'f'},
{"SYS.FN_GET_AUDIT_FILE", 'f'},
{"SYS.FN_MY_PERMISSIONS", 'f'},
{"SYS.STRAGG", 'f'},
{"SYSCOLUMNS", 'k'},
{"SYSDATE", 'f'},
{"SYSDATETIME", 'f'},
{"SYSDATETIMEOFFSET", 'f'},
{"SYSOBJECTS", 'k'},
{"SYSTEM_USER", 'f'},
{"SYSUSERS", 'k'},
{"SYSUTCDATETME", 'f'},
{"TABLE", 'k'},
{"TAN", 'f'},
{"TERMINATED", 'k'},
{"TERTIARY_WEIGHTS", 'f'},
{"TEXTPTR", 'f'},
{"TEXTVALID", 'f'},
{"THEN", 'k'},
{"TIME", 'k'},
{"TIMEDIFF", 'f'},
{"TIMEFROMPARTS", 'f'},
{"TIMEOFDAY", 'f'},
{"TIMESERIAL", 'f'},
{"TIMESTAMP", 'f'},
{"TIMESTAMPADD", 'f'},
{"TIMEVALUE", 'f'},
{"TIME_FORMAT", 'f'},
{"TIME_TO_SEC", 'f'},
{"TINYBLOB", 'k'},
{"TINYINT", 'k'},
{"TINYTEXT", 'k'},
{"TODATETIMEOFFSET", 'f'},
{"TOP", 'k'},
{"TO_ASCII", 'f'},
{"TO_CHAR", 'f'},
{"TO_DATE", 'f'},
{"TO_DAYS", 'f'},
{"TO_HEX", 'f'},
{"TO_NUMBER", 'f'},
{"TO_SECONDS", 'f'},
{"TO_TIMESTAMP", 'f'},
{"TRAILING", 'n'},
{"TRANSACTION_TIMESTAMP", 'f'},
{"TRANSLATE", 'f'},
{"TRIGGER", 'k'},
{"TRIGGER_NESTLEVEL", 'f'},
{"TRIM", 'f'},
{"TRUE", '1'},
{"TRUNC", 'f'},
{"TRUNCATE", 'f'},
{"TRY_CAST", 'f'},
{"TRY_CONVERT", 'f'},
{"TRY_PARSE", 'f'},
{"TYPEPROPERTY", 'f'},
{"TYPE_ID", 'f'},
{"TYPE_NAME", 'f'},
{"UCASE", 'f'},
{"UNCOMPRESS", 'f'},
{"UNCOMPRESS_LENGTH", 'f'},
{"UNDO", 'k'},
{"UNHEX", 'f'},
{"UNION", 'U'},
{"UNIQUE", 'n'},
{"UNIX_TIMESTAMP", 'f'},
{"UNI_ON", 'U'},
{"UNKNOWN", 'k'},
{"UNLOCK", 'k'},
{"UNNEST", 'f'},
{"UNSIGNED", 'k'},
{"UPDATE", 'k'},
{"UPDATEXML", 'f'},
{"UPPER", 'f'},
{"UPPER_INC", 'f'},
{"UPPER_INF", 'f'},
{"USAGE", 'k'},
{"USE", 'k'},
{"USER_ID", 'n'},
{"USER_NAME", 'f'},
{"USING", 'f'},
{"UTC_DATE", 'k'},
{"UTC_TIME", 'k'},
{"UTC_TIMESTAMP", 'k'},
{"UTL_INADDR.GET_HOST_ADDRESS", 'f'},
{"UUID", 'f'},
{"UUID_SHORT", 'f'},
{"VALUES", 'k'},
{"VAR", 'f'},
{"VARBINARY", 'k'},
{"VARCHAR", 'k'},
{"VARCHARACTER", 'k'},
{"VARIANCE", 'f'},
{"VARP", 'f'},
{"VARYING", 'k'},
{"VAR_POP", 'f'},
{"VAR_SAMP", 'f'},
{"VERIFYSIGNEDBYASMKEY", 'f'},
{"VERIFYSIGNEDBYCERT", 'f'},
{"VERSION", 'f'},
{"WAITFOR", 'k'},
{"WEEK", 'f'},
{"WEEKDAY", 'f'},
{"WEEKDAYNAME", 'f'},
{"WEEKOFYEAR", 'f'},
{"WHEN", 'k'},
{"WHERE", 'k'},
{"WHILE", 'k'},
{"WIDTH_BUCKET", 'f'},
{"WITH", 'k'},
{"XMLAGG", 'f'},
{"XMLCOMMENT", 'f'},
{"XMLCONCAT", 'f'},
{"XMLELEMENT", 'f'},
{"XMLEXISTS", 'f'},
{"XMLFOREST", 'f'},
{"XMLFORMAT", 'f'},
{"XMLPI", 'f'},
{"XMLROOT", 'f'},
{"XMLTYPE", 'f'},
{"XML_IS_WELL_FORMED", 'f'},
{"XOR", 'o'},
{"XPATH", 'f'},
{"XPATH_EXISTS", 'f'},
{"XP_EXECRESULTSET", 'k'},
{"YEAR", 'f'},
{"YEARWEEK", 'f'},
{"YEAR_MONTH", 'k'},
{"ZEROFILL", 'k'},
};
static const size_t sql_keywords_sz = 737;
static const char* multikeywords_start[] = {
"ALTER",
"AT",
"AT TIME",
"CROSS",
"FULL",
"GROUP",
"IN",
"IN BOOLEAN",
"INTERSECT",
"IS",
"IS DISTINCT",
"IS NOT",
"LEFT",
"LOCK",
"NATURAL",
"NEXT",
"NEXT VALUE",
"NOT",
"NOT SIMILAR",
"ORDER",
"OWN3D",
"READ",
"RIGHT",
"SELECT",
"SIMILAR",
"SOUNDS",
"UNION",
};
static const size_t multikeywords_start_sz = 27;
static const keyword_t multikeywords[] = {
{"ALTER DOMAIN", 'k'},
{"ALTER TABLE", 'k'},
{"AT TIME", 'n'},
{"AT TIME ZONE", 'k'},
{"CROSS JOIN", 'k'},
{"FULL OUTER", 'k'},
{"GROUP BY", 'B'},
{"IN BOOLEAN", 'n'},
{"IN BOOLEAN MODE", 'k'},
{"INTERSECT ALL", 'o'},
{"IS DISTINCT", 'n'},
{"IS DISTINCT FROM", 'k'},
{"IS NOT", 'o'},
{"IS NOT DISTINCT", 'n'},
{"IS NOT DISTINCT FROM", 'k'},
{"LEFT JOIN", 'k'},
{"LEFT OUTER", 'k'},
{"LOCK TABLE", 'k'},
{"LOCK TABLES", 'k'},
{"NATURAL FULL", 'k'},
{"NATURAL INNER", 'k'},
{"NATURAL JOIN", 'k'},
{"NATURAL LEFT", 'k'},
{"NATURAL OUTER", 'k'},
{"NATURAL RIGHT", 'k'},
{"NEXT VALUE", 'n'},
{"NEXT VALUE FOR", 'k'},
{"NOT BETWEEN", 'o'},
{"NOT IN", 'o'},
{"NOT LIKE", 'o'},
{"NOT REGEXP", 'o'},
{"NOT RLIKE", 'o'},
{"NOT SIMILAR", 'o'},
{"NOT SIMILAR TO", 'o'},
{"ORDER BY", 'B'},
{"OWN3D BY", 'B'},
{"READ WRITE", 'k'},
{"RIGHT JOIN", 'k'},
{"RIGHT OUTER", 'k'},
{"SELECT ALL", 'k'},
{"SIMILAR TO", 'o'},
{"SOUNDS LIKE", 'o'},
{"UNION ALL", 'U'},
};
static const size_t multikeywords_sz = 43;
typedef size_t (*pt2Function)(sfilter *sf);
static const pt2Function char_parse_map[] = {
&parse_white, /* 0 */
&parse_white, /* 1 */
&parse_white, /* 2 */
&parse_white, /* 3 */
&parse_white, /* 4 */
&parse_white, /* 5 */
&parse_white, /* 6 */
&parse_white, /* 7 */
&parse_white, /* 8 */
&parse_white, /* 9 */
&parse_white, /* 10 */
&parse_white, /* 11 */
&parse_white, /* 12 */
&parse_white, /* 13 */
&parse_white, /* 14 */
&parse_white, /* 15 */
&parse_white, /* 16 */
&parse_white, /* 17 */
&parse_white, /* 18 */
&parse_white, /* 19 */
&parse_white, /* 20 */
&parse_white, /* 21 */
&parse_white, /* 22 */
&parse_white, /* 23 */
&parse_white, /* 24 */
&parse_white, /* 25 */
&parse_white, /* 26 */
&parse_white, /* 27 */
&parse_white, /* 28 */
&parse_white, /* 29 */
&parse_white, /* 30 */
&parse_white, /* 31 */
&parse_white, /* 32 */
&parse_operator2, /* 33 */
&parse_string, /* 34 */
&parse_eol_comment, /* 35 */
&parse_money, /* 36 */
&parse_operator1, /* 37 */
&parse_operator2, /* 38 */
&parse_string, /* 39 */
&parse_char, /* 40 */
&parse_char, /* 41 */
&parse_operator2, /* 42 */
&parse_operator1, /* 43 */
&parse_char, /* 44 */
&parse_dash, /* 45 */
&parse_number, /* 46 */
&parse_slash, /* 47 */
&parse_number, /* 48 */
&parse_number, /* 49 */
&parse_number, /* 50 */
&parse_number, /* 51 */
&parse_number, /* 52 */
&parse_number, /* 53 */
&parse_number, /* 54 */
&parse_number, /* 55 */
&parse_number, /* 56 */
&parse_number, /* 57 */
&parse_char, /* 58 */
&parse_char, /* 59 */
&parse_operator2, /* 60 */
&parse_operator2, /* 61 */
&parse_operator2, /* 62 */
&parse_other, /* 63 */
&parse_var, /* 64 */
&parse_word, /* 65 */
&parse_word, /* 66 */
&parse_word, /* 67 */
&parse_word, /* 68 */
&parse_word, /* 69 */
&parse_word, /* 70 */
&parse_word, /* 71 */
&parse_word, /* 72 */
&parse_word, /* 73 */
&parse_word, /* 74 */
&parse_word, /* 75 */
&parse_word, /* 76 */
&parse_word, /* 77 */
&parse_word, /* 78 */
&parse_word, /* 79 */
&parse_word, /* 80 */
&parse_word, /* 81 */
&parse_word, /* 82 */
&parse_word, /* 83 */
&parse_word, /* 84 */
&parse_word, /* 85 */
&parse_word, /* 86 */
&parse_word, /* 87 */
&parse_word, /* 88 */
&parse_word, /* 89 */
&parse_word, /* 90 */
&parse_other, /* 91 */
&parse_backslash, /* 92 */
&parse_other, /* 93 */
&parse_operator1, /* 94 */
&parse_word, /* 95 */
&parse_word, /* 96 */
&parse_word, /* 97 */
&parse_word, /* 98 */
&parse_word, /* 99 */
&parse_word, /* 100 */
&parse_word, /* 101 */
&parse_word, /* 102 */
&parse_word, /* 103 */
&parse_word, /* 104 */
&parse_word, /* 105 */
&parse_word, /* 106 */
&parse_word, /* 107 */
&parse_word, /* 108 */
&parse_word, /* 109 */
&parse_word, /* 110 */
&parse_word, /* 111 */
&parse_word, /* 112 */
&parse_word, /* 113 */
&parse_word, /* 114 */
&parse_word, /* 115 */
&parse_word, /* 116 */
&parse_word, /* 117 */
&parse_word, /* 118 */
&parse_word, /* 119 */
&parse_word, /* 120 */
&parse_word, /* 121 */
&parse_word, /* 122 */
&parse_other, /* 123 */
&parse_operator2, /* 124 */
&parse_other, /* 125 */
&parse_operator1, /* 126 */
&parse_white, /* 127 */
};
#endif

View File

@ -0,0 +1,70 @@
/**
* Copyright 2012, Nick Galbreath
* nickg@client9.com
* BSD License - see COPYING.txt for details
*
* (setq-default indent-tabs-mode nil)
* (setq c-default-style "k&r"
* c-basic-offset 4)
* indent -kr -nut
*/
#ifndef _SQLPARSE_PRIVATE_H
#define _SQLPARSE_PRIVATE_H
#include "sqlparse.h"
typedef struct {
const char *word;
char type;
} keyword_t;
char bsearch_keyword_type(const char *key, const keyword_t keywords[],
size_t len);
int is_operator2(const char *key);
int is_sqli_pattern(const char *key);
size_t parse_none(sfilter * sf);
size_t parse_money(sfilter * sf);
size_t parse_other(sfilter * sf);
size_t parse_white(sfilter * sf);
size_t parse_operator1(sfilter *sf);
size_t parse_char(sfilter *sf);
size_t parse_eol_comment(sfilter *sf);
size_t parse_dash(sfilter *sf);
size_t is_mysql_comment(const char *cs, const size_t len, size_t pos);
size_t parse_slash(sfilter *sf);
size_t parse_backslash(sfilter * sf);
size_t parse_operator2(sfilter *sf);
size_t parse_string_core(const char *cs, const size_t len, size_t pos,
stoken_t * st, char delim, size_t offset);
size_t parse_string(sfilter *sf);
size_t parse_word(sfilter * sf);
size_t parse_var(sfilter * sf);
size_t parse_number(sfilter * sf);
int parse_token(sfilter * sf);
/**
* Looks at syntax_last and syntax_current to see
* if they can be merged into a multi-keyword
*/
int syntax_merge_words(stoken_t * a, stoken_t * b);
void sfilter_reset(sfilter * sf, const char *s, size_t slen);
/**
* Takes a raw stream of SQL tokens and does the following:
* * Merge mutliple strings into one "foo", "bar" --> "foo bar"
* * Remove comments except last one 1, +, -- foo, 1 ->> 1,+,1
* * Merge multi-word keywords and operators into one
* e.g. "UNION", "ALL" --> "UNION ALL"
*/
int sqli_tokenize(sfilter * sf, stoken_t * sout);
int filter_fold(sfilter * sf, stoken_t * sout);
#endif /* _SQLPARSE_PRIVATE_H */

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
@ -391,11 +391,9 @@ apr_status_t modsecurity_tx_init(modsec_rec *msr) {
if (msr->matched_vars == NULL) return -1;
apr_table_clear(msr->matched_vars);
if(msr->txcfg->max_rule_time > 0) {
msr->perf_rules = apr_table_make(msr->mp, 8);
if (msr->perf_rules == NULL) return -1;
apr_table_clear(msr->perf_rules);
}
msr->perf_rules = apr_table_make(msr->mp, 8);
if (msr->perf_rules == NULL) return -1;
apr_table_clear(msr->perf_rules);
/* Locate the cookie headers and parse them */
arr = apr_table_elts(msr->request_headers);

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
@ -442,6 +442,8 @@ struct modsec_rec {
lua_State *L;
#endif
#endif
int msc_sdbm_delete_error;
};
struct directory_config {
@ -579,7 +581,7 @@ struct directory_config {
/* Hash */
apr_array_header_t *hash_method;
const char *crypto_key;
const char *crypto_key;
int crypto_key_len;
const char *crypto_param_name;
int hash_is_enabled;

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
@ -38,7 +38,7 @@
#define MODSEC_VERSION_MAJOR "2"
#define MODSEC_VERSION_MINOR "7"
#define MODSEC_VERSION_MAINT "3"
#define MODSEC_VERSION_MAINT "4"
#define MODSEC_VERSION_TYPE ""
#define MODSEC_VERSION_RELEASE ""
@ -53,10 +53,10 @@
#define MODSEC_MODULE_NAME "ModSecurity for IIS (STABLE)"
#else
#ifdef VERSION_NGINX
#define MODSEC_MODULE_NAME "ModSecurity for nginx (RC)"
#define MODSEC_MODULE_NAME "ModSecurity for nginx (STABLE)"
#else
#ifdef VERSION_STANDALONE
#define MODSEC_MODULE_NAME "ModSecurity Standalone (RC)"
#define MODSEC_MODULE_NAME "ModSecurity Standalone (STABLE)"
#else
#define MODSEC_MODULE_NAME "ModSecurity for Apache"
#endif

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
@ -170,6 +170,7 @@ static apr_status_t modsecurity_request_body_store_memory(modsec_rec *msr,
/* Would storing this chunk mean going over the limit? */
if ((msr->msc_reqbody_spilltodisk)
&& (msr->txcfg->reqbody_buffering != REQUEST_BODY_FORCEBUF_ON)
&& (msr->msc_reqbody_length + length > (apr_size_t)msr->txcfg->reqbody_inmemory_limit))
{
msc_data_chunk **chunks;

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
@ -220,6 +220,7 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
msr_log(msr, 1, "collection_retrieve_ex: Failed deleting collection (name \"%s\", "
"key \"%s\"): %s", log_escape(msr->mp, col_name),
log_escape_ex(msr->mp, col_key, col_key_len), get_apr_error(msr->mp, rc));
msr->msc_sdbm_delete_error = 1;
goto cleanup;
}
@ -467,7 +468,7 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
var->value = apr_psprintf(msr->mp, "%d", newval);
var->value_len = strlen(var->value);
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "collection_store: Delta applied for %s.%s %d->%d (%d): %d + (%d) = %d [%s,%d]",
log_escape_ex(msr->mp, var_name->value, var_name->value_len),
@ -490,7 +491,12 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
/* Now generate the binary object. */
blob = apr_pcalloc(msr->mp, blob_size);
if (blob == NULL) {
goto error;
if (dbm != NULL) {
apr_sdbm_unlock(dbm);
apr_sdbm_close(dbm);
}
return -1;
}
blob[0] = 0x49;
@ -542,10 +548,16 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
rc = apr_sdbm_store(dbm, key, value, APR_SDBM_REPLACE);
if (rc != APR_SUCCESS) {
msr_log(msr, 1, "collection_store: Failed to write to DBM file \"%s\": %s", dbm_filename,
get_apr_error(msr->mp, rc));
goto error;
get_apr_error(msr->mp, rc));
if (dbm != NULL) {
apr_sdbm_unlock(dbm);
apr_sdbm_close(dbm);
}
return -1;
}
apr_sdbm_unlock(dbm);
apr_sdbm_close(dbm);
if (msr->txcfg->debuglog_level >= 4) {
@ -557,11 +569,6 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
return 0;
error:
if (dbm) {
apr_sdbm_close(dbm);
}
return -1;
}
@ -672,9 +679,10 @@ int collections_remove_stale(modsec_rec *msr, const char *col_name) {
msr_log(msr, 1, "collections_remove_stale: Failed deleting collection (name \"%s\", "
"key \"%s\"): %s", log_escape(msr->mp, col_name),
log_escape_ex(msr->mp, key.dptr, key.dsize - 1), get_apr_error(msr->mp, rc));
msr->msc_sdbm_delete_error = 1;
goto error;
}
if (msr->txcfg->debuglog_level >= 4) {
msr_log(msr, 4, "collections_remove_stale: Removed stale collection (name \"%s\", "
"key \"%s\").", log_escape(msr->mp, col_name),

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
@ -2604,12 +2604,16 @@ static int execute_operator(msre_var *var, msre_rule *rule, modsec_rec *msr,
rt_time = apr_table_get(msr->perf_rules, rule->actionset->id);
if(rt_time == NULL) {
rt_time = apr_psprintf(msr->mp, "%" APR_TIME_T_FMT, (t1 - time_before_op));
apr_table_setn(msr->perf_rules, rule->actionset->id, rt_time);
rule_time = (apr_time_t)atoi(rt_time);
if(rule_time >= msr->txcfg->max_rule_time)
apr_table_setn(msr->perf_rules, rule->actionset->id, rt_time);
} else {
rule_time = (apr_time_t)atoi(rt_time);
rule_time += (t1 - time_before_op);
rt_time = apr_psprintf(msr->mp, "%" APR_TIME_T_FMT, rule_time);
apr_table_setn(msr->perf_rules, rule->actionset->id, rt_time);
if(rule_time >= msr->txcfg->max_rule_time) {
rt_time = apr_psprintf(msr->mp, "%" APR_TIME_T_FMT, rule_time);
apr_table_setn(msr->perf_rules, rule->actionset->id, rt_time);
}
}
}
}

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
@ -27,6 +27,9 @@
#include <arpa/inet.h>
#endif
#include "libinjection/sqlparse.h"
#include "libinjection/sqli_fingerprints.h"
/**
*
*/
@ -369,7 +372,7 @@ static int msre_op_ipmatchFromFile_execute(modsec_rec *msr, msre_rule *rule, msr
/* rsub */
static char *param_remove_escape(msre_rule *rule, char *str, int len) {
char *parm = apr_palloc(rule->ruleset->mp, len);
char *parm = apr_pcalloc(rule->ruleset->mp, len);
char *ret = parm;
for(;*str!='\0';str++) {
@ -2129,6 +2132,42 @@ static int msre_op_contains_execute(modsec_rec *msr, msre_rule *rule, msre_var *
return 0;
}
/** libinjection detectSQLi
* links against files in libinjection directory
* See www.client9.com/libinjection for details
* `is_sqli_pattern` right now is a hardwired set of sqli fingerprints.
* In future, change to read from file.
*/
static int msre_op_detectSQLi_execute(modsec_rec *msr, msre_rule *rule, msre_var *var,
char **error_msg) {
sfilter sf;
int issqli = is_sqli(&sf, var->value, var->value_len, is_sqli_pattern);
int capture = apr_table_get(rule->actionset->actions, "capture") ? 1 : 0;
if (error_msg == NULL) return -1;
*error_msg = NULL;
if (issqli) {
set_match_to_tx(msr, capture, sf.pat, 0);
*error_msg = apr_psprintf(msr->mp, "detected SQLi using libinjection fingerprint '%s' at %s",
sf.pat, var->name);
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "detectSQLi: libinjection fingerprint '%s' matched input '%s'",
sf.pat,
log_escape_ex(msr->mp, var->value, var->value_len));
}
} else {
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "detectSQLi: no sql, libinjection no match input '%s' at '%s'",
log_escape_ex(msr->mp, var->value, var->value_len), var->name);
}
}
return issqli;
}
/* containsWord */
static int msre_op_containsWord_execute(modsec_rec *msr, msre_rule *rule, msre_var *var, char **error_msg) {
@ -4502,7 +4541,14 @@ void msre_engine_register_default_operators(msre_engine *engine) {
msre_op_containsWord_execute
);
/* is */
/* detectSQLi */
msre_engine_op_register(engine,
"detectSQLi",
NULL,
msre_op_detectSQLi_execute
);
/* streq */
msre_engine_op_register(engine,
"streq",
NULL, /* ENH init function to flag var substitution */

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
@ -511,6 +511,19 @@ static int var_reqbody_processor_generate(modsec_rec *msr, msre_var *var, msre_r
return 1;
}
/* SDBM_DELETE_ERROR */
static int var_sdbm_delete_error_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
apr_table_t *vartab, apr_pool_t *mptmp)
{
msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var));
rvar->value = apr_psprintf(mptmp, "%d", msr->msc_sdbm_delete_error);
rvar->value_len = strlen(rvar->value);
apr_table_addn(vartab, rvar->name, (void *)rvar);
return 1;
}
/* REQBODY_ERROR */
static int var_reqbody_processor_error_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
@ -700,13 +713,20 @@ static int var_useragent_ip_generate(modsec_rec *msr, msre_var *var, msre_rule *
static int var_remote_addr_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
apr_table_t *vartab, apr_pool_t *mptmp)
{
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 3
if (ap_find_linked_module("mod_remoteip.c") != NULL) {
if(msr->r->useragent_ip != NULL) msr->remote_addr = apr_pstrdup(msr->mp, msr->r->useragent_ip);
return var_simple_generate(var, vartab, mptmp, msr->remote_addr);
}
#endif
return var_simple_generate(var, vartab, mptmp, msr->remote_addr);
}
/* REMOTE_HOST */
static int var_remote_host_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
apr_table_t *vartab, apr_pool_t *mptmp)
apr_table_t *vartab, apr_pool_t *mptmp)
{
const char *value1 = ap_get_remote_host(msr->r->connection, msr->r->per_dir_config,
REMOTE_NAME, NULL);
@ -3117,6 +3137,16 @@ void msre_engine_register_default_variables(msre_engine *engine) {
PHASE_REQUEST_HEADERS
);
msre_engine_variable_register(engine,
"SDBM_DELETE_ERROR",
VAR_SIMPLE,
0, 0,
NULL,
var_sdbm_delete_error_generate,
VAR_DONT_CACHE, /* dynamic */
PHASE_REQUEST_BODY
);
/* REQBODY_PROCESSOR_ERROR - Deprecated */
msre_engine_variable_register(engine,
"REQBODY_PROCESSOR_ERROR",

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -11,7 +11,8 @@ APR_CFLAGS=""
APR_CPPFLAGS=""
APR_LDFLAGS=""
APR_LDADD=""
APR_INCLUDEDIR=""
APR_LINKLD=""
AC_DEFUN([CHECK_APR],
[dnl
@ -63,6 +64,10 @@ if test -n "${apr_path}"; then
if test "$verbose_output" -eq 1; then AC_MSG_NOTICE(apr LDFLAGS: $APR_LDFLAGS); fi
APR_LDADD="`${APR_CONFIG} --link-libtool`"
if test "$verbose_output" -eq 1; then AC_MSG_NOTICE(apr LDADD: $APR_LDADD); fi
APR_INCLUDEDIR="`${APR_CONFIG} --includedir`"
if test "$verbose_output" -eq 1; then AC_MSG_NOTICE(apr INCLUDEDIR: $APR_INCLUDEDIR); fi
APR_LINKLD="`${APR_CONFIG} --link-ld`"
if test "$verbose_output" -eq 1; then AC_MSG_NOTICE(apr LINKLD: $APR_LINKLD); fi
else
AC_MSG_RESULT([no])
fi
@ -73,6 +78,8 @@ AC_SUBST(APR_CFLAGS)
AC_SUBST(APR_CPPFLAGS)
AC_SUBST(APR_LDFLAGS)
AC_SUBST(APR_LDADD)
AC_SUBST(APR_INCLUDEDIR)
AC_SUBST(APR_LINKLD)
if test -z "${APR_VERSION}"; then
AC_MSG_NOTICE([*** apr library not found.])

View File

@ -10,6 +10,8 @@ APU_CONFIG=""
APU_CFLAGS=""
APU_LDFLAGS=""
APU_LDADD=""
APU_INCLUDEDIR=""
APU_LINKLD=""
AC_DEFUN([CHECK_APU],
[dnl
@ -18,7 +20,7 @@ AC_ARG_WITH(
apu,
[AC_HELP_STRING([--with-apu=PATH],[Path to apu prefix or config script])],
[test_paths="${with_apu}"],
[test_paths="/usr/local/libapr-util /usr/local/apr-util /usr/local/libapu /usr/local/apu /usr/local /opt/libapr-util /opt/apr-util /opt/libapu /opt/apu /opt /usr"])
[test_paths="/usr/local/libapr-util /usr/local/apr-util /usr/local/libapu /usr/local/apu /usr/local/apr /usr/local /opt/libapr-util /opt/apr-util /opt/libapu /opt/apu /opt /usr"])
AC_MSG_CHECKING([for libapu config script])
@ -60,6 +62,10 @@ if test -n "${apu_path}"; then
if test "$verbose_output" -eq 1; then AC_MSG_NOTICE(apu LDFLAGS: $APU_LDFLAGS); fi
APU_LDADD="`${APU_CONFIG} --link-libtool`"
if test "$verbose_output" -eq 1; then AC_MSG_NOTICE(apu LDADD: $APU_LDADD); fi
APU_INCLUDEDIR="`${APU_CONFIG} --includedir`"
if test "$verbose_output" -eq 1; then AC_MSG_NOTICE(apu INCLUDEDIR: $APU_INCLUDEDIR); fi
APU_LINKLD="`${APU_CONFIG} --link-ld`"
if test "$verbose_output" -eq 1; then AC_MSG_NOTICE(apu LINKLD: $APU_LINKLD); fi
else
AC_MSG_RESULT([no])
fi
@ -69,6 +75,8 @@ AC_SUBST(APU_VERSION)
AC_SUBST(APU_CFLAGS)
AC_SUBST(APU_LDFLAGS)
AC_SUBST(APU_LDADD)
AC_SUBST(APU_INCLUDEDIR)
AC_SUBST(APU_LINKLD)
if test -z "${APU_VERSION}"; then
AC_MSG_NOTICE([*** apu library not found.])

View File

@ -374,7 +374,7 @@ AC_ARG_ENABLE(htaccess-config,
# Enable phase-1 in post_read_request
AC_ARG_ENABLE(request-early,
AS_HELP_STRING([--enable-request-early],
[Place phase1 into post_read_request hook.]),
[Place phase1 into post_read_request hook. default is hook_request_early]),
[
if test "$enableval" != "no"; then
request_early="-DREQUEST_EARLY"

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,7 +1,7 @@
#!@PERL@
#
# ModSecurity for Apache 2.x, http://www.modsecurity.org/
# Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
# Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
#
# You may not use this file except in compliance with
# the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -77,7 +77,7 @@ FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'"
# Did we see anything that might be a boundary?
#
SecRule MULTIPART_UNMATCHED_BOUNDARY "!@eq 0" \
"id:'200003',phase:2,t:none,log,deny,status:44,msg:'Multipart parser detected a possible unmatched boundary.'"
"id:'200003',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'"
# PCRE Tuning
# We want to avoid a potential RegEx DoS condition

View File

@ -3,5 +3,5 @@ CORE_MODULES="$CORE_MODULES ngx_pool_context_module"
HTTP_AUX_FILTER_MODULES="ngx_http_modsecurity $HTTP_AUX_FILTER_MODULES"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_modsecurity.c $ngx_addon_dir/apr_bucket_nginx.c $ngx_addon_dir/ngx_pool_context.c"
NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/apr_bucket_nginx.h $ngx_addon_dir/ngx_pool_context.h"
CORE_LIBS="$CORE_LIBS $ngx_addon_dir/../../standalone/.libs/standalone.a -lapr-1 -laprutil-1 -lxml2 -lm "
CORE_INCS="$CORE_INCS /usr/include/apache2 /usr/include/apr-1.0 /usr/include/httpd /usr/include/apr-1 $ngx_addon_dir $ngx_addon_dir/../../standalone $ngx_addon_dir/../../apache2 /usr/include/libxml2 "
CORE_LIBS="$CORE_LIBS $ngx_addon_dir/../../standalone/.libs/standalone.a -L/usr/local/apr/lib -lapr-1 -L/usr/local/apr/lib -laprutil-1 -lpcre -lxml2 -lz -lm -ldl "
CORE_INCS="$CORE_INCS $ngx_addon_dir $ngx_addon_dir/../../standalone $ngx_addon_dir/../../apache2 /usr/include/libxml2 /usr/local/apache2/include /usr/local/apr/include/apr-1 /usr/local/apr/include/apr-1"

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
@ -52,7 +52,6 @@ static ngx_int_t ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_cha
static ngx_int_t ngx_http_modsecurity_preconfiguration(ngx_conf_t *cf);
static ngx_int_t ngx_http_modsecurity_init(ngx_conf_t *cf);
static ngx_int_t ngx_http_modsecurity_init_process(ngx_cycle_t *cycle);
static void ngx_http_modsecurity_exit_process(ngx_cycle_t *cycle);
static void *ngx_http_modsecurity_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_modsecurity_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child);
static char *ngx_http_modsecurity_config(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
@ -60,6 +59,7 @@ static char *ngx_http_modsecurity_enable(ngx_conf_t *cf, ngx_command_t *cmd, voi
static ngx_http_modsecurity_ctx_t * ngx_http_modsecurity_create_ctx(ngx_http_request_t *r);
static int ngx_http_modsecurity_drop_action(request_rec *r);
static void ngx_http_modsecurity_finalize(void *data);
static void ngx_http_modsecurity_cleanup(void *data);
static int ngx_http_modsecurity_save_headers_in_visitor(void *data, const char *key, const char *value);
@ -113,8 +113,8 @@ ngx_module_t ngx_http_modsecurity = {
ngx_http_modsecurity_init_process, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
ngx_http_modsecurity_exit_process, /* exit process */
ngx_http_modsecurity_exit_process, /* exit master */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
@ -156,7 +156,8 @@ ngx_pstrdup0(ngx_pool_t *pool, ngx_str_t *src)
}
static inline int ngx_http_modsecurity_method_number(unsigned int nginx)
static inline int
ngx_http_modsecurity_method_number(unsigned int nginx)
{
/*
* http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup
@ -246,7 +247,7 @@ ngx_http_modsecurity_load_request(ngx_http_request_t *r)
}
#endif
req->parsed_uri.path = req->path_info;
req->parsed_uri.path = (char *)ngx_pstrdup0(r->pool, &r->uri);
req->parsed_uri.is_initialized = 1;
str.data = r->port_start;
@ -254,7 +255,7 @@ ngx_http_modsecurity_load_request(ngx_http_request_t *r)
req->parsed_uri.port = ngx_atoi(str.data, str.len);
req->parsed_uri.port_str = (char *)ngx_pstrdup0(r->pool, &str);
req->parsed_uri.query = req->args;
req->parsed_uri.query = r->args.len ? req->args : NULL;
req->parsed_uri.dns_looked_up = 0;
req->parsed_uri.dns_resolved = 0;
@ -786,6 +787,29 @@ ngx_http_modsecurity_save_headers_out_visitor(void *data, const char *key, const
return 1;
}
static ngx_inline ngx_int_t
ngx_http_modsecurity_status(ngx_http_request_t *r, int status)
{
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: status %d", status);
if (status == DECLINED || status == APR_SUCCESS) {
return NGX_DECLINED;
}
/* nginx known status */
if ( (status >= 300 && status < 308) /* 3XX */
|| (status >= 400 && status < 417) /* 4XX */
|| (status >= 500 && status < 508) /* 5XX */
|| (status == NGX_HTTP_CREATED || status == NGX_HTTP_NO_CONTENT) ) {
return status;
}
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
/* create loc conf struct */
static void *
ngx_http_modsecurity_create_loc_conf(ngx_conf_t *cf)
@ -858,7 +882,8 @@ modsec_pcre_free(void *ptr)
static ngx_int_t
ngx_http_modsecurity_preconfiguration(ngx_conf_t *cf)
{
server_rec *s;
server_rec *s;
ngx_pool_cleanup_t *cln;
/* XXX: temporary hack, nginx uses pcre as well and hijacks these two */
pcre_malloc = modsec_pcre_malloc;
@ -873,6 +898,12 @@ ngx_http_modsecurity_preconfiguration(ngx_conf_t *cf)
return NGX_ERROR;
}
cln = ngx_pool_cleanup_add(cf->pool, 0);
if (cln == NULL) {
return NGX_ERROR;
}
cln->handler = ngx_http_modsecurity_finalize;
/* set host name */
s->server_hostname = ngx_palloc(cf->pool, ngx_cycle->hostname.len + 1);
if (s->server_hostname == NULL) {
@ -886,6 +917,12 @@ ngx_http_modsecurity_preconfiguration(ngx_conf_t *cf)
}
static void
ngx_http_modsecurity_finalize(void *data)
{
modsecTerminate();
}
static ngx_int_t
ngx_http_modsecurity_init(ngx_conf_t *cf)
@ -896,9 +933,6 @@ ngx_http_modsecurity_init(ngx_conf_t *cf)
modsecFinalizeConfig();
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
if (cmcf == NULL) {
return NGX_ERROR;
}
h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers);
if (h == NULL) {
@ -921,17 +955,12 @@ ngx_http_modsecurity_init(ngx_conf_t *cf)
static ngx_int_t
ngx_http_modsecurity_init_process(ngx_cycle_t *cycle)
{
/* must set log hook here cf->log maybe changed */
modsecSetLogHook(cycle->log, modsecLog);
modsecInitProcess();
return NGX_OK;
}
static void
ngx_http_modsecurity_exit_process(ngx_cycle_t *cycle)
{
modsecTerminate();
}
/*
** [ENTRY POINT] does : this function called by nginx from the request handler
@ -952,18 +981,18 @@ ngx_http_modsecurity_handler(ngx_http_request_t *r)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "modSecurity: handler");
/* create / retrive request ctx */
if (r->internal) {
/* we have already processed the request headers with previous loc conf */
/* TODO: do we need update ctx and process headers again? */
ctx = ngx_http_get_module_pool_ctx(r, ngx_http_modsecurity);
if (ctx) {
/* we have already processed the request headers */
ngx_http_set_ctx(r, ctx, ngx_http_modsecurity);
return NGX_DECLINED;
}
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "modSecurity: get internel request ctx failed");
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "modSecurity: request pool ctx empty");
}
ctx = ngx_http_modsecurity_create_ctx(r);
@ -978,52 +1007,34 @@ ngx_http_modsecurity_handler(ngx_http_request_t *r)
return NGX_ERROR;
}
ngx_http_modsecurity_load_request(r);
if (ngx_http_modsecurity_load_headers_in(r) != NGX_OK) {
/* load request to request rec */
if (ngx_http_modsecurity_load_request(r) != NGX_OK
|| ngx_http_modsecurity_load_headers_in(r) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
/* processing request headers */
rc = modsecProcessRequestHeaders(ctx->req);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: modsecProcessRequestHeaders %d", rc);
rc = ngx_http_modsecurity_status(r, modsecProcessRequestHeaders(ctx->req));
if (rc == DECLINED) {
if (modsecIsRequestBodyAccessEnabled(ctx->req)
&& r->method == NGX_HTTP_POST) {
/* Processing POST request body, should we process PUT? */
rc = ngx_http_read_client_request_body(r, ngx_http_modsecurity_body_handler);
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
return rc;
}
return NGX_DONE;
}
/* other method */
rc = modsecProcessRequestBody(ctx->req);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: modsecProcessRequestBody %d", rc);
}
if (rc != DECLINED) {
/* Nginx and Apache share same response code */
if (rc < NGX_HTTP_SPECIAL_RESPONSE || rc >= 600) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
if (rc != NGX_DECLINED) {
return rc;
}
/*
if (ngx_http_modsecurity_save_headers_in(r) != NGX_OK) {
if (r->method == NGX_HTTP_POST
&& modsecIsRequestBodyAccessEnabled(ctx->req) ) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
/* read POST request body, should we process PUT? */
rc = ngx_http_read_client_request_body(r, ngx_http_modsecurity_body_handler);
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
return rc;
}
return NGX_DONE;
}
*/
return NGX_DECLINED;
/* other method */
return ngx_http_modsecurity_status(r, modsecProcessRequestBody(ctx->req));
}
@ -1038,19 +1049,12 @@ ngx_http_modsecurity_body_handler(ngx_http_request_t *r)
ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity);
if (ngx_http_modsecurity_load_request_body(r) != NGX_OK) {
return ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
}
rc = modsecProcessRequestBody(ctx->req);
rc = ngx_http_modsecurity_status(r, modsecProcessRequestBody(ctx->req));
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: modsecProcessRequestBody %d", rc);
if (rc != DECLINED) {
/* Nginx and Apache share same response code */
if (rc < NGX_HTTP_SPECIAL_RESPONSE || rc >= 600) {
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
}
if (rc != NGX_DECLINED) {
return ngx_http_finalize_request(r, rc);
}
@ -1070,18 +1074,48 @@ static ngx_int_t
ngx_http_modsecurity_header_filter(ngx_http_request_t *r) {
ngx_http_modsecurity_loc_conf_t *cf;
ngx_http_modsecurity_ctx_t *ctx;
const char *location;
ngx_table_elt_t *h;
ngx_int_t rc;
cf = ngx_http_get_module_loc_conf(r, ngx_http_modsecurity);
ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity);
if (r != r->main || !cf->enable || ctx->complete) {
/* already processed, checking redirect action. */
if (ctx && ctx->complete
&& r->err_status >= NGX_HTTP_MOVED_PERMANENTLY
&& r->err_status < 308) {
/* 3XX load redirect location header so that we can do redirect in phase 3,4 */
location = apr_table_get(ctx->req->headers_out, "Location");
if (location == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
h = ngx_list_push(&r->headers_out.headers);
if (h == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
h->hash = 1;
h->key.data = (u_char *)"Location";
h->key.len = ngx_strlen("Location");
h->value.data = (u_char *)location;
h->value.len = ngx_strlen(location);
return ngx_http_next_header_filter(r);
}
if (r != r->main || !cf->enable || ctx == NULL ||ctx->complete) {
return ngx_http_next_header_filter(r);
}
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "modSecurity: header filter");
if (r->method == NGX_HTTP_HEAD || r->header_only) {
/* header only or SecResponseBodyAccess off */
if (r->header_only || (!modsecIsResponseBodyAccessEnabled(ctx->req)) ) {
ctx->complete = 1;
@ -1091,26 +1125,26 @@ ngx_http_modsecurity_header_filter(ngx_http_request_t *r) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
rc = modsecProcessResponse(ctx->req);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: modsecProcessResponse %d", rc);
rc = ngx_http_modsecurity_status(r, modsecProcessResponse(ctx->req));
if (rc == DECLINED || rc == APR_SUCCESS) {
if (ngx_http_modsecurity_save_headers_in(r) != NGX_OK
|| ngx_http_modsecurity_save_headers_out(r) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
return ngx_http_next_header_filter(r);
if (rc != NGX_DECLINED) {
return ngx_http_filter_finalize_request(r, &ngx_http_modsecurity, rc);
}
if (rc < NGX_HTTP_SPECIAL_RESPONSE || rc >= 600) {
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
if (ngx_http_modsecurity_save_headers_in(r) != NGX_OK
|| ngx_http_modsecurity_save_headers_out(r) != NGX_OK) {
return ngx_http_filter_finalize_request(r, &ngx_http_modsecurity, NGX_HTTP_INTERNAL_SERVER_ERROR);
}
return rc;
return ngx_http_next_header_filter(r);
}
/* SecResponseBodyAccess on, process rules in body filter */
/* pretend we are ngx_http_header_filter */
r->header_sent = 1;
r->filter_need_in_memory = 1;
return NGX_OK;
}
@ -1126,74 +1160,70 @@ ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
cf = ngx_http_get_module_loc_conf(r, ngx_http_modsecurity);
ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity);
if (r != r->main || !cf->enable || ctx->complete) {
if (r != r->main || !cf->enable || ctx == NULL || ctx->complete) {
return ngx_http_next_body_filter(r, in);
}
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "modSecurity: body filter");
if (in == NULL) {
/* waiting for more buffer */
r->buffered |= NGX_HTTP_SSI_BUFFERED;
return NGX_AGAIN;
}
rc = move_chain_to_brigade(in, ctx->brigade, r->pool, 0);
if (rc != NGX_OK) {
/* waiting for more buffer */
r->buffered |= NGX_HTTP_SSI_BUFFERED;
return rc;
}
/* last buf has been saved */
r->buffered &= ~NGX_HTTP_SSI_BUFFERED;
ctx->complete = 1;
modsecSetResponseBrigade(ctx->req, ctx->brigade);
// TODO: do we need reload headers_in ?
//
if (ngx_http_modsecurity_load_headers_in(r) != NGX_OK
|| ngx_http_modsecurity_load_headers_out(r) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
rc = modsecProcessResponse(ctx->req);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: modsecProcessResponse %d", rc);
rc = ngx_http_modsecurity_status(r, modsecProcessResponse(ctx->req));
if (rc == DECLINED || rc == APR_SUCCESS) {
in = NULL;
apr_brigade_length(ctx->brigade, 0, &content_length);
rc = move_brigade_to_chain(ctx->brigade, &in, r->pool);
if (rc == NGX_ERROR) {
return NGX_ERROR;
}
if (ngx_http_modsecurity_save_headers_in(r) != NGX_OK
||ngx_http_modsecurity_save_headers_out(r) != NGX_OK) {
return ngx_http_filter_finalize_request(r, &ngx_http_modsecurity, NGX_HTTP_INTERNAL_SERVER_ERROR);
}
if (r->headers_out.content_length_n != -1) {
r->headers_out.content_length_n = content_length;
r->headers_out.content_length = NULL; /* header filter will set this */
}
rc = ngx_http_next_header_filter(r);
if (rc == NGX_ERROR || rc > NGX_OK) {
return ngx_http_filter_finalize_request(r, &ngx_http_modsecurity, rc);
}
return ngx_http_next_body_filter(r, in);
if (rc != NGX_DECLINED) {
return ngx_http_filter_finalize_request(r, &ngx_http_modsecurity, rc);
}
if (rc < NGX_HTTP_SPECIAL_RESPONSE || rc >= 600) {
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
apr_brigade_length(ctx->brigade, 0, &content_length);
rc = move_brigade_to_chain(ctx->brigade, &in, r->pool);
if (rc == NGX_ERROR) {
return NGX_ERROR;
}
return ngx_http_filter_finalize_request(r, &ngx_http_modsecurity, rc);
if (ngx_http_modsecurity_save_headers_in(r) != NGX_OK
||ngx_http_modsecurity_save_headers_out(r) != NGX_OK) {
return ngx_http_filter_finalize_request(r, &ngx_http_modsecurity, NGX_HTTP_INTERNAL_SERVER_ERROR);
}
if (r->headers_out.content_length_n != -1) {
r->headers_out.content_length_n = content_length;
r->headers_out.content_length = NULL; /* header filter will set this */
}
r->header_sent = 0;
rc = ngx_http_next_header_filter(r);
if (rc == NGX_ERROR || rc > NGX_OK) {
return ngx_http_filter_finalize_request(r, &ngx_http_modsecurity, rc);
}
return ngx_http_next_body_filter(r, in);
}

View File

@ -196,7 +196,7 @@ ngx_pool_context_init_conf(ngx_cycle_t *cycle, void *conf)
{
ngx_pool_context_conf_t *pcf = conf;
ngx_conf_init_uint_value(pcf->size, NGX_POOL_CTX_SIZE);
ngx_conf_init_uint_value(pcf->size, cycle->connection_n);
ngx_pool_context_hash_size = pcf->size;

View File

@ -13,7 +13,7 @@ standalone_la_SOURCES = ../apache2/mod_security2.c \
../apache2/msc_util.c ../apache2/msc_pcre.c ../apache2/persist_dbm.c ../apache2/msc_reqbody.c \
../apache2/msc_geo.c ../apache2/msc_gsb.c ../apache2/msc_unicode.c \
../apache2/acmp.c ../apache2/msc_lua.c ../apache2/msc_release.c \
../apache2/msc_crypt.c ../apache2/msc_tree.c \
../apache2/msc_crypt.c ../apache2/msc_tree.c ../apache2/libinjection/sqlparse.c \
api.c buckets.c \
config.c filters.c \
hooks.c \
@ -72,6 +72,10 @@ standalone_la_LDFLAGS = -no-undefined -module -avoid-version \
@PCRE_LDFLAGS@ @LIBXML2_LDFLAGS@ @LUA_LDFLAGS@
endif
standalone_INCS = `echo "@LIBXML2_CFLAGS@ @LUA_CFLAGS@" | sed -n 's/ *-I *\([^ ]*\) /\1 /gp'` \
@APXS_INCLUDEDIR@ @APR_INCLUDEDIR@ @APU_INCLUDEDIR@
standalone_LIBS = @APR_LINKLD@ @APU_LINKLD@ @APXS_LDFLAGS@ \
@PCRE_LDADD@ @LIBXML2_LDADD@ @LUA_LDADD@
install-exec-hook: $(pkglib_LTLIBRARIES)
@echo "Creating Nginx config file..."; \
rm -f ../nginx/modsecurity/config; \
@ -79,9 +83,9 @@ install-exec-hook: $(pkglib_LTLIBRARIES)
echo "CORE_MODULES=\"\$$CORE_MODULES ngx_pool_context_module\"" >> ../nginx/modsecurity/config; \
echo "HTTP_AUX_FILTER_MODULES=\"ngx_http_modsecurity \$$HTTP_AUX_FILTER_MODULES\"" >> ../nginx/modsecurity/config; \
echo "NGX_ADDON_SRCS=\"\$$NGX_ADDON_SRCS \$$ngx_addon_dir/ngx_http_modsecurity.c \$$ngx_addon_dir/apr_bucket_nginx.c \$$ngx_addon_dir/ngx_pool_context.c\"" >> ../nginx/modsecurity/config;\
echo "NGX_ADDON_DEPS=\"\$$NGX_ADDON_DEPS \$$ngx_addon_dir/apr_bucket_nginx.h \$$ngx_addon_dir/ngx_pool_context.h\"" >> ../nginx/modsecurity/config; \
echo "CORE_LIBS=\"\$$CORE_LIBS \$$ngx_addon_dir/../../standalone/.libs/standalone.a -lapr-1 -laprutil-1 -lxml2 -lm @LUA_LDADD@\"" >> ../nginx/modsecurity/config; \
echo "CORE_INCS=\"\$$CORE_INCS /usr/include/apache2 /usr/include/apr-1.0 /usr/include/httpd /usr/include/apr-1 \$$ngx_addon_dir \$$ngx_addon_dir/../../standalone \$$ngx_addon_dir/../../apache2 /usr/include/libxml2 `echo @LUA_CFLAGS@ | cut -d "I" -f3`\"" >> ../nginx/modsecurity/config; \
echo "NGX_ADDON_DEPS=\"\$$NGX_ADDON_DEPS \$$ngx_addon_dir/apr_bucket_nginx.h \$$ngx_addon_dir/ngx_pool_context.h \$$ngx_addon_dir/ngx_http_modsecurity.c \$$ngx_addon_dir/apr_bucket_nginx.c \$$ngx_addon_dir/ngx_pool_context.c\"" >> ../nginx/modsecurity/config; \
echo "CORE_LIBS=\"\$$CORE_LIBS \$$ngx_addon_dir/../../standalone/.libs/standalone.a $(standalone_LIBS) \"" >> ../nginx/modsecurity/config; \
echo "CORE_INCS=\"\$$CORE_INCS \$$ngx_addon_dir \$$ngx_addon_dir/../../standalone \$$ngx_addon_dir/../../apache2 $(standalone_INCS)\"" >> ../nginx/modsecurity/config; \
echo "Removing unused static libraries..."; \
for m in $(pkglib_LTLIBRARIES); do \
base=`echo $$m | sed 's/\..*//'`; \

View File

@ -1,9 +1,8 @@
# Makefile.in generated by automake 1.11.6 from Makefile.am.
# Makefile.in generated by automake 1.12.2 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
# Foundation, Inc.
# Copyright (C) 1994-2012 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@ -51,7 +50,8 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = standalone
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(top_srcdir)/build/depcomp
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/build/find_apr.m4 \
$(top_srcdir)/build/find_apu.m4 \
@ -149,13 +149,17 @@ AMTAR = @AMTAR@
APR_CFLAGS = @APR_CFLAGS@
APR_CONFIG = @APR_CONFIG@
APR_CPPFLAGS = @APR_CPPFLAGS@
APR_INCLUDEDIR = @APR_INCLUDEDIR@
APR_LDADD = @APR_LDADD@
APR_LDFLAGS = @APR_LDFLAGS@
APR_LINKLD = @APR_LINKLD@
APR_VERSION = @APR_VERSION@
APU_CFLAGS = @APU_CFLAGS@
APU_CONFIG = @APU_CONFIG@
APU_INCLUDEDIR = @APU_INCLUDEDIR@
APU_LDADD = @APU_LDADD@
APU_LDFLAGS = @APU_LDFLAGS@
APU_LINKLD = @APU_LINKLD@
APU_VERSION = @APU_VERSION@
APXS = @APXS@
APXS_BINDIR = @APXS_BINDIR@
@ -381,6 +385,12 @@ standalone_la_LIBADD = @APR_LDADD@ @APU_LDADD@ @PCRE_LDADD@ @LIBXML2_LDADD@ @LUA
@SOLARIS_TRUE@ @APR_LDFLAGS@ @APU_LDFLAGS@ @APXS_LDFLAGS@ \
@SOLARIS_TRUE@ @PCRE_LDFLAGS@ @LIBXML2_LDFLAGS@ @LUA_LDFLAGS@
standalone_INCS = `echo "@LIBXML2_CFLAGS@ @LUA_CFLAGS@" | sed -n 's/ *-I *\([^ ]*\) /\1 /gp'` \
@APXS_INCLUDEDIR@ @APR_INCLUDEDIR@ @APU_INCLUDEDIR@
standalone_LIBS = @APR_LINKLD@ @APU_LINKLD@ @APXS_LDFLAGS@ \
@PCRE_LDADD@ @LIBXML2_LDADD@ @LUA_LDADD@
all: all-am
.SUFFIXES:
@ -441,12 +451,14 @@ uninstall-pkglibLTLIBRARIES:
clean-pkglibLTLIBRARIES:
-test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES)
@list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
test "$$dir" != "$$p" || dir=.; \
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
@list='$(pkglib_LTLIBRARIES)'; \
locs=`for p in $$list; do echo $$p; done | \
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
sort -u`; \
test -z "$$locs" || { \
echo rm -f $${locs}; \
rm -f $${locs}; \
}
standalone.la: $(standalone_la_OBJECTS) $(standalone_la_DEPENDENCIES) $(EXTRA_standalone_la_DEPENDENCIES)
$(standalone_la_LINK) -rpath $(pkglibdir) $(standalone_la_OBJECTS) $(standalone_la_LIBADD) $(LIBS)
@ -797,6 +809,20 @@ GTAGS:
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: $(HEADERS) $(SOURCES) $(LISP)
list='$(SOURCES) $(HEADERS) $(LISP)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
@ -942,32 +968,30 @@ uninstall-am: uninstall-pkglibLTLIBRARIES
.MAKE: install-am install-exec-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-libtool clean-pkglibLTLIBRARIES ctags distclean \
distclean-compile distclean-generic distclean-libtool \
distclean-tags distdir dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-exec-hook \
install-html install-html-am install-info install-info-am \
install-man install-pdf install-pdf-am \
install-pkglibLTLIBRARIES install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
pdf pdf-am ps ps-am tags uninstall uninstall-am \
uninstall-pkglibLTLIBRARIES
clean-libtool clean-pkglibLTLIBRARIES cscopelist ctags \
distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-exec-hook install-html install-html-am \
install-info install-info-am install-man install-pdf \
install-pdf-am install-pkglibLTLIBRARIES install-ps \
install-ps-am install-strip installcheck installcheck-am \
installdirs maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
uninstall-am uninstall-pkglibLTLIBRARIES
install-exec-hook: $(pkglib_LTLIBRARIES)
@echo "Creating Nginx config file..."; \
rm -f ../nginx/modsecurity/config; \
echo "ngx_addon_name=ngx_http_modsecurity" >> ../nginx/modsecurity/config; \
echo "# HTTP_MODULES=\"\$$HTTP_MODULES ngx_http_modsecurity\"" >> ../nginx/modsecurity/config; \
echo "HTTP_HEADERS_FILTER_MODULE=\"ngx_http_modsecurity \$$HTTP_HEADERS_FILTER_MODULE\"" >> ../nginx/modsecurity/config; \
echo "NGX_ADDON_SRCS=\"\$$NGX_ADDON_SRCS \$$ngx_addon_dir/ngx_http_modsecurity.c \$$ngx_addon_dir/apr_bucket_nginx.c\"" >> ../nginx/modsecurity/config;\
echo "NGX_ADDON_DEPS=\"\$$NGX_ADDON_DEPS\"" >> ../nginx/modsecurity/config; \
echo "CORE_LIBS=\"\$$CORE_LIBS \$$ngx_addon_dir/../../standalone/.libs/standalone.a -lapr-1 -laprutil-1 -lxml2 -lm @LUA_LDADD@\"" >> ../nginx/modsecurity/config; \
echo "CORE_INCS=\"\$$CORE_INCS /usr/include/apache2 /usr/include/apr-1.0 /usr/include/httpd /usr/include/apr-1 \$$ngx_addon_dir \$$ngx_addon_dir/../../standalone \$$ngx_addon_dir/../../apache2 /usr/include/libxml2 `echo @LUA_CFLAGS@ | cut -d "I" -f3`\"" >> ../nginx/modsecurity/config; \
echo "have=REQUEST_EARLY . auto/have" >> ../nginx/modsecurity/config;\
echo "CORE_MODULES=\"\$$CORE_MODULES ngx_pool_context_module\"" >> ../nginx/modsecurity/config; \
echo "HTTP_AUX_FILTER_MODULES=\"ngx_http_modsecurity \$$HTTP_AUX_FILTER_MODULES\"" >> ../nginx/modsecurity/config; \
echo "NGX_ADDON_SRCS=\"\$$NGX_ADDON_SRCS \$$ngx_addon_dir/ngx_http_modsecurity.c \$$ngx_addon_dir/apr_bucket_nginx.c \$$ngx_addon_dir/ngx_pool_context.c\"" >> ../nginx/modsecurity/config;\
echo "NGX_ADDON_DEPS=\"\$$NGX_ADDON_DEPS \$$ngx_addon_dir/apr_bucket_nginx.h \$$ngx_addon_dir/ngx_pool_context.h \$$ngx_addon_dir/ngx_http_modsecurity.c \$$ngx_addon_dir/apr_bucket_nginx.c \$$ngx_addon_dir/ngx_pool_context.c \"" >> ../nginx/modsecurity/config; \
echo "CORE_LIBS=\"\$$CORE_LIBS \$$ngx_addon_dir/../../standalone/.libs/standalone.a $(standalone_LIBS) \"" >> ../nginx/modsecurity/config; \
echo "CORE_INCS=\"\$$CORE_INCS \$$ngx_addon_dir \$$ngx_addon_dir/../../standalone \$$ngx_addon_dir/../../apache2 $(standalone_INCS)\"" >> ../nginx/modsecurity/config; \
echo "Removing unused static libraries..."; \
for m in $(pkglib_LTLIBRARIES); do \
base=`echo $$m | sed 's/\..*//'`; \

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
@ -223,40 +223,10 @@ apr_status_t ap_http_in_filter(ap_filter_t *f, apr_bucket_brigade *bb_out,
}
apr_status_t ap_http_out_filter(ap_filter_t *f, apr_bucket_brigade *b) {
modsec_rec *msr = (modsec_rec *)f->ctx;
apr_status_t rc;
apr_bucket_brigade *bb_out;
bb_out = modsecGetResponseBrigade(f->r);
if (bb_out) {
APR_BRIGADE_CONCAT(bb_out, b);
return APR_SUCCESS;
}
// is there a way to tell whether the response body was modified or not?
//
if((msr->txcfg->content_injection_enabled || msr->content_prepend_len != 0 || msr->content_append_len != 0)
&& msr->txcfg->resbody_access) {
if (modsecWriteResponse != NULL) {
char *data = NULL;
apr_size_t length;
rc = apr_brigade_pflatten(msr->of_brigade, &data, &length, msr->mp);
if (rc != APR_SUCCESS) {
msr_log(msr, 1, "Output filter: Failed to flatten brigade (%d): %s", rc,
get_apr_error(msr->mp, rc));
return -1;
}
/* TODO: return ?*/
modsecWriteResponse(msr->r, data, msr->stream_output_length);
}
}
apr_bucket_brigade *bb_out = (apr_bucket_brigade *)f->ctx;
APR_BRIGADE_CONCAT(bb_out, b);
return APR_SUCCESS;
}
@ -551,74 +521,117 @@ int modsecIsResponseBodyAccessEnabled(request_rec *r)
}
int modsecProcessResponse(request_rec *r) {
int status = DECLINED;
int status;
modsec_rec *msr;
apr_bucket *e;
ap_filter_t *f;
apr_bucket_brigade *bb_in, *bb_out, *bb;
if(r->output_filters != NULL) {
modsec_rec *msr = (modsec_rec *)r->output_filters->ctx;
char buf[8192];
char *tmp = NULL;
apr_bucket *e = NULL;
if(r->output_filters == NULL) {
return DECLINED;
}
msr = (modsec_rec *)r->output_filters->ctx;
if (msr == NULL) {
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r->server,
"ModSecurity: Internal Error: msr is null in output filter.");
ap_remove_output_filter(r->output_filters);
return APR_EGENERAL;
}
msr->r = r;
/* create input response brigade */
bb_in = apr_brigade_create(msr->mp, r->connection->bucket_alloc);
if (bb_in == NULL) {
msr_log(msr, 1, "Process response: Failed to create brigade.");
return APR_EGENERAL;
}
/* get input response brigade */
bb = modsecGetResponseBrigade(r);
if (bb != NULL) {
APR_BRIGADE_CONCAT(bb_in, bb);
if (!APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb_in))) {
e = apr_bucket_eos_create(bb_in->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb_in, e);
}
} else if (modsecReadResponse != NULL) {
unsigned int readcnt = 0;
int is_eos = 0;
ap_filter_t *f = NULL;
apr_bucket_brigade *bb_in, *bb = NULL;
char buf[8192];
while(!is_eos) {
modsecReadResponse(r, buf, 8192, &readcnt, &is_eos);
if (msr == NULL) {
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r->server,
"ModSecurity: Internal Error: msr is null in output filter.");
ap_remove_output_filter(r->output_filters);
return send_error_bucket(msr, r->output_filters, HTTP_INTERNAL_SERVER_ERROR);
}
bb = apr_brigade_create(msr->mp, r->connection->bucket_alloc);
if (bb == NULL) {
msr_log(msr, 1, "Process response: Failed to create brigade.");
return APR_EGENERAL;
}
msr->r = r;
bb_in = modsecGetResponseBrigade(r);
if (bb_in != NULL) {
APR_BRIGADE_CONCAT(bb, bb_in);
if (!APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
e = apr_bucket_eos_create(bb->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, e);
if(readcnt > 0) {
char *tmp = (char *)apr_palloc(r->pool, readcnt);
memcpy(tmp, buf, readcnt);
e = apr_bucket_pool_create(tmp, readcnt, r->pool, r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb_in, e);
}
} else if (modsecReadResponse != NULL) {
while(!is_eos) {
modsecReadResponse(r, buf, 8192, &readcnt, &is_eos);
}
if(readcnt > 0) {
tmp = (char *)apr_palloc(r->pool, readcnt);
memcpy(tmp, buf, readcnt);
e = apr_bucket_pool_create(tmp, readcnt, r->pool, r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, e);
}
e = apr_bucket_eos_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb_in, e);
} else {
/* cannot read response body process header only */
e = apr_bucket_eos_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb_in, e);
}
bb_out = bb ? bb : apr_brigade_create(msr->mp, r->connection->bucket_alloc);
if (bb_out == NULL) {
msr_log(msr, 1, "Process response: Failed to create brigade.");
return APR_EGENERAL;
}
/* concat output bucket to bb_out */
f = ap_add_output_filter("HTTP_OUT", bb_out, r, r->connection);
status = ap_pass_brigade(r->output_filters, bb_in);
ap_remove_output_filter(f);
if (status == APR_EGENERAL) {
/* retrive response status from bb_out */
for(e = APR_BRIGADE_FIRST(bb_out);
e != APR_BRIGADE_SENTINEL(bb_out);
e = APR_BUCKET_NEXT(e)) {
if (AP_BUCKET_IS_ERROR(e)) {
return ((ap_bucket_error*) e->data)->status;
}
e = apr_bucket_eos_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, e);
} else {
/* cannot read response body process header only */
e = apr_bucket_eos_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, e);
}
f = ap_add_output_filter("HTTP_OUT", msr, r, r->connection);
status = ap_pass_brigade(r->output_filters, bb);
ap_remove_output_filter(f);
if(status > 0
&& msr->intercept_actionset->intercept_status != 0) {
status = msr->intercept_actionset->intercept_status;
}
return APR_EGENERAL;
}
if (status != DECLINED) {
return status;
}
return status;
/* copy bb_out */
// is there a way to tell whether the response body was modified or not?
if (modsecWriteResponse != NULL
&& (msr->txcfg->content_injection_enabled || msr->content_prepend_len != 0 || msr->content_append_len != 0)
&& msr->txcfg->resbody_access) {
char *data = NULL;
apr_size_t length;
status = apr_brigade_pflatten(msr->of_brigade, &data, &length, msr->mp);
if (status != APR_SUCCESS) {
msr_log(msr, 1, "Output filter: Failed to flatten brigade (%d): %s", status,
get_apr_error(msr->mp, status));
return APR_EGENERAL;
}
if ( modsecWriteResponse(msr->r, data, msr->stream_output_length) != APR_SUCCESS) {
return APR_EGENERAL;
}
}
return DECLINED;
}
int modsecFinishRequest(request_rec *r) {

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

View File

@ -21,7 +21,8 @@ msc_test_SOURCES = msc_test.c \
$(top_srcdir)/apache2/msc_gsb.c \
$(top_srcdir)/apache2/acmp.c \
$(top_srcdir)/apache2/msc_lua.c \
$(top_srcdir)/apache2/msc_release.c
$(top_srcdir)/apache2/msc_release.c \
$(top_srcdir)/apache2/libinjection/sqlparse.c
msc_test_CFLAGS = @APXS_CFLAGS@ @APR_CFLAGS@ @APU_CFLAGS@ \
@PCRE_CFLAGS@ @LIBXML2_CFLAGS@ @MODSEC_EXTRA_CFLAGS@ @LUA_CFLAGS@
msc_test_CPPFLAGS = -I$(top_srcdir)/apache2 \

View File

@ -1,6 +1,6 @@
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License.  You may obtain a copy of the License at

18
tests/op/detectSQLi.t Normal file
View File

@ -0,0 +1,18 @@
{
type => "op",
name => "detectSQLi",
input => "",
ret => 0
},
{
type => "op",
name => "detectSQLi",
input => "this is not isqli",
ret => 0
},
{
type => "op",
name => "detectSQLi",
input => "ascii(substring(version() from 1 for 1))",
ret => 1
}

View File

View File

@ -0,0 +1,22 @@
user root;
worker_processes 1;
daemon on;
error_log logs/error.log debug;
events {
worker_connections 1024;
}
http {
ModSecurityEnabled [% enable %];
ModSecurityConfig [% config %];
server {
listen [% listen %];
server_name localhost;
location / {
}
}
}

View File

@ -0,0 +1,736 @@
#!/usr/bin/perl
#
# Run regression tests.
#
# Syntax: run-regression-tests.pl [options] [file [N]]
#
# All: run-regression-tests.pl
# All in file: run-regression-tests.pl file
# Nth in file: run-regression-tests.pl file N
#
use strict;
use Time::HiRes qw(gettimeofday sleep);
use POSIX qw(WIFEXITED WEXITSTATUS WIFSIGNALED WTERMSIG);
use File::Spec qw(rel2abs);
use File::Basename qw(basename dirname);
use File::Path qw(make_path);
use FileHandle;
use IPC::Open2 qw(open2);
use IPC::Open3 qw(open3);
use Getopt::Std;
use Data::Dumper;
use IO::Socket;
use LWP::UserAgent;
use Cwd 'abs_path';
use Template;
use File::Copy::Recursive qw(dircopy);
my @TYPES = qw(action config misc rule target);
my $SCRIPT = basename($0);
my $SCRIPT_DIR = File::Spec->rel2abs(dirname($0));
my $REG_DIR = "$SCRIPT_DIR/regression";
my $NGINX_DIR = "$REG_DIR/nginx";
my $NGINX_CONF_TEMP = "$REG_DIR/nginx/conf/nginx.conf.template";
my $NGINX = q(/usr/local/nginx/sbin/nginx);
my $PASSED = 0;
my $TOTAL = 0;
my $BUFSIZ = 32768;
my %C = ();
my %FILE = ();
my $UA_NAME = "ModSecurity Regression Tests/1.2.3";
my $UA = LWP::UserAgent->new;
$UA->agent($UA_NAME);
$SIG{TERM} = $SIG{INT} = \&handle_interrupt;
my %opt;
getopts('A:E:D:C:T:H:a:p:dvh', \%opt);
if ($opt{d}) {
$Data::Dumper::Indent = 1;
$Data::Dumper::Terse = 1;
$Data::Dumper::Pad = "";
$Data::Dumper::Quotekeys = 0;
}
sub usage {
print stderr <<"EOT";
@_
Usage: $SCRIPT [options] [file [N]]
Options:
-P path Specify nginx prefix path (default: $NGINX_DIR)
-a file Specify nginx binary (default: $NGINX)
-p port Specify nginx port (default: 8088)
-v Enable verbose output (details on failure).
-d Enable debugging output.
-h This help.
EOT
exit(1);
}
usage() if ($opt{h});
### Check nginx binary
if (defined $opt{a}) {
$NGINX = $opt{a};
}
else {
$opt{a} = $NGINX;
}
usage("Invalid Apache startup script: $NGINX\n") unless (-e $NGINX);
### Defaults
$opt{P} = "$NGINX_DIR" unless (defined $opt{P});
my $CONF_DIR = "$opt{P}/conf";
my $FILES_DIR = "$opt{P}/logs";
my $PID_FILE = "$FILES_DIR/nginx.pid";
$opt{A} = "$FILES_DIR/modsec_audit.log";
$opt{D} = "$FILES_DIR/modsec_debug.log";
$opt{E} = "$FILES_DIR/error.log";
$opt{C} = "$CONF_DIR/nginx.conf";
$opt{p} = 8088 unless (defined $opt{p});
$opt{v} = 1 if ($opt{d});
if ( !-d "$opt{P}" ) {
make_path($opt{P}) or die $!;
}
if ( !-d "$opt{P}/logs" ) {
make_path("$opt{P}/logs") or die $!;
}
if ( !-d "$opt{P}/html" ) {
make_path("$opt{P}/html") or die $!;
}
dircopy("$REG_DIR/server_root/htdocs","$opt{P}/html") or die $!;
%ENV = (
%ENV,
$NGINX_DIR => $opt{P},
SERVER_PORT => $opt{p},
SERVER_NAME => "localhost",
# TEST_NGX_PREFIX => $NGINX_DIR,
# DATA_DIR => $DATA_DIR,
# TEMP_DIR => $TEMP_DIR,
# UPLOAD_DIR => $UPLOAD_DIR,
CONF_DIR => $CONF_DIR,
# MODULES_DIR => $MODULES_DIR,
LOGS_DIR => $FILES_DIR,
SCRIPT_DIR => $SCRIPT_DIR,
REGRESSION_DIR => $REG_DIR,
DIST_ROOT => File::Spec->rel2abs(dirname("$SCRIPT_DIR/../../..")),
AUDIT_LOG => $opt{A},
DEBUG_LOG => $opt{D},
ERROR_LOG => $opt{E},
NGINX_CONF => $opt{C},
# HTDOCS => $opt{H},
USER_AGENT => $UA_NAME,
);
#dbg("OPTIONS: ", \%opt);
if (-e "$PID_FILE") {
msg("Shutting down previous instance: $PID_FILE");
nginx_stop();
}
if (defined $ARGV[0]) {
runfile(dirname($ARGV[0]), basename($ARGV[0]), $ARGV[1]);
done();
}
for my $type (@TYPES) {
my $dir = "$SCRIPT_DIR/regression/$type";
my @cfg = ();
# Get test names
opendir(DIR, "$dir") or quit(1, "Failed to open \"$dir\": $!");
@cfg = grep { /\.t$/ && -f "$dir/$_" } readdir(DIR);
closedir(DIR);
for my $cfg (sort @cfg) {
runfile($dir, $cfg);
}
}
done();
sub runfile {
my($dir, $cfg, $testnum) = @_;
my $fn = "$dir/$cfg";
my @data = ();
my $edata;
my @C = ();
my @test = ();
my $teststr;
my $n = 0;
my $pass = 0;
open(CFG, "<$fn") or quit(1, "Failed to open \"$fn\": $!");
@data = <CFG>;
$edata = q/@C = (/ . join("", @data) . q/)/;
eval $edata;
quit(1, "Failed to read test data \"$cfg\": $@") if ($@);
unless (@C) {
msg("\nNo tests defined for $fn");
return;
}
msg("\nLoaded ".@C." tests from $fn");
for my $t (@C) {
$n++;
next if (defined $testnum and $n != $testnum);
my $nginx_up = 0;
my %t = %{$t || {}};
my $id = sprintf("%3d", $n);
my $out = "";
my $rc = 0;
my $conf_fn;
# Startup nginx with optionally included conf.
if (exists $t{conf} and defined $t{conf}) {
$conf_fn = sprintf "%s/%s_%s_%06d.conf",
$CONF_DIR, $t{type}, $cfg, $n;
#dbg("Writing test config to: $conf_fn");
open(CONF, ">$conf_fn") or die "Failed to open conf \"$conf_fn\": $!\n";
print CONF (ref $t{conf} eq "CODE" ? eval { &{$t{conf}} } : $t{conf});
msg("$@") if ($@);
close CONF;
my %conf=(config => $conf_fn, enable => "on");
$nginx_up = nginx_start($t, \%conf) ? 0 : 1;
}
else {
$nginx_up = nginx_start($t) ? 0 : 1;
}
# Run any prerun setup
if ($rc == 0 and exists $t{prerun} and defined $t{prerun}) {
vrb("Executing perl prerun...");
$rc = &{$t{prerun}};
vrb("Perl prerun returned: $rc");
}
if ($nginx_up) {
# Perform the request and check response
if (exists $t{request}) {
my $resp = do_request($t{request});
if (!$resp) {
msg("invalid response");
vrb("RESPONSE: ", $resp);
$rc = 1;
}
else {
for my $key (keys %{ $t{match_response} || {}}) {
my($neg,$mtype) = ($key =~ m/^(-?)(.*)$/);
my $m = $t{match_response}{$key};
my $match = match_response($mtype, $resp, $m);
if ($neg and defined $match) {
$rc = 1;
msg("response $mtype matched: $m");
vrb($resp);
last;
}
elsif (!$neg and !defined $match) {
$rc = 1;
msg("response $mtype failed to match: $m");
vrb($resp);
last;
}
}
}
}
# Run any arbitrary perl tests
if ($rc == 0 and exists $t{test} and defined $t{test}) {
dbg("Executing perl test(s)...");
$rc = eval { &{$t{test}} };
if (! defined $rc) {
msg("Error running test: $@");
$rc = -1;
}
dbg("Perl tests returned: $rc");
}
# Search for all log matches
if ($rc == 0 and exists $t{match_log} and defined $t{match_log}) {
for my $key (keys %{ $t{match_log} || {}}) {
my($neg,$mtype) = ($key =~ m/^(-?)(.*)$/);
my $m = $t{match_log}{$key};
my $match = match_log($mtype, @{$m || []});
if ($neg and defined $match) {
$rc = 1;
msg("$mtype log matched: $m->[0]");
last;
}
elsif (!$neg and !defined $match) {
$rc = 1;
msg("$mtype log failed to match: $m->[0]");
last;
}
}
}
# Search for all file matches
if ($rc == 0 and exists $t{match_file} and defined $t{match_file}) {
sleep 1; # Make sure the file exists
for my $key (keys %{ $t{match_file} || {}}) {
my($neg,$fn) = ($key =~ m/^(-?)(.*)$/);
my $m = $t{match_file}{$key};
my $match = match_file($fn, $m);
if ($neg and defined $match) {
$rc = 1;
msg("$fn file matched: $m");
last;
}
elsif (!$neg and !defined $match) {
$rc = 1;
msg("$fn file failed match: $m");
last;
}
}
}
}
else {
msg("Failed to start nginx.");
$rc = 1;
}
if ($rc == 0) {
$pass++;
}
else {
vrb("Test Config: $conf_fn");
vrb("Debug Log: $FILE{debug}{fn}");
dbg(escape("$FILE{debug}{buf}"));
vrb("Error Log: $FILE{error}{fn}");
dbg(escape("$FILE{error}{buf}"));
}
msg(sprintf("%s) %s%s: %s%s", $id, $t{type}, (exists($t{comment}) ? " - $t{comment}" : ""), ($rc ? "failed" : "passed"), ((defined($out) && $out ne "")? " ($out)" : "")));
if ($nginx_up) {
$nginx_up = nginx_stop(\%t) ? 0 : 1;
}
}
$TOTAL += $testnum ? 1 : $n;
$PASSED += $pass;
msg(sprintf("Passed: %2d; Failed: %2d", $pass, $testnum ? (1 - $pass) : ($n - $pass)));
}
# Take out any indenting and translate LF -> CRLF
sub normalize_raw_request_data {
my $r = $_[0];
# Allow for indenting in test file
$r =~ s/^[ \t]*\x0d?\x0a//s;
my($indention) = ($r =~ m/^([ \t]*)/s); # indention taken from first line
$r =~ s/^$indention//mg;
$r =~ s/(\x0d?\x0a)[ \t]+$/$1/s;
# Translate LF to CRLF
$r =~ s/^\x0a/\x0d\x0a/mg;
$r =~ s/([^\x0d])\x0a/$1\x0d\x0a/mg;
return $r;
}
sub do_raw_request {
my $sock = new IO::Socket::INET(
Proto => "tcp",
PeerAddr => "localhost",
PeerPort => $opt{p},
) or msg("Failed to connect to localhost:$opt{p}: $@");
return unless ($sock);
# Join togeather the request
my $r = join("", @_);
dbg($r);
# Write to socket
print $sock "$r";
$sock->shutdown(1);
# Read from socket
my @resp = <$sock>;
$sock->close();
return HTTP::Response->parse(join("", @resp));
}
sub do_request {
my $r = $_[0];
# Allow test to execute code
if (ref $r eq "CODE") {
$r = eval { &$r };
msg("$@") unless (defined $r);
}
if (ref $r eq "HTTP::Request") {
my $resp = $UA->request($r);
dbg($resp->request()->as_string()) if ($opt{d});
return $resp
}
else {
return do_raw_request($r);
}
return;
}
sub match_response {
my($name, $resp, $re) = @_;
msg("Warning: Empty regular expression.") if (!defined $re or $re eq "");
if ($name eq "status") {
return $& if ($resp->code =~ m/$re/);
}
elsif ($name eq "content") {
return $& if ($resp->content =~ m/$re/m);
}
elsif ($name eq "raw") {
return $& if ($resp->as_string =~ m/$re/m);
}
return;
}
sub read_log {
my($name, $timeout, $graph) = @_;
return match_log($name, undef, $timeout, $graph);
}
sub match_log {
my($name, $re, $timeout, $graph) = @_;
my $t0 = gettimeofday;
my($fh,$rbuf) = ($FILE{$name}{fd}, \$FILE{$name}{buf});
my $n = length($$rbuf);
my $rc = undef;
unless (defined $fh) {
msg("Error: File \"$name\" is not opened for matching.");
return;
}
$timeout = 0 unless (defined $timeout);
my $i = 0;
my $graphed = 0;
READ: {
do {
my $nbytes = $fh->sysread($$rbuf, $BUFSIZ, $n);
if (!defined($nbytes)) {
msg("Error: Could not read \"$name\" log: $!");
last;
}
elsif (!defined($re) and $nbytes == 0) {
last;
}
# Remove APR pool debugging
$$rbuf =~ s/POOL DEBUG:[^\n]+PALLOC[^\n]+\n//sg;
$n = length($$rbuf);
#dbg("Match \"$re\" in $name \"$$rbuf\" ($n)");
if ($$rbuf =~ m/$re/m) {
$rc = $&;
last;
}
# TODO: Use select()/poll()
sleep 0.1 unless ($nbytes == $BUFSIZ);
if ($graph and $opt{d}) {
$i++;
if ($i == 10) {
$graphed++;
$i=0;
print STDERR $graph if ($graphed == 1);
print STDERR "."
}
}
} while (gettimeofday - $t0 < $timeout);
}
print STDERR "\n" if ($graphed);
return $rc;
}
sub match_file {
my($neg,$fn) = ($_[0] =~ m/^(-?)(.*)$/);
unless (exists $FILE{$fn}) {
eval {
$FILE{$fn}{fn} = $fn;
$FILE{$fn}{fd} = new FileHandle($fn, O_RDONLY) or die "$!\n";
$FILE{$fn}{fd}->blocking(0);
$FILE{$fn}{buf} = "";
};
if ($@) {
msg("Warning: Failed to open file \"$fn\": $@");
return;
}
}
return match_log($_[0], $_[1]); # timeout makes no sense
}
sub quote_shell {
my($s) = @_;
return $s unless ($s =~ m|[^\w!%+,\-./:@^]|);
$s =~ s/(['\\])/\\$1/g;
return "'$s'";
}
sub escape {
my @new = ();
for my $c (split(//, $_[0])) {
my $oc = ord($c);
push @new, ((($oc >= 0x20 and $oc <= 0x7e) or $oc == 0x0a or $oc == 0x0d) ? $c : sprintf("\\x%02x", ord($c)));
}
join('', @new);
}
sub dbg {
return unless(@_ and $opt{d});
my $out = join "", map {
(ref $_ ne "" ? Dumper($_) : $_)
} @_;
$out =~ s/^/DBG: /mg;
print STDOUT "$out\n";
}
sub vrb {
return unless(@_ and $opt{v});
msg(@_);
}
sub msg {
return unless(@_);
my $out = join "", map {
(ref $_ ne "" ? Dumper($_) : $_)
} @_;
print STDOUT "$out\n";
}
sub handle_interrupt {
$SIG{TERM} = $SIG{INT} = \&handle_interrupt;
msg("Interrupted via SIG$_[0]. Shutting down tests...");
nginx_stop();
quit(1);
}
sub quit {
my($ec,$msg) = @_;
$ec = 0 unless (defined $_[0]);
msg("$msg") if (defined $msg);
exit $ec;
}
sub done {
if ($PASSED != $TOTAL) {
quit(1, "\n$PASSED/$TOTAL tests passed.");
}
quit(0, "\nAll tests passed ($TOTAL).");
}
sub nginx_stop {
my $t = shift;
my @p = (
$NGINX,
-p => $opt{P},
-s => "quit",
);
my $nginx_out;
my $nginx_pid = open3(undef, $nginx_out, undef, @p) or quit(1);
my $out = join("\\n", grep(!/POOL DEBUG/, (<$nginx_out>)));
close $nginx_out;
waitpid($nginx_pid, 0);
my $rc = $?;
if ( WIFEXITED($rc) ) {
$rc = WEXITSTATUS($rc);
vrb("Nginx stop returned with $rc.") if ($rc);
}
elsif( WIFSIGNALED($rc) ) {
msg("Nginx stop failed with signal " . WTERMSIG($rc) . ".");
$rc = -1;
}
else {
msg("Nginx stop failed with unknown error.");
$rc = -1;
}
sleep 0.5;
if (-e $PID_FILE) {
msg("Nginx stop failed: $PID_FILE still exists");
}
return $rc;
}
sub nginx_reset_fd {
my($t) = @_;
# Cleanup
for my $key (keys %FILE) {
if (exists $FILE{$key}{fd} and defined $FILE{$key}{fd}) {
$FILE{$key}{fd}->close();
}
delete $FILE{$key};
}
# Error
eval {
$FILE{error}{fn} = $opt{E};
$FILE{error}{fd} = new FileHandle($opt{E}, O_RDWR|O_CREAT) or die "$!\n";
$FILE{error}{fd}->blocking(0);
$FILE{error}{fd}->sysseek(0, 2);
$FILE{error}{buf} = "";
};
if ($@) {
msg("Warning: Failed to open file \"$opt{E}\": $@");
return undef;
}
# Audit
eval {
$FILE{audit}{fn} = $opt{A};
$FILE{audit}{fd} = new FileHandle($opt{A}, O_RDWR|O_CREAT) or die "$!\n";
$FILE{audit}{fd}->blocking(0);
$FILE{audit}{fd}->sysseek(0, 2);
$FILE{audit}{buf} = "";
};
if ($@) {
msg("Warning: Failed to open file \"$opt{A}\": $@");
return undef;
}
# Debug
eval {
$FILE{debug}{fn} = $opt{D};
$FILE{debug}{fd} = new FileHandle($opt{D}, O_RDWR|O_CREAT) or die "$!\n";
$FILE{debug}{fd}->blocking(0);
$FILE{debug}{fd}->sysseek(0, 2);
$FILE{debug}{buf} = "";
};
if ($@) {
msg("Warning: Failed to open file \"$opt{D}\": $@");
return undef;
}
# Any extras listed in "match_log"
if ($t and exists $t->{match_log}) {
for my $k (keys %{ $t->{match_log} || {} }) {
my($neg,$fn) = ($k =~ m/^(-?)(.*)$/);
next if (!$fn or exists $FILE{$fn});
eval {
$FILE{$fn}{fn} = $fn;
$FILE{$fn}{fd} = new FileHandle($fn, O_RDWR|O_CREAT) or die "$!\n";
$FILE{$fn}{fd}->blocking(0);
$FILE{$fn}{fd}->sysseek(0, 2);
$FILE{$fn}{buf} = "";
};
if ($@) {
msg("Warning: Failed to open file \"$fn\": $@");
return undef;
}
}
}
}
sub encode_chunked {
my($data, $size) = @_;
$size = 128 unless ($size);
my $chunked = "";
my $n = 0;
my $bytes = length($data);
while ($bytes >= $size) {
$chunked .= sprintf "%x\x0d\x0a%s\x0d\x0a", $size, substr($data, $n, $size);
$n += $size;
$bytes -= $size;
}
if ($bytes) {
$chunked .= sprintf "%x\x0d\x0a%s\x0d\x0a", $bytes, substr($data, $n, $bytes);
}
$chunked .= "0\x0d\x0a\x0d\x0a"
}
sub nginx_start {
my ($t) = shift;
my($C) = shift;
my %conf = (
listen => "$opt{p}",
config => "$REG_DIR/nginx/conf/empty.conf",
enable => "off",
);
while(my($k,$v)= each %$C){
$conf{$k}=$v;
}
my ($tt) = Template->new(INCLUDE_PATH => "$REG_DIR/nginx/conf/");
my ($output);
$tt->process("nginx.conf.template", \%conf, \$output) || die $tt->error;
open (OUTFILE, ">$opt{C}");
print OUTFILE "$output";
close(OUTFILE);
nginx_reset_fd($t);
my @p = ($NGINX, -p => $opt{P});
my $nginx_out;
my $nginx_pid = open3(undef, $nginx_out, undef, @p) or quit(1);
my $out = join("\\n", grep(!/POOL DEBUG/, (<$nginx_out>)));
close $nginx_out;
waitpid($nginx_pid, 0);
my $rc = $?;
if ( WIFEXITED($rc) ) {
$rc = WEXITSTATUS($rc);
vrb("Nginx start returned with $rc.") if ($rc);
}
elsif( WIFSIGNALED($rc) ) {
msg("Nginx start failed with signal " . WTERMSIG($rc) . ".");
$rc = -1;
}
else {
msg("Nginx start failed with unknown error.");
$rc = -1;
}
# Look for startup msg
# unless (defined match_log("error", qr/start worker process/, 60, "Waiting on nginx to start: ")) {
# vrb(join(" ", map { quote_shell($_) } @p));
# vrb(match_log("error", qr/(^.*ModSecurity: .*)/sm, 10));
# msg("Nginx server failed to start.");
# nginx_stop();
# return -1;
# }
return $rc;
}