]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
pktvars: same name pktvars, key-value vars
authorVictor Julien <victor@inliniac.net>
Sat, 5 Nov 2016 13:02:39 +0000 (09:02 -0400)
committerVictor Julien <victor@inliniac.net>
Thu, 16 Feb 2017 09:35:44 +0000 (10:35 +0100)
src/decode.h
src/detect-flowvar.c
src/detect-flowvar.h
src/detect-pcre.c
src/detect.h
src/output-json.c
src/pkt-var.c
src/pkt-var.h
src/util-var.h

index 6d0ad53ee7c519c02d430edef2c9a548bf7aae8f..d732ce9038b30cef7f1f4181a27b42cf60cd5d32 100644 (file)
@@ -302,8 +302,10 @@ typedef struct PktVar_ {
     struct PktVar_ *next; /* right now just implement this as a list,
                            * in the long run we have thing of something
                            * faster. */
-    uint8_t *value;
+    uint16_t key_len;
     uint16_t value_len;
+    uint8_t *key;
+    uint8_t *value;
 } PktVar;
 
 #ifdef PROFILING
index b0c30d4099b08a99cc78ea22278214d2000b608f..9f84811a12bd760af71b88f187654f17068db65a 100644 (file)
@@ -193,9 +193,29 @@ error:
     return -1;
 }
 
+/** \brief Store flowvar in det_ctx so we can exec it post-match */
+int DetectVarStoreMatchKeyValue(DetectEngineThreadCtx *det_ctx,
+        uint8_t *key, uint16_t key_len,
+        uint8_t *buffer, uint16_t len, int type)
+{
+    DetectVarList *fs = SCCalloc(1, sizeof(*fs));
+    if (unlikely(fs == NULL))
+        return -1;
+
+    fs->len = len;
+    fs->type = type;
+    fs->buffer = buffer;
+    fs->key = key;
+    fs->key_len = key_len;
+
+    fs->next = det_ctx->varlist;
+    det_ctx->varlist = fs;
+    return 0;
+}
 
 /** \brief Store flowvar in det_ctx so we can exec it post-match */
-int DetectVarStoreMatch(DetectEngineThreadCtx *det_ctx, uint32_t idx,
+int DetectVarStoreMatch(DetectEngineThreadCtx *det_ctx,
+        uint32_t idx,
         uint8_t *buffer, uint16_t len, int type)
 {
     DetectVarList *fs = det_ctx->varlist;
@@ -211,7 +231,7 @@ int DetectVarStoreMatch(DetectEngineThreadCtx *det_ctx, uint32_t idx,
     }
 
     if (fs == NULL) {
-        fs = SCMalloc(sizeof(*fs));
+        fs = SCCalloc(1, sizeof(*fs));
         if (unlikely(fs == NULL))
             return -1;
 
@@ -278,7 +298,7 @@ static int DetectFlowvarPostMatch(ThreadVars *tv,
     prev = NULL;
     fs = det_ctx->varlist;
     while (fs != NULL) {
-        if (fd->idx == fs->idx) {
+        if (fd->idx == 0 || fd->idx == fs->idx) {
             SCLogDebug("adding to the flow %u:", fs->idx);
             //PrintRawDataFp(stdout, fs->buffer, fs->len);
 
@@ -286,8 +306,20 @@ static int DetectFlowvarPostMatch(ThreadVars *tv,
                 FlowVarAddStrNoLock(p->flow, fs->idx, fs->buffer, fs->len);
                 /* memory at fs->buffer is now the responsibility of
                  * the flowvar code. */
+            } else if (fs->type == DETECT_VAR_TYPE_PKT_POSTMATCH && fs->key && p) {
+                /* pkt key/value */
+                if (PktVarAddKeyValue(p, (uint8_t *)fs->key, fs->key_len,
+                                         (uint8_t *)fs->buffer, fs->len) == -1)
+                {
+                    SCFree(fs->key);
+                    SCFree(fs->buffer);
+                    /* the rest of fs is freed below */
+                }
             } else if (fs->type == DETECT_VAR_TYPE_PKT_POSTMATCH && p) {
-                PktVarAdd(p, fs->idx, fs->buffer, fs->len);
+                if (PktVarAdd(p, fs->idx, fs->buffer, fs->len) == -1) {
+                    SCFree(fs->buffer);
+                    /* the rest of fs is freed below */
+                }
             }
 
             if (fs == det_ctx->varlist) {
index 59edfc80bc175a0082ccf485a009b2d9d4ec9649..f919c3b031ea0e66a3dc22ec32541255646a19e5 100644 (file)
@@ -36,7 +36,10 @@ typedef struct DetectFlowvarData_ {
 void DetectFlowvarRegister (void);
 
 int DetectFlowvarPostMatchSetup(Signature *s, uint32_t idx);
-int DetectVarStoreMatch(DetectEngineThreadCtx *, uint32_t, uint8_t *, uint16_t, int);
+int DetectVarStoreMatch(DetectEngineThreadCtx *,
+        uint32_t, uint8_t *, uint16_t, int);
+int DetectVarStoreMatchKeyValue(DetectEngineThreadCtx *,
+        uint8_t *, uint16_t, uint8_t *, uint16_t, int);
 
 /* For use only by DetectFlowvarProcessList() */
 void DetectVarProcessListInternal(DetectVarList *fs, Flow *f, Packet *p);
index b4ed145715d0da6b3e7e14d14842bd2acee0eeb8..661a254a3e1d2f0ae825aa15ce44adfeef93ffa6 100644 (file)
@@ -230,7 +230,23 @@ int DetectPcrePayloadMatch(DetectEngineThreadCtx *det_ctx, const Signature *s,
                     SCLogDebug("data %p/%u, type %u id %u p %p",
                             str_ptr, ret, pe->captypes[x], pe->capids[x], p);
 
-                    if (pe->captypes[x] == VAR_TYPE_PKT_VAR) {
+                    if (pe->captypes[x] == VAR_TYPE_PKT_VAR_KV) {
+                        /* get the value, as first capture is the key */
+                        const char *str_ptr2;
+                        int ret2 = pcre_get_substring((char *)ptr, ov, MAX_SUBSTRINGS, x+2, &str_ptr2);
+                        if (unlikely(ret2 == 0)) {
+                            break;
+                        }
+                        /* key length is limited to 256 chars */
+                        uint16_t key_len = (ret < 0xff) ? (uint16_t)ret : 0xff;
+                        capture_len = (ret2 < 0xffff) ? (uint16_t)ret2 : 0xffff;
+
+                        (void)DetectVarStoreMatchKeyValue(det_ctx,
+                                (uint8_t *)str_ptr, key_len,
+                                (uint8_t *)str_ptr2, capture_len,
+                                DETECT_VAR_TYPE_PKT_POSTMATCH);
+
+                    } else if (pe->captypes[x] == VAR_TYPE_PKT_VAR) {
                         /* store max 64k. Errors are ignored */
                         capture_len = (ret < 0xffff) ? (uint16_t)ret : 0xffff;
                         (void)DetectVarStoreMatch(det_ctx, pe->capids[x],
@@ -665,6 +681,7 @@ static int DetectPcreParseCapture(char *regexstr, DetectEngineCtx *de_ctx, Detec
     char *name_array[DETECT_PCRE_CAPTURE_MAX] = { NULL };
     int name_idx = 0;
     int capture_cnt = 0;
+    int key = 0;
 
     SCLogDebug("regexstr %s, pd %p", regexstr, pd);
 
@@ -681,7 +698,25 @@ static int DetectPcreParseCapture(char *regexstr, DetectEngineCtx *de_ctx, Detec
             }
             SCLogDebug("name '%s'", name_array[name_idx]);
 
-            if (strncmp(name_array[name_idx], "flow:", 5) == 0) {
+            if (strcmp(name_array[name_idx], "pkt:key") == 0) {
+                key = 1;
+                SCLogDebug("key-value/key");
+
+                pd->captypes[pd->idx] = VAR_TYPE_PKT_VAR_KV;
+                SCLogDebug("id %u type %u", pd->capids[pd->idx], pd->captypes[pd->idx]);
+                pd->idx++;
+
+            } else if (key == 1 && strcmp(name_array[name_idx], "pkt:value") == 0) {
+                SCLogDebug("key-value/value");
+                key = 0;
+
+            /* kv error conditions */
+            } else if (key == 0 && strcmp(name_array[name_idx], "pkt:value") == 0) {
+                return -1;
+            } else if (key == 1) {
+                return -1;
+
+            } else if (strncmp(name_array[name_idx], "flow:", 5) == 0) {
                 pd->capids[pd->idx] = VarNameStoreSetupAdd(name_array[name_idx]+5, VAR_TYPE_FLOW_VAR);
                 pd->captypes[pd->idx] = VAR_TYPE_FLOW_VAR;
                 pd->idx++;
index 2394ab442ebbe4c4a87f440fe02b3d6683620f20..023b931da41e3ce0dab1197bd9452434deab38cd 100644 (file)
@@ -500,7 +500,9 @@ typedef struct DetectReplaceList_ {
 typedef struct DetectVarList_ {
     uint32_t idx;                       /**< flowvar name idx */
     uint16_t len;                       /**< data len */
+    uint16_t key_len;
     int type;                           /**< type of store candidate POSTMATCH or ALWAYS */
+    uint8_t *key;
     uint8_t *buffer;                    /**< alloc'd buffer, may be freed by
                                              post-match, post-non-match */
     struct DetectVarList_ *next;
index 7aa7a23aa7abdde875a6005fa6090b381d4efdbd..7db6262d33d1ab7884bfb66af0c995cba4e904b2 100644 (file)
@@ -102,23 +102,44 @@ static void JsonAddPacketvars(const Packet *p, json_t *js_vars)
     json_t *js_pktvars = NULL;
     PktVar *pv = p->pktvar;
     while (pv != NULL) {
-        const char *varname = VarNameStoreLookupById(pv->id, VAR_TYPE_PKT_VAR);
-        if (varname) {
+        if (pv->key || pv->id > 0) {
             if (js_pktvars == NULL) {
-                js_pktvars = json_object();
+                js_pktvars = json_array();
                 if (js_pktvars == NULL)
                     break;
             }
+            json_t *js_pair = json_object();
+            if (js_pair == NULL) {
+                break;
+            }
 
-            uint32_t len = pv->value_len;
-            uint8_t printable_buf[len + 1];
-            uint32_t offset = 0;
-            PrintStringsToBuffer(printable_buf, &offset,
-                    sizeof(printable_buf),
-                    pv->value, pv->value_len);
-
-            json_object_set_new(js_pktvars, varname,
-                    json_string((char *)printable_buf));
+            if (pv->key != NULL) {
+                uint32_t offset = 0;
+                uint8_t keybuf[pv->key_len + 1];
+                PrintStringsToBuffer(keybuf, &offset,
+                        sizeof(keybuf),
+                        pv->key, pv->key_len);
+                uint32_t len = pv->value_len;
+                uint8_t printable_buf[len + 1];
+                offset = 0;
+                PrintStringsToBuffer(printable_buf, &offset,
+                        sizeof(printable_buf),
+                        pv->value, pv->value_len);
+                json_object_set_new(js_pair, (char *)keybuf,
+                        json_string((char *)printable_buf));
+            } else {
+                const char *varname = VarNameStoreLookupById(pv->id, VAR_TYPE_PKT_VAR);
+                uint32_t len = pv->value_len;
+                uint8_t printable_buf[len + 1];
+                uint32_t offset = 0;
+                PrintStringsToBuffer(printable_buf, &offset,
+                        sizeof(printable_buf),
+                        pv->value, pv->value_len);
+
+                json_object_set_new(js_pair, varname,
+                        json_string((char *)printable_buf));
+            }
+            json_array_append_new(js_pktvars, js_pair);
         }
         pv = pv->next;
     }
index 333f2977bd4407ac86c422292d6ffc661ea8f5b4..a81af35e1af20214e7580a05f3965f65f8f3d830 100644 (file)
 #include "pkt-var.h"
 #include "util-debug.h"
 
-/* puts a new value into a pktvar */
-static void PktVarUpdate(PktVar *pv, uint8_t *value, uint16_t size)
-{
-    if (pv->value)
-        SCFree(pv->value);
-    pv->value = value;
-    pv->value_len = size;
-}
-
 /* get the pktvar with name 'name' from the pkt
  *
  * name is a normal string*/
@@ -58,37 +49,63 @@ PktVar *PktVarGet(Packet *p, uint32_t id)
     return NULL;
 }
 
-/* add a pktvar to the pkt, or update it */
-void PktVarAdd(Packet *p, uint32_t id, uint8_t *value, uint16_t size)
+/**
+ *  \brief add a key-value pktvar to the pkt
+ *  \retval r 0 ok, -1 error
+ */
+int PktVarAddKeyValue(Packet *p, uint8_t *key, uint16_t ksize, uint8_t *value, uint16_t size)
 {
-    //printf("Adding packet var \"%s\" with value(%" PRId32 ") \"%s\"\n", name, size, value);
+    PktVar *pv = SCCalloc(1, sizeof(PktVar));
+    if (unlikely(pv == NULL))
+        return -1;
 
-    PktVar *pv = PktVarGet(p, id);
-    if (pv == NULL) {
-        pv = SCMalloc(sizeof(PktVar));
-        if (unlikely(pv == NULL))
-            return;
+    pv->key = key;
+    pv->key_len = ksize;
+    pv->value = value;
+    pv->value_len = size;
 
-        pv->id = id;
-        pv->value = value;
-        pv->value_len = size;
-        pv->next = NULL;
+    PktVar *tpv = p->pktvar;
+    if (p->pktvar == NULL)
+        p->pktvar = pv;
+    else {
+        while(tpv) {
+            if (tpv->next == NULL) {
+                tpv->next = pv;
+                return 0;
+            }
+            tpv = tpv->next;
+        }
+    }
+    return 0;
+}
+
+/**
+ *  \brief add a key-value pktvar to the pkt
+ *  \retval r 0 ok, -1 error
+ */
+int PktVarAdd(Packet *p, uint32_t id, uint8_t *value, uint16_t size)
+{
+    PktVar *pv = SCCalloc(1, sizeof(PktVar));
+    if (unlikely(pv == NULL))
+        return -1;
+
+    pv->id = id;
+    pv->value = value;
+    pv->value_len = size;
 
-        PktVar *tpv = p->pktvar;
-        if (p->pktvar == NULL)
-            p->pktvar = pv;
-        else {
-            while(tpv) {
-                if (tpv->next == NULL) {
-                    tpv->next = pv;
-                    return;
-                }
-                tpv = tpv->next;
+    PktVar *tpv = p->pktvar;
+    if (p->pktvar == NULL)
+        p->pktvar = pv;
+    else {
+        while(tpv) {
+            if (tpv->next == NULL) {
+                tpv->next = pv;
+                return 0;
             }
+            tpv = tpv->next;
         }
-    } else {
-        PktVarUpdate(pv, value, size);
     }
+    return 0;
 }
 
 void PktVarFree(PktVar *pv)
@@ -96,6 +113,8 @@ void PktVarFree(PktVar *pv)
     if (pv == NULL)
         return;
 
+    if (pv->key != NULL)
+        SCFree(pv->key);
     if (pv->value != NULL)
         SCFree(pv->value);
     PktVar *pv_next = pv->next;
index cfdd6f5aee5cb608c9bcf5f24248ac23a1efbe4a..0a261c9ffaaf5d53ce63d33e0f5d22d0f2a6c718 100644 (file)
@@ -24,7 +24,8 @@
 #ifndef __PKT_VAR_H__
 #define __PKT_VAR_H__
 
-void PktVarAdd(Packet *, uint32_t id, uint8_t *, uint16_t);
+int WARN_UNUSED PktVarAddKeyValue(Packet *, uint8_t *, uint16_t, uint8_t *, uint16_t);
+int WARN_UNUSED PktVarAdd(Packet *, uint32_t id, uint8_t *, uint16_t);
 PktVar *PktVarGet(Packet *, uint32_t id);
 void PktVarFree(PktVar *);
 
index 3deeaf747912500cdaf0c1113745e1b0f0e84361..ac9de2d3fb478740913d53320cf9044330aea122 100644 (file)
@@ -30,6 +30,7 @@ enum VarTypes {
     VAR_TYPE_PKT_BIT,
     VAR_TYPE_PKT_INT,
     VAR_TYPE_PKT_VAR,
+    VAR_TYPE_PKT_VAR_KV, // key-value
 
     VAR_TYPE_FLOW_BIT,
     VAR_TYPE_FLOW_INT,