You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
suricata/src/detect-seq.c

239 lines
6.2 KiB
C

/* Copyright (C) 2007-2010 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* 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
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
16 years ago
/**
* \file
*
16 years ago
* \author Brian Rectanus <brectanu@gmail.com>
*
* Implements the seq keyword.
16 years ago
*/
#include "suricata-common.h"
16 years ago
#include "debug.h"
#include "decode.h"
#include "detect.h"
#include "detect-parse.h"
#include "detect-engine.h"
#include "detect-engine-mpm.h"
#include "detect-seq.h"
#include "util-byte.h"
#include "util-unittest.h"
#include "util-unittest-helper.h"
#include "util-debug.h"
16 years ago
static int DetectSeqSetup(DetectEngineCtx *, Signature *, char *);
static int DetectSeqMatch(ThreadVars *, DetectEngineThreadCtx *,
Packet *, Signature *, SigMatch *);
16 years ago
static void DetectSeqRegisterTests(void);
static void DetectSeqFree(void *);
16 years ago
void DetectSeqRegister(void) {
sigmatch_table[DETECT_SEQ].name = "seq";
sigmatch_table[DETECT_SEQ].Match = DetectSeqMatch;
sigmatch_table[DETECT_SEQ].Setup = DetectSeqSetup;
sigmatch_table[DETECT_SEQ].Free = DetectSeqFree;
sigmatch_table[DETECT_SEQ].RegisterTests = DetectSeqRegisterTests;
}
/**
* \internal
* \brief This function is used to match packets with a given Seq number
*
* \param t pointer to thread vars
* \param det_ctx pointer to the pattern matcher thread
* \param p pointer to the current packet
* \param m pointer to the sigmatch that we will cast into DetectSeqData
*
* \retval 0 no match
* \retval 1 match
*/
static int DetectSeqMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
Packet *p, Signature *s, SigMatch *m)
{
DetectSeqData *data = (DetectSeqData *)m->ctx;
16 years ago
/* This is only needed on TCP packets */
if (!(PKT_IS_TCP(p)) || PKT_IS_PSEUDOPKT(p)) {
16 years ago
return 0;
}
return (data->seq == TCP_GET_SEQ(p)) ? 1 : 0;
16 years ago
}
/**
* \internal
* \brief this function is used to add the seq option into the signature
*
* \param de_ctx pointer to the Detection Engine Context
* \param s pointer to the Current Signature
* \param optstr pointer to the user provided options
*
* \retval 0 on Success
* \retval -1 on Failure
*/
static int DetectSeqSetup (DetectEngineCtx *de_ctx, Signature *s, char *optstr)
16 years ago
{
Memory leak cleanup in detectors Hello, I ran the code through an analysis program and found several leaks that should be cleaned up. *In src/detect-engine-address-ipv4.c at line 472, the test for ag == NULL will never be true since that is the loop entry test. *In src/detect-engine-port.c at line 1133, the test for p == NULL will never be true since that is the loop entry test. *In src/detect-engine-mpm.c at line 263 is a return without freeing fast_pattern *In src/detect-ack.c at line 80 and 85, data catches the return from malloc. One of them should be deleted. *In src/detect-seq.c at line 81 and 86, data catches the return from malloc. One of them should be deleted. *In src/detect-content.c at line 749, many of the paths that lead to the error exit still has temp pointing to allocated memory. To clean this up, temp should be set to NULL if not immediately assigning and new value. *In src/detect-uricontent.c at line 319, both cd and str needto be freed. At lines 344, str needs to be freed. And at line 347 str and temp need to be freed. *In src/detect-flowbits.c at line 231 and 235, str was not being freed. cd was not being freed at line 235. *In src/detect-flowvar.c at line 127, str was not being freed. At line 194, cd and str were not being freed. *In src/detect-flowint.c at line 277, sfd was not being freed. At line 315, str was not being freed. *In src/detect-pktvar.c at line 121, str was not being freed. At line 188, str and cd was not being freed. *In src/detect-pcre.c at line 389, there is an extra free of "re" that should be deleted. *In src/detect-depth.c at line 42 & 48, str has not been freed. *In src/detect-distance.c at line 49 and 55, str has not been freed *In src/detect-offset.c at line 45, str has not been freed. The patch below fixes these issues. -Steve
16 years ago
DetectSeqData *data;
16 years ago
SigMatch *sm = NULL;
data = SCMalloc(sizeof(DetectSeqData));
if (data == NULL)
16 years ago
goto error;
sm = SigMatchAlloc();
if (sm == NULL) {
goto error;
}
sm->type = DETECT_SEQ;
if (-1 == ByteExtractStringUint32(&data->seq, 10, 0, optstr)) {
16 years ago
goto error;
}
sm->ctx = data;
16 years ago
SigMatchAppendPacket(s, sm);
s->flags |= SIG_FLAG_REQUIRE_PACKET;
16 years ago
return 0;
error:
if (data) SCFree(data);
16 years ago
return -1;
}
/**
* \internal
* \brief this function will free memory associated with seq option
*
* \param data pointer to seq configuration data
*/
static void DetectSeqFree(void *ptr)
{
DetectSeqData *data = (DetectSeqData *)ptr;
SCFree(data);
16 years ago
}
#ifdef UNITTESTS
16 years ago
/**
* \test DetectSeqSigTest01 tests parses
16 years ago
*/
static int DetectSeqSigTest01(void)
16 years ago
{
int result = 0;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
16 years ago
goto end;
/* These three are crammed in here as there is no Parse */
if (SigInit(de_ctx,
"alert tcp any any -> any any "
"(msg:\"Testing seq\";seq:foo;sid:1;)") != NULL)
{
printf("invalid seq accepted: ");
goto cleanup;
16 years ago
}
if (SigInit(de_ctx,
"alert tcp any any -> any any "
"(msg:\"Testing seq\";seq:9999999999;sid:1;)") != NULL)
{
printf("overflowing seq accepted: ");
goto cleanup;
16 years ago
}
if (SigInit(de_ctx,
"alert tcp any any -> any any "
"(msg:\"Testing seq\";seq:-100;sid:1;)") != NULL)
{
printf("negative seq accepted: ");
goto cleanup;
}
result = 1;
cleanup:
if (de_ctx) {
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
}
16 years ago
end:
return result;
}
/**
* \test DetectSeqSigTest02 tests seq keyword
16 years ago
*/
static int DetectSeqSigTest02(void)
16 years ago
{
int result = 0;
uint8_t *buf = (uint8_t *)"Hi all!";
uint16_t buflen = strlen((char *)buf);
Packet *p[3];
p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
p[1] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
p[2] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_ICMP);
if (p[0] == NULL || p[1] == NULL ||p[2] == NULL)
goto end;
16 years ago
/* TCP w/seq=42 */
p[0]->tcph->th_seq = htonl(42);
16 years ago
/* TCP w/seq=100 */
p[1]->tcph->th_seq = htonl(100);
char *sigs[2];
sigs[0]= "alert tcp any any -> any any (msg:\"Testing seq\"; seq:41; sid:1;)";
sigs[1]= "alert tcp any any -> any any (msg:\"Testing seq\"; seq:42; sid:2;)";
uint32_t sid[2] = {1, 2};
uint32_t results[3][2] = {
/* packet 0 match sid 1 but should not match sid 2 */
{0, 1},
/* packet 1 should not match */
{0, 0},
/* packet 2 should not match */
{0, 0} };
result = UTHGenericTest(p, 3, sigs, sid, (uint32_t *) results, 2);
UTHFreePackets(p, 3);
end:
return result;
16 years ago
}
#endif /* UNITTESTS */
/**
* \internal
* \brief This function registers unit tests for DetectSeq
*/
static void DetectSeqRegisterTests(void)
{
#ifdef UNITTESTS
UtRegisterTest("DetectSeqSigTest01", DetectSeqSigTest01, 1);
UtRegisterTest("DetectSeqSigTest02", DetectSeqSigTest02, 1);
16 years ago
#endif /* UNITTESTS */
}