From: Victor Julien Date: Fri, 11 Mar 2016 11:00:22 +0000 (+0100) Subject: QA: direct access from commandline to AppLayer API X-Git-Tag: suricata-3.1RC1~262 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=077ac81688c335724532ed97796cce0322f31253;p=thirdparty%2Fsuricata.git QA: direct access from commandline to AppLayer API This patch introduces a new set of commandline options meant for assisting in fuzz testing the app layer implementations. Per protocol, 2 commandline options are added: --afl-http-request= --afl-http= In the former case, the contents of the file are passed directly to the HTTP parser as request data. In the latter case, the data is devided between request and responses. First 64 bytes are request, then next 64 are response, next 64 are request, etc, etc. --- diff --git a/configure.ac b/configure.ac index 21e07fc40b..47fe5e942d 100644 --- a/configure.ac +++ b/configure.ac @@ -267,6 +267,7 @@ AC_DEFINE([AFLFUZZ_DISABLE_MGTTHREADS], [1], [Disable all management threads]) AC_DEFINE([AFLFUZZ_PCAP_RUNMODE], [1], [Enable special AFL 'single' runmode]) AC_DEFINE([AFLFUZZ_CONF_TEST], [1], [Enable special --afl-parse-rules commandline option]) + AC_DEFINE([AFLFUZZ_APPLAYER], [1], [Enable --afl-$proto-request commandline option]) ]) # disable TLS on user request diff --git a/src/app-layer-htp.c b/src/app-layer-htp.c index 50ff3e7314..a3db82b189 100644 --- a/src/app-layer-htp.c +++ b/src/app-layer-htp.c @@ -2162,7 +2162,11 @@ static void HTPConfigSetDefaultsPhase1(HTPCfgRec *cfg_prec) cfg_prec->request_inspect_window = HTP_CONFIG_DEFAULT_REQUEST_INSPECT_WINDOW; cfg_prec->response_inspect_min_size = HTP_CONFIG_DEFAULT_RESPONSE_INSPECT_MIN_SIZE; cfg_prec->response_inspect_window = HTP_CONFIG_DEFAULT_RESPONSE_INSPECT_WINDOW; +#ifndef AFLFUZZ_NO_RANDOM cfg_prec->randomize = HTP_CONFIG_DEFAULT_RANDOMIZE; +#else + cfg_prec->randomize = 0; +#endif cfg_prec->randomize_range = HTP_CONFIG_DEFAULT_RANDOMIZE_RANGE; htp_config_register_request_header_data(cfg_prec->cfg, HTPCallbackRequestHeaderData); @@ -2441,7 +2445,9 @@ static void HTPConfigParseParameters(HTPCfgRec *cfg_prec, ConfNode *s, (size_t)HTP_CONFIG_DEFAULT_FIELD_LIMIT_SOFT, (size_t)limit); } else if (strcasecmp("randomize-inspection-sizes", p->name) == 0) { +#ifndef AFLFUZZ_NO_RANDOM cfg_prec->randomize = ConfValIsTrue(p->val); +#endif } else if (strcasecmp("randomize-inspection-range", p->name) == 0) { uint32_t range = atoi(p->val); if (range > 100) { diff --git a/src/app-layer-modbus.c b/src/app-layer-modbus.c index 827f4042e3..e55c431bf1 100644 --- a/src/app-layer-modbus.c +++ b/src/app-layer-modbus.c @@ -1433,7 +1433,9 @@ void RegisterModbusParsers(void) proto_name, ALPROTO_MODBUS, 0, sizeof(ModbusHeader), ModbusProbingParser)) { +#ifndef AFLFUZZ_APPLAYER return; +#endif } } @@ -1448,11 +1450,16 @@ void RegisterModbusParsers(void) } SCLogInfo("Modbus request flood protection level: %u", request_flood); } else { +#ifndef AFLFUZZ_APPLAYER SCLogInfo("Protocol detection and parser disabled for %s protocol.", proto_name); return; +#endif } - +#ifndef AFLFUZZ_APPLAYER if (AppLayerParserConfParserEnabled("tcp", proto_name)) { +#else + if (1) { +#endif AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_MODBUS, STREAM_TOSERVER, ModbusParseRequest); AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_MODBUS, STREAM_TOCLIENT, ModbusParseResponse); AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_MODBUS, ModbusStateAlloc, ModbusStateFree); diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index ffbc0978af..51efa30d40 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -1189,6 +1189,141 @@ void AppLayerParserStatePrintDetails(AppLayerParserState *pstate) } #endif +#ifdef AFLFUZZ_APPLAYER +int AppLayerParserRequestFromFile(AppProto alproto, char *filename) +{ + int result = 1; + Flow *f = NULL; + TcpSession ssn; + AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); + + memset(&ssn, 0, sizeof(ssn)); + + f = SCCalloc(1, sizeof(Flow)); + if (f == NULL) + goto end; + FLOW_INITIALIZE(f); + + f->flags |= FLOW_IPV4; + f->src.addr_data32[0] = 0x01020304; + f->dst.addr_data32[0] = 0x05060708; + f->sp = 10000; + f->dp = 80; + f->protoctx = &ssn; + f->proto = IPPROTO_TCP; + f->alproto = alproto; + + FILE *fp = fopen(filename, "r"); + BUG_ON(fp == NULL); + + uint8_t buffer[256]; + + int start = 1; + while (1) { + int done = 0; + size_t result = fread(&buffer, 1, sizeof(buffer), fp); + if (result < sizeof(buffer)) + done = 1; + + //SCLogInfo("result %u done %d start %d", (uint)result, done, start); + + uint8_t flags = STREAM_TOSERVER; + + if (start--) { + flags |= STREAM_START; + } + if (done) { + flags |= STREAM_EOF; + } + //PrintRawDataFp(stdout, buffer, result); + + (void)AppLayerParserParse(alp_tctx, f, alproto, flags, buffer, result); + if (done) + break; + } + + result = 0; + fclose(fp); +end: + if (alp_tctx != NULL) + AppLayerParserThreadCtxFree(alp_tctx); + if (f != NULL) { + FlowFree(f); + } + return result; +} + +int AppLayerParserFromFile(AppProto alproto, char *filename) +{ + int result = 1; + Flow *f = NULL; + TcpSession ssn; + AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); + + memset(&ssn, 0, sizeof(ssn)); + + f = SCCalloc(1, sizeof(Flow)); + if (f == NULL) + goto end; + FLOW_INITIALIZE(f); + + f->flags |= FLOW_IPV4; + f->src.addr_data32[0] = 0x01020304; + f->dst.addr_data32[0] = 0x05060708; + f->sp = 10000; + f->dp = 80; + f->protoctx = &ssn; + f->proto = IPPROTO_TCP; + f->alproto = alproto; + + FILE *fp = fopen(filename, "r"); + BUG_ON(fp == NULL); + + uint8_t buffer[64]; + + int start = 1; + int flip = 0; + while (1) { + int done = 0; + size_t result = fread(&buffer, 1, sizeof(buffer), fp); + if (result < sizeof(buffer)) + done = 1; + + //SCLogInfo("result %u done %d start %d", (uint)result, done, start); + + uint8_t flags = 0; + if (flip) { + flags = STREAM_TOCLIENT; + flip = 0; + } else { + flags = STREAM_TOSERVER; + flip = 1; + } + + if (start--) { + flags |= STREAM_START; + } + if (done) { + flags |= STREAM_EOF; + } + //PrintRawDataFp(stdout, buffer, result); + + (void)AppLayerParserParse(alp_tctx, f, alproto, flags, buffer, result); + if (done) + break; + } + + result = 0; + fclose(fp); +end: + if (alp_tctx != NULL) + AppLayerParserThreadCtxFree(alp_tctx); + if (f != NULL) { + FlowFree(f); + } + return result; +} +#endif /***** Unittests *****/ diff --git a/src/app-layer-parser.h b/src/app-layer-parser.h index 62cb8f6869..2dee75e7c7 100644 --- a/src/app-layer-parser.h +++ b/src/app-layer-parser.h @@ -222,6 +222,11 @@ void AppLayerParserStateFree(AppLayerParserState *pstate); void AppLayerParserStatePrintDetails(AppLayerParserState *pstate); #endif +#ifdef AFLFUZZ_APPLAYER +int AppLayerParserRequestFromFile(AppProto alproto, char *filename); +int AppLayerParserFromFile(AppProto alproto, char *filename); +#endif + /***** Unittests *****/ #ifdef UNITTESTS diff --git a/src/suricata.c b/src/suricata.c index 543f662fc2..d3b069ef6a 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -145,6 +145,13 @@ #include "app-layer.h" #include "app-layer-parser.h" #include "app-layer-htp.h" +#include "app-layer-ssl.h" +#include "app-layer-dns-tcp.h" +#include "app-layer-ssh.h" +#include "app-layer-ftp.h" +#include "app-layer-smtp.h" +#include "app-layer-smb.h" +#include "app-layer-modbus.h" #include "util-radix-tree.h" #include "util-host-os-info.h" @@ -1136,6 +1143,22 @@ static TmEcode ParseCommandLine(int argc, char** argv, SCInstance *suri) {"netmap", optional_argument, 0, 0}, {"pcap", optional_argument, 0, 0}, {"simulate-ips", 0, 0 , 0}, + {"afl-http-request", required_argument, 0 , 0}, + {"afl-http", required_argument, 0 , 0}, + {"afl-tls-request", required_argument, 0 , 0}, + {"afl-tls", required_argument, 0 , 0}, + {"afl-dns-request", required_argument, 0 , 0}, + {"afl-dns", required_argument, 0 , 0}, + {"afl-ssh-request", required_argument, 0 , 0}, + {"afl-ssh", required_argument, 0 , 0}, + {"afl-ftp-request", required_argument, 0 , 0}, + {"afl-ftp", required_argument, 0 , 0}, + {"afl-smtp-request", required_argument, 0 , 0}, + {"afl-smtp", required_argument, 0 , 0}, + {"afl-smb-request", required_argument, 0 , 0}, + {"afl-smb", required_argument, 0 , 0}, + {"afl-modbus-request", required_argument, 0 , 0}, + {"afl-modbus", required_argument, 0 , 0}, #ifdef BUILD_UNIX_SOCKET {"unix-socket", optional_argument, 0, 0}, #endif @@ -1324,6 +1347,92 @@ static TmEcode ParseCommandLine(int argc, char** argv, SCInstance *suri) usage(argv[0]); return TM_ECODE_FAILED; } +#ifdef AFLFUZZ_APPLAYER + } else if(strcmp((long_opts[option_index]).name, "afl-http-request") == 0) { + //printf("arg: //%s\n", optarg); + AppLayerParserSetup(); + RegisterHTPParsers(); + exit(AppLayerParserRequestFromFile(ALPROTO_HTTP, optarg)); + } else if(strcmp((long_opts[option_index]).name, "afl-http") == 0) { + //printf("arg: //%s\n", optarg); + AppLayerParserSetup(); + RegisterHTPParsers(); + exit(AppLayerParserFromFile(ALPROTO_HTTP, optarg)); + + } else if(strcmp((long_opts[option_index]).name, "afl-tls-request") == 0) { + //printf("arg: //%s\n", optarg); + RegisterSSLParsers(); + exit(AppLayerParserRequestFromFile(ALPROTO_TLS, optarg)); + } else if(strcmp((long_opts[option_index]).name, "afl-tls") == 0) { + //printf("arg: //%s\n", optarg); + AppLayerParserSetup(); + RegisterSSLParsers(); + exit(AppLayerParserFromFile(ALPROTO_TLS, optarg)); + + } else if(strcmp((long_opts[option_index]).name, "afl-dns-request") == 0) { + //printf("arg: //%s\n", optarg); + RegisterDNSTCPParsers(); + exit(AppLayerParserRequestFromFile(ALPROTO_DNS, optarg)); + } else if(strcmp((long_opts[option_index]).name, "afl-dns") == 0) { + //printf("arg: //%s\n", optarg); + AppLayerParserSetup(); + RegisterDNSTCPParsers(); + exit(AppLayerParserFromFile(ALPROTO_DNS, optarg)); + + } else if(strcmp((long_opts[option_index]).name, "afl-ssh-request") == 0) { + //printf("arg: //%s\n", optarg); + RegisterSSHParsers(); + exit(AppLayerParserRequestFromFile(ALPROTO_SSH, optarg)); + } else if(strcmp((long_opts[option_index]).name, "afl-ssh") == 0) { + //printf("arg: //%s\n", optarg); + AppLayerParserSetup(); + RegisterSSHParsers(); + exit(AppLayerParserFromFile(ALPROTO_SSH, optarg)); + + } else if(strcmp((long_opts[option_index]).name, "afl-ftp-request") == 0) { + //printf("arg: //%s\n", optarg); + RegisterFTPParsers(); + exit(AppLayerParserRequestFromFile(ALPROTO_FTP, optarg)); + } else if(strcmp((long_opts[option_index]).name, "afl-ftp") == 0) { + //printf("arg: //%s\n", optarg); + AppLayerParserSetup(); + RegisterFTPParsers(); + exit(AppLayerParserFromFile(ALPROTO_FTP, optarg)); + + } else if(strcmp((long_opts[option_index]).name, "afl-smtp-request") == 0) { + //printf("arg: //%s\n", optarg); + MpmTableSetup(); + AppLayerParserSetup(); + RegisterSMTPParsers(); + exit(AppLayerParserRequestFromFile(ALPROTO_SMTP, optarg)); + } else if(strcmp((long_opts[option_index]).name, "afl-smtp") == 0) { + //printf("arg: //%s\n", optarg); + MpmTableSetup(); + AppLayerParserSetup(); + RegisterSMTPParsers(); + exit(AppLayerParserFromFile(ALPROTO_SMTP, optarg)); + + } else if(strcmp((long_opts[option_index]).name, "afl-smb-request") == 0) { + //printf("arg: //%s\n", optarg); + RegisterSMBParsers(); + exit(AppLayerParserRequestFromFile(ALPROTO_SMB, optarg)); + } else if(strcmp((long_opts[option_index]).name, "afl-smb") == 0) { + //printf("arg: //%s\n", optarg); + AppLayerParserSetup(); + RegisterSMBParsers(); + exit(AppLayerParserFromFile(ALPROTO_SMB, optarg)); + + } else if(strcmp((long_opts[option_index]).name, "afl-modbus-request") == 0) { + //printf("arg: //%s\n", optarg); + AppLayerParserSetup(); + RegisterModbusParsers(); + exit(AppLayerParserRequestFromFile(ALPROTO_MODBUS, optarg)); + } else if(strcmp((long_opts[option_index]).name, "afl-modbus") == 0) { + //printf("arg: //%s\n", optarg); + AppLayerParserSetup(); + RegisterModbusParsers(); + exit(AppLayerParserFromFile(ALPROTO_MODBUS, optarg)); +#endif } else if(strcmp((long_opts[option_index]).name, "simulate-ips") == 0) { SCLogInfo("Setting IPS mode"); EngineModeSetIPS();