blob: a1581245ece3239e77079048cc401c039ddbc8c0 [file] [log] [blame] [raw]
/*
* NAXSI, a web application firewall for NGINX
* Copyright (C) 2011, Thibault 'bui' Koechlin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FOO_H__
#define __FOO_H__
#define NAXSI_VERSION "0.50"
#include <nginx.h>
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include <ngx_event.h>
#include <ngx_md5.h>
#include <ngx_http_core_module.h>
#include <pcre.h>
#include <ctype.h>
extern ngx_module_t ngx_http_naxsi_module;
/*
** Here is globally how the structures are organized :
**
** [[ngx_http_dummy_main_conf_t]] is the main structure for the module.
** it contains the core rules and a set of ngx_http_dummy_loc_conf_t,
** for each NGINX location.
** ---
** [[ngx_http_dummy_loc_conf_t]] is the main structure for any NGINX
** locations, that is - a web site. It contains both pointers to the core
** rules, as well as whitelists, scores, denied_url and all flags. all
** the data of a nginx location is held into the loc_conf_t struct.
** The sets of rules are actually containted into [[ngx_http_rule_t]] structs.
** ---
** [[ngx_http_rule_t]] structs are used to hold any info about a rule, as well
** as whitelists. (whitelists is just a 'kind' of rule).
**
*/
enum MATCH_TYPE {
URI_ONLY=0,
NAME_ONLY,
MIXED
};
enum DUMMY_MATCH_ZONE {
HEADERS=0,
URL,
ARGS,
BODY,
FILE_EXT,
UNKNOWN
};
/*
** struct used to store a specific match zone
** in conf : MATCH_ZONE:[GET_VAR|HEADER|POST_VAR]:VAR_NAME:
*/
typedef struct
{
/* match in [name] var of body */
ngx_flag_t body_var:1;
/* match in [name] var of headers */
ngx_flag_t headers_var:1;
/* match in [name] var of args */
ngx_flag_t args_var:1;
/* match on URL [name] */
ngx_flag_t specific_url:1;
ngx_str_t target;
ngx_uint_t hash;
} ngx_http_custom_rule_location_t;
/*
** WhiteList Rules Definition :
** A whitelist contains :
** - an URI
**
** - one or several sets containing :
** - an variable name ('foo') associated with a zone ($GET_VAR:foo)
** - one or several rules id to whitelist
*/
#define WEIRD_REQUEST_INTERNAL_RULE_ID 1
#define BIG_BODY_INTERNAL_RULE_ID 2
typedef struct
{
/* match in full body (POST DATA) */
ngx_flag_t body:1;
/* match in [name] var of body */
ngx_flag_t body_var:1;
/* match in all headers */
ngx_flag_t headers:1;
/* match in [name] var of headers */
ngx_flag_t headers_var:1;
/* match in URI */
ngx_flag_t url:1;
/* match in args (bla.php?<ARGS>) */
ngx_flag_t args:1;
/* match in [name] var of args */
ngx_flag_t args_var:1;
/* match on a global flag : weird_request, big_body etc. */
ngx_flag_t flags:1;
/* match on file upload extension */
ngx_flag_t file_ext:1;
/* set if defined "custom" match zone (GET_VAR/POST_VAR/...) */
ngx_array_t *ids;
ngx_str_t *name;
} ngx_http_whitelist_location_t;
/*
** this struct is used to aggregate all whitelist
** that point to the same URI or the same VARNAME
** all the "subrules" will then be stored in the "whitelist_locations"
*/
typedef struct
{
//ngx_http_whitelist_location_t
ngx_array_t *whitelist_locations;
// zone to wich the WL applies
enum DUMMY_MATCH_ZONE zone;
// if the "name" is only an url, specify it
int uri_only:1;
/* does the rule targets the name
instead of the content ?*/
int target_name;
ngx_str_t *name;
ngx_int_t hash;
ngx_array_t *ids;
} ngx_http_whitelist_rule_t;
/* basic rule */
typedef struct
{
ngx_str_t *str; // string
ngx_regex_compile_t *rx; // or regex
ngx_int_t transform; //transform rule to apply, as flags.
/* ~~~~~ match zones ~~~~~~ */
/* match in full body (POST DATA) */
ngx_flag_t body:1;
ngx_flag_t body_var:1;
/* match in all headers */
ngx_flag_t headers:1;
ngx_flag_t headers_var:1;
/* match in URI */
ngx_flag_t url:1;
/* match in args (bla.php?<ARGS>) */
ngx_flag_t args:1;
ngx_flag_t args_var:1;
/* match on flags (weird_uri, big_body etc. */
ngx_flag_t flags:1;
/* match on file upload extension */
ngx_flag_t file_ext:1;
/* set if defined "custom" match zone (GET_VAR/POST_VAR/...) */
ngx_flag_t custom_location:1;
ngx_int_t custom_location_only;
/* does the rule targets variable name instead ? */
ngx_int_t target_name;
/* custom location match zones list (GET_VAR/POST_VAR ...) */
ngx_array_t *custom_locations;
/* ~~~~~~~ specific flags ~~~~~~~~~ */
ngx_flag_t negative:1;
} ngx_http_basic_rule_t;
/* define for RULE TYPE in rule_t */
#define BR 1
//#define FR 2 UNUSED
//#define WR 3 UNUSED
/* flags used for 'custom match rules', like $XSS > 7 */
#define SUP 1
#define SUP_OR_EQUAL 2
#define INF 3
#define INF_OR_EQUAL 4
/*
** This struct is used to store custom scores at runtime.
** ie : $XSS = 7
** tag is the $XSS and sc_score is 7
*/
typedef struct
{
ngx_str_t *sc_tag;
ngx_int_t sc_score;
ngx_flag_t block:1;
ngx_flag_t allow:1;
ngx_flag_t log:1;
} ngx_http_special_score_t;
/*
** This one is very related to the previous one,
** it's used to store a score rule comparison.
** ie : $XSS > 7
*/
typedef struct
{
ngx_str_t sc_tag;
ngx_int_t sc_score;
ngx_int_t cmp;
ngx_flag_t block:1;
ngx_flag_t allow:1;
ngx_flag_t log:1;
} ngx_http_check_rule_t;
/* TOP level rule structure */
typedef struct
{
/* type of the rule */
ngx_int_t type;
// simply put a flag if it's a wlr, wl_id array will be used to store the whitelisted IDs
ngx_flag_t whitelist:1;
ngx_int_t *wl_id;
/* "common" data for all rules */
ngx_int_t rule_id;
ngx_str_t *log_msg; // a specific log message
ngx_int_t score; //also handles DENY and ALLOW
/* List of scores increased on rule match. */
ngx_array_t *sscores;
/*ngx_str_t *sc_tag; //specific score tag
ngx_int_t sc_score; //specific score value*/
ngx_flag_t sc_block:1; //
ngx_flag_t sc_allow:1; //
// end of specific score tag stuff
ngx_flag_t block:1;
ngx_flag_t allow:1;
ngx_flag_t log:1;
/* flag set if we're linked FROM or TO another rule */
ngx_flag_t lnk_to:1;
ngx_flag_t lnk_from:1;
/* pointers on specific rule stuff */
ngx_http_basic_rule_t *br;
} ngx_http_rule_t;
typedef struct
{
ngx_array_t *get_rules; /*ngx_http_rule_t*/
ngx_array_t *body_rules;
ngx_array_t *header_rules;
ngx_array_t *generic_rules;
ngx_array_t *locations; /*ngx_http_dummy_loc_conf_t*/
ngx_log_t *log;
} ngx_http_dummy_main_conf_t;
/* TOP level configuration structure */
typedef struct
{
ngx_array_t *get_rules;
ngx_array_t *body_rules;
ngx_array_t *header_rules;
ngx_array_t *generic_rules;
ngx_array_t *check_rules;
/* raw array of whitelisted rules */
ngx_array_t *whitelist_rules;
/* raw array of transformed whitelists */
ngx_array_t *tmp_wlr;
/* hash table of whitelisted URL rules */
ngx_hash_t *wlr_url_hash;
/* hash table of whitelisted ARGS rules */
ngx_hash_t *wlr_args_hash;
/* hash table of whitelisted BODY rules */
ngx_hash_t *wlr_body_hash;
/* hash table of whitelisted HEADERS rules */
ngx_hash_t *wlr_headers_hash;
/* rules that are globally disabled in one location */
ngx_array_t *disabled_rules;
/* counters for both processed requests and
blocked requests, used in naxsi_fmt */
size_t request_processed;
size_t request_blocked;
ngx_int_t error;
ngx_array_t *persistant_data;
ngx_flag_t extensive:1;
ngx_flag_t learning:1;
ngx_flag_t enabled:1;
ngx_flag_t force_disabled:1;
ngx_flag_t pushed:1;
ngx_str_t *denied_url;
/* precomputed hash for dynamic variable lookup,
variable themselves are boolean */
ngx_uint_t flag_enable_h;
ngx_uint_t flag_learning_h;
ngx_uint_t flag_post_action_h;
ngx_uint_t flag_extensive_log_h;
} ngx_http_dummy_loc_conf_t;
/*
** used to store sets of matched rules during runtime
*/
typedef struct
{
/* matched in [name] var of body */
ngx_flag_t body_var:1;
/* matched in [name] var of headers */
ngx_flag_t headers_var:1;
/* matched in [name] var of args */
ngx_flag_t args_var:1;
/* matched on URL */
ngx_flag_t url:1;
/* matched in filename [name] of args*/
ngx_flag_t file_ext:1;
/* matched within the 'NAME' */
ngx_flag_t target_name:1;
ngx_str_t *name;
ngx_http_rule_t *rule;
} ngx_http_matched_rule_t;
/*
** Context structure
*/
typedef struct
{
ngx_array_t *special_scores;
ngx_int_t score;
/* blocking flags */
ngx_flag_t log:1;
ngx_flag_t block:1;
ngx_flag_t allow:1;
/* state */
ngx_flag_t wait_for_body:1;
ngx_flag_t ready:1;
ngx_flag_t over:1;
/* flag request */
ngx_flag_t weird_request:1;
ngx_flag_t big_request:1;
/* matched rules */
ngx_array_t *matched;
/* runtime flags (modifiers) */
ngx_flag_t learning:1;
ngx_flag_t enabled:1;
ngx_flag_t post_action:1;
ngx_flag_t extensive_log:1;
} ngx_http_request_ctx_t;
#define TOP_DENIED_URL_T "DeniedUrl"
#define TOP_LEARNING_FLAG_T "LearningMode"
#define TOP_ENABLED_FLAG_T "SecRulesEnabled"
#define TOP_DISABLED_FLAG_T "SecRulesDisabled"
#define TOP_CHECK_RULE_T "CheckRule"
#define TOP_BASIC_RULE_T "BasicRule"
#define TOP_MAIN_BASIC_RULE_T "MainRule"
/* nginx-style names */
#define TOP_DENIED_URL_N "denied_url"
#define TOP_LEARNING_FLAG_N "learning_mode"
#define TOP_ENABLED_FLAG_N "rules_enabled"
#define TOP_DISABLED_FLAG_N "rules_disabled"
#define TOP_CHECK_RULE_N "check_rule"
#define TOP_BASIC_RULE_N "basic_rule"
#define TOP_MAIN_BASIC_RULE_N "main_rule"
/*possible 'tokens' in rule */
#define ID_T "id:"
#define TRANSFORM_T "t:"
#define SCORE_T "s:"
//#define PERSISTANT_SCORE_T "ps:"
#define MSG_T "msg:"
#define RX_T "rx:"
#define STR_T "str:"
#define MATCH_ZONE_T "mz:"
#define WHITELIST_T "wl:"
#define NEGATIVE_T "negative"
/* name of hardcoded variables to
change behavior of naxsi at runtime */
#define RT_EXTENSIVE_LOG "naxsi_extensive_log"
#define RT_ENABLE "naxsi_flag_enable"
#define RT_LEARNING "naxsi_flag_learning"
#define RT_POST_ACTION "naxsi_flag_post_action"
extern ngx_http_dummy_loc_conf_t *dummy_lc;
void *ngx_http_dummy_cfg_parse_one_rule(ngx_conf_t *cf,
ngx_str_t *value,
ngx_http_rule_t *rule,
ngx_int_t nb_elem);
char *strfaststr(unsigned char *haystack, unsigned int hl,
unsigned char *needle, unsigned int nl);
char *strnchr(const char *s, int c, int len);
char *strncasechr(const char *s, int c, int len);
ngx_int_t ngx_http_dummy_create_hashtables(ngx_http_dummy_loc_conf_t *dlc,
ngx_conf_t *cf);
ngx_int_t ngx_http_dummy_create_hashtables_n(ngx_http_dummy_loc_conf_t *dlc,
ngx_conf_t *cf);
void ngx_http_dummy_data_parse(ngx_http_request_ctx_t *ctx,
ngx_http_request_t *r);
ngx_int_t ngx_http_output_forbidden_page(ngx_http_request_ctx_t *ctx,
ngx_http_request_t *r);
void
naxsi_unescape_uri(u_char **dst, u_char **src, size_t size, ngx_uint_t type);
int naxsi_unescape(ngx_str_t *str);
/* static ngx_int_t ngx_http_dummy_subrequest(ngx_http_request_t *r, */
/* ngx_chain_t *in); */
//ngx_int_t ngx_http_dummy_subrequest(ngx_http_request_t *r);
#endif