#include "util-byte.h"
#include "util-debug.h"
-#define PARSE_REGEX "^\\s*([A-Za-z0-9]+)\\s*,\"?\\s*\"?\\s*([a-zA-Z0-9\\-_\\.\\/\\?\\=]+)\"?\\s*\"?"
+/* Breakout key and scheme (optional) and domain/path (mandatory) */
+#define PARSE_REGEX \
+ "^\\s*([A-Za-z0-9]+)\\s*,\"?\\s*\"?\\s*([a-zA-Z]+:\\/\\/)?([a-zA-Z0-9\\-_\\.\\/" \
+ "\\?\\=]+)\"?\\s*\"?"
static DetectParseRegex parse_regex;
{
SCEnter();
+ if (ref->key)
+ SCFree(ref->key);
+
if (ref->reference != NULL) {
SCFree(ref->reference);
}
int res = 0;
size_t pcre2len;
char key[REFERENCE_SYSTEM_NAME_MAX] = "";
- char content[REFERENCE_CONTENT_NAME_MAX] = "";
+ char scheme[REFERENCE_SYSTEM_NAME_MAX] = "";
+ char uri[REFERENCE_CONTENT_NAME_MAX] = "";
pcre2_match_data *match = NULL;
int ret = DetectParsePcreExec(&parse_regex, &match, rawstr, 0, 0);
- if (ret < 2) {
+ if (ret != 4) {
SCLogError("Unable to parse \"reference\" "
"keyword argument - \"%s\". Invalid argument.",
rawstr);
return NULL;
}
+ /* Position 1 = key (mandatory) */
pcre2len = sizeof(key);
res = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)key, &pcre2len);
if (res < 0) {
- SCLogError("pcre2_substring_copy_bynumber failed");
+ SCLogError("pcre2_substring_copy_bynumber key failed");
goto error;
}
- pcre2len = sizeof(content);
- res = pcre2_substring_copy_bynumber(match, 2, (PCRE2_UCHAR8 *)content, &pcre2len);
+ /* Position 2 = scheme (optional) */
+ pcre2len = sizeof(scheme);
+ (void)pcre2_substring_copy_bynumber(match, 2, (PCRE2_UCHAR8 *)scheme, &pcre2len);
+
+ /* Position 3 = domain-path (mandatory) */
+ pcre2len = sizeof(uri);
+ res = pcre2_substring_copy_bynumber(match, 3, (PCRE2_UCHAR8 *)uri, &pcre2len);
if (res < 0) {
- SCLogError("pcre2_substring_copy_bynumber failed");
+ SCLogError("pcre2_substring_copy_bynumber domain-path failed");
goto error;
}
- if (strlen(key) == 0 || strlen(content) == 0)
+ int ref_len = strlen(uri);
+ /* no key, reference -- return an error */
+ if (strlen(key) == 0 || ref_len == 0)
goto error;
- SCRConfReference *lookup_ref_conf = SCRConfGetReference(key, de_ctx);
- if (lookup_ref_conf != NULL) {
- ref->key = lookup_ref_conf->url;
+ if (strlen(scheme)) {
+ SCLogConfig("scheme value %s overrides key %s", scheme, key);
+ ref->key = SCStrdup(scheme);
+ /* already bound checked to be REFERENCE_SYSTEM_NAME_MAX or less */
+ ref->key_len = (uint16_t)strlen(scheme);
} else {
- if (SigMatchStrictEnabled(DETECT_REFERENCE)) {
- SCLogError("unknown reference key \"%s\"", key);
- goto error;
- }
-
- SCLogWarning("unknown reference key \"%s\"", key);
- char str[2048];
- snprintf(str, sizeof(str), "config reference: %s undefined\n", key);
-
- if (SCRConfAddReference(de_ctx, str) < 0)
- goto error;
- lookup_ref_conf = SCRConfGetReference(key, de_ctx);
- if (lookup_ref_conf == NULL)
- goto error;
+ SCRConfReference *lookup_ref_conf = SCRConfGetReference(key, de_ctx);
+ if (lookup_ref_conf != NULL) {
+ ref->key = SCStrdup(lookup_ref_conf->url);
+ /* already bound checked to be REFERENCE_SYSTEM_NAME_MAX or less */
+ ref->key_len = (uint16_t)strlen(ref->key);
+ } else {
+ if (SigMatchStrictEnabled(DETECT_REFERENCE)) {
+ SCLogError("unknown reference key \"%s\"", key);
+ goto error;
+ }
+
+ SCLogWarning("unknown reference key \"%s\"", key);
+
+ char str[2048];
+ snprintf(str, sizeof(str), "config reference: %s undefined\n", key);
+
+ if (SCRConfAddReference(de_ctx, str) < 0)
+ goto error;
+ lookup_ref_conf = SCRConfGetReference(key, de_ctx);
+ if (lookup_ref_conf == NULL)
+ goto error;
+ }
}
/* make a copy so we can free pcre's substring */
- ref->reference = SCStrdup(content);
+ ref->reference = SCStrdup(uri);
if (ref->reference == NULL) {
SCLogError("strdup failed: %s", strerror(errno));
goto error;
}
+ /* already bound checked to be REFERENCE_CONTENT_NAME_MAX or less */
+ ref->reference_len = (uint16_t)ref_len;
+
pcre2_match_data_free(match);
/* free the substrings */
SCReturnPtr(ref, "Reference");
-/* Copyright (C) 2013-2023 Open Information Security Foundation
+/* Copyright (C) 2013-2024 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
#include "util-print.h"
#include "util-optimize.h"
#include "util-buffer.h"
+#include "util-reference-config.h"
#include "util-validate.h"
#include "action-globals.h"
#define LOG_JSON_WEBSOCKET_PAYLOAD BIT_U16(11)
#define LOG_JSON_WEBSOCKET_PAYLOAD_BASE64 BIT_U16(12)
#define LOG_JSON_PAYLOAD_LENGTH BIT_U16(13)
+#define LOG_JSON_REFERENCE BIT_U16(14)
#define METADATA_DEFAULTS ( LOG_JSON_FLOW | \
LOG_JSON_APP_LAYER | \
jb_close(js);
}
+static void AlertJsonReference(const PacketAlert *pa, JsonBuilder *jb)
+{
+ if (!pa->s->references) {
+ return;
+ }
+
+ const DetectReference *kv = pa->s->references;
+ jb_open_array(jb, "references");
+ while (kv) {
+ /* Note that the key and reference sizes have been bound
+ * checked during parsing
+ */
+ const size_t size_needed = kv->key_len + kv->reference_len + 1;
+ char kv_store[size_needed];
+ snprintf(kv_store, size_needed, "%s%s", kv->key, kv->reference);
+ jb_append_string(jb, kv_store);
+ kv = kv->next;
+ }
+ jb_close(jb);
+}
+
static void AlertJsonMetadata(AlertJsonOutputCtx *json_output_ctx,
const PacketAlert *pa, JsonBuilder *js)
{
AlertJsonSourceTarget(p, pa, js, addr);
}
+ if ((json_output_ctx != NULL) && (flags & LOG_JSON_REFERENCE)) {
+ AlertJsonReference(pa, js);
+ }
+
if ((json_output_ctx != NULL) && (flags & LOG_JSON_RULE_METADATA)) {
AlertJsonMetadata(json_output_ctx, pa, js);
}
SetFlag(rule_metadata, "raw", LOG_JSON_RULE, &flags);
SetFlag(rule_metadata, "metadata", LOG_JSON_RULE_METADATA,
&flags);
+ SetFlag(rule_metadata, "reference", LOG_JSON_REFERENCE, &flags);
}
SetFlag(metadata, "flow", LOG_JSON_FLOW, &flags);
SetFlag(metadata, "app-layer", LOG_JSON_APP_LAYER, &flags);