Browse code

readdb: changed signature modifier delimiter from '/' to '::' readdb: moved signature modifier handling from cli_parse_add to loadldb readdb: fixed an issue regarding ';' within pcre subsigs

Kevin Lin authored on 2015/06/06 04:01:44
Showing 1 changed files
... ...
@@ -123,8 +123,9 @@ static int sigopts_handler(struct cli_matcher *root, const char *virname, const
123 123
     char *hexcpy, *start, *end;
124 124
     int i, ret = CL_SUCCESS;
125 125
 
126
-    /* prevent cyclic loops with cli_parse_add on same hexsig
127
-     * cyclic loops should be impossible though
126
+    /*
127
+     * cyclic loops with cli_parse_add are impossible now as cli_parse_add 
128
+     * no longer calls sigopts_handler; leaving here for safety
128 129
      */
129 130
     if (sigopts & ACPATT_OPTION_ONCE) {
130 131
         cli_errmsg("sigopts_handler: invalidly called multiple times!\n");
... ...
@@ -351,7 +352,7 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex
351 351
         return CL_SUCCESS;
352 352
     }
353 353
     if (strrchr(hexsig, '/')) {
354
-        char *start, *end, *sub;
354
+        char *start, *end;
355 355
 
356 356
         /* get copied */
357 357
         hexcpy = cli_strdup(hexsig);
... ...
@@ -362,75 +363,41 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex
362 362
         start = strchr(hexcpy, '/');
363 363
         end = strrchr(hexcpy, '/');
364 364
 
365
-        /* get plus-ed (modifiers) */
366
-        sub = strchr(end, '+');
367
-        if (sub && start == end)
368
-            *end = '\0';
369
-
370 365
         /* get pcre-ed */
371
-        if (!sub && start != end) {
366
+        if (start == end) {
367
+            cli_errmsg("cli_parseadd(): PCRE subsig mismatched '/' delimiter\n");
368
+            return CL_EMALFDB;
369
+        }
372 370
 #if HAVE_PCRE
373
-            /* expected format => ^offset:trigger/regex/[cflags]$ */
374
-            const char *trigger, *pattern, *cflags;
371
+        /* expected format => ^offset:trigger/regex/[cflags]$ */
372
+        const char *trigger, *pattern, *cflags;
375 373
 
376
-            /* get checked */
377
-            if (hexsig[0] == '/') {
378
-                cli_errmsg("cli_parseadd(): PCRE subsig must contain logical trigger\n");
379
-                return CL_EMALFDB;
380
-            }
374
+        /* get checked */
375
+        if (hexsig[0] == '/') {
376
+            cli_errmsg("cli_parseadd(): PCRE subsig must contain logical trigger\n");
377
+            return CL_EMALFDB;
378
+        }
381 379
 
382
-            /* get NULL-ed */
383
-            *start = '\0';
384
-            *end = '\0';
380
+        /* get NULL-ed */
381
+        *start = '\0';
382
+        *end = '\0';
385 383
 
386
-            /* get tokens-ed */
387
-            trigger = hexcpy;
388
-            pattern = start+1;
389
-            cflags = end+1;
390
-            if (*cflags == '\0') /* get compat-ed */
391
-                cflags = NULL;
384
+        /* get tokens-ed */
385
+        trigger = hexcpy;
386
+        pattern = start+1;
387
+        cflags = end+1;
388
+        if (*cflags == '\0') /* get compat-ed */
389
+            cflags = NULL;
392 390
 
393
-            /* normal trigger, get added */
394
-            ret = cli_pcre_addpatt(root, virname, trigger, pattern, cflags, offset, lsigid, options);
395
-            free(hexcpy);
396
-            return ret;
391
+        /* normal trigger, get added */
392
+        ret = cli_pcre_addpatt(root, virname, trigger, pattern, cflags, offset, lsigid, options);
393
+        free(hexcpy);
394
+        return ret;
397 395
 #else
398
-            free(hexcpy);
399
-            cli_errmsg("cli_parseadd(): cannot parse PCRE subsig without PCRE support\n");
400
-            return CL_EPARSE;
396
+        free(hexcpy);
397
+        cli_errmsg("cli_parseadd(): cannot parse PCRE subsig without PCRE support\n");
398
+        return CL_EPARSE;
401 399
 #endif
402
-        } else { /* get option-ed */
403
-            /* get NULL-ed */
404
-            char *opt = sub ? sub : end;
405
-            uint8_t sigopts = 0;
406
-
407
-            *opt++ = '\0';
408
-            while (*opt != '\0') {
409
-                switch (*opt) {
410
-                case 'i':
411
-                    sigopts |= ACPATT_OPTION_NOCASE;
412
-                    break;
413
-                case 'f':
414
-                    sigopts |= ACPATT_OPTION_FULLWORD;
415
-                    break;
416
-                case 'w':
417
-                    sigopts |= ACPATT_OPTION_WIDE;
418
-                    break;
419
-                case 'a':
420
-                    sigopts |= ACPATT_OPTION_ASCII;
421
-                    break;
422
-                default:
423
-                    cli_errmsg("cli_parse_add: Signature for %s uses invalid option: %02x\n", virname, *opt);
424
-                    return CL_EMALFDB;
425
-                }
426
-
427
-                opt++;
428
-            }
429
-
430
-            ret = sigopts_handler(root, virname, hexcpy, sigopts, rtype, type, offset, target, lsigid, options);
431
-            free(hexcpy);
432
-            return ret;
433
-        }
434 400
     }
435 401
     else if((wild = strchr(hexsig, '{'))) {
436 402
         if(sscanf(wild, "%c%u%c", &l, &range, &r) == 3 && l == '{' && r == '}' && range > 0 && range < 128) {
... ...
@@ -1610,25 +1577,55 @@ static inline int init_tdb(struct cli_lsig_tdb *tdb, struct cl_engine *engine, c
1610 1610
 }
1611 1611
 
1612 1612
 /*     0         1        2      3        4        5    ... (max 66)
1613
- * VirusName:Attributes:Logic:SubSig1[:SubSig2[:SubSig3 ... ]]
1613
+ * VirusName;Attributes;Logic;SubSig1[;SubSig2[;SubSig3 ... ]]
1614 1614
  * NOTE: Maximum of 64(see MAX_LDB_SUBSIGS) subsignatures (last would be token 66)
1615 1615
  */
1616 1616
 #define LDB_TOKENS 67
1617
+static int ldb_tokenize(char *buffer, const char **tokens)
1618
+{
1619
+    const size_t token_count = LDB_TOKENS + 1;
1620
+    size_t tokens_found, i;
1621
+    int within_pcre = 0;
1622
+
1623
+    for(tokens_found = 0; tokens_found < token_count; ) {
1624
+        tokens[tokens_found++] = buffer;
1625
+
1626
+        while (*buffer != '\0') {
1627
+            if (!within_pcre && (*buffer == ';'))
1628
+                break;
1629
+            else if ((tokens_found > 2) && (*buffer == '/'))
1630
+                within_pcre = !within_pcre;
1631
+            buffer++;
1632
+        }
1633
+
1634
+        if(*buffer != '\0') {
1635
+            *buffer++ = '\0';
1636
+        } else {
1637
+            i = tokens_found;
1638
+            while(i < token_count)
1639
+                tokens[i++] = NULL;
1640
+            return tokens_found;
1641
+        }
1642
+    }
1643
+    return tokens_found;
1644
+}
1645
+
1617 1646
 static int load_oneldb(char *buffer, int chkpua, struct cl_engine *engine, unsigned int options, const char *dbname, unsigned int line, unsigned int *sigs, unsigned bc_idx, const char *buffer_cpy, int *skip)
1618 1647
 {
1619 1648
     const char *sig, *virname, *offset, *logic;
1620 1649
     struct cli_ac_lsig **newtable, *lsig;
1621
-    char *tokens[LDB_TOKENS+1], *pt, *pt2;
1650
+    char *tokens[LDB_TOKENS+1], *pt, *lsl, *rsl;
1622 1651
     int i, subsigs, tokens_count;
1623 1652
     unsigned short target = 0;
1624 1653
     struct cli_matcher *root;
1625 1654
     struct cli_lsig_tdb tdb;
1626 1655
     uint32_t lsigid[2];
1656
+    uint8_t subsig_opts;
1627 1657
     int ret;
1628 1658
 
1629 1659
     UNUSEDPARAM(dbname);
1630 1660
 
1631
-    tokens_count = cli_strtokenize(buffer, ';', LDB_TOKENS + 1, (const char **) tokens);
1661
+    tokens_count = ldb_tokenize(buffer, (const char **) tokens);
1632 1662
     if(tokens_count < 4) {
1633 1663
         return CL_EMALFDB;
1634 1664
     }
... ...
@@ -1737,22 +1734,59 @@ static int load_oneldb(char *buffer, int chkpua, struct cl_engine *engine, unsig
1737 1737
     tdb.subsigs = subsigs;
1738 1738
 
1739 1739
     for(i = 0; i < subsigs; i++) {
1740
+        subsig_opts = 0;
1741
+
1740 1742
         lsigid[1] = i;
1743
+        offset = "*";
1741 1744
         sig = tokens[3 + i];
1742 1745
 
1743
-        pt2 = strchr(tokens[3 + i], '/');
1744
-        pt = strchr(tokens[3 + i], ':');
1745
-        if(pt && (!pt2 || (pt < pt2))) {
1746
-            *pt = 0;
1747
-            sig = ++pt;
1748
-            offset = tokens[3 + i];
1749
-        } else {
1750
-            offset = "*";
1751
-            sig = tokens[3 + i];
1746
+        /* check for offset and subsig modifiers */
1747
+        pt = tokens[3 + i];
1748
+        lsl = strchr(tokens[3 + i], '/');
1749
+        rsl = strrchr(tokens[3 + i], '/');
1750
+        while((pt = strchr(pt, ':'))) {
1751
+            /* pcre subsig expression */
1752
+            if((lsl && rsl) && (lsl < pt) && (pt <  rsl)) {
1753
+                pt++;
1754
+                continue;
1755
+            }
1756
+
1757
+            *pt++ = 0;
1758
+            if(*pt == ':') { /* signature modifiers */
1759
+                *pt++ = 0;
1760
+                while(*pt != '\0') {
1761
+                    switch(*pt) {
1762
+                    case 'i':
1763
+                        subsig_opts |= ACPATT_OPTION_NOCASE;
1764
+                        break;
1765
+                    case 'f':
1766
+                        subsig_opts |= ACPATT_OPTION_FULLWORD;
1767
+                        break;
1768
+                    case 'w':
1769
+                        subsig_opts |= ACPATT_OPTION_WIDE;
1770
+                        break;
1771
+                    case 'a':
1772
+                        subsig_opts |= ACPATT_OPTION_ASCII;
1773
+                        break;
1774
+                    default:
1775
+                        cli_errmsg("cli_loadldb: Signature for %s uses invalid option: %02x\n", virname, *pt);
1776
+                        return CL_EMALFDB;
1777
+                    }
1778
+
1779
+                    pt++;
1780
+                }
1781
+            } else {
1782
+                sig = pt;
1783
+                offset = tokens[3 + i];
1784
+            }
1752 1785
         }
1753 1786
 
1787
+        if(subsig_opts)
1788
+            ret = sigopts_handler(root, virname, sig, subsig_opts, 0, 0, offset, target, lsigid, options);
1789
+        else
1790
+            ret = cli_parse_add(root, virname, sig, 0, 0, 0, offset, target, lsigid, options);
1754 1791
 
1755
-        if((ret = cli_parse_add(root, virname, sig, 0, 0, 0, offset, target, lsigid, options)))
1792
+        if(ret)
1756 1793
             return ret;
1757 1794
 
1758 1795
         if(sig[0] == '$' && i) {