Browse code

initial support for MD5 signatures

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
Showing 8 changed files
... ...
@@ -1,3 +1,7 @@
1
+Tue Jul 13 05:24:07 CEST 2004 (tk)
2
+----------------------------------
3
+  * libclamav: initial support for MD5 signatures
4
+
1 5
 Mon Jul 12 16:03:11 BST 2004 (trog)
2 6
 -----------------------------------
3 7
   * libclamav/htmlnorm.c: fix decoding of hex char encoding
... ...
@@ -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;
... ...
@@ -22,7 +22,7 @@
22 22
 #include "clamav.h"
23 23
 
24 24
 struct nodelist {
25
-    struct cl_node *node;
25
+    struct cli_ac_node *node;
26 26
     struct nodelist *next;
27 27
 };
28 28
 
... ...
@@ -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