git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@667 77e5149b-7576-45b1-b177-96237e5ba77b
Tomasz Kojm authored on 2004/07/13 12:30:49... | ... |
@@ -85,15 +85,25 @@ struct cli_patt { |
85 | 85 |
struct cli_patt *next; |
86 | 86 |
}; |
87 | 87 |
|
88 |
-struct cl_node { |
|
88 |
+struct cli_ac_node { |
|
89 | 89 |
char islast; |
90 | 90 |
struct cli_patt *list; |
91 |
- struct cl_node *trans[CL_NUM_CHILDS], *fail; |
|
91 |
+ struct cli_ac_node *trans[CL_NUM_CHILDS], *fail; |
|
92 |
+}; |
|
92 | 93 |
|
93 |
- /* FIXME: these variables are only used in a root node */ |
|
94 |
+struct cli_md5_node { |
|
95 |
+ char *virname, *viralias, *md5; |
|
96 |
+ struct cli_md5_node *next; |
|
97 |
+}; |
|
98 |
+ |
|
99 |
+struct cl_node { |
|
100 |
+ /* Aho-Corasick */ |
|
101 |
+ struct cli_ac_node *ac_root, **nodetable; |
|
94 | 102 |
unsigned int maxpatlen, partsigs; |
95 | 103 |
unsigned int nodes; |
96 |
- struct cl_node **nodetable; |
|
104 |
+ |
|
105 |
+ /* MD5 */ |
|
106 |
+ struct cli_md5_node *hlist[256]; |
|
97 | 107 |
}; |
98 | 108 |
|
99 | 109 |
struct cl_limits { |
... | ... |
@@ -167,15 +177,6 @@ extern int cl_mbox(const char *dir, int desc); |
167 | 167 |
/* compute MD5 message digest from file (compatible with md5sum(1)) */ |
168 | 168 |
extern char *cl_md5file(const char *filename); |
169 | 169 |
|
170 |
-/* decode hexadecimal string */ |
|
171 |
-extern short int *cl_hex2str(const char *hex); |
|
172 |
- |
|
173 |
-/* encode a buffer 'string' length of 'len' to a hexadecimal string */ |
|
174 |
-extern char *cl_str2hex(const char *string, unsigned int len); |
|
175 |
- |
|
176 |
-/* generate a pseudo-random number */ |
|
177 |
-extern unsigned int cl_rndnum(unsigned int max); |
|
178 |
- |
|
179 | 170 |
/* generate unique file name in temporary directory */ |
180 | 171 |
char *cl_gentemp(const char *dir); |
181 | 172 |
|
... | ... |
@@ -39,27 +39,27 @@ |
39 | 39 |
|
40 | 40 |
int cli_addpatt(struct cl_node *root, struct cli_patt *pattern) |
41 | 41 |
{ |
42 |
- struct cl_node *pos, *next; |
|
42 |
+ struct cli_ac_node *pos, *next; |
|
43 | 43 |
int i; |
44 | 44 |
|
45 | 45 |
if(pattern->length < CL_MIN_LENGTH) { |
46 | 46 |
return CL_EPATSHORT; |
47 | 47 |
} |
48 | 48 |
|
49 |
- pos = root; |
|
49 |
+ pos = root->ac_root; |
|
50 | 50 |
|
51 | 51 |
for(i = 0; i < CL_MIN_LENGTH; i++) { |
52 | 52 |
next = pos->trans[((unsigned char) pattern->pattern[i]) & 0xff]; |
53 | 53 |
|
54 | 54 |
if(!next) { |
55 |
- next = (struct cl_node *) cli_calloc(1, sizeof(struct cl_node)); |
|
55 |
+ next = (struct cli_ac_node *) cli_calloc(1, sizeof(struct cli_ac_node)); |
|
56 | 56 |
if(!next) { |
57 | 57 |
cli_dbgmsg("Unable to allocate pattern node (%d)\n", sizeof(struct cl_node)); |
58 | 58 |
return CL_EMEM; |
59 | 59 |
} |
60 | 60 |
|
61 | 61 |
root->nodes++; |
62 |
- root->nodetable = (struct cl_node **) realloc(root->nodetable, (root->nodes) * sizeof(struct cl_node *)); |
|
62 |
+ root->nodetable = (struct cli_ac_node **) realloc(root->nodetable, (root->nodes) * sizeof(struct cli_ac_node *)); |
|
63 | 63 |
if (root->nodetable == NULL) { |
64 | 64 |
cli_dbgmsg("Unable to realloc nodetable (%d)\n", (root->nodes) * sizeof(struct cl_node *)); |
65 | 65 |
return CL_EMEM; |
... | ... |
@@ -80,7 +80,7 @@ int cli_addpatt(struct cl_node *root, struct cli_patt *pattern) |
80 | 80 |
return 0; |
81 | 81 |
} |
82 | 82 |
|
83 |
-static int cli_enqueue(struct nodelist **bfs, struct cl_node *n) |
|
83 |
+static int cli_enqueue(struct nodelist **bfs, struct cli_ac_node *n) |
|
84 | 84 |
{ |
85 | 85 |
struct nodelist *new; |
86 | 86 |
|
... | ... |
@@ -96,10 +96,10 @@ static int cli_enqueue(struct nodelist **bfs, struct cl_node *n) |
96 | 96 |
return 0; |
97 | 97 |
} |
98 | 98 |
|
99 |
-static struct cl_node *cli_dequeue(struct nodelist **bfs) |
|
99 |
+static struct cli_ac_node *cli_dequeue(struct nodelist **bfs) |
|
100 | 100 |
{ |
101 | 101 |
struct nodelist *handler, *prev = NULL; |
102 |
- struct cl_node *pt; |
|
102 |
+ struct cli_ac_node *pt; |
|
103 | 103 |
|
104 | 104 |
handler = *bfs; |
105 | 105 |
|
... | ... |
@@ -125,12 +125,12 @@ static struct cl_node *cli_dequeue(struct nodelist **bfs) |
125 | 125 |
static int cli_maketrans(struct cl_node *root) |
126 | 126 |
{ |
127 | 127 |
struct nodelist *bfs = NULL; |
128 |
- struct cl_node *child, *node; |
|
128 |
+ struct cli_ac_node *ac_root = root->ac_root, *child, *node; |
|
129 | 129 |
int i, ret; |
130 | 130 |
|
131 | 131 |
|
132 |
- root->fail = NULL; |
|
133 |
- if((ret = cli_enqueue(&bfs, root)) != 0) { |
|
132 |
+ ac_root->fail = NULL; |
|
133 |
+ if((ret = cli_enqueue(&bfs, ac_root)) != 0) { |
|
134 | 134 |
return ret; |
135 | 135 |
} |
136 | 136 |
|
... | ... |
@@ -144,12 +144,12 @@ static int cli_maketrans(struct cl_node *root) |
144 | 144 |
if(node->fail) |
145 | 145 |
node->trans[i] = (node->fail)->trans[i]; |
146 | 146 |
else |
147 |
- node->trans[i] = root; |
|
147 |
+ node->trans[i] = ac_root; |
|
148 | 148 |
} else { |
149 | 149 |
if(node->fail) |
150 | 150 |
child->fail = (node->fail)->trans[i]; |
151 | 151 |
else |
152 |
- child->fail = root; |
|
152 |
+ child->fail = ac_root; |
|
153 | 153 |
|
154 | 154 |
if((ret = cli_enqueue(&bfs, child)) != 0) { |
155 | 155 |
return ret; |
... | ... |
@@ -167,6 +167,11 @@ int cl_buildtrie(struct cl_node *root) |
167 | 167 |
if(!root) |
168 | 168 |
return CL_EMALFDB; |
169 | 169 |
|
170 |
+ if(!root->ac_root) { |
|
171 |
+ cli_dbgmsg("Pattern matcher not initialised\n"); |
|
172 |
+ return 0; |
|
173 |
+ } |
|
174 |
+ |
|
170 | 175 |
if((ret = cli_addtypesigs(root))) |
171 | 176 |
return ret; |
172 | 177 |
|
... | ... |
@@ -200,12 +205,14 @@ void cl_freetrie(struct cl_node *root) |
200 | 200 |
{ |
201 | 201 |
unsigned int i; |
202 | 202 |
|
203 |
+ |
|
203 | 204 |
for(i = 0; i < root->nodes; i++) { |
204 | 205 |
cli_freepatt(root->nodetable[i]->list); |
205 | 206 |
free(root->nodetable[i]); |
206 | 207 |
} |
207 | 208 |
|
208 | 209 |
free(root->nodetable); |
210 |
+ free(root->ac_root); |
|
209 | 211 |
free(root); |
210 | 212 |
} |
211 | 213 |
|
... | ... |
@@ -248,20 +255,24 @@ int inline cli_findpos(const char *buffer, int offset, int length, const struct |
248 | 248 |
|
249 | 249 |
int cli_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_node *root, int *partcnt, int typerec, unsigned long int offset, unsigned long int *partoff) |
250 | 250 |
{ |
251 |
- struct cl_node *current; |
|
251 |
+ struct cli_ac_node *current; |
|
252 | 252 |
struct cli_patt *pt; |
253 | 253 |
int position, type = CL_CLEAN, dist; |
254 | 254 |
unsigned int i; |
255 | 255 |
|
256 |
-int j; |
|
257 | 256 |
|
258 |
- current = (struct cl_node *) root; |
|
257 |
+ if(!root->ac_root) { |
|
258 |
+ cli_dbgmsg("cli_scanbuff: Pattern matcher not initialised\n"); |
|
259 |
+ return CL_CLEAN; |
|
260 |
+ } |
|
259 | 261 |
|
260 | 262 |
if(!partcnt || !partoff) { |
261 | 263 |
cli_dbgmsg("cli_scanbuff(): partcnt == NULL || partoff == NULL\n"); |
262 | 264 |
return CL_EMEM; |
263 | 265 |
} |
264 | 266 |
|
267 |
+ current = root->ac_root; |
|
268 |
+ |
|
265 | 269 |
for(i = 0; i < length; i++) { |
266 | 270 |
current = current->trans[(unsigned char) buffer[i] & 0xff]; |
267 | 271 |
|
... | ... |
@@ -282,12 +293,6 @@ int j; |
282 | 282 |
if(dist && pt->mindist) |
283 | 283 |
if(offset + i - partoff[pt->sigid] < pt->mindist) |
284 | 284 |
dist = 0; |
285 |
-/* |
|
286 |
- printf("dist == %d\n", dist); |
|
287 |
- printf("curr offset == %d\n", offset + i); |
|
288 |
- printf("min dist == %d\n", pt->mindist); |
|
289 |
- printf("max dist == %d\n", pt->maxdist); |
|
290 |
-*/ |
|
291 | 285 |
|
292 | 286 |
if(dist) { |
293 | 287 |
partoff[pt->sigid] = offset + i + pt->length; |
... | ... |
@@ -57,8 +57,7 @@ static int cli_addsig(struct cl_node *root, const char *virname, const char *hex |
57 | 57 |
new->maxdist = maxdist; |
58 | 58 |
|
59 | 59 |
if(strchr(hexsig, '(')) { |
60 |
- char *hexcpy, *hexnew, *start, *h; |
|
61 |
- short int *c; |
|
60 |
+ char *hexcpy, *hexnew, *start, *h, *c; |
|
62 | 61 |
|
63 | 62 |
if(!(hexcpy = strdup(hexsig))) { |
64 | 63 |
free(new); |
... | ... |
@@ -115,13 +114,13 @@ static int cli_addsig(struct cl_node *root, const char *virname, const char *hex |
115 | 115 |
break; |
116 | 116 |
} |
117 | 117 |
|
118 |
- if((c = cl_hex2str(h)) == NULL) { |
|
118 |
+ if((c = cli_hex2str(h)) == NULL) { |
|
119 | 119 |
free(h); |
120 | 120 |
error = 1; |
121 | 121 |
break; |
122 | 122 |
} |
123 | 123 |
|
124 |
- new->altc[new->alt - 1][i] = (char) *c; |
|
124 |
+ new->altc[new->alt - 1][i] = *c; |
|
125 | 125 |
free(c); |
126 | 126 |
free(h); |
127 | 127 |
} |
... | ... |
@@ -158,7 +157,7 @@ static int cli_addsig(struct cl_node *root, const char *virname, const char *hex |
158 | 158 |
if(new->length > root->maxpatlen) |
159 | 159 |
root->maxpatlen = new->length; |
160 | 160 |
|
161 |
- if((new->pattern = cl_hex2str(hex)) == NULL) { |
|
161 |
+ if((new->pattern = cli_hex2si(hex)) == NULL) { |
|
162 | 162 |
if(new->alt) { |
163 | 163 |
free(new->altn); |
164 | 164 |
for(i = 0; i < new->alt; i++) |
... | ... |
@@ -339,95 +338,166 @@ int cli_parse_add(struct cl_node *root, char *virname, const char *hexsig, int t |
339 | 339 |
return 0; |
340 | 340 |
} |
341 | 341 |
|
342 |
-int cl_loaddb(const char *filename, struct cl_node **root, int *virnum) |
|
342 |
+static int cli_loaddb(FILE *fd, struct cl_node **root, int *virnum) |
|
343 | 343 |
{ |
344 |
- FILE *fd; |
|
345 |
- char *buffer, *pt, *start; |
|
346 |
- int line = 0, ret; |
|
344 |
+ char buffer[FILEBUFF], *pt, *start; |
|
345 |
+ int line = 0, ret = 0; |
|
347 | 346 |
|
348 | 347 |
|
349 |
- if((fd = fopen(filename, "rb")) == NULL) { |
|
350 |
- cli_errmsg("cl_loaddb(): Can't open file %s\n", filename); |
|
351 |
- return CL_EOPEN; |
|
348 |
+ if(!*root) { |
|
349 |
+ cli_dbgmsg("Initializing main node\n"); |
|
350 |
+ *root = (struct cl_node *) cli_calloc(1, sizeof(struct cl_node)); |
|
351 |
+ if(!*root) |
|
352 |
+ return CL_EMEM; |
|
352 | 353 |
} |
353 | 354 |
|
354 |
- cli_dbgmsg("Loading %s\n", filename); |
|
355 |
- |
|
356 |
- if(!(buffer = (char *) cli_malloc(FILEBUFF))) { |
|
357 |
- fclose(fd); |
|
358 |
- return CL_EMEM; |
|
355 |
+ if(!(*root)->ac_root) { |
|
356 |
+ cli_dbgmsg("Initializing trie\n"); |
|
357 |
+ (*root)->ac_root = (struct cli_ac_node *) cli_calloc(1, sizeof(struct cli_ac_node)); |
|
358 |
+ if(!(*root)->ac_root) { |
|
359 |
+ free(*root); |
|
360 |
+ return CL_EMEM; |
|
361 |
+ } |
|
359 | 362 |
} |
360 | 363 |
|
361 |
- memset(buffer, 0, FILEBUFF); |
|
364 |
+ while(fgets(buffer, FILEBUFF, fd)) { |
|
365 |
+ line++; |
|
366 |
+ cli_chomp(buffer); |
|
367 |
+ |
|
368 |
+ pt = strchr(buffer, '='); |
|
369 |
+ if(!pt) { |
|
370 |
+ cli_errmsg("Malformed pattern line %d\n", line); |
|
371 |
+ ret = CL_EMALFDB; |
|
372 |
+ break; |
|
373 |
+ } |
|
374 |
+ |
|
375 |
+ start = buffer; |
|
376 |
+ *pt++ = 0; |
|
362 | 377 |
|
363 |
- /* test for CVD file */ |
|
378 |
+ if(*pt == '=') continue; |
|
364 | 379 |
|
365 |
- if (fgets(buffer, 12, fd) == NULL) { |
|
366 |
- cli_dbgmsg("%s: failure reading header\n", filename); |
|
367 |
- free(buffer); |
|
368 |
- fclose(fd); |
|
369 |
- return CL_EMALFDB; |
|
380 |
+ if((ret = cli_parse_add(*root, start, pt, 0))) { |
|
381 |
+ cli_errmsg("Problem parsing signature at line %d\n", line); |
|
382 |
+ ret = CL_EMALFDB; |
|
383 |
+ break; |
|
384 |
+ } |
|
370 | 385 |
} |
371 | 386 |
|
372 |
- rewind(fd); |
|
387 |
+ if(!line) { |
|
388 |
+ cli_errmsg("Empty database file\n"); |
|
389 |
+ /* FIXME: release memory */ |
|
390 |
+ return CL_EMALFDB; |
|
391 |
+ } |
|
373 | 392 |
|
374 |
- if(!strncmp(buffer, "ClamAV-VDB:", 11)) { |
|
375 |
- cli_dbgmsg("%s: CVD file detected\n", filename); |
|
376 |
- ret = cli_cvdload(fd, root, virnum); |
|
377 |
- free(buffer); |
|
378 |
- fclose(fd); |
|
393 |
+ if(ret) { |
|
394 |
+ /* FIXME: release memory */ |
|
379 | 395 |
return ret; |
380 | 396 |
} |
381 | 397 |
|
382 |
- while(fgets(buffer, FILEBUFF, fd)) { |
|
398 |
+ if(virnum != NULL) |
|
399 |
+ *virnum += line; |
|
400 |
+ |
|
401 |
+ return 0; |
|
402 |
+} |
|
403 |
+ |
|
404 |
+static int cli_loadhdb(FILE *fd, struct cl_node **root, int *virnum) |
|
405 |
+{ |
|
406 |
+ char buffer[FILEBUFF], *pt, *start; |
|
407 |
+ int line = 0, ret = 0; |
|
408 |
+ struct cli_md5_node *new; |
|
383 | 409 |
|
410 |
+ |
|
411 |
+ if(!*root) { |
|
412 |
+ cli_dbgmsg("Initializing main node\n"); |
|
413 |
+ *root = (struct cl_node *) cli_calloc(1, sizeof(struct cl_node)); |
|
414 |
+ if(!*root) |
|
415 |
+ return CL_EMEM; |
|
416 |
+ } |
|
417 |
+ |
|
418 |
+ while(fgets(buffer, FILEBUFF, fd)) { |
|
384 | 419 |
line++; |
385 | 420 |
cli_chomp(buffer); |
386 | 421 |
|
387 |
- pt = strchr(buffer, '='); |
|
388 |
- if(!pt) { |
|
389 |
- cli_errmsg("readdb(): Malformed pattern line %d (file %s).\n", line, filename); |
|
390 |
- free(buffer); |
|
391 |
- fclose(fd); |
|
392 |
- return CL_EMALFDB; |
|
422 |
+ new = (struct cli_md5_node *) cli_calloc(1, sizeof(struct cli_md5_node)); |
|
423 |
+ if(!new) { |
|
424 |
+ ret = CL_EMEM; |
|
425 |
+ break; |
|
393 | 426 |
} |
394 | 427 |
|
395 |
- start = buffer; |
|
396 |
- *pt++ = 0; |
|
397 |
- |
|
398 |
- if(*pt == '=') continue; |
|
428 |
+ if(!(pt = cli_strtok(buffer, 0, ":"))) { |
|
429 |
+ free(new); |
|
430 |
+ ret = CL_EMALFDB; |
|
431 |
+ break; |
|
432 |
+ } |
|
399 | 433 |
|
400 |
- if(!*root) { |
|
401 |
- cli_dbgmsg("Initializing trie.\n"); |
|
402 |
- *root = (struct cl_node *) cli_calloc(1, sizeof(struct cl_node)); |
|
403 |
- if(!*root) { |
|
404 |
- free(buffer); |
|
405 |
- fclose(fd); |
|
406 |
- return CL_EMEM; |
|
407 |
- } |
|
408 |
- (*root)->maxpatlen = 0; |
|
434 |
+ if(!(new->md5 = cli_hex2str(pt))) { |
|
435 |
+ cli_errmsg("Malformed MD5 string at line %d\n", line); |
|
436 |
+ free(pt); |
|
437 |
+ free(new); |
|
438 |
+ ret = CL_EMALFDB; |
|
439 |
+ break; |
|
409 | 440 |
} |
441 |
+ free(pt); |
|
410 | 442 |
|
411 |
- if((ret = cli_parse_add(*root, start, pt, 0))) { |
|
412 |
- cli_errmsg("readdb(): Problem parsing signature at line %d (file %s).\n", line, filename); |
|
413 |
- free(buffer); |
|
414 |
- fclose(fd); |
|
415 |
- return ret; |
|
443 |
+ if(!(new->virname = cli_strtok(buffer, 1, ":"))) { |
|
444 |
+ free(new->md5); |
|
445 |
+ free(new); |
|
446 |
+ ret = CL_EMALFDB; |
|
447 |
+ break; |
|
416 | 448 |
} |
449 |
+ |
|
450 |
+ new->viralias = cli_strtok(buffer, 1, ":"); /* aliases are optional */ |
|
451 |
+ |
|
452 |
+ new->next = (*root)->hlist[new->md5[0] & 0xff]; |
|
453 |
+ (*root)->hlist[new->md5[0] & 0xff] = new; |
|
417 | 454 |
} |
418 | 455 |
|
419 |
- if(virnum != NULL) |
|
420 |
- *virnum += line; |
|
456 |
+ if(!line) { |
|
457 |
+ cli_errmsg("Empty database file\n"); |
|
458 |
+ /* FIXME: release memory */ |
|
459 |
+ return CL_EMALFDB; |
|
460 |
+ } |
|
421 | 461 |
|
422 |
- free(buffer); |
|
423 |
- fclose(fd); |
|
462 |
+ if(ret) { |
|
463 |
+ /* FIXME: release memory */ |
|
464 |
+ return ret; |
|
465 |
+ } |
|
424 | 466 |
|
425 | 467 |
return 0; |
426 | 468 |
} |
427 | 469 |
|
428 |
-const char *cl_retdbdir(void) |
|
470 |
+int cl_loaddb(const char *filename, struct cl_node **root, int *virnum) |
|
429 | 471 |
{ |
430 |
- return DATADIR; |
|
472 |
+ FILE *fd; |
|
473 |
+ int ret; |
|
474 |
+ |
|
475 |
+ |
|
476 |
+ if((fd = fopen(filename, "rb")) == NULL) { |
|
477 |
+ cli_errmsg("cl_loaddb(): Can't open file %s\n", filename); |
|
478 |
+ return CL_EOPEN; |
|
479 |
+ } |
|
480 |
+ |
|
481 |
+ cli_dbgmsg("Loading %s\n", filename); |
|
482 |
+ |
|
483 |
+ if(cli_strbcasestr(filename, ".db") || cli_strbcasestr(filename, ".db2") || cli_strbcasestr(filename, ".db3")) { |
|
484 |
+ ret = cli_loaddb(fd, root, virnum); |
|
485 |
+ |
|
486 |
+ } else if(cli_strbcasestr(filename, ".cvd")) { |
|
487 |
+ ret = cli_cvdload(fd, root, virnum); |
|
488 |
+ |
|
489 |
+ } else if(cli_strbcasestr(filename, ".hdb")) { |
|
490 |
+ ret = cli_loadhdb(fd, root, virnum); |
|
491 |
+ |
|
492 |
+ } else { |
|
493 |
+ cli_dbgmsg("cl_loaddb: unknown extension - assuming old database format\n"); |
|
494 |
+ ret = cli_loaddb(fd, root, virnum); |
|
495 |
+ } |
|
496 |
+ |
|
497 |
+ if(ret) |
|
498 |
+ cli_errmsg("Malformed database file %s\n", filename); |
|
499 |
+ |
|
500 |
+ fclose(fd); |
|
501 |
+ return ret; |
|
431 | 502 |
} |
432 | 503 |
|
433 | 504 |
int cl_loaddbdir(const char *dirname, struct cl_node **root, int *virnum) |
... | ... |
@@ -454,6 +524,7 @@ int cl_loaddbdir(const char *dirname, struct cl_node **root, int *virnum) |
454 | 454 |
(cli_strbcasestr(dent->d_name, ".db") || |
455 | 455 |
cli_strbcasestr(dent->d_name, ".db2") || |
456 | 456 |
cli_strbcasestr(dent->d_name, ".db3") || |
457 |
+ cli_strbcasestr(dent->d_name, ".hdb") || |
|
457 | 458 |
cli_strbcasestr(dent->d_name, ".cvd"))) { |
458 | 459 |
|
459 | 460 |
dbfile = (char *) cli_calloc(strlen(dent->d_name) + strlen(dirname) + 2, sizeof(char)); |
... | ... |
@@ -479,6 +550,11 @@ int cl_loaddbdir(const char *dirname, struct cl_node **root, int *virnum) |
479 | 479 |
return 0; |
480 | 480 |
} |
481 | 481 |
|
482 |
+const char *cl_retdbdir(void) |
|
483 |
+{ |
|
484 |
+ return DATADIR; |
|
485 |
+} |
|
486 |
+ |
|
482 | 487 |
int cl_statinidir(const char *dirname, struct cl_stat *dbstat) |
483 | 488 |
{ |
484 | 489 |
DIR *dd; |
... | ... |
@@ -507,7 +583,7 @@ int cl_statinidir(const char *dirname, struct cl_stat *dbstat) |
507 | 507 |
if(dent->d_ino) |
508 | 508 |
#endif |
509 | 509 |
{ |
510 |
- if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") && (cli_strbcasestr(dent->d_name, ".db") || cli_strbcasestr(dent->d_name, ".db2") || cli_strbcasestr(dent->d_name, ".db3") || cli_strbcasestr(dent->d_name, ".cvd"))) { |
|
510 |
+ if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") && (cli_strbcasestr(dent->d_name, ".db") || cli_strbcasestr(dent->d_name, ".db2") || cli_strbcasestr(dent->d_name, ".db3") || cli_strbcasestr(dent->d_name, ".hdb") || cli_strbcasestr(dent->d_name, ".cvd"))) { |
|
511 | 511 |
|
512 | 512 |
dbstat->no++; |
513 | 513 |
dbstat->stattab = (struct stat *) realloc(dbstat->stattab, dbstat->no * sizeof(struct stat)); |
... | ... |
@@ -549,7 +625,7 @@ int cl_statchkdir(const struct cl_stat *dbstat) |
549 | 549 |
if(dent->d_ino) |
550 | 550 |
#endif |
551 | 551 |
{ |
552 |
- if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") && (cli_strbcasestr(dent->d_name, ".db") || cli_strbcasestr(dent->d_name, ".db2") || cli_strbcasestr(dent->d_name, ".db3") || cli_strbcasestr(dent->d_name, ".cvd"))) { |
|
552 |
+ if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") && (cli_strbcasestr(dent->d_name, ".db") || cli_strbcasestr(dent->d_name, ".db2") || cli_strbcasestr(dent->d_name, ".db3") || cli_strbcasestr(dent->d_name, ".hdb") || cli_strbcasestr(dent->d_name, ".cvd"))) { |
|
553 | 553 |
|
554 | 554 |
fname = cli_calloc(strlen(dbstat->dir) + strlen(dent->d_name) + 2, sizeof(char)); |
555 | 555 |
sprintf(fname, "%s/%s", dbstat->dir, dent->d_name); |
... | ... |
@@ -57,6 +57,7 @@ extern short cli_leavetemps_flag; |
57 | 57 |
#include "pe.h" |
58 | 58 |
#include "filetypes.h" |
59 | 59 |
#include "htmlnorm.h" |
60 |
+#include "md5.h" |
|
60 | 61 |
|
61 | 62 |
#ifdef HAVE_ZLIB_H |
62 | 63 |
#include <zlib.h> |
... | ... |
@@ -77,15 +78,38 @@ extern short cli_leavetemps_flag; |
77 | 77 |
|
78 | 78 |
#define MAX_MAIL_RECURSION 15 |
79 | 79 |
|
80 |
+#define MD5_BLOCKSIZE 4096 |
|
80 | 81 |
|
81 | 82 |
static int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *arec, int *mrec); |
82 | 83 |
static int cli_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *arec, int *mrec); |
83 | 84 |
|
85 |
+ |
|
86 |
+struct cli_md5_node *cli_vermd5(const char *md5, const struct cl_node *root) |
|
87 |
+{ |
|
88 |
+ struct cli_md5_node *pt; |
|
89 |
+ |
|
90 |
+ |
|
91 |
+ if(!(pt = root->hlist[md5[0] & 0xff])) |
|
92 |
+ return NULL; |
|
93 |
+ |
|
94 |
+ while(pt) { |
|
95 |
+ if(!memcmp(pt->md5, md5, 16)) |
|
96 |
+ return pt; |
|
97 |
+ |
|
98 |
+ pt = pt->next; |
|
99 |
+ } |
|
100 |
+ |
|
101 |
+ return NULL; |
|
102 |
+} |
|
103 |
+ |
|
84 | 104 |
static int cli_scandesc(int desc, const char **virname, long int *scanned, const struct cl_node *root, int typerec) |
85 | 105 |
{ |
86 | 106 |
char *buffer, *buff, *endbl, *pt; |
87 | 107 |
int bytes, buffsize, length, ret, *partcnt, type = CL_CLEAN; |
88 | 108 |
unsigned long int *partoff, offset = 0; |
109 |
+ struct md5_ctx ctx; |
|
110 |
+ unsigned char md5buff[16]; |
|
111 |
+ struct cli_md5_node *md5_node; |
|
89 | 112 |
|
90 | 113 |
|
91 | 114 |
/* prepare the buffer */ |
... | ... |
@@ -106,6 +130,8 @@ static int cli_scandesc(int desc, const char **virname, long int *scanned, const |
106 | 106 |
return CL_EMEM; |
107 | 107 |
} |
108 | 108 |
|
109 |
+ md5_init_ctx (&ctx); |
|
110 |
+ |
|
109 | 111 |
buff = buffer; |
110 | 112 |
buff += root->maxpatlen; /* pointer to read data block */ |
111 | 113 |
endbl = buff + SCANBUFF - root->maxpatlen; /* pointer to the last block |
... | ... |
@@ -139,11 +165,37 @@ static int cli_scandesc(int desc, const char **virname, long int *scanned, const |
139 | 139 |
|
140 | 140 |
pt = buffer; |
141 | 141 |
length = buffsize; |
142 |
+ |
|
143 |
+ /* compute MD5 */ |
|
144 |
+ |
|
145 |
+ if(bytes % 64 == 0) { |
|
146 |
+ md5_process_block(buff, bytes, &ctx); |
|
147 |
+ } else { |
|
148 |
+ int block = bytes; |
|
149 |
+ char *mpt = buff; |
|
150 |
+ |
|
151 |
+ while(block >= MD5_BLOCKSIZE) { |
|
152 |
+ md5_process_block(mpt, MD5_BLOCKSIZE, &ctx); |
|
153 |
+ mpt += MD5_BLOCKSIZE; |
|
154 |
+ block -= MD5_BLOCKSIZE; |
|
155 |
+ } |
|
156 |
+ |
|
157 |
+ if(block) |
|
158 |
+ md5_process_bytes(mpt, block, &ctx); |
|
159 |
+ } |
|
142 | 160 |
} |
143 | 161 |
|
144 | 162 |
free(buffer); |
145 | 163 |
free(partcnt); |
146 | 164 |
|
165 |
+ md5_finish_ctx(&ctx, &md5buff); |
|
166 |
+ |
|
167 |
+ if((md5_node = cli_vermd5(md5buff, root))) { |
|
168 |
+ if(virname) |
|
169 |
+ *virname = md5_node->virname; |
|
170 |
+ return CL_VIRUS; |
|
171 |
+ } |
|
172 |
+ |
|
147 | 173 |
return typerec ? type : CL_CLEAN; |
148 | 174 |
} |
149 | 175 |
|
... | ... |
@@ -46,16 +46,16 @@ static int cli_hex2int(int c) |
46 | 46 |
return -1; |
47 | 47 |
} |
48 | 48 |
|
49 |
-short int *cl_hex2str(const char *hex) |
|
49 |
+short int *cli_hex2si(const char *hex) |
|
50 | 50 |
{ |
51 | 51 |
short int *str, *ptr, val, c; |
52 | 52 |
int i, len; |
53 | 53 |
|
54 |
+ |
|
54 | 55 |
len = strlen(hex); |
55 | 56 |
|
56 |
- /* additional check - hex strings are parity length here */ |
|
57 | 57 |
if(len % 2 != 0) { |
58 |
- cli_errmsg("cl_hex2str(): Malformed hexstring: %s (length: %d)\n", hex, len); |
|
58 |
+ cli_errmsg("cl_hex2si(): Malformed hexstring: %s (length: %d)\n", hex, len); |
|
59 | 59 |
return NULL; |
60 | 60 |
} |
61 | 61 |
|
... | ... |
@@ -90,6 +90,45 @@ short int *cl_hex2str(const char *hex) |
90 | 90 |
return str; |
91 | 91 |
} |
92 | 92 |
|
93 |
+char *cli_hex2str(const char *hex) |
|
94 |
+{ |
|
95 |
+ char *str, *ptr, val, c; |
|
96 |
+ int i, len; |
|
97 |
+ |
|
98 |
+ |
|
99 |
+ len = strlen(hex); |
|
100 |
+ |
|
101 |
+ if(len % 2 != 0) { |
|
102 |
+ cli_errmsg("cl_hex2str(): Malformed hexstring: %s (length: %d)\n", hex, len); |
|
103 |
+ return NULL; |
|
104 |
+ } |
|
105 |
+ |
|
106 |
+ str = cli_calloc((len / 2) + 1, sizeof(char)); |
|
107 |
+ if(!str) |
|
108 |
+ return NULL; |
|
109 |
+ |
|
110 |
+ ptr = str; |
|
111 |
+ |
|
112 |
+ for(i = 0; i < len; i += 2) { |
|
113 |
+ if((c = cli_hex2int(hex[i])) >= 0) { |
|
114 |
+ val = c; |
|
115 |
+ if((c = cli_hex2int(hex[i+1])) >= 0) { |
|
116 |
+ val = (val << 4) + c; |
|
117 |
+ } else { |
|
118 |
+ free(str); |
|
119 |
+ return NULL; |
|
120 |
+ } |
|
121 |
+ } else { |
|
122 |
+ free(str); |
|
123 |
+ return NULL; |
|
124 |
+ } |
|
125 |
+ |
|
126 |
+ *ptr++ = val; |
|
127 |
+ } |
|
128 |
+ |
|
129 |
+ return str; |
|
130 |
+} |
|
131 |
+ |
|
93 | 132 |
char *cl_str2hex(const char *string, unsigned int len) |
94 | 133 |
{ |
95 | 134 |
char *hexstr; |
... | ... |
@@ -190,5 +229,3 @@ char *cli_strtok(const char *line, int fieldno, const char *delim) |
190 | 190 |
|
191 | 191 |
return buffer; |
192 | 192 |
} |
193 |
- |
|
194 |
- |
... | ... |
@@ -16,11 +16,13 @@ |
16 | 16 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
17 | 17 |
*/ |
18 | 18 |
|
19 |
-#ifndef __STRINGS_H |
|
20 |
-#define __STRINGS_H |
|
19 |
+#ifndef __STR_H |
|
20 |
+#define __STR_H |
|
21 | 21 |
|
22 | 22 |
int cli_strbcasestr(const char *haystack, const char *needle); |
23 |
-int cli_chomp(char *string); |
|
23 |
+int cli_chomp(char *string); |
|
24 | 24 |
char *cli_strtok(const char *line, int field, const char *delim); |
25 |
+short int *cli_hex2si(const char *hex); |
|
26 |
+char *cli_hex2str(const char *hex); |
|
25 | 27 |
|
26 | 28 |
#endif |