... | ... |
@@ -69,8 +69,11 @@ Execute update script FILE in current directory. |
69 | 69 |
\fB\-\-verify\-cdiff=FILE, \-r FILE\fR |
70 | 70 |
Verify DIFF against CVD/INCDIR. |
71 | 71 |
.TP |
72 |
-\fB\-l, \-\-list\-sigs\fR |
|
73 |
-List signature names. |
|
72 |
+\fB\-l[FILE], \-\-list\-sigs[=FILE]\fR |
|
73 |
+List all signature names from the local database directory (default) or from FILE. |
|
74 |
+.TP |
|
75 |
+\fB\-fREGEX, \-\-find\-sigs=REGEX\fR |
|
76 |
+Find and display signatures from the local database directory which match the given REGEX. The whole signature body (name, hex string, etc.) is checked. |
|
74 | 77 |
.SH "EXAMPLES" |
75 | 78 |
.LP |
76 | 79 |
.TP |
... | ... |
@@ -106,6 +106,7 @@ const struct clam_option clam_options[] = { |
106 | 106 |
{ NULL, "unpack-current", 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" }, |
107 | 107 |
{ NULL, "info", 'i', TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" }, |
108 | 108 |
{ NULL, "list-sigs", 'l', TYPE_STRING, NULL, -1, DATADIR, 0, OPT_SIGTOOL, "", "" }, |
109 |
+ { NULL, "find-sigs", 'f', TYPE_STRING, NULL, -1, DATADIR, FLAG_REQUIRED, OPT_SIGTOOL, "", "" }, |
|
109 | 110 |
{ NULL, "vba", 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" }, |
110 | 111 |
{ NULL, "vba-hex", 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" }, |
111 | 112 |
{ NULL, "diff", 'd', TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" }, |
... | ... |
@@ -980,15 +980,14 @@ static int cvdinfo(const struct optstruct *opts) |
980 | 980 |
return 0; |
981 | 981 |
} |
982 | 982 |
|
983 |
-static int listdb(const char *filename); |
|
983 |
+static int listdb(const char *filename, const regex_t *regex); |
|
984 | 984 |
|
985 |
-static int listdir(const char *dirname) |
|
985 |
+static int listdir(const char *dirname, const regex_t *regex) |
|
986 | 986 |
{ |
987 | 987 |
DIR *dd; |
988 | 988 |
struct dirent *dent; |
989 | 989 |
char *dbfile; |
990 | 990 |
|
991 |
- |
|
992 | 991 |
if((dd = opendir(dirname)) == NULL) { |
993 | 992 |
mprintf("!listdir: Can't open directory %s\n", dirname); |
994 | 993 |
return -1; |
... | ... |
@@ -1021,7 +1020,7 @@ static int listdir(const char *dirname) |
1021 | 1021 |
} |
1022 | 1022 |
sprintf(dbfile, "%s"PATHSEP"%s", dirname, dent->d_name); |
1023 | 1023 |
|
1024 |
- if(listdb(dbfile) == -1) { |
|
1024 |
+ if(listdb(dbfile, regex) == -1) { |
|
1025 | 1025 |
mprintf("!listdb: Error listing database %s\n", dbfile); |
1026 | 1026 |
free(dbfile); |
1027 | 1027 |
closedir(dd); |
... | ... |
@@ -1036,7 +1035,7 @@ static int listdir(const char *dirname) |
1036 | 1036 |
return 0; |
1037 | 1037 |
} |
1038 | 1038 |
|
1039 |
-static int listdb(const char *filename) |
|
1039 |
+static int listdb(const char *filename, const regex_t *regex) |
|
1040 | 1040 |
{ |
1041 | 1041 |
FILE *fh; |
1042 | 1042 |
char *buffer, *pt, *start, *dir; |
... | ... |
@@ -1086,7 +1085,7 @@ static int listdb(const char *filename) |
1086 | 1086 |
} |
1087 | 1087 |
|
1088 | 1088 |
/* list extracted directory */ |
1089 |
- if(listdir(dir) == -1) { |
|
1089 |
+ if(listdir(dir, regex) == -1) { |
|
1090 | 1090 |
mprintf("!listdb: Can't list directory %s\n", filename); |
1091 | 1091 |
cli_rmdirs(dir); |
1092 | 1092 |
free(dir); |
... | ... |
@@ -1102,6 +1101,11 @@ static int listdb(const char *filename) |
1102 | 1102 |
if(cli_strbcasestr(filename, ".db")) { /* old style database */ |
1103 | 1103 |
|
1104 | 1104 |
while(fgets(buffer, FILEBUFF, fh)) { |
1105 |
+ if(regex) { |
|
1106 |
+ if(!cli_regexec(regex, buffer, 0, NULL, 0)) |
|
1107 |
+ mprintf("%s", buffer); |
|
1108 |
+ continue; |
|
1109 |
+ } |
|
1105 | 1110 |
line++; |
1106 | 1111 |
pt = strchr(buffer, '='); |
1107 | 1112 |
if(!pt) { |
... | ... |
@@ -1123,6 +1127,11 @@ static int listdb(const char *filename) |
1123 | 1123 |
} else if(cli_strbcasestr(filename, ".hdb") || cli_strbcasestr(filename, ".hdu") || cli_strbcasestr(filename, ".mdb") || cli_strbcasestr(filename, ".mdu")) { /* hash database */ |
1124 | 1124 |
|
1125 | 1125 |
while(fgets(buffer, FILEBUFF, fh)) { |
1126 |
+ if(regex) { |
|
1127 |
+ if(!cli_regexec(regex, buffer, 0, NULL, 0)) |
|
1128 |
+ mprintf("%s", buffer); |
|
1129 |
+ continue; |
|
1130 |
+ } |
|
1126 | 1131 |
line++; |
1127 | 1132 |
cli_chomp(buffer); |
1128 | 1133 |
start = cli_strtok(buffer, 2, ":"); |
... | ... |
@@ -1144,6 +1153,11 @@ static int listdb(const char *filename) |
1144 | 1144 |
} else if(cli_strbcasestr(filename, ".ndb") || cli_strbcasestr(filename, ".ndu") || cli_strbcasestr(filename, ".ldb") || cli_strbcasestr(filename, ".ldu") || cli_strbcasestr(filename, ".sdb") || cli_strbcasestr(filename, ".zmd") || cli_strbcasestr(filename, ".rmd")) { |
1145 | 1145 |
|
1146 | 1146 |
while(fgets(buffer, FILEBUFF, fh)) { |
1147 |
+ if(regex) { |
|
1148 |
+ if(!cli_regexec(regex, buffer, 0, NULL, 0)) |
|
1149 |
+ mprintf("%s", buffer); |
|
1150 |
+ continue; |
|
1151 |
+ } |
|
1147 | 1152 |
line++; |
1148 | 1153 |
cli_chomp(buffer); |
1149 | 1154 |
|
... | ... |
@@ -1171,31 +1185,45 @@ static int listdb(const char *filename) |
1171 | 1171 |
return 0; |
1172 | 1172 |
} |
1173 | 1173 |
|
1174 |
-static int listsigs(const struct optstruct *opts) |
|
1174 |
+static int listsigs(const struct optstruct *opts, int mode) |
|
1175 | 1175 |
{ |
1176 | 1176 |
int ret; |
1177 | 1177 |
const char *name; |
1178 | 1178 |
char *dbdir; |
1179 | 1179 |
struct stat sb; |
1180 |
+ regex_t reg; |
|
1180 | 1181 |
|
1181 | 1182 |
|
1182 |
- name = optget(opts, "list-sigs")->strarg; |
|
1183 |
- if(stat(name, &sb) == -1) { |
|
1184 |
- mprintf("--list-sigs: Can't get status of %s\n", name); |
|
1185 |
- return -1; |
|
1186 |
- } |
|
1183 |
+ if(mode == 0) { |
|
1184 |
+ name = optget(opts, "list-sigs")->strarg; |
|
1185 |
+ if(stat(name, &sb) == -1) { |
|
1186 |
+ mprintf("--list-sigs: Can't get status of %s\n", name); |
|
1187 |
+ return -1; |
|
1188 |
+ } |
|
1187 | 1189 |
|
1188 |
- mprintf_stdout = 1; |
|
1189 |
- if(S_ISDIR(sb.st_mode)) { |
|
1190 |
- if(!strcmp(name, DATADIR)) { |
|
1191 |
- dbdir = freshdbdir(); |
|
1192 |
- ret = listdir(dbdir); |
|
1193 |
- free(dbdir); |
|
1190 |
+ mprintf_stdout = 1; |
|
1191 |
+ if(S_ISDIR(sb.st_mode)) { |
|
1192 |
+ if(!strcmp(name, DATADIR)) { |
|
1193 |
+ dbdir = freshdbdir(); |
|
1194 |
+ ret = listdir(dbdir, NULL); |
|
1195 |
+ free(dbdir); |
|
1196 |
+ } else { |
|
1197 |
+ ret = listdir(name, NULL); |
|
1198 |
+ } |
|
1194 | 1199 |
} else { |
1195 |
- ret = listdir(name); |
|
1200 |
+ ret = listdb(name, NULL); |
|
1196 | 1201 |
} |
1202 |
+ |
|
1197 | 1203 |
} else { |
1198 |
- ret = listdb(name); |
|
1204 |
+ if(cli_regcomp(®, optget(opts, "find-sigs")->strarg, REG_EXTENDED | REG_NOSUB) != 0) { |
|
1205 |
+ mprintf("--find-sigs: Can't compile regex\n"); |
|
1206 |
+ return -1; |
|
1207 |
+ } |
|
1208 |
+ mprintf_stdout = 1; |
|
1209 |
+ dbdir = freshdbdir(); |
|
1210 |
+ ret = listdir(dbdir, ®); |
|
1211 |
+ free(dbdir); |
|
1212 |
+ cli_regfree(®); |
|
1199 | 1213 |
} |
1200 | 1214 |
|
1201 | 1215 |
return ret; |
... | ... |
@@ -1798,6 +1826,7 @@ static void help(void) |
1798 | 1798 |
mprintf(" --unpack=FILE -u FILE Unpack a CVD/CLD file\n"); |
1799 | 1799 |
mprintf(" --unpack-current=SHORTNAME Unpack local CVD/CLD into cwd\n"); |
1800 | 1800 |
mprintf(" --list-sigs[=FILE] -l[FILE] List signature names\n"); |
1801 |
+ mprintf(" --find-sigs=REGEX -fREGEX Find signatures matching REGEX\n"); |
|
1801 | 1802 |
mprintf(" --vba=FILE Extract VBA/Word6 macro code\n"); |
1802 | 1803 |
mprintf(" --vba-hex=FILE Extract Word6 macro code with hex values\n"); |
1803 | 1804 |
mprintf(" --diff=OLD NEW -d OLD NEW Create diff for OLD and NEW CVDs\n"); |
... | ... |
@@ -1860,7 +1889,9 @@ int main(int argc, char **argv) |
1860 | 1860 |
else if(optget(opts, "info")->enabled) |
1861 | 1861 |
ret = cvdinfo(opts); |
1862 | 1862 |
else if(optget(opts, "list-sigs")->active) |
1863 |
- ret = listsigs(opts); |
|
1863 |
+ ret = listsigs(opts, 0); |
|
1864 |
+ else if(optget(opts, "find-sigs")->active) |
|
1865 |
+ ret = listsigs(opts, 1); |
|
1864 | 1866 |
else if(optget(opts, "vba")->enabled || optget(opts, "vba-hex")->enabled) |
1865 | 1867 |
ret = vbadump(opts); |
1866 | 1868 |
else if(optget(opts, "diff")->enabled) |