/* buffer set up by sigmatch is tracked in case we add a stickybuffer for the
* same list. */
s->init_data->curbuf->sm_init = true;
+ if (s->init_data->init_flags & SIG_FLAG_INIT_FORCE_TOCLIENT) {
+ s->init_data->curbuf->only_tc = true;
+ }
+ if (s->init_data->init_flags & SIG_FLAG_INIT_FORCE_TOSERVER) {
+ s->init_data->curbuf->only_ts = true;
+ }
SCLogDebug("s->init_data->buffer_index %u", s->init_data->buffer_index);
}
}
return -1;
}
+/**
+ * \brief Parse and setup a direction
+ *
+ * \param s signature
+ * \param str argument to the keyword
+ * \param only_dir argument wether the keyword only accepts a direction
+ *
+ * \retval 0 on success, -1 on failure
+ */
+static int DetectSetupDirection(Signature *s, char **str, bool only_dir)
+{
+ char *orig = *str;
+ if (strncmp(*str, "to_client", strlen("to_client")) == 0) {
+ *str += strlen("to_client");
+ // skip space
+ while (**str && isblank(**str)) {
+ (*str)++;
+ }
+ // check comma or nothing
+ if (**str) {
+ if (only_dir) {
+ SCLogError("unknown option: only accepts to_server or to_client");
+ return -1;
+ }
+ if (**str != ',') {
+ // leave to_client_something for next parser if not only_dir
+ *str = orig;
+ return 0;
+ } else {
+ (*str)++;
+ }
+ while (**str && isblank(**str)) {
+ (*str)++;
+ }
+ }
+ s->init_data->init_flags |= SIG_FLAG_INIT_FORCE_TOCLIENT;
+ if ((s->flags & SIG_FLAG_TXBOTHDIR) == 0) {
+ if (s->flags & SIG_FLAG_TOSERVER) {
+ SCLogError("contradictory directions");
+ return -1;
+ }
+ s->flags |= SIG_FLAG_TOCLIENT;
+ }
+ } else if (strncmp(*str, "to_server", strlen("to_server")) == 0) {
+ *str += strlen("to_server");
+ // skip space
+ while (**str && isblank(**str)) {
+ (*str)++;
+ }
+ // check comma or nothing
+ if (**str) {
+ if (only_dir) {
+ SCLogError("unknown option: only accepts to_server or to_client");
+ return -1;
+ }
+ if (**str != ',') {
+ // leave to_client_something for next parser if not only_dir
+ *str = orig;
+ return 0;
+ } else {
+ (*str)++;
+ }
+ while (**str && isblank(**str)) {
+ (*str)++;
+ }
+ }
+ s->init_data->init_flags |= SIG_FLAG_INIT_FORCE_TOSERVER;
+ if ((s->flags & SIG_FLAG_TXBOTHDIR) == 0) {
+ if (s->flags & SIG_FLAG_TOCLIENT) {
+ SCLogError("contradictory directions");
+ return -1;
+ }
+ s->flags |= SIG_FLAG_TOSERVER;
+ }
+ } else if (only_dir) {
+ SCLogError("unknown option: only accepts to_server or to_client");
+ return -1;
+ }
+ return 0;
+}
+
static int SigParseOptions(DetectEngineCtx *de_ctx, Signature *s, char *optstr, char *output,
size_t output_size, bool requires)
{
}
}
/* setup may or may not add a new SigMatch to the list */
+ if (st->flags & SIGMATCH_SUPPORT_DIR) {
+ if (DetectSetupDirection(s, &ptr, st->flags & SIGMATCH_OPTIONAL_OPT) < 0) {
+ SCLogError("%s failed to setup direction", st->name);
+ goto error;
+ }
+ }
setup_ret = st->Setup(de_ctx, s, ptr);
+ s->init_data->init_flags &= ~SIG_FLAG_INIT_FORCE_TOSERVER;
+ s->init_data->init_flags &= ~SIG_FLAG_INIT_FORCE_TOCLIENT;
} else {
/* setup may or may not add a new SigMatch to the list */
setup_ret = st->Setup(de_ctx, s, NULL);
}
}
-/**
- * \brief Parse and setup a direction
- *
- * \param s siganture
- * \param str argument to the keyword
- *
- * \retval 0 on success, -1 on failure
- */
-int DetectSetupDirection(Signature *s, const char *str)
-{
- if (str) {
- if (strcmp(str, "to_client") == 0) {
- s->init_data->init_flags |= SIG_FLAG_INIT_FORCE_TOCLIENT;
- if ((s->flags & SIG_FLAG_TXBOTHDIR) == 0) {
- if (s->flags & SIG_FLAG_TOSERVER) {
- SCLogError("contradictory directions");
- return -1;
- }
- s->flags |= SIG_FLAG_TOCLIENT;
- }
- } else if (strcmp(str, "to_server") == 0) {
- s->init_data->init_flags |= SIG_FLAG_INIT_FORCE_TOSERVER;
- if ((s->flags & SIG_FLAG_TXBOTHDIR) == 0) {
- if (s->flags & SIG_FLAG_TOCLIENT) {
- SCLogError("contradictory directions");
- return -1;
- }
- s->flags |= SIG_FLAG_TOSERVER;
- }
- } else {
- SCLogError("unknown option: only accepts to_server or to_client");
- return -1;
- }
- }
- return 0;
-}
-
/*
* TESTS
*/
PASS;
}
+static int DetectSetupDirection01(void)
+{
+ Signature *s = SigAlloc();
+ FAIL_IF_NULL(s);
+ // Basic case : ok
+ char *str = (char *)"to_client";
+ FAIL_IF(DetectSetupDirection(s, &str, true) < 0);
+ SigFree(NULL, s);
+ PASS;
+}
+
+static int DetectSetupDirection02(void)
+{
+ Signature *s = SigAlloc();
+ FAIL_IF_NULL(s);
+ char *str = (char *)"to_server";
+ FAIL_IF(DetectSetupDirection(s, &str, true) < 0);
+ // ok so far
+ str = (char *)"to_client";
+ FAIL_IF(DetectSetupDirection(s, &str, true) >= 0);
+ // fails because we cannot have both to_client and to_server for same signature
+ SigFree(NULL, s);
+ PASS;
+}
+
+static int DetectSetupDirection03(void)
+{
+ Signature *s = SigAlloc();
+ FAIL_IF_NULL(s);
+ char *str = (char *)"to_client , something";
+ FAIL_IF(DetectSetupDirection(s, &str, false) < 0);
+ FAIL_IF(strcmp(str, "something") != 0);
+ str = (char *)"to_client,something";
+ FAIL_IF(DetectSetupDirection(s, &str, false) < 0);
+ FAIL_IF(strcmp(str, "something") != 0);
+ SigFree(NULL, s);
+ PASS;
+}
+
+static int DetectSetupDirection04(void)
+{
+ Signature *s = SigAlloc();
+ FAIL_IF_NULL(s);
+ // invalid case
+ char *str = (char *)"to_client_toto";
+ FAIL_IF(DetectSetupDirection(s, &str, true) >= 0);
+ // test we do not change the string pointer if only_dir is false
+ str = (char *)"to_client_toto";
+ FAIL_IF(DetectSetupDirection(s, &str, false) < 0);
+ FAIL_IF(strcmp(str, "to_client_toto") != 0);
+ str = (char *)"to_client,something";
+ // fails because we call with only_dir=true
+ FAIL_IF(DetectSetupDirection(s, &str, true) >= 0);
+ SigFree(NULL, s);
+ PASS;
+}
+
#endif /* UNITTESTS */
#ifdef UNITTESTS
UtRegisterTest("SigSetMultiAppProto", SigSetMultiAppProto);
+ UtRegisterTest("DetectSetupDirection01", DetectSetupDirection01);
+ UtRegisterTest("DetectSetupDirection02", DetectSetupDirection02);
+ UtRegisterTest("DetectSetupDirection03", DetectSetupDirection03);
+ UtRegisterTest("DetectSetupDirection04", DetectSetupDirection04);
+
#endif /* UNITTESTS */
}