?? snort_httpinspect.c
字號(hào):
/**************************************************************************** * * Copyright (C) 2003-2007 Sourcefire, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License Version 2 as * published by the Free Software Foundation. You may not use, modify or * distribute this program under any other version of the GNU General * Public License. * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ****************************************************************************/ /**** @file snort_httpinspect.c**** @author Daniel Roelker <droelker@sourcefire.com>**** @brief This file wraps the HttpInspect functionality for Snort** and starts the HttpInspect flow.****** The file takes a Packet structure from the Snort IDS to start the** HttpInspect flow. This also uses the Stream Interface Module which** is also Snort-centric. Mainly, just a wrapper to HttpInspect ** functionality, but a key part to starting the basic flow.**** The main bulk of this file is taken up with user configuration and** parsing. The reason this is so large is because HttpInspect takes** very detailed configuration parameters for each specified server.** Hopefully every web server that is out there can be emulated** with these configuration options.** ** The main functions of note are:** - HttpInspectSnortConf::this is the configuration portion** - SnortHttpInspect::this is the actual inspection flow** - LogEvents:this is where we log the HttpInspect events**** NOTES:**** - 2.11.03: Initial Development. DJR** - 2.4.05: Added tab_uri_delimiter config option. AJM.*/#include <stdlib.h>#include <string.h>#include <sys/types.h>#ifndef WIN32#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#endif#include "snort.h"#include "detect.h"#include "decode.h"#include "log.h"#include "event.h"#include "generators.h"#include "debug.h"#include "plugbase.h"#include "util.h"#include "event_queue.h"#include "stream_api.h"#include "sfsnprintfappend.h"#include "hi_return_codes.h"#include "hi_ui_config.h"#include "hi_ui_iis_unicode_map.h"#include "hi_si.h"#include "hi_mi.h"#include "hi_norm.h"#include "profiler.h"#ifdef PERF_PROFILINGextern PreprocStats hiDetectPerfStats;extern int hiDetectCalled;#endifextern PV pv;/* Stats tracking for HTTP Inspect */HIStats hi_stats;#define MAX_FILENAME 1000/**** The definition of the configuration separators in the snort.conf** configure line.*/#define CONF_SEPARATORS " \t\n\r"/*** These are the definitions of the parser section delimiting ** keywords to configure HttpInspect. When one of these keywords** are seen, we begin a new section.*/#define GLOBAL "global"#define GLOBAL_SERVER "global_server"#define SERVER "server"/*** GLOBAL subkeywords.*//**** Takes an integer arugment*/#define MAX_PIPELINE "max_pipeline"/**** Specifies whether to alert on anomalous** HTTP servers or not.*/#define ANOMALOUS_SERVERS "detect_anomalous_servers"/**** Alert on general proxy use*/#define PROXY_ALERT "proxy_alert"/**** Takes an inspection type argument** stateful or stateless*/#define INSPECT_TYPE "inspection_type"#define DEFAULT "default"/*** GLOBAL subkeyword values*/#define INSPECT_TYPE_STATELESS "stateless"#define INSPECT_TYPE_STATEFUL "stateful"/*** SERVER subkeywords.*/#define PORTS "ports"#define FLOW_DEPTH "flow_depth"#define POST_DEPTH "post_depth"#define IIS_UNICODE_MAP "iis_unicode_map"#define CHUNK_LENGTH "chunk_length"#define PIPELINE "no_pipeline_req"#define ASCII "ascii"#define DOUBLE_DECODE "double_decode"#define U_ENCODE "u_encode"#define BARE_BYTE "bare_byte"#define BASE36 "base36"#define UTF_8 "utf_8"#define IIS_UNICODE "iis_unicode"#define NON_RFC_CHAR "non_rfc_char"#define MULTI_SLASH "multi_slash"#define IIS_BACKSLASH "iis_backslash"#define DIRECTORY "directory"#define APACHE_WS "apache_whitespace"#define IIS_DELIMITER "iis_delimiter"#define PROFILE "profile"#define NON_STRICT "non_strict"#define ALLOW_PROXY "allow_proxy_use"#define OVERSIZE_DIR "oversize_dir_length"#define INSPECT_URI_ONLY "inspect_uri_only"#define GLOBAL_ALERT "no_alerts"#define WEBROOT "webroot"#define TAB_URI_DELIMITER "tab_uri_delimiter"#define WHITESPACE "whitespace_chars"/*** Alert subkeywords*/#define BOOL_YES "yes"#define BOOL_NO "no"/*** PROFILE subkeywords*/#define APACHE "apache"#define IIS "iis"#define IIS4_0 "iis4_0"#define IIS5_0 "iis5_0" /* 5.0 only. For 5.1 and beyond, use IIS */#define ALL "all"/*** Port list delimiters*/#define START_PORT_LIST "{"#define END_PORT_LIST "}"/*** Keyword for the default server configuration*/#define SERVER_DEFAULT "default"/*** NAME** ProcessGlobalAlert::*//**** Process the global alert keyword.**** There is no arguments to this keyword, because you can only turn** all the alerts off. As of now, we aren't going to support turning** all the alerts on.**** @param GlobalConf pointer to the global configuration** @param ErrorString error string buffer** @param ErrStrLen the lenght of the error string buffer**** @return an error code integer ** (0 = success, >0 = non-fatal error, <0 = fatal error)**** @retval 0 successs** @retval -1 generic fatal error** @retval 1 generic non-fatal error*//*static int ProcessGlobalAlert(HTTPINSPECT_GLOBAL_CONF *GlobalConf,{ GlobalConf->no_alerts = 1; return 0;}*//* ** NAME** ProcessMaxPipeline::*//**** Process the max pipeline configuration.**** This sets the maximum number of pipeline requests that we** will buffer while waiting for responses, before inspection.** There is a maximum limit on this, but we can track a user** defined amount.**** @param GlobalConf pointer to the global configuration** @param ErrorString error string buffer** @param ErrStrLen the lenght of the error string buffer**** @return an error code integer ** (0 = success, >0 = non-fatal error, <0 = fatal error)**** @retval 0 successs** @retval -1 generic fatal error** @retval 1 generic non-fatal error*/static int ProcessMaxPipeline(HTTPINSPECT_GLOBAL_CONF *GlobalConf, char *ErrorString, int ErrStrLen){ char *pcToken; char *pcEnd = NULL; pcToken = strtok(NULL, CONF_SEPARATORS); if(pcToken == NULL) { SnortSnprintf(ErrorString, ErrStrLen, "No argument to token '%s'.", MAX_PIPELINE); return -1; } GlobalConf->max_pipeline_requests = strtol(pcToken, &pcEnd, 10); /* ** Let's check to see if the entire string was valid. ** If there is an address here, then there was an ** invalid character in the string. */ if(*pcEnd) { SnortSnprintf(ErrorString, ErrStrLen, "Invalid argument to token '%s'. Must be a positive " "number between 0 and %d.", MAX_PIPELINE, HI_UI_CONFIG_MAX_PIPE); return -1; } if(GlobalConf->max_pipeline_requests < 0 || GlobalConf->max_pipeline_requests > HI_UI_CONFIG_MAX_PIPE) { SnortSnprintf(ErrorString, ErrStrLen, "Invalid argument to token '%s'. Must be a positive " "number between 0 and %d.", MAX_PIPELINE, HI_UI_CONFIG_MAX_PIPE); return -1; } return 0;}/* ** NAME** ProcessInspectType::*//**** Process the type of inspection.**** This sets the type of inspection for HttpInspect to do.**** @param GlobalConf pointer to the global configuration** @param ErrorString error string buffer**** @param ErrStrLen the lenght of the error string buffer**** @return an error code integer ** (0 = success, >0 = non-fatal error, <0 = fatal error)**** @retval 0 successs** @retval -1 generic fatal error** @retval 1 generic non-fatal error*/static int ProcessInspectType(HTTPINSPECT_GLOBAL_CONF *GlobalConf, char *ErrorString, int ErrStrLen){ char *pcToken; pcToken = strtok(NULL, CONF_SEPARATORS); if(pcToken == NULL) { SnortSnprintf(ErrorString, ErrStrLen, "No argument to token '%s'.", INSPECT_TYPE); return -1; } if(!strcmp(INSPECT_TYPE_STATEFUL, pcToken)) { GlobalConf->inspection_type = HI_UI_CONFIG_STATEFUL; /* ** We don't support this option yet, so we'll give an error and ** bail. */ SnortSnprintf(ErrorString, ErrStrLen, "Stateful HttpInspect processing is not yet available. " "Please use stateless processing for now."); return -1; } else if(!strcmp(INSPECT_TYPE_STATELESS, pcToken)) { GlobalConf->inspection_type = HI_UI_CONFIG_STATELESS; } else { SnortSnprintf(ErrorString, ErrStrLen, "Invalid argument to token '%s'. Must be either '%s' or '%s'.", INSPECT_TYPE, INSPECT_TYPE_STATEFUL, INSPECT_TYPE_STATELESS); return -1; } return 0;}static int ProcessIISUnicodeMap(int **iis_unicode_map, char **iis_unicode_map_filename, int *iis_unicode_map_codepage, char *ErrorString, int ErrStrLen){ char *pcToken; int iRet; char filename[MAX_FILENAME]; char *pcEnd; int iCodeMap; pcToken = strtok(NULL, CONF_SEPARATORS); if(pcToken == NULL) { SnortSnprintf(ErrorString, ErrStrLen, "No argument to token '%s'.", IIS_UNICODE_MAP); return -1; } /* ** If an absolute path is specified, then use that. */#ifndef WIN32 if(pcToken[0] == '/') { iRet = SnortSnprintf(filename, sizeof(filename), "%s", pcToken); } else { /* ** Set up the file name directory */ if(pv.config_dir[strlen(pv.config_dir)-1] == '/') { iRet = SnortSnprintf(filename, sizeof(filename), "%s%s", pv.config_dir, pcToken); } else { iRet = SnortSnprintf(filename, sizeof(filename), "%s/%s", pv.config_dir, pcToken); } }#else if(strlen(pcToken)>3 && pcToken[1]==':' && pcToken[2]=='\\') { iRet = SnortSnprintf(filename, sizeof(filename), "%s", pcToken); } else { /* ** Set up the file name directory */ if(pv.config_dir[strlen(pv.config_dir)-1] == '\\' || pv.config_dir[strlen(pv.config_dir)-1] == '/' ) { iRet = SnortSnprintf(filename, sizeof(filename), "%s%s", pv.config_dir, pcToken); } else { iRet = SnortSnprintf(filename, sizeof(filename), "%s\\%s", pv.config_dir, pcToken); } }#endif if(iRet != SNORT_SNPRINTF_SUCCESS) { SnortSnprintf(ErrorString, ErrStrLen, "Filename too long for token '%s'.", IIS_UNICODE_MAP); return -1; } /* ** Set the filename */ *iis_unicode_map_filename = strdup(filename); if(*iis_unicode_map_filename == NULL) { SnortSnprintf(ErrorString, ErrStrLen, "Could not strdup() '%s' filename.", IIS_UNICODE_MAP); return -1; } pcToken = strtok(NULL, CONF_SEPARATORS); if(pcToken == NULL) { SnortSnprintf(ErrorString, ErrStrLen, "No codemap to select from IIS Unicode Map file."); return -1; } /* ** Grab the unicode codemap to use */ iCodeMap = strtol(pcToken, &pcEnd, 10); if(*pcEnd || iCodeMap < 0) { SnortSnprintf(ErrorString, ErrStrLen, "Invalid IIS codemap argument."); return -1; } /* ** Set the codepage */ *iis_unicode_map_codepage = iCodeMap; /* ** Assume that the pcToken we now have is the filename of the map ** table. */ iRet = hi_ui_parse_iis_unicode_map(iis_unicode_map, filename, iCodeMap); if (iRet) { if(iRet == HI_INVALID_FILE) {
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -