Browse code

libclamav: improve handling of signature offsets

Tomasz Kojm authored on 2009/08/14 21:38:13
Showing 15 changed files
... ...
@@ -1,3 +1,7 @@
1
+Fri Aug 14 14:37:21 CEST 2009 (tk)
2
+----------------------------------
3
+ * libclamav: improve handling of signature offsets
4
+
1 5
 Tue Aug 11 02:04:54 CEST 2009 (acab)
2 6
 ------------------------------------
3 7
  * libclamav/7z/Types.h: workaround "Byte" clash in lzma/7z (bb#805 - regression)
... ...
@@ -25,6 +25,11 @@
25 25
 #define CLI_DEFAULT_AC_MAXDEPTH	    3
26 26
 #define CLI_DEFAULT_AC_TRACKLEN	    8
27 27
 
28
+#define CLI_DEFAULT_MOVETOAC_LEN    8 /* all static sigs shorter than
29
+				       * this value will automatically
30
+				       * go to AC instead of BM
31
+				       */
32
+
28 33
 #define CLI_DEFAULT_LSIG_BUFSIZE    32768
29 34
 #define CLI_DEFAULT_DBIO_BUFSIZE    CLI_DEFAULT_LSIG_BUFSIZE + 1
30 35
 
... ...
@@ -176,7 +176,7 @@ cli_file_t cli_filetype2(int desc, const struct cl_engine *engine)
176 176
 	if(cli_ac_initdata(&mdata, root->ac_partsigs, root->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN))
177 177
 	    return ret;
178 178
 
179
-	sret = cli_ac_scanbuff(buff, bread, NULL, NULL, NULL, engine->root[0], &mdata, 0, ret, desc, NULL, AC_SCAN_FT, NULL);
179
+	sret = cli_ac_scanbuff(buff, bread, NULL, NULL, NULL, engine->root[0], &mdata, 0, ret, NULL, AC_SCAN_FT, NULL);
180 180
 
181 181
 	cli_ac_freedata(&mdata);
182 182
 
... ...
@@ -188,7 +188,7 @@ cli_file_t cli_filetype2(int desc, const struct cl_engine *engine)
188 188
 
189 189
 	    decoded = (unsigned char *) cli_utf16toascii((char *) buff, bread);
190 190
 	    if(decoded) {
191
-		sret = cli_ac_scanbuff(decoded, strlen((char *) decoded), NULL, NULL, NULL,  engine->root[0], &mdata, 0, CL_TYPE_TEXT_ASCII, desc, NULL, AC_SCAN_FT, NULL);
191
+		sret = cli_ac_scanbuff(decoded, strlen((char *) decoded), NULL, NULL, NULL,  engine->root[0], &mdata, 0, CL_TYPE_TEXT_ASCII, NULL, AC_SCAN_FT, NULL);
192 192
 		free(decoded);
193 193
 		if(sret == CL_TYPE_HTML)
194 194
 		    ret = CL_TYPE_HTML_UTF16;
... ...
@@ -221,7 +221,7 @@ cli_file_t cli_filetype2(int desc, const struct cl_engine *engine)
221 221
 					    return ret;
222 222
 
223 223
 				    if(out_area.length > 0) {
224
-					    sret = cli_ac_scanbuff(decodedbuff, out_area.length, NULL, NULL, NULL, engine->root[0], &mdata, 0, 0, desc, NULL, AC_SCAN_FT, NULL); /* FIXME: can we use CL_TYPE_TEXT_ASCII instead of 0? */
224
+					    sret = cli_ac_scanbuff(decodedbuff, out_area.length, NULL, NULL, NULL, engine->root[0], &mdata, 0, 0, NULL, AC_SCAN_FT, NULL); /* FIXME: can we use CL_TYPE_TEXT_ASCII instead of 0? */
225 225
 					    if(sret == CL_TYPE_HTML) {
226 226
 						    cli_dbgmsg("cli_filetype2: detected HTML signature in Unicode file\n");
227 227
 						    /* htmlnorm is able to handle any unicode now, since it skips null chars */
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2007-2008 Sourcefire, Inc.
2
+ *  Copyright (C) 2007-2009 Sourcefire, Inc.
3 3
  *
4 4
  *  Authors: Tomasz Kojm
5 5
  *
... ...
@@ -386,8 +386,6 @@ void cli_ac_free(struct cli_matcher *root)
386 386
 	patt = root->ac_pattable[i];
387 387
 	mpool_free(root->mempool, patt->prefix ? patt->prefix : patt->pattern);
388 388
 	mpool_free(root->mempool, patt->virname);
389
-	if(patt->offset)
390
-	    mpool_free(root->mempool, patt->offset);
391 389
 	if(patt->alt)
392 390
 	    mpool_ac_free_alt(root->mempool, patt);
393 391
 	mpool_free(root->mempool, patt);
... ...
@@ -395,6 +393,9 @@ void cli_ac_free(struct cli_matcher *root)
395 395
     if(root->ac_pattable)
396 396
 	mpool_free(root->mempool, root->ac_pattable);
397 397
 
398
+    if(root->ac_reloff)
399
+	mpool_free(root->mempool, root->ac_reloff);
400
+
398 401
     for(i = 0; i < root->ac_nodes; i++) {
399 402
 	if(!IS_LEAF(root->ac_nodetable[i]))
400 403
 	    mpool_free(root->mempool, root->ac_nodetable[i]->trans);
... ...
@@ -812,6 +813,31 @@ int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint32_t lsigs,
812 812
     return CL_SUCCESS;
813 813
 }
814 814
 
815
+int cli_ac_caloff(struct cli_matcher *root, int fd)
816
+{
817
+	int ret;
818
+	unsigned int i;
819
+	struct cli_ac_patt *patt;
820
+	struct cli_target_info info;
821
+
822
+    memset(&info, 0, sizeof(info));
823
+    for(i = 0; i < root->ac_reloff_num; i++) {
824
+	patt = root->ac_reloff[i];
825
+	if(fd == -1) {
826
+	    patt->offset_min = CLI_OFF_NONE;
827
+	} else if((ret = cli_caloff(NULL, &info, fd, root->type, patt->offdata, &patt->offset_min, &patt->offset_max))) {
828
+	    cli_errmsg("cli_ac_caloff: Can't calculate relative offset in signature for %s\n", patt->virname);
829
+	    if(info.exeinfo.section)
830
+		free(info.exeinfo.section);
831
+	    return ret;
832
+	}
833
+    }
834
+    if(info.exeinfo.section)
835
+	free(info.exeinfo.section);
836
+
837
+    return CL_SUCCESS;
838
+}
839
+
815 840
 void cli_ac_freedata(struct cli_ac_data *data)
816 841
 {
817 842
 	uint32_t i;
... ...
@@ -867,7 +893,7 @@ inline static int ac_addtype(struct cli_matched_type **list, cli_file_t type, of
867 867
     return CL_SUCCESS;
868 868
 }
869 869
 
870
-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, int fd, struct cli_matched_type **ftoffset, unsigned int mode, const cli_ctx *ctx)
870
+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, const cli_ctx *ctx)
871 871
 {
872 872
 	struct cli_ac_node *current;
873 873
 	struct cli_ac_patt *patt, *pt;
... ...
@@ -875,11 +901,9 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
875 875
 	uint16_t j;
876 876
 	int32_t **offmatrix;
877 877
 	uint8_t found;
878
-	struct cli_target_info info;
879 878
 	int type = CL_CLEAN;
880 879
 	struct cli_ac_result *newres;
881 880
 
882
-
883 881
     if(!root->ac_root)
884 882
 	return CL_CLEAN;
885 883
 
... ...
@@ -888,7 +912,6 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
888 888
 	return CL_ENULLARG;
889 889
     }
890 890
 
891
-    memset(&info, 0, sizeof(info));
892 891
     current = root->ac_root;
893 892
 
894 893
     for(i = 0; i < length; i++)  {
... ...
@@ -902,24 +925,44 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
902 902
 	    patt = current->list;
903 903
 	    while(patt) {
904 904
 		bp = i + 1 - patt->depth;
905
-		if(ac_findmatch(buffer, bp, length, patt, &matchend)) {
906
-		    pt = patt;
905
+		pt = patt;
906
+		/*
907
+		while(pt) {
908
+		    if((pt->type && !(mode & AC_SCAN_FT)) || (!pt->type && !(mode & AC_SCAN_VIR))) {
909
+			pt = pt->next_same;
910
+			continue;
911
+		    }
912
+		    if(pt->offset_min == CLI_OFF_NONE) {
913
+			pt = pt->next_same;
914
+			continue;
915
+		    }
916
+		    realoff = offset + bp - pt->prefix_length;
917
+		    if(pt->offset_min != CLI_OFF_ANY && (!pt->sigid || pt->partno == 1)) {
918
+			if(pt->offset_max > realoff || pt->offset_min < realoff) {
919
+			    pt = pt->next_same;
920
+			    continue;
921
+			}
922
+		    }
923
+		    break;
924
+		}
925
+		*/
926
+		if(pt && ac_findmatch(buffer, bp, length, patt, &matchend)) {
907 927
 		    while(pt) {
908
-
909 928
 			if((pt->type && !(mode & AC_SCAN_FT)) || (!pt->type && !(mode & AC_SCAN_VIR))) {
910 929
 			    pt = pt->next_same;
911 930
 			    continue;
912 931
 			}
913
-
932
+			if(pt->offset_min == CLI_OFF_NONE) {
933
+			    pt = pt->next_same;
934
+			    continue;
935
+			}
914 936
 			realoff = offset + bp - pt->prefix_length;
915
-
916
-			if(pt->offset && (!pt->sigid || pt->partno == 1)) {
917
-			    if(!cli_validatesig(ftype, pt->offset, realoff, &info, fd, pt->virname)) {
937
+			if(pt->offset_min != CLI_OFF_ANY && (!pt->sigid || pt->partno == 1)) {
938
+			    if(pt->offset_max > realoff || pt->offset_min < realoff) {
918 939
 				pt = pt->next_same;
919 940
 				continue;
920 941
 			    }
921 942
 			}
922
-
923 943
 			if(pt->sigid) { /* it's a partial signature */
924 944
 
925 945
 			    if(pt->partno != 1 && (!mdata->offmatrix[pt->sigid - 1] || !mdata->offmatrix[pt->sigid - 1][pt->partno - 2][0])) {
... ...
@@ -931,8 +974,6 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
931 931
 				mdata->offmatrix[pt->sigid - 1] = cli_malloc(pt->parts * sizeof(int32_t *));
932 932
 				if(!mdata->offmatrix[pt->sigid - 1]) {
933 933
 				    cli_errmsg("cli_ac_scanbuff: Can't allocate memory for mdata->offmatrix[%u]\n", pt->sigid - 1);
934
-				    if(info.exeinfo.section)
935
-					free(info.exeinfo.section);
936 934
 				    return CL_EMEM;
937 935
 				}
938 936
 
... ...
@@ -941,8 +982,6 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
941 941
 				    cli_errmsg("cli_ac_scanbuff: Can't allocate memory for mdata->offmatrix[%u][0]\n", pt->sigid - 1);
942 942
 				    free(mdata->offmatrix[pt->sigid - 1]);
943 943
 				    mdata->offmatrix[pt->sigid - 1] = NULL;
944
-				    if(info.exeinfo.section)
945
-					free(info.exeinfo.section);
946 944
 				    return CL_EMEM;
947 945
 				}
948 946
 				memset(mdata->offmatrix[pt->sigid - 1][0], -1, pt->parts * (CLI_DEFAULT_AC_TRACKLEN + 1) * sizeof(int32_t));
... ...
@@ -981,25 +1020,17 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
981 981
 			    } else if(found && pt->partno == pt->parts) {
982 982
 				if(pt->type) {
983 983
 
984
-				    if(pt->type == CL_TYPE_IGNORED && (!pt->rtype || ftype == pt->rtype)) {
985
-					if(info.exeinfo.section)
986
-					    free(info.exeinfo.section);
987
-
984
+				    if(pt->type == CL_TYPE_IGNORED && (!pt->rtype || ftype == pt->rtype))
988 985
 					return CL_TYPE_IGNORED;
989
-				    }
990 986
 
991 987
 				    if((pt->type > type || pt->type >= CL_TYPE_SFX || pt->type == CL_TYPE_MSEXE) && (!pt->rtype || ftype == pt->rtype)) {
992 988
 					cli_dbgmsg("Matched signature for file type %s\n", pt->virname);
993 989
 					type = pt->type;
994 990
 					if(ftoffset && (!*ftoffset || (*ftoffset)->cnt < MAX_EMBEDDED_OBJ || type == CL_TYPE_ZIPSFX) && (type >= CL_TYPE_SFX || ((ftype == CL_TYPE_MSEXE || ftype == CL_TYPE_ZIP || ftype == CL_TYPE_MSOLE2) && type == CL_TYPE_MSEXE)))  {
995 991
 					    /* FIXME: we don't know which offset of the first part is the correct one */
996
-					    for(j = 1; j <= CLI_DEFAULT_AC_TRACKLEN && offmatrix[0][j] != -1; j++) {
997
-						if(ac_addtype(ftoffset, type, offmatrix[pt->parts - 1][j], ctx)) {
998
-						    if(info.exeinfo.section)
999
-							free(info.exeinfo.section);
992
+					    for(j = 1; j <= CLI_DEFAULT_AC_TRACKLEN && offmatrix[0][j] != -1; j++)
993
+						if(ac_addtype(ftoffset, type, offmatrix[pt->parts - 1][j], ctx))
1000 994
 						    return CL_EMEM;
1001
-						}
1002
-					    }
1003 995
 					}
1004 996
 
1005 997
 					memset(offmatrix[0], -1, pt->parts * (CLI_DEFAULT_AC_TRACKLEN + 1) * sizeof(int32_t));
... ...
@@ -1016,11 +1047,8 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
1016 1016
 
1017 1017
 				    if(res) {
1018 1018
 					newres = (struct cli_ac_result *) malloc(sizeof(struct cli_ac_result));
1019
-					if(!newres) {
1020
-					    if(info.exeinfo.section)
1021
-						free(info.exeinfo.section);
1019
+					if(!newres)
1022 1020
 					    return CL_EMEM;
1023
-					}
1024 1021
 					newres->virname = pt->virname;
1025 1022
 					newres->customdata = pt->customdata;
1026 1023
 					newres->next = *res;
... ...
@@ -1033,10 +1061,6 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
1033 1033
 					    *virname = pt->virname;
1034 1034
 					if(customdata)
1035 1035
 					    *customdata = pt->customdata;
1036
-
1037
-					if(info.exeinfo.section)
1038
-					    free(info.exeinfo.section);
1039
-
1040 1036
 					return CL_VIRUS;
1041 1037
 				    }
1042 1038
 				}
... ...
@@ -1044,22 +1068,16 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
1044 1044
 
1045 1045
 			} else { /* old type signature */
1046 1046
 			    if(pt->type) {
1047
-				if(pt->type == CL_TYPE_IGNORED && (!pt->rtype || ftype == pt->rtype)) {
1048
-				    if(info.exeinfo.section)
1049
-					free(info.exeinfo.section);
1050
-
1047
+				if(pt->type == CL_TYPE_IGNORED && (!pt->rtype || ftype == pt->rtype))
1051 1048
 				    return CL_TYPE_IGNORED;
1052
-				}
1049
+
1053 1050
 				if((pt->type > type || pt->type >= CL_TYPE_SFX || pt->type == CL_TYPE_MSEXE) && (!pt->rtype || ftype == pt->rtype)) {
1054 1051
 				    cli_dbgmsg("Matched signature for file type %s at %u\n", pt->virname, realoff);
1055 1052
 				    type = pt->type;
1056 1053
 				    if(ftoffset && (!*ftoffset || (*ftoffset)->cnt < MAX_EMBEDDED_OBJ || type == CL_TYPE_ZIPSFX) && (type >= CL_TYPE_SFX || ((ftype == CL_TYPE_MSEXE || ftype == CL_TYPE_ZIP || ftype == CL_TYPE_MSOLE2) && type == CL_TYPE_MSEXE)))  {
1057 1054
 
1058
-					if(ac_addtype(ftoffset, type, realoff, ctx)) {
1059
-					    if(info.exeinfo.section)
1060
-						free(info.exeinfo.section);
1055
+					if(ac_addtype(ftoffset, type, realoff, ctx))
1061 1056
 					    return CL_EMEM;
1062
-					}
1063 1057
 				    }
1064 1058
 				}
1065 1059
 			    } else {
... ...
@@ -1071,11 +1089,8 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
1071 1071
 
1072 1072
 				if(res) {
1073 1073
 				    newres = (struct cli_ac_result *) malloc(sizeof(struct cli_ac_result));
1074
-				    if(!newres) {
1075
-					if(info.exeinfo.section)
1076
-					    free(info.exeinfo.section);
1074
+				    if(!newres)
1077 1075
 					return CL_EMEM;
1078
-				    }
1079 1076
 				    newres->virname = pt->virname;
1080 1077
 				    newres->customdata = pt->customdata;
1081 1078
 				    newres->next = *res;
... ...
@@ -1088,10 +1103,6 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
1088 1088
 					*virname = pt->virname;
1089 1089
 				    if(customdata)
1090 1090
 					*customdata = pt->customdata;
1091
-
1092
-				    if(info.exeinfo.section)
1093
-					free(info.exeinfo.section);
1094
-
1095 1091
 				    return CL_VIRUS;
1096 1092
 				}
1097 1093
 			    }
... ...
@@ -1104,9 +1115,6 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
1104 1104
 	}
1105 1105
     }
1106 1106
 
1107
-    if(info.exeinfo.section)
1108
-	free(info.exeinfo.section);
1109
-
1110 1107
     return (mode & AC_SCAN_FT) ? type : CL_CLEAN;
1111 1108
 }
1112 1109
 
... ...
@@ -1445,26 +1453,32 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex
1445 1445
     if(new->lsigid[0])
1446 1446
 	root->ac_lsigtable[new->lsigid[1]]->virname = new->virname;
1447 1447
 
1448
-    if(offset) {
1449
-	new->offset = cli_mpool_strdup(root->mempool, offset);
1450
-	if(!new->offset) {
1451
-	    mpool_free(root->mempool, new->prefix ? new->prefix : new->pattern);
1452
-	    mpool_ac_free_alt(root->mempool, new);
1453
-	    mpool_free(root->mempool, new->virname);
1454
-	    mpool_free(root->mempool, new);
1455
-	    return CL_EMEM;
1456
-	}
1448
+    ret = cli_caloff(offset, NULL, -1, root->type, new->offdata, &new->offset_min, &new->offset_max);
1449
+    if(ret != CL_SUCCESS) {
1450
+	mpool_free(root->mempool, new->prefix ? new->prefix : new->pattern);
1451
+	mpool_ac_free_alt(root->mempool, new);
1452
+	mpool_free(root->mempool, new->virname);
1453
+	mpool_free(root->mempool, new);
1454
+	return ret;
1457 1455
     }
1458 1456
 
1459 1457
     if((ret = cli_ac_addpatt(root, new))) {
1460 1458
 	mpool_free(root->mempool, new->prefix ? new->prefix : new->pattern);
1461 1459
 	mpool_free(root->mempool, new->virname);
1462 1460
 	mpool_ac_free_alt(root->mempool, new);
1463
-	if(new->offset)
1464
-	    mpool_free(root->mempool, new->offset);
1465 1461
 	mpool_free(root->mempool, new);
1466 1462
 	return ret;
1467 1463
     }
1468 1464
 
1465
+    if(new->offdata[0] != CLI_OFF_ANY && new->offdata[0] != CLI_OFF_ABSOLUTE) {
1466
+	root->ac_reloff = (struct cli_ac_patt **) mpool_realloc2(root->mempool, root->ac_reloff, (root->ac_reloff_num + 1) * sizeof(struct cli_ac_patt *));
1467
+	if(!root->ac_reloff) {
1468
+	    cli_errmsg("cli_ac_addsig: Can't allocate memory for root->ac_reloff\n");
1469
+	    return CL_EMEM;
1470
+	}
1471
+	root->ac_reloff[root->ac_reloff_num] = new;
1472
+	root->ac_reloff_num++;
1473
+    }
1474
+
1469 1475
     return CL_SUCCESS;
1470 1476
 }
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2007-2008 Sourcefire, Inc.
2
+ *  Copyright (C) 2007-2009 Sourcefire, Inc.
3 3
  *
4 4
  *  Authors: Tomasz Kojm
5 5
  *
... ...
@@ -50,7 +50,7 @@ struct cli_ac_patt {
50 50
     uint32_t sigid;
51 51
     uint32_t lsigid[3];
52 52
     uint16_t ch[2];
53
-    char *virname, *offset;
53
+    char *virname;
54 54
     void *customdata;
55 55
     uint16_t ch_mindist[2];
56 56
     uint16_t ch_maxdist[2];
... ...
@@ -59,6 +59,7 @@ struct cli_ac_patt {
59 59
     struct cli_ac_patt *next, *next_same;
60 60
     uint8_t depth;
61 61
     uint16_t rtype, type;
62
+    uint32_t offdata[4], offset_min, offset_max;
62 63
 };
63 64
 
64 65
 struct cli_ac_node {
... ...
@@ -81,9 +82,10 @@ int cli_ac_addpatt(struct cli_matcher *root, struct cli_ac_patt *pattern);
81 81
 int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint32_t lsigs, uint8_t tracklen);
82 82
 int cli_ac_chklsig(const char *expr, const char *end, uint32_t *lsigcnt, unsigned int *cnt, uint64_t *ids, unsigned int parse_only);
83 83
 void cli_ac_freedata(struct cli_ac_data *data);
84
-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, int fd, struct cli_matched_type **ftoffset, unsigned int mode, const cli_ctx *ctx);
84
+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, const cli_ctx *ctx);
85 85
 int cli_ac_buildtrie(struct cli_matcher *root);
86 86
 int cli_ac_init(struct cli_matcher *root, uint8_t mindepth, uint8_t maxdepth);
87
+int cli_ac_caloff(struct cli_matcher *root, int fd);
87 88
 void cli_ac_free(struct cli_matcher *root);
88 89
 int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hexsig, 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);
89 90
 
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2007-2008 Sourcefire, Inc.
2
+ *  Copyright (C) 2007-2009 Sourcefire, Inc.
3 3
  *
4 4
  *  Authors: Tomasz Kojm
5 5
  *
... ...
@@ -38,11 +38,12 @@
38 38
 #define BM_BLOCK_SIZE	3
39 39
 #define HASH(a,b,c) (211 * a + 37 * b + c)
40 40
 
41
-int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern)
41
+int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern, const char *offset)
42 42
 {
43 43
 	uint16_t idx, i;
44 44
 	const unsigned char *pt = pattern->pattern;
45 45
 	struct cli_bm_patt *prev, *next = NULL;
46
+	int ret;
46 47
 
47 48
 
48 49
     if(pattern->length < BM_MIN_LENGTH) {
... ...
@@ -50,6 +51,13 @@ int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern)
50 50
 	return CL_EMALFDB;
51 51
     }
52 52
 
53
+    if((ret = cli_caloff(offset, NULL, -1, root->type, pattern->offdata, &pattern->offset_min, &pattern->offset_max))) {
54
+	cli_errmsg("cli_bm_addpatt: Can't calculate offset for signature %s\n", pattern->virname);
55
+	return ret;
56
+    }
57
+    if(pattern->offdata[0] != CLI_OFF_ANY && pattern->offdata[0] != CLI_OFF_ABSOLUTE)
58
+	root->bm_reloff_num++;
59
+
53 60
 #if BM_MIN_LENGTH == BM_BLOCK_SIZE
54 61
     /* try to load balance bm_suffix (at the cost of bm_shift) */
55 62
     for(i = 0; i < pattern->length - BM_BLOCK_SIZE + 1; i++) {
... ...
@@ -137,8 +145,6 @@ void cli_bm_free(struct cli_matcher *root)
137 137
 		    mpool_free(root->mempool, prev->pattern);
138 138
 		if(prev->virname)
139 139
 		    mpool_free(root->mempool, prev->virname);
140
-		if(prev->offset)
141
-		    mpool_free(root->mempool, prev->offset);
142 140
 		mpool_free(root->mempool, prev);
143 141
 	    }
144 142
 	}
... ...
@@ -146,7 +152,7 @@ void cli_bm_free(struct cli_matcher *root)
146 146
     }
147 147
 }
148 148
 
149
-int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, cli_file_t ftype, int fd)
149
+int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, int fd)
150 150
 {
151 151
 	uint32_t i, j, off;
152 152
 	uint8_t found, pchain, shift;
... ...
@@ -154,7 +160,8 @@ int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
154 154
 	struct cli_bm_patt *p;
155 155
 	const unsigned char *bp, *pt;
156 156
 	unsigned char prefix;
157
-	struct cli_target_info info;
157
+        struct cli_target_info info;
158
+        int ret;
158 159
 
159 160
 
160 161
     if(!root || !root->bm_shift)
... ...
@@ -164,7 +171,6 @@ int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
164 164
 	return CL_CLEAN;
165 165
 
166 166
     memset(&info, 0, sizeof(info));
167
-
168 167
     for(i = BM_MIN_LENGTH - BM_BLOCK_SIZE; i < length - BM_BLOCK_SIZE + 1; ) {
169 168
 	idx = HASH(buffer[i], buffer[i + 1], buffer[i + 2]);
170 169
 	shift = root->bm_shift[idx];
... ...
@@ -214,21 +220,26 @@ int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
214 214
 		}
215 215
 
216 216
 		if(found && p->length + p->prefix_length == j) {
217
-
218
-		    if(p->offset) {
217
+		    if(p->offset_min != CLI_OFF_ANY) {
218
+			if(p->offdata[0] != CLI_OFF_ABSOLUTE) {
219
+			    ret = cli_caloff(NULL, &info, fd, root->type, p->offdata, &p->offset_min, &p->offset_max);
220
+			    if(ret != CL_SUCCESS) {
221
+				cli_errmsg("cli_bm_scanbuff: Can't calculate relative offset in signature for %s\n", p->virname);
222
+				if(info.exeinfo.section)
223
+				    free(info.exeinfo.section);
224
+				return ret;
225
+			    }
226
+			}
219 227
 			off = offset + i - p->prefix_length - BM_MIN_LENGTH + BM_BLOCK_SIZE;
220
-			if(!cli_validatesig(ftype, p->offset, off, &info, fd, p->virname)) {
228
+			if(p->offset_max > off || p->offset_min < off) {
221 229
 			    p = p->next;
222 230
 			    continue;
223 231
 			}
224 232
 		    }
225
-
226 233
 		    if(virname)
227 234
 			*virname = p->virname;
228
-
229 235
 		    if(info.exeinfo.section)
230 236
 			free(info.exeinfo.section);
231
-
232 237
 		    return CL_VIRUS;
233 238
 		}
234 239
 
... ...
@@ -243,6 +254,5 @@ int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
243 243
 
244 244
     if(info.exeinfo.section)
245 245
 	free(info.exeinfo.section);
246
-
247 246
     return CL_CLEAN;
248 247
 }
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2007-2008 Sourcefire, Inc.
2
+ *  Copyright (C) 2007-2009 Sourcefire, Inc.
3 3
  *
4 4
  *  Authors: Tomasz Kojm
5 5
  *
... ...
@@ -27,17 +27,17 @@
27 27
 
28 28
 struct cli_bm_patt {
29 29
     unsigned char *pattern, *prefix;
30
-    char *virname, *offset;
30
+    char *virname;
31
+    uint32_t offdata[4], offset_min, offset_max;
31 32
     struct cli_bm_patt *next;
32 33
     uint16_t length, prefix_length;
33 34
     uint16_t cnt;
34 35
     unsigned char pattern0;
35
-    uint8_t target;
36 36
 };
37 37
 
38
-int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern);
38
+int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern, const char *offset);
39 39
 int cli_bm_init(struct cli_matcher *root);
40
-int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, cli_file_t ftype, int fd);
40
+int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, int fd);
41 41
 void cli_bm_free(struct cli_matcher *root);
42 42
 
43 43
 #endif
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2007-2008 Sourcefire, Inc.
2
+ *  Copyright (C) 2007-2009 Sourcefire, Inc.
3 3
  *
4 4
  *  Authors: Tomasz Kojm
5 5
  *
... ...
@@ -76,8 +76,8 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset,
76 76
 	if(!acdata && (ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
77 77
 	    return ret;
78 78
 
79
-	if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, troot, offset, ftype, -1)) != CL_VIRUS)
80
-	    ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, troot, acdata ? (acdata[0]) : (&mdata), offset, ftype, -1, NULL, AC_SCAN_VIR, NULL);
79
+	if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, troot, offset, -1)) != CL_VIRUS)
80
+	    ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, troot, acdata ? (acdata[0]) : (&mdata), offset, ftype, NULL, AC_SCAN_VIR, NULL);
81 81
 
82 82
 	if(!acdata)
83 83
 	    cli_ac_freedata(&mdata);
... ...
@@ -89,8 +89,8 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset,
89 89
     if(!acdata && (ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
90 90
 	return ret;
91 91
 
92
-    if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, groot, offset, ftype, -1)) != CL_VIRUS)
93
-	ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, groot, acdata ? (acdata[1]) : (&mdata), offset, ftype, -1, NULL, AC_SCAN_VIR, NULL);
92
+    if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, groot, offset, -1)) != CL_VIRUS)
93
+	ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, groot, acdata ? (acdata[1]) : (&mdata), offset, ftype, NULL, AC_SCAN_VIR, NULL);
94 94
 
95 95
     if(!acdata)
96 96
 	cli_ac_freedata(&mdata);
... ...
@@ -98,112 +98,188 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset,
98 98
     return ret;
99 99
 }
100 100
 
101
-off_t cli_caloff(const char *offstr, struct cli_target_info *info, int fd, cli_file_t ftype, int *ret, unsigned int *maxshift)
101
+/*
102
+ * offdata[0]: type
103
+ * offdata[1]: offset value
104
+ * offdata[2]: max shift
105
+ * offdata[3]: section number
106
+ */
107
+int cli_caloff(const char *offstr, struct cli_target_info *info, int fd, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max)
102 108
 {
103 109
 	int (*einfo)(int, struct cli_exe_info *) = NULL;
110
+	char offcpy[65];
104 111
 	unsigned int n, val;
105
-	const char *pt;
106
-	off_t pos, offset;
107
-
108
-
109
-    *ret = 0;
112
+	char *pt;
113
+	off_t pos;
114
+	struct stat sb;
110 115
 
111
-    if((pt = strchr(offstr, ',')))
112
-	*maxshift = atoi(++pt);
113 116
 
114
-    if(isdigit(offstr[0]))
115
-	return atoi(offstr);
117
+    if(!info) { /* decode offset string */
118
+	if(!offstr) {
119
+	    cli_errmsg("cli_caloff: offstr == NULL\n");
120
+	    return CL_ENULLARG;
121
+	}
116 122
 
117
-    if(fd == -1) {
118
-	*ret = -1;
119
-	return 0;
120
-    }
123
+	if(!strcmp(offstr, "*")) {
124
+	    offdata[0] = *offset_max = *offset_min = CLI_OFF_ANY;
125
+	    return CL_SUCCESS;
126
+	}
121 127
 
122
-    if(!strncmp(offstr, "EP", 2) || offstr[0] == 'S') {
128
+	if(strlen(offstr) > 64) {
129
+	    cli_errmsg("cli_caloff: Offset string too long\n");
130
+	    return CL_EMALFDB;
131
+	}
132
+	strcpy(offcpy, offstr);
123 133
 
124
-	if(info->status == -1) {
125
-	    *ret = -1;
126
-	    return 0;
134
+	if((pt = strchr(offcpy, ','))) {
135
+	    if(!cli_isnumber(pt + 1)) {
136
+		cli_errmsg("cli_caloff: Invalid offset shift value\n");
137
+		return CL_EMALFDB;
138
+	    }
139
+	    offdata[2] = atoi(pt + 1);
140
+	    *pt = 0;
141
+	} else {
142
+	    offdata[2] = 0;
143
+	}
127 144
 
128
-	} else if(!info->status) {
145
+	*offset_max = *offset_min = CLI_OFF_NONE;
129 146
 
130
-	    if(ftype == CL_TYPE_MSEXE)
131
-		einfo = cli_peheader;
132
-	    else if(ftype == CL_TYPE_ELF)
133
-		einfo = cli_elfheader;
134
-	    else if(ftype == CL_TYPE_MACHO)
135
-		einfo = cli_machoheader;
147
+	if(!strncmp(offcpy, "EP+", 3) || !strncmp(offcpy, "EP-", 3)) {
148
+	    if(offcpy[2] == '+')
149
+		offdata[0] = CLI_OFF_EP_PLUS;
150
+	    else
151
+		offdata[0] = CLI_OFF_EP_MINUS;
136 152
 
137
-	    if(einfo) {
138
-		if((pos = lseek(fd, 0, SEEK_CUR)) == -1) {
139
-		    cli_dbgmsg("Invalid descriptor\n");
140
-		    info->status = *ret = -1;
141
-		    return 0;
153
+	    if(!cli_isnumber(&offcpy[3])) {
154
+		cli_errmsg("cli_caloff: Invalid offset value\n");
155
+		return CL_EMALFDB;
156
+	    }
157
+	    offdata[1] = atoi(&offcpy[3]);
158
+
159
+	} else if(offcpy[0] == 'S') {
160
+	    if(!strncmp(offstr, "SL+", 3)) {
161
+		offdata[0] = CLI_OFF_SL_PLUS;
162
+		if(!cli_isnumber(&offcpy[3])) {
163
+		    cli_errmsg("cli_caloff: Invalid offset value\n");
164
+		    return CL_EMALFDB;
142 165
 		}
166
+		offdata[1] = atoi(&offcpy[3]);
167
+
168
+	    } else if(sscanf(offcpy, "S%u+%u", &n, &val) == 2) {
169
+		offdata[0] = CLI_OFF_SX_PLUS;
170
+		offdata[1] = val;
171
+		offdata[3] = n;
172
+	    } else {
173
+		cli_errmsg("cli_caloff: Invalid offset string\n");
174
+		return CL_EMALFDB;
175
+	    }
143 176
 
144
-		lseek(fd, 0, SEEK_SET);
145
-		if(einfo(fd, &info->exeinfo)) {
146
-		    lseek(fd, pos, SEEK_SET);
147
-		    info->status = *ret = -1;
148
-		    return 0;
149
-		}
150
-		lseek(fd, pos, SEEK_SET);
151
-		info->status = 1;
177
+	} else if(!strncmp(offcpy, "EOF-", 4)) {
178
+	    offdata[0] = CLI_OFF_EOF_MINUS;
179
+	    if(!cli_isnumber(&offcpy[4])) {
180
+		cli_errmsg("cli_caloff: Invalid offset value\n");
181
+		return CL_EMALFDB;
152 182
 	    }
183
+	    offdata[1] = atoi(&offcpy[4]);
184
+	} else {
185
+	    offdata[0] = CLI_OFF_ABSOLUTE;
186
+	    if(!cli_isnumber(offcpy)) {
187
+		cli_errmsg("cli_caloff: Invalid offset value\n");
188
+		return CL_EMALFDB;
189
+	    }
190
+	    *offset_min = offdata[1] = atoi(offcpy);
191
+	    *offset_max = *offset_min + offdata[2];
153 192
 	}
154
-    }
155
-
156
-    if(info->status == 1 && (!strncmp(offstr, "EP+", 3) || !strncmp(offstr, "EP-", 3))) {
157
-
158
-	if(offstr[2] == '+')
159
-	    return info->exeinfo.ep + atoi(offstr + 3);
160
-	else
161
-	    return info->exeinfo.ep - atoi(offstr + 3);
162 193
 
163
-    } else if(info->status == 1 && offstr[0] == 'S') {
194
+	if(offdata[0] != CLI_OFF_ANY && offdata[0] != CLI_OFF_ABSOLUTE && offdata[0] != CLI_OFF_EOF_MINUS) {
195
+	    if(target != 1 && target != 6 && target != 9) {
196
+		cli_errmsg("cli_caloff: Invalid offset type for target %u\n", target);
197
+		return CL_EMALFDB;
198
+	    }
199
+	}
164 200
 
165
-	if(!strncmp(offstr, "SL", 2) && info->exeinfo.section[info->exeinfo.nsections - 1].rsz) {
201
+    } else {
202
+	/* calculate relative offsets */
203
+	if(info->status == -1) {
204
+	    *offset_min = *offset_max = 0;
205
+	    return CL_SUCCESS;
206
+	}
166 207
 
167
-	    if(sscanf(offstr, "SL+%u", &val) != 1) {
168
-		*ret = -1;
169
-		return 0;
208
+	if((offdata[0] == CLI_OFF_EOF_MINUS)) {
209
+	    if(!info->fsize) {
210
+		if(fstat(fd, &sb) == -1) {
211
+		    cli_errmsg("cli_caloff: fstat(%d) failed\n", fd);
212
+		    return CL_ESTAT;
213
+		}
214
+		info->fsize = sb.st_size;
170 215
 	    }
171 216
 
172
-	    offset = val + info->exeinfo.section[info->exeinfo.nsections - 1].raw;
173
-
174
-	} else {
217
+	} else if(!info->status) {
218
+	    if(target == 1)
219
+		einfo = cli_peheader;
220
+	    else if(target == 6)
221
+		einfo = cli_elfheader;
222
+	    else if(target == 9)
223
+		einfo = cli_machoheader;
175 224
 
176
-	    if(sscanf(offstr, "S%u+%u", &n, &val) != 2) {
177
-		*ret = -1;
178
-		return 0;
225
+	    if(!einfo) {
226
+		cli_errmsg("cli_caloff: Invalid offset/filetype\n");
227
+		return CL_EMALFDB;
179 228
 	    }
180 229
 
181
-	    if(n >= info->exeinfo.nsections || !info->exeinfo.section[n].rsz) {
182
-		*ret = -1;
183
-		return 0;
230
+	    if((pos = lseek(fd, 0, SEEK_CUR)) == -1) {
231
+		cli_errmsg("cli_caloff: lseek(%d) failed\n", fd);
232
+		return CL_ESEEK;
184 233
 	    }
185 234
 
186
-	    offset = val + info->exeinfo.section[n].raw;
235
+	    lseek(fd, 0, SEEK_SET);
236
+	    if(einfo(fd, &info->exeinfo)) {
237
+		/* einfo *may* fail */
238
+		lseek(fd, pos, SEEK_SET);
239
+		info->status = -1;
240
+		*offset_min = *offset_max = 0;
241
+		return CL_SUCCESS;
242
+	    }
243
+	    lseek(fd, pos, SEEK_SET);
244
+	    info->status = 1;
187 245
 	}
188 246
 
189
-	return offset;
247
+	switch(offdata[0]) {
248
+	    case CLI_OFF_EOF_MINUS:
249
+		*offset_min = info->fsize - offdata[1];
250
+		break;
190 251
 
191
-    } else if(!strncmp(offstr, "EOF-", 4)) {
192
-	    struct stat sb;
252
+	    case CLI_OFF_EP_PLUS:
253
+		*offset_min = info->exeinfo.ep + offdata[1];
254
+		break;
193 255
 
194
-	if(!info->fsize) {
195
-	    if(fstat(fd, &sb) == -1) {
196
-		info->status = *ret = -1;
197
-		return 0;
198
-	    }
199
-	    info->fsize = sb.st_size;
256
+	    case CLI_OFF_EP_MINUS:
257
+		*offset_min = info->exeinfo.ep - offdata[1];
258
+		break;
259
+
260
+	    case CLI_OFF_SL_PLUS:
261
+		*offset_min = info->exeinfo.section[info->exeinfo.nsections - 1].raw + offdata[1];
262
+		break;
263
+
264
+	    case CLI_OFF_SX_PLUS:
265
+		if(offdata[3] >= info->exeinfo.nsections)
266
+		    *offset_min = 0;
267
+		else
268
+		    *offset_min = info->exeinfo.section[offdata[3]].raw + offdata[1];
269
+		break;
270
+
271
+	    default:
272
+		cli_errmsg("cli_caloff: Not a relative offset (type: %u)\n", offdata[0]);
273
+		return CL_EARG;
200 274
 	}
201 275
 
202
-	return info->fsize - atoi(offstr + 4);
276
+	if(!*offset_min)
277
+	    *offset_max = 0;
278
+	else
279
+	    *offset_max = *offset_min + offdata[2];
203 280
     }
204 281
 
205
-    *ret = -1;
206
-    return 0;
282
+    return CL_SUCCESS;
207 283
 }
208 284
 
209 285
 int cli_checkfp(int fd, cli_ctx *ctx)
... ...
@@ -227,7 +303,7 @@ int cli_checkfp(int fd, cli_ctx *ctx)
227 227
 	    return 0;
228 228
 	}
229 229
 
230
-	if(cli_bm_scanbuff(digest, 16, &virname, ctx->engine->md5_fp, 0, 0, -1) == CL_VIRUS) {
230
+	if(cli_bm_scanbuff(digest, 16, &virname, ctx->engine->md5_fp, 0, -1) == CL_VIRUS) {
231 231
 	    cli_dbgmsg("cli_checkfp(): Found false positive detection (fp sig: %s)\n", virname);
232 232
 	    free(digest);
233 233
 	    lseek(fd, pos, SEEK_SET);
... ...
@@ -240,33 +316,6 @@ int cli_checkfp(int fd, cli_ctx *ctx)
240 240
     return 0;
241 241
 }
242 242
 
243
-int cli_validatesig(cli_file_t ftype, const char *offstr, off_t fileoff, struct cli_target_info *info, int desc, const char *virname)
244
-{
245
-	off_t offset;
246
-	int ret;
247
-	unsigned int maxshift = 0;
248
-
249
-
250
-    if(offstr) {
251
-	offset = cli_caloff(offstr, info, desc, ftype, &ret, &maxshift);
252
-
253
-	if(ret == -1)
254
-	    return 0;
255
-
256
-	if(maxshift) {
257
-	    if((fileoff < offset) || (fileoff > offset + (off_t) maxshift)) {
258
-		/* cli_dbgmsg("Signature offset: %lu, expected: [%lu..%lu] (%s)\n", (unsigned long int) fileoff, (unsigned long int) offset, (unsigned long int) (offset + maxshift), virname); */
259
-		return 0;
260
-	    }
261
-	} else if(fileoff != offset) {
262
-	    /* cli_dbgmsg("Signature offset: %lu, expected: %lu (%s)\n", (unsigned long int) fileoff, (unsigned long int) offset, virname); */
263
-	    return 0;
264
-	}
265
-    }
266
-
267
-    return 1;
268
-}
269
-
270 243
 int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode)
271 244
 {
272 245
  	unsigned char *buffer, *buff, *endbl, *upt;
... ...
@@ -316,12 +365,16 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc
316 316
 	return CL_EMEM;
317 317
     }
318 318
 
319
-    if(!ftonly && (ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
320
-	return ret;
319
+    if(!ftonly)
320
+	if((ret = cli_ac_caloff(groot, desc)) || (ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
321
+	    return ret;
321 322
 
322 323
     if(troot) {
323
-	if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
324
+	if((ret = cli_ac_caloff(troot, desc)) || (ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN))) {
325
+	    if(!ftonly)
326
+		cli_ac_freedata(&gdata);
324 327
 	    return ret;
328
+	}
325 329
     }
326 330
 
327 331
     if(!ftonly && ctx->engine->md5_hdb)
... ...
@@ -344,8 +397,8 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc
344 344
 	    length += maxpatlen;
345 345
 
346 346
 	if(troot) {
347
-	    if(troot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, troot, offset, ftype, desc)) != CL_VIRUS)
348
-		ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, troot, &tdata, offset, ftype, desc, ftoffset, acmode, NULL);
347
+	    if(troot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, troot, offset, desc)) != CL_VIRUS)
348
+		ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, troot, &tdata, offset, ftype, ftoffset, acmode, NULL);
349 349
 
350 350
 	    if(ret == CL_VIRUS) {
351 351
 		free(buffer);
... ...
@@ -361,8 +414,8 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc
361 361
 	}
362 362
 
363 363
 	if(!ftonly) {
364
-	    if(groot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, groot, offset, ftype, desc)) != CL_VIRUS)
365
-		ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, groot, &gdata, offset, ftype, desc, ftoffset, acmode, NULL);
364
+	    if(groot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, groot, offset, desc)) != CL_VIRUS)
365
+		ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, groot, &gdata, offset, ftype, ftoffset, acmode, NULL);
366 366
 
367 367
 	    if(ret == CL_VIRUS) {
368 368
 		free(buffer);
... ...
@@ -439,7 +492,7 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc
439 439
 
440 440
     if(!ftonly && ctx->engine->md5_hdb) {
441 441
 	cli_md5_final(digest, &md5ctx);
442
-	if(cli_bm_scanbuff(digest, 16, ctx->virname, ctx->engine->md5_hdb, 0, 0, -1) == CL_VIRUS && (cli_bm_scanbuff(digest, 16, NULL, ctx->engine->md5_fp, 0, 0, -1) != CL_VIRUS))
442
+	if(cli_bm_scanbuff(digest, 16, ctx->virname, ctx->engine->md5_hdb, 0, -1) == CL_VIRUS && (cli_bm_scanbuff(digest, 16, NULL, ctx->engine->md5_fp, 0, -1) != CL_VIRUS))
443 443
 	    return CL_VIRUS;
444 444
     }
445 445
 
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2007-2008 Sourcefire, Inc.
2
+ *  Copyright (C) 2007-2009 Sourcefire, Inc.
3 3
  *
4 4
  *  Authors: Tomasz Kojm
5 5
  *
... ...
@@ -69,18 +69,22 @@ struct cli_ac_lsig {
69 69
 };
70 70
 
71 71
 struct cli_matcher {
72
+    unsigned int type;
73
+
72 74
     /* Extended Boyer-Moore */
73 75
     uint8_t *bm_shift;
74 76
     struct cli_bm_patt **bm_suffix;
75 77
     struct cli_hashset md5_sizes_hs;
76 78
     uint32_t *soff, soff_len; /* for PE section sigs */
77
-    uint32_t bm_patterns;
79
+    uint32_t bm_patterns, bm_reloff_num;
78 80
 
79 81
     /* Extended Aho-Corasick */
80 82
     uint32_t ac_partsigs, ac_nodes, ac_patterns, ac_lsigs;
81 83
     struct cli_ac_lsig **ac_lsigtable;
82 84
     struct cli_ac_node *ac_root, **ac_nodetable;
83 85
     struct cli_ac_patt **ac_pattable;
86
+    struct cli_ac_patt **ac_reloff;
87
+    uint32_t ac_reloff_num;
84 88
     uint8_t ac_mindepth, ac_maxdepth;
85 89
 
86 90
     uint16_t maxpatlen;
... ...
@@ -124,13 +128,20 @@ struct cli_target_info {
124 124
     int8_t status; /* 0 == not initialised, 1 == initialised OK, -1 == error */
125 125
 };
126 126
 
127
+#define CLI_OFF_ANY         0xffffffff
128
+#define CLI_OFF_NONE	    0xfffffffe
129
+#define CLI_OFF_ABSOLUTE    1
130
+#define CLI_OFF_EOF_MINUS   2
131
+#define CLI_OFF_EP_PLUS     3
132
+#define CLI_OFF_EP_MINUS    4
133
+#define CLI_OFF_SL_PLUS     5
134
+#define CLI_OFF_SX_PLUS     6
135
+
127 136
 int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, cli_ctx *ctx, cli_file_t ftype, struct cli_ac_data **acdata);
128 137
 
129 138
 int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode);
130 139
 
131
-int cli_validatesig(cli_file_t ftype, const char *offstr, off_t fileoff, struct cli_target_info *info, int desc, const char *virname);
132
-
133
-off_t cli_caloff(const char *offstr, struct cli_target_info *info, int fd, cli_file_t ftype, int *ret, unsigned int *maxshift);
140
+int cli_caloff(const char *offstr, struct cli_target_info *info, int fd, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max);
134 141
 
135 142
 int cli_checkfp(int fd, cli_ctx *ctx);
136 143
 
... ...
@@ -928,8 +928,8 @@ int cli_scanpe(int desc, cli_ctx *ctx)
928 928
 		for(j = 0; j < md5_sect->soff_len && md5_sect->soff[j] <= exe_sections[i].rsz; j++) {
929 929
 		    if(md5_sect->soff[j] == exe_sections[i].rsz) {
930 930
 			unsigned char md5_dig[16];
931
-			if(cli_md5sect(desc, &exe_sections[i], md5_dig) && cli_bm_scanbuff(md5_dig, 16, ctx->virname, ctx->engine->md5_mdb, 0, 0, -1) == CL_VIRUS) {
932
-			    if(cli_bm_scanbuff(md5_dig, 16, NULL, ctx->engine->md5_fp, 0, 0, -1) != CL_VIRUS) {
931
+			if(cli_md5sect(desc, &exe_sections[i], md5_dig) && cli_bm_scanbuff(md5_dig, 16, ctx->virname, ctx->engine->md5_mdb, 0, -1) == CL_VIRUS) {
932
+			    if(cli_bm_scanbuff(md5_dig, 16, NULL, ctx->engine->md5_fp, 0, -1) != CL_VIRUS) {
933 933
 
934 934
 				free(section_hdr);
935 935
 				free(exe_sections);
... ...
@@ -1198,13 +1198,13 @@ static int hash_match(const struct regex_matcher *rlist, const char *host, size_
1198 1198
 	    h[64]='\0';
1199 1199
 	    cli_dbgmsg("Looking up hash %s for %s(%u)%s(%u)\n", h, host, (unsigned)hlen, path, (unsigned)plen);
1200 1200
 	    if (prefix_matched) {
1201
-		if (cli_bm_scanbuff(sha256_dig, 4, &virname, &rlist->hostkey_prefix,0,0,-1) == CL_VIRUS) {
1201
+		if (cli_bm_scanbuff(sha256_dig, 4, &virname, &rlist->hostkey_prefix,0,-1) == CL_VIRUS) {
1202 1202
 		    cli_dbgmsg("prefix matched\n");
1203 1203
 		    *prefix_matched = 1;
1204 1204
 		} else
1205 1205
 		    return CL_SUCCESS;
1206 1206
 	    }
1207
-	    if (cli_bm_scanbuff(sha256_dig, 32, &virname, &rlist->sha256_hashes,0,0,-1) == CL_VIRUS) {
1207
+	    if (cli_bm_scanbuff(sha256_dig, 32, &virname, &rlist->sha256_hashes,0,-1) == CL_VIRUS) {
1208 1208
 		cli_dbgmsg("This hash matched: %s\n", h);
1209 1209
 		switch(*virname) {
1210 1210
 		    case 'W':
... ...
@@ -120,10 +120,11 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex
120 120
 	struct cli_bm_patt *bm_new;
121 121
 	char *pt, *hexcpy, *start, *n;
122 122
 	int ret, asterisk = 0;
123
-	unsigned int i, j, len, parts = 0;
123
+	unsigned int i, j, hexlen, parts = 0;
124 124
 	int mindist = 0, maxdist = 0, error = 0;
125 125
 
126 126
 
127
+    hexlen = strlen(hexsig);
127 128
     if(strchr(hexsig, '{')) {
128 129
 
129 130
 	root->ac_partsigs++;
... ...
@@ -131,8 +132,7 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex
131 131
 	if(!(hexcpy = cli_strdup(hexsig)))
132 132
 	    return CL_EMEM;
133 133
 
134
-	len = strlen(hexsig);
135
-	for(i = 0; i < len; i++)
134
+	for(i = 0; i < hexlen; i++)
136 135
 	    if(hexsig[i] == '{' || hexsig[i] == '*')
137 136
 		parts++;
138 137
 
... ...
@@ -224,8 +224,7 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex
224 224
     } else if(strchr(hexsig, '*')) {
225 225
 	root->ac_partsigs++;
226 226
 
227
-	len = strlen(hexsig);
228
-	for(i = 0; i < len; i++)
227
+	for(i = 0; i < hexlen; i++)
229 228
 	    if(hexsig[i] == '*')
230 229
 		parts++;
231 230
 
... ...
@@ -247,7 +246,7 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex
247 247
 	    free(pt);
248 248
 	}
249 249
 
250
-    } else if(root->ac_only || strpbrk(hexsig, "?(") || type || lsigid) {
250
+    } else if(root->ac_only || type || lsigid /* || (hexlen / 2 < CLI_DEFAULT_MOVETOAC_LEN) FIXME: unit tests */ ||  strpbrk(hexsig, "?(")) {
251 251
 	if((ret = cli_ac_addsig(root, virname, hexsig, 0, 0, 0, rtype, type, 0, 0, offset, lsigid, options))) {
252 252
 	    cli_errmsg("cli_parse_add(): Problem adding signature (3).\n");
253 253
 	    return ret;
... ...
@@ -262,7 +261,7 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex
262 262
 	    mpool_free(root->mempool, bm_new);
263 263
 	    return CL_EMALFDB;
264 264
 	}
265
-	bm_new->length = strlen(hexsig) / 2;
265
+	bm_new->length = hexlen / 2;
266 266
 
267 267
 	bm_new->virname = cli_mpool_virname(root->mempool, (char *) virname, options & CL_DB_OFFICIAL);
268 268
 	if(!bm_new->virname) {
... ...
@@ -271,22 +270,10 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex
271 271
 	    return CL_EMEM;
272 272
 	}
273 273
 
274
-	if(offset) {
275
-	    bm_new->offset = cli_mpool_strdup(root->mempool, offset);
276
-	    if(!bm_new->offset) {
277
-	        mpool_free(root->mempool, bm_new->pattern);
278
-		mpool_free(root->mempool, bm_new->virname);
279
-		mpool_free(root->mempool, bm_new);
280
-		return CL_EMEM;
281
-	    }
282
-	}
283
-
284
-	bm_new->target = target;
285
-
286 274
 	if(bm_new->length > root->maxpatlen)
287 275
 	    root->maxpatlen = bm_new->length;
288 276
 
289
-	if((ret = cli_bm_addpatt(root, bm_new))) {
277
+	if((ret = cli_bm_addpatt(root, bm_new, offset))) {
290 278
 	    cli_errmsg("cli_parse_add(): Problem adding signature (4).\n");
291 279
 	    mpool_free(root->mempool, bm_new->pattern);
292 280
 	    mpool_free(root->mempool, bm_new->virname);
... ...
@@ -308,14 +295,14 @@ static int cli_initroots(struct cl_engine *engine, unsigned int options)
308 308
 	if(!engine->root[i]) {
309 309
 	    cli_dbgmsg("Initializing engine->root[%d]\n", i);
310 310
 	    root = engine->root[i] = (struct cli_matcher *) mpool_calloc(engine->mempool, 1, sizeof(struct cli_matcher));
311
-#ifdef USE_MPOOL
312
-	    root->mempool = engine->mempool;
313
-#endif
314 311
 	    if(!root) {
315 312
 		cli_errmsg("cli_initroots: Can't allocate memory for cli_matcher\n");
316 313
 		return CL_EMEM;
317 314
 	    }
318
-
315
+#ifdef USE_MPOOL
316
+	    root->mempool = engine->mempool;
317
+#endif
318
+	    root->type = i;
319 319
 	    if(cli_mtargets[i].ac_only || engine->ac_only)
320 320
 		root->ac_only = 1;
321 321
 
... ...
@@ -511,7 +498,7 @@ static int cli_loaddb(FILE *fs, struct cl_engine *engine, unsigned int *signo, u
511 511
 
512 512
 	if(*pt == '=') continue;
513 513
 
514
-	if((ret = cli_parse_add(root, start, pt, 0, 0, NULL, 0, NULL, options))) {
514
+	if((ret = cli_parse_add(root, start, pt, 0, 0, "*", 0, NULL, options))) {
515 515
 	    ret = CL_EMALFDB;
516 516
 	    break;
517 517
 	}
... ...
@@ -576,27 +563,6 @@ static int cli_loadpdb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
576 576
     return CL_SUCCESS;
577 577
 }
578 578
 
579
-static int cli_checkoffset(const char *offset, unsigned int type)
580
-{
581
-	unsigned int foo;
582
-	const char *pt = offset;
583
-
584
-    if(isdigit(*offset)) {
585
-	while(*pt++)
586
-	    if(!strchr("0123456789,", *pt))
587
-		return 1;
588
-	return 0;
589
-    }
590
-
591
-    if(!strncmp(offset, "EOF-", 4))
592
-	return 0;
593
-
594
-    if((type == 1 || type == 6 || type == 9) && (!strncmp(offset, "EP+", 3) || !strncmp(offset, "EP-", 3) || (sscanf(offset, "SL+%u", &foo) == 1) || (sscanf(offset, "S%u+%u", &foo, &foo) == 2)))
595
-	return 0;
596
-
597
-    return 1;
598
-}
599
-
600 579
 #define NDB_TOKENS 6
601 580
 static int cli_loadndb(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned short sdb, unsigned int options, struct cli_dbio *dbio, const char *dbname)
602 581
 {
... ...
@@ -680,15 +646,6 @@ static int cli_loadndb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
680 680
 	root = engine->root[target];
681 681
 
682 682
 	offset = tokens[2];
683
-	if(!strcmp(offset, "*"))
684
-	    offset = NULL;
685
-
686
-	if(offset && cli_checkoffset(offset, target)) {
687
-	    cli_errmsg("Incorrect offset '%s' for signature type-%u\n", offset, target);
688
-	    ret = CL_EMALFDB;
689
-	    break;
690
-	}
691
-
692 683
 	sig = tokens[3];
693 684
 
694 685
 	if((ret = cli_parse_add(root, virname, sig, 0, 0, offset, target, NULL, options))) {
... ...
@@ -1025,19 +982,11 @@ static int cli_loadldb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
1025 1025
 		*pt = 0;
1026 1026
 		sig = ++pt;
1027 1027
 		offset = tokens[3 + i];
1028
-		if(!strcmp(offset, "*"))
1029
-		    offset = NULL;
1030 1028
 	    } else {
1031
-		offset = NULL;
1029
+		offset = "*";
1032 1030
 		sig = tokens[3 + i];
1033 1031
 	    }
1034 1032
 
1035
-	    if(offset && cli_checkoffset(offset, tdb.target[0])) {
1036
-		cli_errmsg("Incorrect offset '%s' in subsignature id %u for signature type-%u\n", offset, i, tdb.target[0]);
1037
-		ret = CL_EMALFDB;
1038
-		break;
1039
-	    }
1040
-
1041 1033
 	    if((ret = cli_parse_add(root, virname, sig, 0, 0, offset, target, lsigid, options))) {
1042 1034
 		ret = CL_EMALFDB;
1043 1035
 		break;
... ...
@@ -1131,7 +1080,7 @@ static int cli_loadftm(FILE *fs, struct cl_engine *engine, unsigned int options,
1131 1131
 	}
1132 1132
 
1133 1133
 	if(atoi(tokens[0]) == 1) { /* A-C */
1134
-	    if((ret = cli_parse_add(engine->root[0], tokens[3], tokens[2], rtype, type, strcmp(tokens[1], "*") ? tokens[1] : NULL, 0, NULL, options)))
1134
+	    if((ret = cli_parse_add(engine->root[0], tokens[3], tokens[2], rtype, type, tokens[1], 0, NULL, options)))
1135 1135
 		break;
1136 1136
 
1137 1137
 	} else if(atoi(tokens[0]) == 0) { /* memcmp() */
... ...
@@ -1394,7 +1343,7 @@ static int cli_loadmd5(FILE *fs, struct cl_engine *engine, unsigned int *signo,
1394 1394
 	    MD5_DB;
1395 1395
 	}
1396 1396
 
1397
-	if((ret = cli_bm_addpatt(db, new))) {
1397
+	if((ret = cli_bm_addpatt(db, new, "0"))) {
1398 1398
 	    cli_errmsg("cli_loadmd5: Error adding BM pattern\n");
1399 1399
 	    mpool_free(engine->mempool, new->pattern);
1400 1400
 	    mpool_free(engine->mempool, new->virname);
... ...
@@ -2203,7 +2152,7 @@ int cl_engine_compile(struct cl_engine *engine)
2203 2203
 	if((root = engine->root[i])) {
2204 2204
 	    if((ret = cli_ac_buildtrie(root)))
2205 2205
 		return ret;
2206
-	    cli_dbgmsg("matcher[%u]: %s: AC sigs: %u BM sigs: %u %s\n", i, cli_mtargets[i].name, root->ac_patterns, root->bm_patterns, root->ac_only ? "(ac_only mode)" : "");
2206
+	    cli_dbgmsg("matcher[%u]: %s: AC sigs: %u (reloff: %u) BM sigs: %u (reloff: %u) %s\n", i, cli_mtargets[i].name, root->ac_patterns, root->ac_reloff_num, root->bm_patterns, root->bm_reloff_num, root->ac_only ? "(ac_only mode)" : "");
2207 2207
 	}
2208 2208
     }
2209 2209
 
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2007-2008 Sourcefire, Inc.
2
+ *  Copyright (C) 2007-2009 Sourcefire, Inc.
3 3
  *
4 4
  *  Authors: Tomasz Kojm
5 5
  *
... ...
@@ -305,7 +305,7 @@ int regex_list_match(struct regex_matcher* matcher,char* real_url,const char* di
305 305
 			 * negatives */
306 306
 			return 0;
307 307
 		}
308
-		rc = cli_ac_scanbuff((const unsigned char*)bufrev,buffer_len, NULL, (void*)&regex, &res, &matcher->suffixes,&mdata,0,0,-1,NULL,AC_SCAN_VIR,NULL);
308
+		rc = cli_ac_scanbuff((const unsigned char*)bufrev,buffer_len, NULL, (void*)&regex, &res, &matcher->suffixes,&mdata,0,0,NULL,AC_SCAN_VIR,NULL);
309 309
 		free(bufrev);
310 310
 		cli_ac_freedata(&mdata);
311 311
 
... ...
@@ -455,7 +455,7 @@ static int add_hash(struct regex_matcher *matcher, char* pattern, const char fl,
455 455
 
456 456
 	if (fl != 'W' && pat->length == 32 &&
457 457
 	    cli_hashset_contains(&matcher->sha256_pfx_set, cli_readint32(pat->pattern)) &&
458
-	    cli_bm_scanbuff(pat->pattern, 32, &vname, &matcher->sha256_hashes,0,0,-1) == CL_VIRUS) {
458
+	    cli_bm_scanbuff(pat->pattern, 32, &vname, &matcher->sha256_hashes,0,-1) == CL_VIRUS) {
459 459
 	    if (*vname == 'W') {
460 460
 		/* hash is whitelisted in local.gdb */
461 461
 		cli_dbgmsg("Skipping hash %s\n", pattern);
... ...
@@ -471,7 +471,7 @@ static int add_hash(struct regex_matcher *matcher, char* pattern, const char fl,
471 471
 	}
472 472
 	*pat->virname = fl;
473 473
 	cli_hashset_addkey(&matcher->sha256_pfx_set, cli_readint32(pat->pattern));
474
-	if((rc = cli_bm_addpatt(bm, pat))) {
474
+	if((rc = cli_bm_addpatt(bm, pat, "*"))) {
475 475
 		cli_errmsg("add_hash: failed to add BM pattern\n");
476 476
 		free(pat->pattern);
477 477
 		free(pat->virname);
... ...
@@ -675,7 +675,7 @@ static int add_newsuffix(struct regex_matcher *matcher, struct regex_list *info,
675 675
 	new->partno = 0;
676 676
 	new->mindist = 0;
677 677
 	new->maxdist = 0;
678
-	new->offset = 0;
678
+	new->offset_min = CLI_OFF_ANY;
679 679
 	new->length = len;
680 680
 
681 681
 	new->ch[0] = new->ch[1] |= CLI_MATCH_IGNORE;
... ...
@@ -69,7 +69,7 @@ START_TEST (test_ac_scanbuff) {
69 69
     fail_unless(ret == CL_SUCCESS, "cli_ac_init() failed");
70 70
 
71 71
     for(i = 0; ac_testdata[i].data; i++) {
72
-	ret = cli_parse_add(root, ac_testdata[i].virname, ac_testdata[i].hexsig, 0, 0, NULL, 0, NULL, 0);
72
+	ret = cli_parse_add(root, ac_testdata[i].virname, ac_testdata[i].hexsig, 0, 0, "*", 0, NULL, 0);
73 73
 	fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed");
74 74
     }
75 75
 
... ...
@@ -80,7 +80,7 @@ START_TEST (test_ac_scanbuff) {
80 80
     fail_unless(ret == CL_SUCCESS, "cli_ac_initdata() failed");
81 81
 
82 82
     for(i = 0; ac_testdata[i].data; i++) {
83
-	ret = cli_ac_scanbuff(ac_testdata[i].data, strlen(ac_testdata[i].data), &virname, NULL, NULL, root, &mdata, 0, 0, -1, NULL, AC_SCAN_VIR, NULL);
83
+	ret = cli_ac_scanbuff(ac_testdata[i].data, strlen(ac_testdata[i].data), &virname, NULL, NULL, root, &mdata, 0, 0, NULL, AC_SCAN_VIR, NULL);
84 84
 	fail_unless_fmt(ret == CL_VIRUS, "cli_ac_scanbuff() failed for %s", ac_testdata[i].virname);
85 85
 	fail_unless_fmt(!strncmp(virname, ac_testdata[i].virname, strlen(ac_testdata[i].virname)), "Dataset %u matched with %s", i, virname);
86 86
     }
... ...
@@ -109,14 +109,14 @@ START_TEST (test_bm_scanbuff) {
109 109
     ret = cli_bm_init(root);
110 110
     fail_unless(ret == CL_SUCCESS, "cli_bm_init() failed");
111 111
 
112
-    ret = cli_parse_add(root, "Sig1", "deadbabe", 0, 0, NULL, 0, NULL, 0);
112
+    ret = cli_parse_add(root, "Sig1", "deadbabe", 0, 0, "*", 0, NULL, 0);
113 113
     fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed");
114
-    ret = cli_parse_add(root, "Sig2", "deadbeef", 0, 0, NULL, 0, NULL, 0);
114
+    ret = cli_parse_add(root, "Sig2", "deadbeef", 0, 0, "*", 0, NULL, 0);
115 115
     fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed");
116
-    ret = cli_parse_add(root, "Sig3", "babedead", 0, 0, NULL, 0, NULL, 0);
116
+    ret = cli_parse_add(root, "Sig3", "babedead", 0, 0, "*", 0, NULL, 0);
117 117
     fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed");
118 118
 
119
-    ret = cli_bm_scanbuff("blah\xde\xad\xbe\xef", 12, &virname, root, 0, 0, -1);
119
+    ret = cli_bm_scanbuff("blah\xde\xad\xbe\xef", 12, &virname, root, 0, -1);
120 120
     fail_unless(ret == CL_VIRUS, "cli_bm_scanbuff() failed");
121 121
     fail_unless(!strncmp(virname, "Sig2", 4), "Incorrect signature matched in cli_bm_scanbuff()\n");
122 122
     cli_bm_free(root);