Browse code

finished support for AC trie nocase variant added check to prevent adding nocase signatures to case-sensitive AC tries

Kevin Lin authored on 2015/02/07 04:13:20
Showing 6 changed files
... ...
@@ -111,7 +111,7 @@ int cli_ac_addpatt(struct cli_matcher *root, struct cli_ac_patt *pattern)
111 111
             }
112 112
         }
113 113
 
114
-        if (root->ac_nocase)
114
+        if (root->ac_opts & AC_OPTION_NOCASE)
115 115
             next = pt->trans[cli_nocase((unsigned char) (pattern->pattern[i] & 0xff))];
116 116
         else
117 117
             next = pt->trans[(unsigned char) (pattern->pattern[i] & 0xff)];
... ...
@@ -146,7 +146,10 @@ int cli_ac_addpatt(struct cli_matcher *root, struct cli_ac_patt *pattern)
146 146
             root->ac_nodetable = (struct cli_ac_node **) newtable;
147 147
             root->ac_nodetable[root->ac_nodes - 1] = next;
148 148
 
149
-            pt->trans[(unsigned char) (pattern->pattern[i] & 0xff)] = next;
149
+            if (root->ac_opts & AC_OPTION_NOCASE)
150
+                pt->trans[cli_nocase((unsigned char) (pattern->pattern[i] & 0xff))] = next;
151
+            else
152
+                pt->trans[(unsigned char) (pattern->pattern[i] & 0xff)] = next;
150 153
         }
151 154
 
152 155
         pt = next;
... ...
@@ -408,7 +411,7 @@ int cli_ac_buildtrie(struct cli_matcher *root)
408 408
     return ac_maketrans(root);
409 409
 }
410 410
 
411
-int cli_ac_init(struct cli_matcher *root, uint8_t mindepth, uint8_t maxdepth, uint8_t dconf_prefiltering)
411
+int cli_ac_init(struct cli_matcher *root, uint8_t mindepth, uint8_t maxdepth, uint8_t dconf_prefiltering, uint8_t ac_opts)
412 412
 {
413 413
 #ifdef USE_MPOOL
414 414
     assert(root->mempool && "mempool must be initialized");
... ...
@@ -429,6 +432,7 @@ int cli_ac_init(struct cli_matcher *root, uint8_t mindepth, uint8_t maxdepth, ui
429 429
 
430 430
     root->ac_mindepth = mindepth;
431 431
     root->ac_maxdepth = maxdepth;
432
+    root->ac_opts = ac_opts;
432 433
 
433 434
     if (cli_mtargets[root->type].enable_prefiltering && dconf_prefiltering) {
434 435
         root->filter = mpool_malloc(root->mempool, sizeof(*root->filter));
... ...
@@ -843,9 +847,9 @@ int cli_ac_chklsig(const char *expr, const char *end, uint32_t *lsigcnt, unsigne
843 843
 	    match = 0;									\
844 844
     }
845 845
 
846
-inline static int ac_findmatch(const unsigned char *buffer, uint32_t offset, uint32_t fileoffset, uint32_t length, const struct cli_ac_patt *pattern, uint32_t *end)
846
+inline static int ac_findmatch(const unsigned char *buffer, uint32_t offset, uint32_t fileoffset, uint32_t length, const struct cli_ac_patt *pattern, uint32_t *end, uint8_t ac_opts)
847 847
 {
848
-    uint32_t bp, match;
848
+    uint32_t bp, pstart, match;
849 849
     uint16_t wc, i, j, specialcnt = pattern->special_pattern;
850 850
     struct cli_ac_special *special;
851 851
 
... ...
@@ -853,10 +857,17 @@ inline static int ac_findmatch(const unsigned char *buffer, uint32_t offset, uin
853 853
     if((offset + pattern->length > length) || (pattern->prefix_length > offset))
854 854
         return 0;
855 855
 
856
-    bp = offset + pattern->depth;
856
+    if (!pattern->nocase && (ac_opts & AC_OPTION_NOCASE)) {
857
+        bp = offset;
858
+        pstart = 0;
859
+    }
860
+    else {
861
+        bp = offset + pattern->depth;
862
+        pstart = pattern->depth;
863
+    }
857 864
 
858 865
     match = 1;
859
-    for(i = pattern->depth; i < pattern->length && bp < length; i++) {
866
+    for(i = pstart; i < pattern->length && bp < length; i++) {
860 867
         AC_MATCH_CHAR(pattern->pattern[i],buffer[bp]);
861 868
         if(!match)
862 869
             return 0;
... ...
@@ -1257,7 +1268,7 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
1257 1257
     current = root->ac_root;
1258 1258
 
1259 1259
     for(i = 0; i < length; i++)  {
1260
-        if (root->ac_nocase)
1260
+        if (root->ac_opts & AC_OPTION_NOCASE)
1261 1261
             current = current->trans[cli_nocase(buffer[i])];
1262 1262
         else
1263 1263
             current = current->trans[buffer[i]];
... ...
@@ -1292,7 +1303,7 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
1292 1292
                 }
1293 1293
 
1294 1294
                 pt = patt;
1295
-                if(ac_findmatch(buffer, bp, offset + bp - patt->prefix_length, length, patt, &matchend)) {
1295
+                if(ac_findmatch(buffer, bp, offset + bp - patt->prefix_length, length, patt, &matchend, root->ac_opts)) {
1296 1296
                     while(pt) {
1297 1297
                         if(pt->partno > mdata->min_partno)
1298 1298
                             break;
... ...
@@ -1561,19 +1572,23 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex
1561 1561
     }
1562 1562
 
1563 1563
     if (sigopts) {
1564
-	i = 0;
1565
-	while (sigopts[i] != '\0') {
1566
-	    switch (sigopts[i]) {
1567
-	    case 'i':
1568
-		nocase = 1;
1569
-		break;
1570
-	    default:
1571
-		cli_errmsg("cli_ac_addsig: Signature for %s uses invalid option: %02x\n", virname, sigopts[i]);
1572
-		return CL_EMALFDB;
1573
-	    }
1564
+        i = 0;
1565
+        while (sigopts[i] != '\0') {
1566
+            switch (sigopts[i]) {
1567
+            case 'i':
1568
+                if (!(root->ac_opts & AC_OPTION_NOCASE)) {
1569
+                    cli_errmsg("cli_ac_addsig: Signature for %s using nocase cannot be added to case-sensitive AC trie\n", virname);
1570
+                    return CL_EMALFDB;
1571
+                }
1572
+                nocase = 1;
1573
+                break;
1574
+            default:
1575
+                cli_errmsg("cli_ac_addsig: Signature for %s uses invalid option: %02x\n", virname, sigopts[i]);
1576
+                return CL_EMALFDB;
1577
+            }
1574 1578
 
1575
-	    i++;
1576
-	}
1579
+            i++;
1580
+        }
1577 1581
     }
1578 1582
 
1579 1583
     if((new = (struct cli_ac_patt *) mpool_calloc(root->mempool, 1, sizeof(struct cli_ac_patt))) == NULL)
... ...
@@ -1881,6 +1896,8 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex
1881 1881
 
1882 1882
     /* setting nocase match */
1883 1883
     if (nocase) {
1884
+	new->nocase = 1;
1885
+
1884 1886
 	for (i = 0; i < new->length; ++i)
1885 1887
 	    if ((new->pattern[i] & CLI_MATCH_METADATA) == CLI_MATCH_CHAR)
1886 1888
 		new->pattern[i] += CLI_MATCH_NOCASE;
... ...
@@ -30,9 +30,14 @@
30 30
 
31 31
 #define AC_CH_MAXDIST 32
32 32
 
33
+/* AC scanning modes */
33 34
 #define AC_SCAN_VIR 1
34 35
 #define AC_SCAN_FT  2
35 36
 
37
+/* AC trie options */
38
+#define AC_OPTION_NOOPTS 0x0
39
+#define AC_OPTION_NOCASE 0x1
40
+
36 41
 struct cli_ac_data {
37 42
     int32_t ***offmatrix;
38 43
     uint32_t partsigs, lsigs, reloffsigs;
... ...
@@ -69,6 +74,7 @@ struct cli_ac_patt {
69 69
     uint32_t offdata[4], offset_min, offset_max;
70 70
     uint32_t boundary;
71 71
     uint8_t depth;
72
+    uint8_t nocase;
72 73
 };
73 74
 
74 75
 struct cli_ac_node {
... ...
@@ -96,7 +102,7 @@ int cli_ac_chklsig(const char *expr, const char *end, uint32_t *lsigcnt, unsigne
96 96
 void cli_ac_freedata(struct cli_ac_data *data);
97 97
 int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, void **customdata, struct cli_ac_result **res, const struct cli_matcher *root, struct cli_ac_data *mdata, uint32_t offset, cli_file_t ftype, struct cli_matched_type **ftoffset, unsigned int mode, cli_ctx *ctx);
98 98
 int cli_ac_buildtrie(struct cli_matcher *root);
99
-int cli_ac_init(struct cli_matcher *root, uint8_t mindepth, uint8_t maxdepth, uint8_t dconf_prefiltering);
99
+int cli_ac_init(struct cli_matcher *root, uint8_t mindepth, uint8_t maxdepth, uint8_t dconf_prefiltering, uint8_t ac_opts);
100 100
 int cli_ac_caloff(const struct cli_matcher *root, struct cli_ac_data *data, const struct cli_target_info *info);
101 101
 void cli_ac_free(struct cli_matcher *root);
102 102
 int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hexsig, const char *sigopts, uint32_t sigid, uint16_t parts, uint16_t partno, uint16_t rtype, uint16_t type, uint32_t mindist, uint32_t maxdist, const char *offset, const uint32_t *lsigid, unsigned int options);
... ...
@@ -110,7 +110,7 @@ struct cli_matcher {
110 110
     struct filter *filter;
111 111
 
112 112
     uint16_t maxpatlen;
113
-    uint8_t ac_nocase, ac_only;
113
+    uint8_t ac_opts, ac_only;
114 114
 
115 115
     /* Perl-Compiled Regular Expressions */
116 116
 #if HAVE_PCRE
... ...
@@ -442,7 +442,7 @@ int cli_initroots(struct cl_engine *engine, unsigned int options)
442 442
 		root->ac_only = 1;
443 443
 
444 444
 	    cli_dbgmsg("Initialising AC pattern matcher of root[%d]\n", i);
445
-	    if((ret = cli_ac_init(root, engine->ac_mindepth, engine->ac_maxdepth, engine->dconf->other&OTHER_CONF_PREFILTERING))) {
445
+	    if((ret = cli_ac_init(root, engine->ac_mindepth, engine->ac_maxdepth, engine->dconf->other&OTHER_CONF_PREFILTERING, 0))) {
446 446
 		/* no need to free previously allocated memory here */
447 447
 		cli_errmsg("cli_initroots: Can't initialise AC pattern matcher\n");
448 448
 		return ret;
... ...
@@ -270,7 +270,7 @@ int init_regex_list(struct regex_matcher* matcher, uint8_t dconf_prefiltering)
270 270
 	matcher->suffixes.mempool = mp;
271 271
 	assert(mp && "mempool must be initialized");
272 272
 #endif
273
-	if((rc = cli_ac_init(&matcher->suffixes, 2, 32, dconf_prefiltering))) {
273
+	if((rc = cli_ac_init(&matcher->suffixes, 2, 32, dconf_prefiltering, 0))) {
274 274
 		return rc;
275 275
 	}
276 276
 #ifdef USE_MPOOL
... ...
@@ -94,7 +94,7 @@ START_TEST (test_ac_scanbuff) {
94 94
 #ifdef USE_MPOOL
95 95
     root->mempool = mpool_create();
96 96
 #endif
97
-    ret = cli_ac_init(root, CLI_DEFAULT_AC_MINDEPTH, CLI_DEFAULT_AC_MAXDEPTH, 1);
97
+    ret = cli_ac_init(root, CLI_DEFAULT_AC_MINDEPTH, CLI_DEFAULT_AC_MAXDEPTH, 1, 0);
98 98
     fail_unless(ret == CL_SUCCESS, "cli_ac_init() failed");
99 99
 
100 100
 
... ...
@@ -164,7 +164,7 @@ START_TEST (test_ac_scanbuff_allscan) {
164 164
 #ifdef USE_MPOOL
165 165
     root->mempool = mpool_create();
166 166
 #endif
167
-    ret = cli_ac_init(root, CLI_DEFAULT_AC_MINDEPTH, CLI_DEFAULT_AC_MAXDEPTH, 1);
167
+    ret = cli_ac_init(root, CLI_DEFAULT_AC_MINDEPTH, CLI_DEFAULT_AC_MAXDEPTH, 1, 0);
168 168
     fail_unless(ret == CL_SUCCESS, "cli_ac_init() failed");
169 169
 
170 170