From 6f8cfd999f868cde0f52a80c571bdbddb41efa17 Mon Sep 17 00:00:00 2001 From: Anoop Saldanha Date: Sat, 3 Aug 2013 14:53:13 +0530 Subject: [PATCH] Allow detection ports for alproto to be specified via the conf file. To understand the option have a look at the option app-layer.protocols.tls.detection-ports --- src/app-layer-dns-tcp.c | 22 ++++++---- src/app-layer-dns-udp.c | 22 ++++++---- src/app-layer-parser.c | 86 +++++++++++++++++++++++++++++++++++++++ src/app-layer-parser.h | 3 ++ src/app-layer-protos.c | 77 +++++++++++++++++++++++++---------- src/app-layer-protos.h | 4 +- src/app-layer-smb.c | 22 ++++++---- src/app-layer-ssl.c | 22 ++++++---- src/detect-dns-query.c | 60 ++++++++++++++++++++------- src/detect-engine-proto.c | 18 ++++---- suricata.yaml.in | 16 ++++++++ 11 files changed, 273 insertions(+), 79 deletions(-) diff --git a/src/app-layer-dns-tcp.c b/src/app-layer-dns-tcp.c index a098f75f14..b8f6072635 100644 --- a/src/app-layer-dns-tcp.c +++ b/src/app-layer-dns-tcp.c @@ -579,14 +579,20 @@ void RegisterDNSTCPParsers(void) { /** DNS */ if (AppLayerProtoDetectionEnabled(proto_name)) { - AppLayerRegisterProbingParser(&alp_proto_ctx, - IPPROTO_TCP, - "53", - proto_name, - ALPROTO_DNS_TCP, - 0, sizeof(DNSTcpHeader), - STREAM_TOSERVER, - DNSTcpProbingParser); + if (RunmodeIsUnittests()) { + AppLayerRegisterProbingParser(&alp_proto_ctx, + IPPROTO_TCP, + "53", + proto_name, + ALPROTO_DNS_TCP, + 0, sizeof(DNSTcpHeader), + STREAM_TOSERVER, + DNSTcpProbingParser); + } else { + AppLayerParseProbingParserPorts(proto_name, ALPROTO_DNS_TCP, + 0, sizeof(DNSTcpHeader), + DNSTcpProbingParser); + } } else { SCLogInfo("Protocol detection and parser disabled for %s protocol.", proto_name); diff --git a/src/app-layer-dns-udp.c b/src/app-layer-dns-udp.c index 9857b26f1d..91354c10ab 100644 --- a/src/app-layer-dns-udp.c +++ b/src/app-layer-dns-udp.c @@ -299,14 +299,20 @@ void RegisterDNSUDPParsers(void) { /** DNS */ if (AppLayerProtoDetectionEnabled(proto_name)) { - AppLayerRegisterProbingParser(&alp_proto_ctx, - IPPROTO_UDP, - "53", - proto_name, - ALPROTO_DNS_UDP, - 0, sizeof(DNSHeader), - STREAM_TOSERVER, - DNSUdpProbingParser); + if (RunmodeIsUnittests()) { + AppLayerRegisterProbingParser(&alp_proto_ctx, + IPPROTO_UDP, + "53", + proto_name, + ALPROTO_DNS_UDP, + 0, sizeof(DNSHeader), + STREAM_TOSERVER, + DNSUdpProbingParser); + } else { + AppLayerParseProbingParserPorts(proto_name, ALPROTO_DNS_UDP, + 0, sizeof(DNSHeader), + DNSUdpProbingParser); + } } else { SCLogInfo("Protocol detection and parser disabled for %s protocol.", proto_name); diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index f2a9710d51..2360e59ea6 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -1630,6 +1630,92 @@ int AppLayerProtoDetectionEnabled(const char *al_proto) return enabled; } +void AppLayerParseProbingParserPorts(const char *al_proto_name, uint16_t al_proto, + uint16_t min_depth, uint16_t max_depth, + uint16_t (*ProbingParser)(uint8_t *input, + uint32_t input_len, + uint32_t *offset)) +{ + char param[100]; + int r; + ConfNode *node; + ConfNode *proto_node = NULL; + ConfNode *port_node = NULL; + + r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.", + al_proto_name, ".detection-ports"); + if (r < 0) { + SCLogError(SC_ERR_FATAL, "snprintf failure."); + exit(EXIT_FAILURE); + } else if (r > (int)sizeof(param)) { + SCLogError(SC_ERR_FATAL, "buffer not big enough to write param."); + exit(EXIT_FAILURE); + } + node = ConfGetNode(param); + if (node == NULL) { + SCLogDebug("Entry for %s not found.", param); + return; + } + + /* for each proto */ + TAILQ_FOREACH(proto_node, &node->head, next) { + DetectProto dp; + int ip_proto = DetectProtoParse(&dp, proto_node->name); + if (ip_proto <= 0) { + SCLogError(SC_ERR_INVALID_YAML_CONF_ENTRY, "Invalid entry for " + "%s.%s", param, proto_node->name); + exit(EXIT_FAILURE); + } + + /* toserver */ + r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.", + al_proto_name, ".detection-ports.", proto_node->name, ".toserver"); + if (r < 0) { + SCLogError(SC_ERR_FATAL, "snprintf failure."); + exit(EXIT_FAILURE); + } else if (r > (int)sizeof(param)) { + SCLogError(SC_ERR_FATAL, "buffer not big enough to write param."); + exit(EXIT_FAILURE); + } + port_node = ConfGetNode(param); + if (port_node != NULL && port_node->val != NULL) { + AppLayerRegisterProbingParser(&alp_proto_ctx, + ip_proto, + port_node->val, + (char *)al_proto_name, + al_proto, + min_depth, max_depth, + STREAM_TOSERVER, + ProbingParser); + } + + /* toclient */ + r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.", + al_proto_name, ".detection-ports.", proto_node->name, ".toclient"); + if (r < 0) { + SCLogError(SC_ERR_FATAL, "snprintf failure."); + exit(EXIT_FAILURE); + } else if (r > (int)sizeof(param)) { + SCLogError(SC_ERR_FATAL, "buffer not big enough to write param."); + exit(EXIT_FAILURE); + } + port_node = ConfGetNode(param); + if (port_node != NULL && port_node->val != NULL) { + AppLayerRegisterProbingParser(&alp_proto_ctx, + ip_proto, + port_node->val, + (char *)al_proto_name, + al_proto, + min_depth, max_depth, + STREAM_TOCLIENT, + ProbingParser); + + } + } + + return; +} + /********************************Probing Parsers*******************************/ diff --git a/src/app-layer-parser.h b/src/app-layer-parser.h index 814746d02c..6b16e67c2b 100644 --- a/src/app-layer-parser.h +++ b/src/app-layer-parser.h @@ -418,5 +418,8 @@ void AppLayerTriggerRawStreamReassembly(Flow *); int AppLayerParserEnabled(const char *alproto); int AppLayerProtoDetectionEnabled(const char *alproto); +void AppLayerParseProbingParserPorts(const char *al_proto_name, uint16_t al_proto, + uint16_t min_depth, uint16_t max_depth, + uint16_t (*ProbingParser)(uint8_t *input, uint32_t input_len, uint32_t *offset)); #endif /* __APP_LAYER_PARSER_H__ */ diff --git a/src/app-layer-protos.c b/src/app-layer-protos.c index bbeb103a86..37e3b34999 100644 --- a/src/app-layer-protos.c +++ b/src/app-layer-protos.c @@ -32,29 +32,64 @@ * * \retval string equivalent for the alproto */ -const char *TmModuleAlprotoToString(int proto) +const char *TmModuleAlprotoToString(enum AppProto proto) { - switch (proto) { - CASE_CODE (ALPROTO_UNKNOWN); - CASE_CODE (ALPROTO_HTTP); - CASE_CODE (ALPROTO_FTP); - CASE_CODE (ALPROTO_SMTP); - CASE_CODE (ALPROTO_TLS); - CASE_CODE (ALPROTO_SSH); - CASE_CODE (ALPROTO_IMAP); - CASE_CODE (ALPROTO_MSN); - CASE_CODE (ALPROTO_JABBER); - CASE_CODE (ALPROTO_SMB); - CASE_CODE (ALPROTO_SMB2); - CASE_CODE (ALPROTO_DCERPC); - CASE_CODE (ALPROTO_DCERPC_UDP); - - CASE_CODE (ALPROTO_DNS); - CASE_CODE (ALPROTO_DNS_UDP); - CASE_CODE (ALPROTO_DNS_TCP); + const char *proto_name = NULL; - default: - return "ALPROTO_UNDEFINED"; + switch (proto) { + case ALPROTO_HTTP: + proto_name = "http"; + break; + case ALPROTO_FTP: + proto_name = "ftp"; + break; + case ALPROTO_SMTP: + proto_name = "smtp"; + break; + case ALPROTO_TLS: + proto_name = "tls"; + break; + case ALPROTO_SSH: + proto_name = "ssh"; + break; + case ALPROTO_IMAP: + proto_name = "imap"; + break; + case ALPROTO_MSN: + proto_name = "msn"; + break; + case ALPROTO_JABBER: + proto_name = "jabber"; + break; + case ALPROTO_SMB: + proto_name = "smb"; + break; + case ALPROTO_SMB2: + proto_name = "smb2"; + break; + case ALPROTO_DCERPC: + proto_name = "dcerpc"; + break; + case ALPROTO_DCERPC_UDP: + proto_name = "dcerpcudp"; + break; + case ALPROTO_IRC: + proto_name = "irc"; + break; + case ALPROTO_DNS_TCP: + proto_name = "dnstcp"; + break; + case ALPROTO_DNS_UDP: + proto_name = "dnsudp"; + break; + case ALPROTO_DNS: + case ALPROTO_FAILED: + case ALPROTO_TEST: + case ALPROTO_MAX: + case ALPROTO_UNKNOWN: + break; } + + return proto_name; } diff --git a/src/app-layer-protos.h b/src/app-layer-protos.h index 8c1c93154f..409d8814e5 100644 --- a/src/app-layer-protos.h +++ b/src/app-layer-protos.h @@ -24,7 +24,7 @@ #ifndef __APP_LAYER_PROTOS_H__ #define __APP_LAYER_PROTOS_H__ -enum { +enum AppProto { ALPROTO_UNKNOWN = 0, ALPROTO_HTTP, ALPROTO_FTP, @@ -54,7 +54,7 @@ enum { ALPROTO_MAX, }; -const char *TmModuleAlprotoToString(int proto); +const char *TmModuleAlprotoToString(enum AppProto proto); #endif /* __APP_LAYER_PROTOS_H__ */ diff --git a/src/app-layer-smb.c b/src/app-layer-smb.c index 8bcf12a155..7b9989ab7c 100644 --- a/src/app-layer-smb.c +++ b/src/app-layer-smb.c @@ -1406,14 +1406,20 @@ void RegisterSMBParsers(void) { /** SMB2 */ AlpProtoAdd(&alp_proto_ctx, "smb2", IPPROTO_TCP, ALPROTO_SMB2, "|fe|SMB", 8, 4, STREAM_TOSERVER); - AppLayerRegisterProbingParser(&alp_proto_ctx, - IPPROTO_TCP, - "139", - "smb", - ALPROTO_SMB, - SMB_PROBING_PARSER_MIN_DEPTH, 0, - STREAM_TOSERVER, - SMBProbingParser); + if (RunmodeIsUnittests()) { + AppLayerRegisterProbingParser(&alp_proto_ctx, + IPPROTO_TCP, + "139", + "smb", + ALPROTO_SMB, + SMB_PROBING_PARSER_MIN_DEPTH, 0, + STREAM_TOSERVER, + SMBProbingParser); + } else { + AppLayerParseProbingParserPorts(proto_name, ALPROTO_SMB, + SMB_PROBING_PARSER_MIN_DEPTH, 0, + SMBProbingParser); + } } else { SCLogInfo("Protocol detection and parser disabled for %s protocol.", proto_name); diff --git a/src/app-layer-ssl.c b/src/app-layer-ssl.c index 8771bab46d..0a782611f2 100644 --- a/src/app-layer-ssl.c +++ b/src/app-layer-ssl.c @@ -1016,14 +1016,20 @@ void RegisterSSLParsers(void) AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_TLS, "|01 03 03|", 3, 0, STREAM_TOSERVER); AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_TLS, "|16 03 03|", 3, 0, STREAM_TOSERVER); /* client hello */ - AppLayerRegisterProbingParser(&alp_proto_ctx, - IPPROTO_TCP, - "443", - proto_name, - ALPROTO_TLS, - 0, 3, - STREAM_TOSERVER, - SSLProbingParser); + if (RunmodeIsUnittests()) { + AppLayerRegisterProbingParser(&alp_proto_ctx, + IPPROTO_TCP, + "443", + proto_name, + ALPROTO_TLS, + 0, 3, + STREAM_TOSERVER, + SSLProbingParser); + } else { + AppLayerParseProbingParserPorts(proto_name, ALPROTO_TLS, + 0, 3, + SSLProbingParser); + } } else { SCLogInfo("Protocol detection and parser disabled for %s protocol", proto_name); diff --git a/src/detect-dns-query.c b/src/detect-dns-query.c index 69d9237b67..398fa159e3 100644 --- a/src/detect-dns-query.c +++ b/src/detect-dns-query.c @@ -148,7 +148,9 @@ static int DetectDnsQueryTest01(void) { memset(&tv, 0, sizeof(ThreadVars)); memset(&f, 0, sizeof(Flow)); - p = UTHBuildPacket(buf, sizeof(buf), IPPROTO_UDP); + p = UTHBuildPacketReal(buf, sizeof(buf), IPPROTO_UDP, + "192.168.1.5", "192.168.1.1", + 41424, 53); FLOW_INITIALIZE(&f); f.flags |= FLOW_IPV4; @@ -256,9 +258,15 @@ static int DetectDnsQueryTest02(void) { memset(&tv, 0, sizeof(ThreadVars)); memset(&f, 0, sizeof(Flow)); - p1 = UTHBuildPacket(buf1, sizeof(buf1), IPPROTO_UDP); - p2 = UTHBuildPacket(buf2, sizeof(buf2), IPPROTO_UDP); - p3 = UTHBuildPacket(buf3, sizeof(buf3), IPPROTO_UDP); + p1 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_UDP, + "192.168.1.5", "192.168.1.1", + 41424, 53); + p2 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_UDP, + "192.168.1.5", "192.168.1.1", + 41424, 53); + p3 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_UDP, + "192.168.1.5", "192.168.1.1", + 41424, 53); FLOW_INITIALIZE(&f); f.flags |= FLOW_IPV4; @@ -411,7 +419,9 @@ static int DetectDnsQueryTest03(void) { memset(&f, 0, sizeof(Flow)); memset(&ssn, 0, sizeof(TcpSession)); - p = UTHBuildPacket(buf, sizeof(buf), IPPROTO_TCP); + p = UTHBuildPacketReal(buf, sizeof(buf), IPPROTO_TCP, + "192.168.1.5", "192.168.1.1", + 41424, 53); FLOW_INITIALIZE(&f); f.protoctx = (void *)&ssn; @@ -503,8 +513,12 @@ static int DetectDnsQueryTest04(void) { memset(&f, 0, sizeof(Flow)); memset(&ssn, 0, sizeof(TcpSession)); - p1 = UTHBuildPacket(buf1, sizeof(buf1), IPPROTO_TCP); - p2 = UTHBuildPacket(buf2, sizeof(buf2), IPPROTO_TCP); + p1 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_TCP, + "192.168.1.5", "192.168.1.1", + 41424, 53); + p2 = UTHBuildPacketReal(buf2, sizeof(buf2), IPPROTO_TCP, + "192.168.1.5", "192.168.1.1", + 41424, 53); FLOW_INITIALIZE(&f); f.protoctx = (void *)&ssn; @@ -644,10 +658,18 @@ static int DetectDnsQueryTest05(void) { memset(&f, 0, sizeof(Flow)); memset(&ssn, 0, sizeof(TcpSession)); - p1 = UTHBuildPacket(buf1, sizeof(buf1), IPPROTO_TCP); - p2 = UTHBuildPacket(buf2, sizeof(buf2), IPPROTO_TCP); - p3 = UTHBuildPacket(buf3, sizeof(buf3), IPPROTO_TCP); - p4 = UTHBuildPacket(buf4, sizeof(buf4), IPPROTO_TCP); + p1 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_TCP, + "192.168.1.5", "192.168.1.1", + 41424, 53); + p2 = UTHBuildPacketReal(buf2, sizeof(buf2), IPPROTO_TCP, + "192.168.1.5", "192.168.1.1", + 41424, 53); + p3 = UTHBuildPacketReal(buf3, sizeof(buf3), IPPROTO_TCP, + "192.168.1.5", "192.168.1.1", + 41424, 53); + p4 = UTHBuildPacketReal(buf4, sizeof(buf4), IPPROTO_TCP, + "192.168.1.5", "192.168.1.1", + 41424, 53); FLOW_INITIALIZE(&f); f.protoctx = (void *)&ssn; @@ -824,7 +846,9 @@ static int DetectDnsQueryTest06(void) { memset(&tv, 0, sizeof(ThreadVars)); memset(&f, 0, sizeof(Flow)); - p = UTHBuildPacket(buf, sizeof(buf), IPPROTO_UDP); + p = UTHBuildPacketReal(buf, sizeof(buf), IPPROTO_UDP, + "192.168.1.5", "192.168.1.1", + 41424, 53); FLOW_INITIALIZE(&f); f.flags |= FLOW_IPV4; @@ -946,9 +970,15 @@ static int DetectDnsQueryTest07(void) { memset(&tv, 0, sizeof(ThreadVars)); memset(&f, 0, sizeof(Flow)); - p1 = UTHBuildPacket(buf1, sizeof(buf1), IPPROTO_UDP); - p2 = UTHBuildPacket(buf2, sizeof(buf2), IPPROTO_UDP); - p3 = UTHBuildPacket(buf3, sizeof(buf3), IPPROTO_UDP); + p1 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_UDP, + "192.168.1.5", "192.168.1.1", + 41424, 53); + p2 = UTHBuildPacketReal(buf2, sizeof(buf2), IPPROTO_UDP, + "192.168.1.5", "192.168.1.1", + 41424, 53); + p3 = UTHBuildPacketReal(buf3, sizeof(buf3), IPPROTO_UDP, + "192.168.1.5", "192.168.1.1", + 41424, 53); FLOW_INITIALIZE(&f); f.flags |= FLOW_IPV4; diff --git a/src/detect-engine-proto.c b/src/detect-engine-proto.c index 7994e486e6..14b89ee4f1 100644 --- a/src/detect-engine-proto.c +++ b/src/detect-engine-proto.c @@ -154,7 +154,7 @@ int DetectProtoParse(DetectProto *dp, char *str) } #endif } - return 0; + return proto; error: return -1; @@ -213,7 +213,7 @@ static int DetectProtoInitTest(DetectEngineCtx **de_ctx, Signature **sig, *sig = (*de_ctx)->sig_list; - if (DetectProtoParse(dp, str) != 0) + if (DetectProtoParse(dp, str) < 0) goto end; result = 1; @@ -232,7 +232,7 @@ static int ProtoTestParse01 (void) memset(&dp,0,sizeof(DetectProto)); int r = DetectProtoParse(&dp, "6"); - if (r != 0) { + if (r < 0) { return 1; } @@ -249,7 +249,7 @@ static int ProtoTestParse02 (void) memset(&dp,0,sizeof(DetectProto)); int r = DetectProtoParse(&dp, "tcp"); - if (r == 0 && dp.proto[(IPPROTO_TCP/8)] & (1<<(IPPROTO_TCP%8))) { + if (r >= 0 && dp.proto[(IPPROTO_TCP/8)] & (1<<(IPPROTO_TCP%8))) { return 1; } @@ -266,7 +266,7 @@ static int ProtoTestParse03 (void) memset(&dp,0,sizeof(DetectProto)); int r = DetectProtoParse(&dp, "ip"); - if (r == 0 && dp.flags & DETECT_PROTO_ANY) { + if (r >= 0 && dp.flags & DETECT_PROTO_ANY) { return 1; } @@ -285,7 +285,7 @@ static int ProtoTestParse04 (void) /* Check for a bad number */ int r = DetectProtoParse(&dp, "4242"); - if (r == -1) { + if (r < 0) { return 1; } @@ -304,7 +304,7 @@ static int ProtoTestParse05 (void) /* Check for a bad string */ int r = DetectProtoParse(&dp, "tcp/udp"); - if (r == -1) { + if (r < 0) { return 1; } @@ -322,7 +322,7 @@ static int ProtoTestParse06 (void) /* Check for a bad string */ int r = DetectProtoParse(&dp, "tcp-pkt"); - if (r == -1) { + if (r < -1) { printf("parsing tcp-pkt failed: "); return 0; } @@ -345,7 +345,7 @@ static int ProtoTestParse07 (void) /* Check for a bad string */ int r = DetectProtoParse(&dp, "tcp-stream"); - if (r == -1) { + if (r < -1) { printf("parsing tcp-stream failed: "); return 0; } diff --git a/suricata.yaml.in b/suricata.yaml.in index 3b31465c99..af24486c25 100644 --- a/suricata.yaml.in +++ b/suricata.yaml.in @@ -989,6 +989,9 @@ app-layer: protocols: tls: enabled: yes + detection-ports: + tcp: + toserver: 443 #no-reassemble: yes dcerpc: @@ -1005,9 +1008,22 @@ app-layer: enabled: detection-only smb: enabled: yes + detection-ports: + tcp: + toserver: 139 # smb2 detection is disabled internally inside the engine. #smb2: # enabled: yes + dnstcp: + enabled: yes + detection-ports: + tcp: + toserver: 53 + dnsudp: + enabled: yes + detection-ports: + udp: + toserver: 53 http: enabled: yes