git-svn: trunk@3993
Tomasz Kojm authored on 2008/07/26 04:00:25... | ... |
@@ -1,3 +1,7 @@ |
1 |
+Fri Jul 25 20:41:21 CEST 2008 (tk) |
|
2 |
+---------------------------------- |
|
3 |
+ * libclamav: add initial support for logical signatures (bb#896) |
|
4 |
+ |
|
1 | 5 |
Fri Jul 25 02:24:53 CEST 2008 (acab) |
2 | 6 |
------------------------------------ |
3 | 7 |
* libclamav/scanners.c: warn if no bzip2 support - bb#1060 |
... | ... |
@@ -163,7 +163,7 @@ cli_file_t cli_filetype2(int desc, const struct cl_engine *engine) |
163 | 163 |
if(!root) |
164 | 164 |
return ret; |
165 | 165 |
|
166 |
- if(cli_ac_initdata(&mdata, root->ac_partsigs, AC_DEFAULT_TRACKLEN)) |
|
166 |
+ if(cli_ac_initdata(&mdata, root->ac_partsigs, root->ac_lsigs, AC_DEFAULT_TRACKLEN)) |
|
167 | 167 |
return ret; |
168 | 168 |
|
169 | 169 |
sret = cli_ac_scanbuff(buff, bread, NULL, engine->root[0], &mdata, 0, ret, desc, NULL, AC_SCAN_FT, NULL); |
... | ... |
@@ -173,7 +173,7 @@ cli_file_t cli_filetype2(int desc, const struct cl_engine *engine) |
173 | 173 |
if(sret >= CL_TYPENO) { |
174 | 174 |
ret = sret; |
175 | 175 |
} else { |
176 |
- if(cli_ac_initdata(&mdata, root->ac_partsigs, AC_DEFAULT_TRACKLEN)) |
|
176 |
+ if(cli_ac_initdata(&mdata, root->ac_partsigs, root->ac_lsigs, AC_DEFAULT_TRACKLEN)) |
|
177 | 177 |
return ret; |
178 | 178 |
|
179 | 179 |
decoded = (unsigned char *) cli_utf16toascii((char *) buff, bread); |
... | ... |
@@ -208,7 +208,7 @@ cli_file_t cli_filetype2(int desc, const struct cl_engine *engine) |
208 | 208 |
* (just eliminating zeros and matching would introduce false positives */ |
209 | 209 |
if(encoding_normalize_toascii(&in_area, encoding, &out_area) >= 0 && out_area.length > 0) { |
210 | 210 |
out_area.buffer[out_area.length] = '\0'; |
211 |
- if(cli_ac_initdata(&mdata, root->ac_partsigs, AC_DEFAULT_TRACKLEN)) |
|
211 |
+ if(cli_ac_initdata(&mdata, root->ac_partsigs, root->ac_lsigs, AC_DEFAULT_TRACKLEN)) |
|
212 | 212 |
return ret; |
213 | 213 |
|
214 | 214 |
if(out_area.length > 0) { |
... | ... |
@@ -25,6 +25,7 @@ |
25 | 25 |
#include <stdio.h> |
26 | 26 |
#include <string.h> |
27 | 27 |
#include <stdlib.h> |
28 |
+#include <ctype.h> |
|
28 | 29 |
#ifdef HAVE_UNISTD_H |
29 | 30 |
#include <unistd.h> |
30 | 31 |
#endif |
... | ... |
@@ -373,6 +374,228 @@ void cli_ac_free(struct cli_matcher *root) |
373 | 373 |
} |
374 | 374 |
} |
375 | 375 |
|
376 |
+/* |
|
377 |
+ * In parse_only mode this function returns -1 on error or the max subsig id |
|
378 |
+ */ |
|
379 |
+int cli_ac_chklsig(const char *expr, const char *end, uint32_t *lsigcnt, unsigned int *cnt, unsigned int parse_only) |
|
380 |
+{ |
|
381 |
+ unsigned int i, len = end - expr, pth = 0, opoff = 0, op1off = 0, val; |
|
382 |
+ unsigned int blkend = 0, id, modval, lcnt = 0, rcnt = 0, tcnt, modoff = 0; |
|
383 |
+ int ret, lval, rval; |
|
384 |
+ char op = 0, op1 = 0, mod = 0, blkmod = 0; |
|
385 |
+ const char *lstart = expr, *lend = NULL, *rstart = NULL, *rend = end, *pt; |
|
386 |
+ |
|
387 |
+ |
|
388 |
+ for(i = 0; i < len; i++) { |
|
389 |
+ switch(expr[i]) { |
|
390 |
+ case '(': |
|
391 |
+ pth++; |
|
392 |
+ break; |
|
393 |
+ |
|
394 |
+ case ')': |
|
395 |
+ if(!pth) { |
|
396 |
+ cli_errmsg("cli_ac_chklsig: Syntax error: Missing opening parenthesis\n"); |
|
397 |
+ return -1; |
|
398 |
+ } |
|
399 |
+ pth--; |
|
400 |
+ |
|
401 |
+ case '>': |
|
402 |
+ case '<': |
|
403 |
+ case '=': |
|
404 |
+ mod = expr[i]; |
|
405 |
+ modoff = i; |
|
406 |
+ break; |
|
407 |
+ |
|
408 |
+ default: |
|
409 |
+ if(strchr("&|", expr[i])) { |
|
410 |
+ if(!pth) { |
|
411 |
+ op = expr[i]; |
|
412 |
+ opoff = i; |
|
413 |
+ } else if(pth == 1) { |
|
414 |
+ op1 = expr[i]; |
|
415 |
+ op1off = i; |
|
416 |
+ } |
|
417 |
+ } |
|
418 |
+ } |
|
419 |
+ |
|
420 |
+ if(op) |
|
421 |
+ break; |
|
422 |
+ |
|
423 |
+ if(op1 && !pth) { |
|
424 |
+ blkend = i; |
|
425 |
+ if(expr[i + 1] == '>' || expr[i + 1] == '<' || expr[i + 1] == '=') { |
|
426 |
+ blkmod = expr[i + 1]; |
|
427 |
+ ret = sscanf(&expr[i + 2], "%u", &modval); |
|
428 |
+ if(!ret || ret == EOF) { |
|
429 |
+ cli_errmsg("chklexpr: Syntax error: Missing number after '%c'\n", expr[i + 1]); |
|
430 |
+ return -1; |
|
431 |
+ } |
|
432 |
+ for(i += 2; i + 1 < len && isdigit(expr[i + 1]); i++); |
|
433 |
+ } |
|
434 |
+ |
|
435 |
+ if(&expr[i + 1] == rend) |
|
436 |
+ break; |
|
437 |
+ else |
|
438 |
+ blkmod = 0; |
|
439 |
+ } |
|
440 |
+ } |
|
441 |
+ |
|
442 |
+ if(pth) { |
|
443 |
+ cli_errmsg("cli_ac_chklsig: Syntax error: Missing closing parenthesis\n"); |
|
444 |
+ return -1; |
|
445 |
+ } |
|
446 |
+ |
|
447 |
+ if(!op && !op1) { |
|
448 |
+ if(expr[0] == '(') |
|
449 |
+ return cli_ac_chklsig(++expr, --end, lsigcnt, cnt, parse_only); |
|
450 |
+ |
|
451 |
+ ret = sscanf(expr, "%u", &id); |
|
452 |
+ if(!ret || ret == EOF) { |
|
453 |
+ cli_errmsg("cli_ac_chklsig: Can't parse %s\n", expr); |
|
454 |
+ return -1; |
|
455 |
+ } |
|
456 |
+ |
|
457 |
+ if(parse_only) |
|
458 |
+ val = id; |
|
459 |
+ else |
|
460 |
+ val = lsigcnt[id]; |
|
461 |
+ |
|
462 |
+ if(mod) { |
|
463 |
+ pt = strchr(expr, mod) + modoff; |
|
464 |
+ ret = sscanf(pt, "%u", &modval); |
|
465 |
+ if(!ret || ret == EOF) { |
|
466 |
+ cli_errmsg("chklexpr: Syntax error: Missing number after '%c'\n", mod); |
|
467 |
+ return -1; |
|
468 |
+ } |
|
469 |
+ if(!parse_only) switch(mod) { |
|
470 |
+ case '=': |
|
471 |
+ if(val == modval) { |
|
472 |
+ *cnt += val; |
|
473 |
+ return 1; |
|
474 |
+ } else { |
|
475 |
+ return 0; |
|
476 |
+ } |
|
477 |
+ break; |
|
478 |
+ case '<': |
|
479 |
+ if(val < modval) { |
|
480 |
+ *cnt += val; |
|
481 |
+ return 1; |
|
482 |
+ } else { |
|
483 |
+ return 0; |
|
484 |
+ } |
|
485 |
+ break; |
|
486 |
+ case '>': |
|
487 |
+ if(val > modval) { |
|
488 |
+ *cnt += val; |
|
489 |
+ return 1; |
|
490 |
+ } else { |
|
491 |
+ return 0; |
|
492 |
+ } |
|
493 |
+ } |
|
494 |
+ } |
|
495 |
+ |
|
496 |
+ if(parse_only) { |
|
497 |
+ return val; |
|
498 |
+ } else { |
|
499 |
+ *cnt += val; |
|
500 |
+ return val ? 1 : 0; |
|
501 |
+ } |
|
502 |
+ } |
|
503 |
+ |
|
504 |
+ if(!op) { |
|
505 |
+ op = op1; |
|
506 |
+ opoff = op1off; |
|
507 |
+ lstart++; |
|
508 |
+ rend = &expr[blkend]; |
|
509 |
+ } |
|
510 |
+ |
|
511 |
+ if(!opoff) { |
|
512 |
+ cli_errmsg("cli_ac_chklsig: Syntax error: Missing left argument\n"); |
|
513 |
+ return -1; |
|
514 |
+ } |
|
515 |
+ lend = &expr[opoff]; |
|
516 |
+ if(opoff + 1 == len) { |
|
517 |
+ cli_errmsg("cli_ac_chklsig: Syntax error: Missing right argument\n"); |
|
518 |
+ return -1; |
|
519 |
+ } |
|
520 |
+ rstart = &expr[opoff + 1]; |
|
521 |
+ |
|
522 |
+ lval = cli_ac_chklsig(lstart, lend, lsigcnt, &lcnt, parse_only); |
|
523 |
+ if(lval == -1) { |
|
524 |
+ cli_errmsg("cli_ac_chklsig: Calculation of lval failed\n"); |
|
525 |
+ return -1; |
|
526 |
+ } |
|
527 |
+ |
|
528 |
+ rval = cli_ac_chklsig(rstart, rend, lsigcnt, &rcnt, parse_only); |
|
529 |
+ if(rval == -1) { |
|
530 |
+ cli_errmsg("cli_ac_chklsig: Calculation of rval failed\n"); |
|
531 |
+ return -1; |
|
532 |
+ } |
|
533 |
+ |
|
534 |
+ if(parse_only) { |
|
535 |
+ switch(op) { |
|
536 |
+ case '&': |
|
537 |
+ case '|': |
|
538 |
+ return MAX(lval, rval); |
|
539 |
+ default: |
|
540 |
+ cli_errmsg("cli_ac_chklsig: Incorrect operator type\n"); |
|
541 |
+ return -1; |
|
542 |
+ } |
|
543 |
+ } else { |
|
544 |
+ switch(op) { |
|
545 |
+ case '&': |
|
546 |
+ ret = lval && rval; |
|
547 |
+ break; |
|
548 |
+ case '|': |
|
549 |
+ ret = lval || rval; |
|
550 |
+ break; |
|
551 |
+ default: |
|
552 |
+ cli_errmsg("cli_ac_chklsig: Incorrect operator type\n"); |
|
553 |
+ return -1; |
|
554 |
+ } |
|
555 |
+ |
|
556 |
+ if(!blkmod) { |
|
557 |
+ if(ret) |
|
558 |
+ *cnt += lcnt + rcnt; |
|
559 |
+ |
|
560 |
+ return ret; |
|
561 |
+ } else { |
|
562 |
+ if(ret) |
|
563 |
+ tcnt = lcnt + rcnt; |
|
564 |
+ else |
|
565 |
+ tcnt = 0; |
|
566 |
+ |
|
567 |
+ switch(blkmod) { |
|
568 |
+ case '=': |
|
569 |
+ if(tcnt == modval) { |
|
570 |
+ *cnt += tcnt; |
|
571 |
+ return 1; |
|
572 |
+ } else { |
|
573 |
+ return 0; |
|
574 |
+ } |
|
575 |
+ break; |
|
576 |
+ case '<': |
|
577 |
+ if(tcnt < modval) { |
|
578 |
+ *cnt += tcnt; |
|
579 |
+ return 1; |
|
580 |
+ } else { |
|
581 |
+ return 0; |
|
582 |
+ } |
|
583 |
+ break; |
|
584 |
+ case '>': |
|
585 |
+ if(tcnt > modval) { |
|
586 |
+ *cnt += tcnt; |
|
587 |
+ return 1; |
|
588 |
+ } else { |
|
589 |
+ return 0; |
|
590 |
+ } |
|
591 |
+ default: |
|
592 |
+ return 0; |
|
593 |
+ } |
|
594 |
+ } |
|
595 |
+ } |
|
596 |
+} |
|
597 |
+ |
|
376 | 598 |
/* |
377 | 599 |
* FIXME: the current support for string alternatives uses a brute-force |
378 | 600 |
* approach and doesn't perform any kind of verification and |
... | ... |
@@ -501,8 +724,10 @@ inline static int ac_findmatch(const unsigned char *buffer, uint32_t offset, uin |
501 | 501 |
return 1; |
502 | 502 |
} |
503 | 503 |
|
504 |
-int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint8_t tracklen) |
|
504 |
+int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint32_t lsigs, uint8_t tracklen) |
|
505 | 505 |
{ |
506 |
+ unsigned int i; |
|
507 |
+ |
|
506 | 508 |
|
507 | 509 |
if(!data) { |
508 | 510 |
cli_errmsg("cli_ac_init: data == NULL\n"); |
... | ... |
@@ -511,15 +736,35 @@ int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint8_t trackle |
511 | 511 |
|
512 | 512 |
data->partsigs = partsigs; |
513 | 513 |
|
514 |
- if(!partsigs) |
|
515 |
- return CL_SUCCESS; |
|
516 |
- |
|
517 |
- data->offmatrix = (int32_t ***) cli_calloc(partsigs, sizeof(int32_t **)); |
|
518 |
- if(!data->offmatrix) { |
|
519 |
- cli_errmsg("cli_ac_init: Can't allocate memory for data->offmatrix\n"); |
|
520 |
- return CL_EMEM; |
|
514 |
+ if(partsigs) { |
|
515 |
+ data->offmatrix = (int32_t ***) cli_calloc(partsigs, sizeof(int32_t **)); |
|
516 |
+ if(!data->offmatrix) { |
|
517 |
+ cli_errmsg("cli_ac_init: Can't allocate memory for data->offmatrix\n"); |
|
518 |
+ return CL_EMEM; |
|
519 |
+ } |
|
521 | 520 |
} |
522 |
- |
|
521 |
+ |
|
522 |
+ data->lsigs = lsigs; |
|
523 |
+ if(lsigs) { |
|
524 |
+ data->lsigcnt = (uint32_t **) cli_malloc(lsigs * sizeof(uint32_t *)); |
|
525 |
+ if(!data->lsigcnt) { |
|
526 |
+ if(partsigs) |
|
527 |
+ free(data->offmatrix); |
|
528 |
+ cli_errmsg("cli_ac_init: Can't allocate memory for data->lsigcnt\n"); |
|
529 |
+ return CL_EMEM; |
|
530 |
+ } |
|
531 |
+ data->lsigcnt[0] = (uint32_t *) cli_calloc(lsigs * 64, sizeof(uint32_t)); |
|
532 |
+ if(!data->lsigcnt[0]) { |
|
533 |
+ free(data->lsigcnt); |
|
534 |
+ if(partsigs) |
|
535 |
+ free(data->offmatrix); |
|
536 |
+ cli_errmsg("cli_ac_init: Can't allocate memory for data->lsigcnt[0]\n"); |
|
537 |
+ return CL_EMEM; |
|
538 |
+ } |
|
539 |
+ for(i = 1; i < lsigs; i++) |
|
540 |
+ data->lsigcnt[i] = data->lsigcnt[0] + 64 * i; |
|
541 |
+ } |
|
542 |
+ |
|
523 | 543 |
return CL_SUCCESS; |
524 | 544 |
} |
525 | 545 |
|
... | ... |
@@ -536,6 +781,13 @@ void cli_ac_freedata(struct cli_ac_data *data) |
536 | 536 |
} |
537 | 537 |
} |
538 | 538 |
free(data->offmatrix); |
539 |
+ data->partsigs = 0; |
|
540 |
+ } |
|
541 |
+ |
|
542 |
+ if(data && data->lsigs) { |
|
543 |
+ free(data->lsigcnt[0]); |
|
544 |
+ free(data->lsigcnt); |
|
545 |
+ data->lsigs = 0; |
|
539 | 546 |
} |
540 | 547 |
} |
541 | 548 |
|
... | ... |
@@ -581,6 +833,7 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
581 | 581 |
uint8_t found; |
582 | 582 |
struct cli_target_info info; |
583 | 583 |
int type = CL_CLEAN; |
584 |
+ unsigned int evalcnt; |
|
584 | 585 |
|
585 | 586 |
|
586 | 587 |
if(!root->ac_root) |
... | ... |
@@ -707,6 +960,12 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
707 | 707 |
} |
708 | 708 |
|
709 | 709 |
} else { /* !pt->type */ |
710 |
+ if(pt->lsigid[0]) { |
|
711 |
+ mdata->lsigcnt[pt->lsigid[1]][pt->lsigid[2]]++; |
|
712 |
+ pt = pt->next; |
|
713 |
+ continue; |
|
714 |
+ } |
|
715 |
+ |
|
710 | 716 |
if(virname) |
711 | 717 |
*virname = pt->virname; |
712 | 718 |
|
... | ... |
@@ -738,6 +997,12 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
738 | 738 |
} |
739 | 739 |
} |
740 | 740 |
} else { |
741 |
+ if(pt->lsigid[0]) { |
|
742 |
+ mdata->lsigcnt[pt->lsigid[1]][pt->lsigid[2]]++; |
|
743 |
+ pt = pt->next; |
|
744 |
+ continue; |
|
745 |
+ } |
|
746 |
+ |
|
741 | 747 |
if(virname) |
742 | 748 |
*virname = pt->virname; |
743 | 749 |
|
... | ... |
@@ -757,11 +1022,20 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
757 | 757 |
if(info.exeinfo.section) |
758 | 758 |
free(info.exeinfo.section); |
759 | 759 |
|
760 |
+ for(i = 0; i < root->ac_lsigs; i++) { |
|
761 |
+ evalcnt = 0; |
|
762 |
+ if(cli_ac_chklsig(root->ac_lsigtable[i]->logic, root->ac_lsigtable[i]->logic + strlen(root->ac_lsigtable[i]->logic), mdata->lsigcnt[i], &evalcnt, 0) == 1) { |
|
763 |
+ if(virname) |
|
764 |
+ *virname = root->ac_lsigtable[i]->virname; |
|
765 |
+ return CL_VIRUS; |
|
766 |
+ } |
|
767 |
+ } |
|
768 |
+ |
|
760 | 769 |
return (mode & AC_SCAN_FT) ? type : CL_CLEAN; |
761 | 770 |
} |
762 | 771 |
|
763 | 772 |
/* FIXME: clean up the code */ |
764 |
-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, uint8_t target, unsigned int options) |
|
773 |
+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, uint8_t target, const uint32_t *lsigid, unsigned int options) |
|
765 | 774 |
{ |
766 | 775 |
struct cli_ac_patt *new; |
767 | 776 |
char *pt, *pt2, *hex = NULL, *hexcpy = NULL; |
... | ... |
@@ -771,6 +1045,11 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex |
771 | 771 |
int ret, error = CL_SUCCESS; |
772 | 772 |
|
773 | 773 |
|
774 |
+ if(!root) { |
|
775 |
+ cli_errmsg("cli_ac_addsig: root == NULL\n"); |
|
776 |
+ return CL_ENULLARG; |
|
777 |
+ } |
|
778 |
+ |
|
774 | 779 |
if(strlen(hexsig) / 2 < root->ac_mindepth) |
775 | 780 |
return CL_EPATSHORT; |
776 | 781 |
|
... | ... |
@@ -787,6 +1066,10 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex |
787 | 787 |
new->target = target; |
788 | 788 |
new->ch[0] |= CLI_MATCH_IGNORE; |
789 | 789 |
new->ch[1] |= CLI_MATCH_IGNORE; |
790 |
+ if(lsigid) { |
|
791 |
+ new->lsigid[0] = 1; |
|
792 |
+ memcpy(&new->lsigid[1], lsigid, 2 * sizeof(uint32_t)); |
|
793 |
+ } |
|
790 | 794 |
|
791 | 795 |
if(strchr(hexsig, '[')) { |
792 | 796 |
if(!(hexcpy = cli_strdup(hexsig))) { |
... | ... |
@@ -1068,6 +1351,9 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex |
1068 | 1068 |
return CL_EMEM; |
1069 | 1069 |
} |
1070 | 1070 |
|
1071 |
+ if(new->lsigid[0]) |
|
1072 |
+ root->ac_lsigtable[new->lsigid[1]]->virname = new->virname; |
|
1073 |
+ |
|
1071 | 1074 |
if(offset) { |
1072 | 1075 |
new->offset = cli_strdup(offset); |
1073 | 1076 |
if(!new->offset) { |
... | ... |
@@ -37,7 +37,8 @@ extern uint8_t cli_ac_mindepth, cli_ac_maxdepth; |
37 | 37 |
|
38 | 38 |
struct cli_ac_data { |
39 | 39 |
int32_t ***offmatrix; |
40 |
- uint32_t partsigs; |
|
40 |
+ uint32_t partsigs, lsigs; |
|
41 |
+ uint32_t **lsigcnt; |
|
41 | 42 |
}; |
42 | 43 |
|
43 | 44 |
struct cli_ac_alt { |
... | ... |
@@ -51,6 +52,7 @@ struct cli_ac_patt { |
51 | 51 |
uint16_t *pattern, *prefix, length, prefix_length; |
52 | 52 |
uint32_t mindist, maxdist; |
53 | 53 |
uint32_t sigid; |
54 |
+ uint32_t lsigid[3]; |
|
54 | 55 |
char *virname, *offset; |
55 | 56 |
uint16_t ch[2]; |
56 | 57 |
uint16_t ch_mindist[2]; |
... | ... |
@@ -72,13 +74,14 @@ struct cli_ac_node { |
72 | 72 |
#include "matcher.h" |
73 | 73 |
|
74 | 74 |
int cli_ac_addpatt(struct cli_matcher *root, struct cli_ac_patt *pattern); |
75 |
-int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint8_t tracklen); |
|
75 |
+int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint32_t lsigs, uint8_t tracklen); |
|
76 |
+int cli_ac_chklsig(const char *expr, const char *end, uint32_t *lsigcnt, unsigned int *cnt, unsigned int parse_only); |
|
76 | 77 |
void cli_ac_freedata(struct cli_ac_data *data); |
77 | 78 |
int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, 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); |
78 | 79 |
int cli_ac_buildtrie(struct cli_matcher *root); |
79 | 80 |
int cli_ac_init(struct cli_matcher *root, uint8_t mindepth, uint8_t maxdepth); |
80 | 81 |
void cli_ac_free(struct cli_matcher *root); |
81 |
-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, uint8_t target, unsigned int options); |
|
82 |
+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, uint8_t target, const uint32_t *lsigid, unsigned int options); |
|
82 | 83 |
void cli_ac_setdepth(uint8_t mindepth, uint8_t maxdepth); |
83 | 84 |
|
84 | 85 |
#endif |
... | ... |
@@ -72,7 +72,7 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, cli_ctx *ctx, cli |
72 | 72 |
|
73 | 73 |
if(troot) { |
74 | 74 |
|
75 |
- if((ret = cli_ac_initdata(&mdata, troot->ac_partsigs, AC_DEFAULT_TRACKLEN))) |
|
75 |
+ if((ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, AC_DEFAULT_TRACKLEN))) |
|
76 | 76 |
return ret; |
77 | 77 |
|
78 | 78 |
if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, troot, 0, ftype, -1)) != CL_VIRUS) |
... | ... |
@@ -84,7 +84,7 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, cli_ctx *ctx, cli |
84 | 84 |
return ret; |
85 | 85 |
} |
86 | 86 |
|
87 |
- if((ret = cli_ac_initdata(&mdata, groot->ac_partsigs, AC_DEFAULT_TRACKLEN))) |
|
87 |
+ if((ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, AC_DEFAULT_TRACKLEN))) |
|
88 | 88 |
return ret; |
89 | 89 |
|
90 | 90 |
if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, groot, 0, ftype, -1)) != CL_VIRUS) |
... | ... |
@@ -295,11 +295,11 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc |
295 | 295 |
return CL_EMEM; |
296 | 296 |
} |
297 | 297 |
|
298 |
- if(!ftonly && (ret = cli_ac_initdata(&gdata, groot->ac_partsigs, AC_DEFAULT_TRACKLEN))) |
|
298 |
+ if(!ftonly && (ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, AC_DEFAULT_TRACKLEN))) |
|
299 | 299 |
return ret; |
300 | 300 |
|
301 | 301 |
if(troot) { |
302 |
- if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, AC_DEFAULT_TRACKLEN))) |
|
302 |
+ if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, groot->ac_lsigs, AC_DEFAULT_TRACKLEN))) |
|
303 | 303 |
return ret; |
304 | 304 |
} |
305 | 305 |
|
... | ... |
@@ -41,6 +41,28 @@ |
41 | 41 |
#define CLI_MATCH_NIBBLE_HIGH 0x0300 |
42 | 42 |
#define CLI_MATCH_NIBBLE_LOW 0x0400 |
43 | 43 |
|
44 |
+struct cli_lsig_tdb { |
|
45 |
+#define CLI_TDB_UINT 0 |
|
46 |
+#define CLI_TDB_RANGE 1 |
|
47 |
+#define CLI_TDB_STR 2 |
|
48 |
+#define CLI_TDB_RANGE2 3 |
|
49 |
+ uint32_t *val, *range; |
|
50 |
+ char *str; |
|
51 |
+ uint32_t cnt[3]; |
|
52 |
+ |
|
53 |
+ const uint32_t *target; |
|
54 |
+ const uint32_t *engine, *nos, *ep; |
|
55 |
+ const uint32_t *sectoff, *sectrva, *sectvsz, *sectraw, *sectrsz, |
|
56 |
+ *secturva, *sectuvsz, *secturaw, *sectursz; |
|
57 |
+}; |
|
58 |
+ |
|
59 |
+struct cli_ac_lsig { |
|
60 |
+ uint32_t id; |
|
61 |
+ char *logic; |
|
62 |
+ const char *virname; |
|
63 |
+ struct cli_lsig_tdb tdb; |
|
64 |
+}; |
|
65 |
+ |
|
44 | 66 |
struct cli_matcher { |
45 | 67 |
/* Extended Boyer-Moore */ |
46 | 68 |
uint8_t *bm_shift; |
... | ... |
@@ -50,7 +72,8 @@ struct cli_matcher { |
50 | 50 |
uint32_t bm_patterns; |
51 | 51 |
|
52 | 52 |
/* Extended Aho-Corasick */ |
53 |
- uint32_t ac_partsigs, ac_nodes, ac_patterns; |
|
53 |
+ uint32_t ac_partsigs, ac_nodes, ac_patterns, ac_lsigs; |
|
54 |
+ struct cli_ac_lsig **ac_lsigtable; |
|
54 | 55 |
struct cli_ac_node *ac_root, **ac_nodetable; |
55 | 56 |
struct cli_ac_patt **ac_pattable; |
56 | 57 |
uint8_t ac_mindepth, ac_maxdepth; |
... | ... |
@@ -18,10 +18,6 @@ |
18 | 18 |
* MA 02110-1301, USA. |
19 | 19 |
*/ |
20 | 20 |
|
21 |
-#ifdef _MSC_VER |
|
22 |
-#include <winsock.h> /* for Sleep() */ |
|
23 |
-#endif |
|
24 |
- |
|
25 | 21 |
#if HAVE_CONFIG_H |
26 | 22 |
#include "clamav-config.h" |
27 | 23 |
#endif |
... | ... |
@@ -58,6 +54,7 @@ |
58 | 58 |
#include "filetypes.h" |
59 | 59 |
#include "filetypes_int.h" |
60 | 60 |
#include "readdb.h" |
61 |
+#include "cltypes.h" |
|
61 | 62 |
|
62 | 63 |
#include "phishcheck.h" |
63 | 64 |
#include "phish_whitelist.h" |
... | ... |
@@ -143,7 +140,7 @@ char *cli_virname(char *virname, unsigned int official, unsigned int allocated) |
143 | 143 |
return virname; |
144 | 144 |
} |
145 | 145 |
|
146 |
-static int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hexsig, uint16_t rtype, uint16_t type, const char *offset, uint8_t target, unsigned int options) |
|
146 |
+static int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hexsig, uint16_t rtype, uint16_t type, const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options) |
|
147 | 147 |
{ |
148 | 148 |
struct cli_bm_patt *bm_new; |
149 | 149 |
char *pt, *hexcpy, *start, *n; |
... | ... |
@@ -186,7 +183,7 @@ static int cli_parse_add(struct cli_matcher *root, const char *virname, const ch |
186 | 186 |
*pt++ = 0; |
187 | 187 |
} |
188 | 188 |
|
189 |
- if((ret = cli_ac_addsig(root, virname, start, root->ac_partsigs, parts, i, rtype, type, mindist, maxdist, offset, target, options))) { |
|
189 |
+ if((ret = cli_ac_addsig(root, virname, start, root->ac_partsigs, parts, i, rtype, type, mindist, maxdist, offset, target, lsigid, options))) { |
|
190 | 190 |
cli_errmsg("cli_parse_add(): Problem adding signature (1).\n"); |
191 | 191 |
error = 1; |
192 | 192 |
break; |
... | ... |
@@ -266,7 +263,7 @@ static int cli_parse_add(struct cli_matcher *root, const char *virname, const ch |
266 | 266 |
return CL_EMALFDB; |
267 | 267 |
} |
268 | 268 |
|
269 |
- if((ret = cli_ac_addsig(root, virname, pt, root->ac_partsigs, parts, i, rtype, type, 0, 0, offset, target, options))) { |
|
269 |
+ if((ret = cli_ac_addsig(root, virname, pt, root->ac_partsigs, parts, i, rtype, type, 0, 0, offset, target, lsigid, options))) { |
|
270 | 270 |
cli_errmsg("cli_parse_add(): Problem adding signature (2).\n"); |
271 | 271 |
free(pt); |
272 | 272 |
return ret; |
... | ... |
@@ -275,8 +272,8 @@ static int cli_parse_add(struct cli_matcher *root, const char *virname, const ch |
275 | 275 |
free(pt); |
276 | 276 |
} |
277 | 277 |
|
278 |
- } else if(root->ac_only || strpbrk(hexsig, "?(") || type) { |
|
279 |
- if((ret = cli_ac_addsig(root, virname, hexsig, 0, 0, 0, rtype, type, 0, 0, offset, target, options))) { |
|
278 |
+ } else if(root->ac_only || strpbrk(hexsig, "?(") || type || lsigid) { |
|
279 |
+ if((ret = cli_ac_addsig(root, virname, hexsig, 0, 0, 0, rtype, type, 0, 0, offset, target, lsigid, options))) { |
|
280 | 280 |
cli_errmsg("cli_parse_add(): Problem adding signature (3).\n"); |
281 | 281 |
return ret; |
282 | 282 |
} |
... | ... |
@@ -490,7 +487,7 @@ static int cli_loaddb(FILE *fs, struct cl_engine **engine, unsigned int *signo, |
490 | 490 |
|
491 | 491 |
if(*pt == '=') continue; |
492 | 492 |
|
493 |
- if((ret = cli_parse_add(root, start, pt, 0, 0, NULL, 0, options))) { |
|
493 |
+ if((ret = cli_parse_add(root, start, pt, 0, 0, NULL, 0, NULL, options))) { |
|
494 | 494 |
ret = CL_EMALFDB; |
495 | 495 |
break; |
496 | 496 |
} |
... | ... |
@@ -669,7 +666,7 @@ static int cli_loadndb(FILE *fs, struct cl_engine **engine, unsigned int *signo, |
669 | 669 |
break; |
670 | 670 |
} |
671 | 671 |
|
672 |
- if((ret = cli_parse_add(root, virname, sig, 0, 0, offset, target, options))) { |
|
672 |
+ if((ret = cli_parse_add(root, virname, sig, 0, 0, offset, target, NULL, options))) { |
|
673 | 673 |
ret = CL_EMALFDB; |
674 | 674 |
break; |
675 | 675 |
} |
... | ... |
@@ -699,6 +696,335 @@ static int cli_loadndb(FILE *fs, struct cl_engine **engine, unsigned int *signo, |
699 | 699 |
return CL_SUCCESS; |
700 | 700 |
} |
701 | 701 |
|
702 |
+struct lsig_attrib { |
|
703 |
+ const char *name; |
|
704 |
+ unsigned int type; |
|
705 |
+ void **pt; |
|
706 |
+}; |
|
707 |
+ |
|
708 |
+/* TODO: rework this */ |
|
709 |
+static int lsigattribs(char *attribs, struct cli_lsig_tdb *tdb) |
|
710 |
+{ |
|
711 |
+ struct lsig_attrib attrtab[] = { |
|
712 |
+#define ATTRIB_TOKENS 2 |
|
713 |
+ { "Target", CLI_TDB_UINT, (void **) &tdb->target }, |
|
714 |
+ { "Engine", CLI_TDB_RANGE, (void **) &tdb->engine }, |
|
715 |
+/* |
|
716 |
+ { "NoS", CLI_TDB_RANGE, (void **) &tdb->nos }, |
|
717 |
+ { "EP", CLI_TDB_RANGE, (void **) &tdb->ep }, |
|
718 |
+ { "SectOff", CLI_TDB_RANGE2, (void **) &tdb->sectoff }, |
|
719 |
+ { "SectRVA", CLI_TDB_RANGE2, (void **) &tdb->sectrva }, |
|
720 |
+ { "SectVSZ", CLI_TDB_RANGE2, (void **) &tdb->sectvsz }, |
|
721 |
+ { "SectRAW", CLI_TDB_RANGE2, (void **) &tdb->sectraw }, |
|
722 |
+ { "SectRSZ", CLI_TDB_RANGE2, (void **) &tdb->sectrsz }, |
|
723 |
+ { "SectURVA", CLI_TDB_RANGE2, (void **) &tdb->secturva }, |
|
724 |
+ { "SectUVSZ", CLI_TDB_RANGE2, (void **) &tdb->sectuvsz }, |
|
725 |
+ { "SectURAW", CLI_TDB_RANGE2, (void **) &tdb->secturaw }, |
|
726 |
+ { "SectURSZ", CLI_TDB_RANGE2, (void **) &tdb->sectursz }, |
|
727 |
+*/ |
|
728 |
+ { NULL, 0, NULL, } |
|
729 |
+ }; |
|
730 |
+ struct lsig_attrib *apt; |
|
731 |
+ char *tokens[ATTRIB_TOKENS], *pt, *pt2; |
|
732 |
+ unsigned int v1, v2, v3, i, j; |
|
733 |
+ uint32_t cnt, off[ATTRIB_TOKENS]; |
|
734 |
+ |
|
735 |
+ |
|
736 |
+ cli_strtokenize(attribs, ',', ATTRIB_TOKENS, (const char **) tokens); |
|
737 |
+ |
|
738 |
+ for(i = 0; tokens[i]; i++) { |
|
739 |
+ if(!(pt = strchr(tokens[i], ':'))) { |
|
740 |
+ cli_errmsg("lsigattribs: Incorrect format of attribute '%s'\n", tokens[i]); |
|
741 |
+ return -1; |
|
742 |
+ } |
|
743 |
+ *pt++ = 0; |
|
744 |
+ |
|
745 |
+ apt = NULL; |
|
746 |
+ for(j = 0; attrtab[j].name; j++) { |
|
747 |
+ if(!strcmp(attrtab[j].name, tokens[i])) { |
|
748 |
+ apt = &attrtab[j]; |
|
749 |
+ break; |
|
750 |
+ } |
|
751 |
+ } |
|
752 |
+ |
|
753 |
+ if(!apt) { |
|
754 |
+ cli_dbgmsg("lsigattribs: Unknown attribute name '%s'\n", tokens[i]); |
|
755 |
+ continue; |
|
756 |
+ } |
|
757 |
+ |
|
758 |
+ switch(apt->type) { |
|
759 |
+ case CLI_TDB_UINT: |
|
760 |
+ off[i] = cnt = tdb->cnt[CLI_TDB_UINT]++; |
|
761 |
+ tdb->val = (uint32_t *) cli_realloc2(tdb->val, tdb->cnt[CLI_TDB_UINT] * sizeof(uint32_t)); |
|
762 |
+ if(!tdb->val) { |
|
763 |
+ tdb->cnt[CLI_TDB_UINT] = 0; |
|
764 |
+ return -1; |
|
765 |
+ } |
|
766 |
+ tdb->val[cnt] = atoi(pt); |
|
767 |
+ break; |
|
768 |
+ |
|
769 |
+ case CLI_TDB_RANGE: |
|
770 |
+ if(!(pt2 = strchr(pt, '-'))) { |
|
771 |
+ cli_errmsg("lsigattribs: Incorrect parameters in '%s'\n", tokens[i]); |
|
772 |
+ return -1; |
|
773 |
+ } |
|
774 |
+ *pt2++ = 0; |
|
775 |
+ off[i] = cnt = tdb->cnt[CLI_TDB_RANGE]; |
|
776 |
+ tdb->cnt[CLI_TDB_RANGE] += 2; |
|
777 |
+ tdb->range = (uint32_t *) cli_realloc2(tdb->range, tdb->cnt[CLI_TDB_RANGE] * sizeof(uint32_t)); |
|
778 |
+ if(!tdb->range) { |
|
779 |
+ tdb->cnt[CLI_TDB_RANGE] = 0; |
|
780 |
+ return -1; |
|
781 |
+ } |
|
782 |
+ tdb->range[cnt] = atoi(pt); |
|
783 |
+ tdb->range[cnt + 1] = atoi(pt2); |
|
784 |
+ break; |
|
785 |
+ |
|
786 |
+ case CLI_TDB_RANGE2: |
|
787 |
+ if(!strchr(pt, '-') || !strchr(pt, '.')) { |
|
788 |
+ cli_errmsg("lsigattribs: Incorrect parameters in '%s'\n", tokens[i]); |
|
789 |
+ return -1; |
|
790 |
+ } |
|
791 |
+ off[i] = cnt = tdb->cnt[CLI_TDB_RANGE]; |
|
792 |
+ tdb->cnt[CLI_TDB_RANGE] += 3; |
|
793 |
+ tdb->range = (uint32_t *) cli_realloc2(tdb->range, tdb->cnt[CLI_TDB_RANGE] * sizeof(uint32_t)); |
|
794 |
+ if(!tdb->range) { |
|
795 |
+ tdb->cnt[CLI_TDB_RANGE] = 0; |
|
796 |
+ return -1; |
|
797 |
+ } |
|
798 |
+ if(sscanf(pt, "%u.%u-%u", &v1, &v2, &v3) != 3) { |
|
799 |
+ cli_errmsg("lsigattribs: Can't parse parameters in '%s'\n", tokens[i]); |
|
800 |
+ return -1; |
|
801 |
+ } |
|
802 |
+ tdb->range[cnt] = (uint32_t) v1; |
|
803 |
+ tdb->range[cnt + 1] = (uint32_t) v2; |
|
804 |
+ tdb->range[cnt + 2] = (uint32_t) v3; |
|
805 |
+ break; |
|
806 |
+ |
|
807 |
+ case CLI_TDB_STR: |
|
808 |
+ off[i] = cnt = tdb->cnt[CLI_TDB_STR]; |
|
809 |
+ tdb->cnt[CLI_TDB_STR] += strlen(pt) + 1; |
|
810 |
+ tdb->str = (char *) cli_realloc2(tdb->str, tdb->cnt[CLI_TDB_STR] * sizeof(char)); |
|
811 |
+ if(!tdb->str) { |
|
812 |
+ cli_errmsg("lsigattribs: Can't allocate memory for tdb->str\n"); |
|
813 |
+ return -1; |
|
814 |
+ } |
|
815 |
+ memcpy(&tdb->str[cnt], pt, strlen(pt)); |
|
816 |
+ tdb->str[tdb->cnt[CLI_TDB_STR] - 1] = 0; |
|
817 |
+ break; |
|
818 |
+ } |
|
819 |
+ } |
|
820 |
+ |
|
821 |
+ if(!i) { |
|
822 |
+ cli_errmsg("lsigattribs: Empty TDB\n"); |
|
823 |
+ return -1; |
|
824 |
+ } |
|
825 |
+ |
|
826 |
+ for(i = 0; tokens[i]; i++) { |
|
827 |
+ for(j = 0; attrtab[j].name; j++) { |
|
828 |
+ if(!strcmp(attrtab[j].name, tokens[i])) { |
|
829 |
+ apt = &attrtab[j]; |
|
830 |
+ break; |
|
831 |
+ } |
|
832 |
+ } |
|
833 |
+ switch(apt->type) { |
|
834 |
+ case CLI_TDB_UINT: |
|
835 |
+ *apt->pt = (uint32_t *) &tdb->val[off[i]]; |
|
836 |
+ break; |
|
837 |
+ |
|
838 |
+ case CLI_TDB_RANGE: |
|
839 |
+ case CLI_TDB_RANGE2: |
|
840 |
+ *apt->pt = (uint32_t *) &tdb->range[off[i]]; |
|
841 |
+ break; |
|
842 |
+ |
|
843 |
+ case CLI_TDB_STR: |
|
844 |
+ *apt->pt = (char *) &tdb->str[off[i]]; |
|
845 |
+ break; |
|
846 |
+ } |
|
847 |
+ } |
|
848 |
+ |
|
849 |
+ return 0; |
|
850 |
+} |
|
851 |
+ |
|
852 |
+#define FREE_TDB(x) \ |
|
853 |
+ if(x.cnt[CLI_TDB_UINT]) \ |
|
854 |
+ free(x.val); \ |
|
855 |
+ if(x.cnt[CLI_TDB_RANGE]) \ |
|
856 |
+ free(x.range); \ |
|
857 |
+ if(x.cnt[CLI_TDB_STR]) \ |
|
858 |
+ free(x.str); |
|
859 |
+ |
|
860 |
+#define LDB_TOKENS 67 |
|
861 |
+static int cli_loadldb(FILE *fs, struct cl_engine **engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio, const char *dbname) |
|
862 |
+{ |
|
863 |
+ char *tokens[LDB_TOKENS]; |
|
864 |
+ char buffer[32768], *pt; |
|
865 |
+ const char *sig, *virname, *offset, *logic; |
|
866 |
+ struct cli_matcher *root; |
|
867 |
+ unsigned int line = 0, sigs = 0; |
|
868 |
+ unsigned short target = 0; |
|
869 |
+ struct cli_ac_lsig **newtable, *lsig; |
|
870 |
+ uint32_t lsigid[2]; |
|
871 |
+ int ret = CL_SUCCESS, i, subsigs; |
|
872 |
+ struct cli_lsig_tdb tdb; |
|
873 |
+ |
|
874 |
+ |
|
875 |
+ if((ret = cli_initengine(engine, options))) { |
|
876 |
+ cl_free(*engine); |
|
877 |
+ return ret; |
|
878 |
+ } |
|
879 |
+ |
|
880 |
+ if((ret = cli_initroots(*engine, options))) { |
|
881 |
+ cl_free(*engine); |
|
882 |
+ return ret; |
|
883 |
+ } |
|
884 |
+ |
|
885 |
+ while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) { |
|
886 |
+ line++; |
|
887 |
+ sigs++; |
|
888 |
+ cli_chomp(buffer); |
|
889 |
+ |
|
890 |
+ cli_strtokenize(buffer, ';', LDB_TOKENS, (const char **) tokens); |
|
891 |
+ |
|
892 |
+ if(!(virname = tokens[0])) { |
|
893 |
+ ret = CL_EMALFDB; |
|
894 |
+ break; |
|
895 |
+ } |
|
896 |
+ |
|
897 |
+ if((*engine)->ignored && cli_chkign((*engine)->ignored, dbname, line, virname)) |
|
898 |
+ continue; |
|
899 |
+ |
|
900 |
+ if(!(logic = tokens[2])) { |
|
901 |
+ ret = CL_EMALFDB; |
|
902 |
+ break; |
|
903 |
+ } |
|
904 |
+ |
|
905 |
+ subsigs = cli_ac_chklsig(logic, logic + strlen(logic), NULL, NULL, 1); |
|
906 |
+ if(subsigs == -1) { |
|
907 |
+ ret = CL_EMALFDB; |
|
908 |
+ break; |
|
909 |
+ } |
|
910 |
+ subsigs++; |
|
911 |
+ |
|
912 |
+ if(subsigs > 64) { |
|
913 |
+ cli_errmsg("cli_loadldb: Broken logical expression or too many subsignatures\n"); |
|
914 |
+ ret = CL_EMALFDB; |
|
915 |
+ break; |
|
916 |
+ } |
|
917 |
+ |
|
918 |
+ /* TDB */ |
|
919 |
+ memset(&tdb, 0, sizeof(tdb)); |
|
920 |
+ |
|
921 |
+ if(lsigattribs(tokens[1], &tdb) == -1) { |
|
922 |
+ FREE_TDB(tdb); |
|
923 |
+ ret = CL_EMALFDB; |
|
924 |
+ break; |
|
925 |
+ } |
|
926 |
+ |
|
927 |
+ if(tdb.engine) { |
|
928 |
+ if(tdb.engine[0] > cl_retflevel()) { |
|
929 |
+ cli_dbgmsg("cli_loadldb: Signature for %s not loaded (required f-level: %u)\n", virname, tdb.engine[0]); |
|
930 |
+ FREE_TDB(tdb); |
|
931 |
+ sigs--; |
|
932 |
+ continue; |
|
933 |
+ } else if(tdb.engine[1] < cl_retflevel()) { |
|
934 |
+ FREE_TDB(tdb); |
|
935 |
+ sigs--; |
|
936 |
+ continue; |
|
937 |
+ } |
|
938 |
+ } |
|
939 |
+ |
|
940 |
+ if(!tdb.target) { |
|
941 |
+ cli_errmsg("cli_loadldb: No target specified in TDB\n"); |
|
942 |
+ FREE_TDB(tdb); |
|
943 |
+ ret = CL_EMALFDB; |
|
944 |
+ break; |
|
945 |
+ } else if(tdb.target[0] >= CLI_MTARGETS) { |
|
946 |
+ cli_dbgmsg("cli_loadldb: Not supported target type in logical signature for %s\n", virname); |
|
947 |
+ FREE_TDB(tdb); |
|
948 |
+ sigs--; |
|
949 |
+ continue; |
|
950 |
+ } |
|
951 |
+ |
|
952 |
+ root = (*engine)->root[tdb.target[0]]; |
|
953 |
+ |
|
954 |
+ lsig = (struct cli_ac_lsig *) cli_calloc(1, sizeof(struct cli_ac_lsig)); |
|
955 |
+ if(!lsig) { |
|
956 |
+ cli_errmsg("cli_loadldb: Can't allocate memory for lsig\n"); |
|
957 |
+ FREE_TDB(tdb); |
|
958 |
+ ret = CL_EMEM; |
|
959 |
+ break; |
|
960 |
+ } |
|
961 |
+ lsig->logic = cli_strdup(logic); |
|
962 |
+ if(!lsig->logic) { |
|
963 |
+ cli_errmsg("cli_loadldb: Can't allocate memory for lsig->logic\n"); |
|
964 |
+ FREE_TDB(tdb); |
|
965 |
+ ret = CL_EMEM; |
|
966 |
+ free(lsig); |
|
967 |
+ break; |
|
968 |
+ } |
|
969 |
+ |
|
970 |
+ lsigid[0] = lsig->id = root->ac_lsigs; |
|
971 |
+ memcpy(&lsig->tdb, &tdb, sizeof(tdb)); |
|
972 |
+ |
|
973 |
+ root->ac_lsigs++; |
|
974 |
+ newtable = (struct cli_ac_lsig **) cli_realloc(root->ac_lsigtable, root->ac_lsigs * sizeof(struct cli_ac_lsig *)); |
|
975 |
+ if(!newtable) { |
|
976 |
+ root->ac_lsigs--; |
|
977 |
+ cli_errmsg("cli_loadldb: Can't realloc root->ac_lsigtable\n"); |
|
978 |
+ FREE_TDB(tdb); |
|
979 |
+ free(lsig); |
|
980 |
+ ret = CL_EMEM; |
|
981 |
+ break; |
|
982 |
+ } |
|
983 |
+ newtable[root->ac_lsigs - 1] = lsig; |
|
984 |
+ root->ac_lsigtable = newtable; |
|
985 |
+ |
|
986 |
+ for(i = 0; i < subsigs; i++) { |
|
987 |
+ if(!tokens[3 + i]) { |
|
988 |
+ cli_errmsg("cli_loadldb: Missing subsignature id %u\n", i); |
|
989 |
+ ret = CL_EMALFDB; |
|
990 |
+ break; |
|
991 |
+ } |
|
992 |
+ lsigid[1] = i; |
|
993 |
+ sig = tokens[3 + i]; |
|
994 |
+ |
|
995 |
+ if((pt = strchr(tokens[3 + i], ':'))) { |
|
996 |
+ *pt = 0; |
|
997 |
+ sig = ++pt; |
|
998 |
+ offset = tokens[3 + i]; |
|
999 |
+ } else { |
|
1000 |
+ offset = NULL; |
|
1001 |
+ sig = tokens[3 + i]; |
|
1002 |
+ } |
|
1003 |
+ |
|
1004 |
+ if((ret = cli_parse_add(root, virname, sig, 0, 0, offset, target, lsigid, options))) { |
|
1005 |
+ ret = CL_EMALFDB; |
|
1006 |
+ break; |
|
1007 |
+ } |
|
1008 |
+ } |
|
1009 |
+ if(ret) |
|
1010 |
+ break; |
|
1011 |
+ } |
|
1012 |
+ |
|
1013 |
+ if(!line) { |
|
1014 |
+ cli_errmsg("Empty database file\n"); |
|
1015 |
+ cl_free(*engine); |
|
1016 |
+ return CL_EMALFDB; |
|
1017 |
+ } |
|
1018 |
+ |
|
1019 |
+ if(ret) { |
|
1020 |
+ cli_errmsg("Problem parsing database at line %u\n", line); |
|
1021 |
+ cl_free(*engine); |
|
1022 |
+ return ret; |
|
1023 |
+ } |
|
1024 |
+ |
|
1025 |
+ if(signo) |
|
1026 |
+ *signo += sigs; |
|
1027 |
+ |
|
1028 |
+ return CL_SUCCESS; |
|
1029 |
+} |
|
1030 |
+ |
|
702 | 1031 |
#define FTM_TOKENS 8 |
703 | 1032 |
static int cli_loadftm(FILE *fs, struct cl_engine **engine, unsigned int options, unsigned int internal, struct cli_dbio *dbio) |
704 | 1033 |
{ |
... | ... |
@@ -766,7 +1092,7 @@ static int cli_loadftm(FILE *fs, struct cl_engine **engine, unsigned int options |
766 | 766 |
} |
767 | 767 |
|
768 | 768 |
if(atoi(tokens[0]) == 1) { /* A-C */ |
769 |
- if((ret = cli_parse_add((*engine)->root[0], tokens[3], tokens[2], rtype, type, strcmp(tokens[1], "*") ? tokens[1] : NULL, 0, options))) |
|
769 |
+ if((ret = cli_parse_add((*engine)->root[0], tokens[3], tokens[2], rtype, type, strcmp(tokens[1], "*") ? tokens[1] : NULL, 0, NULL, options))) |
|
770 | 770 |
break; |
771 | 771 |
|
772 | 772 |
} else if(atoi(tokens[0]) == 0) { /* memcmp() */ |
... | ... |
@@ -1324,6 +1650,15 @@ int cli_load(const char *filename, struct cl_engine **engine, unsigned int *sign |
1324 | 1324 |
else |
1325 | 1325 |
ret = cli_loadndb(fs, engine, signo, 0, options, dbio, dbname); |
1326 | 1326 |
|
1327 |
+ } else if(cli_strbcasestr(filename, ".ldb")) { |
|
1328 |
+ ret = cli_loadldb(fs, engine, signo, options, dbio, dbname); |
|
1329 |
+ |
|
1330 |
+ } else if(cli_strbcasestr(filename, ".ldu")) { |
|
1331 |
+ if(options & CL_DB_PUA) |
|
1332 |
+ ret = cli_loadldb(fs, engine, signo, options, dbio, dbname); |
|
1333 |
+ else |
|
1334 |
+ skipped = 1; |
|
1335 |
+ |
|
1327 | 1336 |
} else if(cli_strbcasestr(dbname, ".sdb")) { |
1328 | 1337 |
ret = cli_loadndb(fs, engine, signo, 1, options, dbio, dbname); |
1329 | 1338 |
|
... | ... |
@@ -1715,7 +2050,7 @@ int cl_statfree(struct cl_stat *dbstat) |
1715 | 1715 |
|
1716 | 1716 |
void cl_free(struct cl_engine *engine) |
1717 | 1717 |
{ |
1718 |
- int i; |
|
1718 |
+ unsigned int i, j; |
|
1719 | 1719 |
struct cli_meta_node *metapt, *metah; |
1720 | 1720 |
struct cli_matcher *root; |
1721 | 1721 |
|
... | ... |
@@ -1749,6 +2084,14 @@ void cl_free(struct cl_engine *engine) |
1749 | 1749 |
if(!root->ac_only) |
1750 | 1750 |
cli_bm_free(root); |
1751 | 1751 |
cli_ac_free(root); |
1752 |
+ if(root->ac_lsigtable) { |
|
1753 |
+ for(j = 0; j < root->ac_lsigs; j++) { |
|
1754 |
+ free(root->ac_lsigtable[j]->logic); |
|
1755 |
+ FREE_TDB(root->ac_lsigtable[j]->tdb); |
|
1756 |
+ free(root->ac_lsigtable[j]); |
|
1757 |
+ } |
|
1758 |
+ free(root->ac_lsigtable); |
|
1759 |
+ } |
|
1752 | 1760 |
free(root); |
1753 | 1761 |
} |
1754 | 1762 |
} |
... | ... |
@@ -39,6 +39,8 @@ |
39 | 39 |
cli_strbcasestr(ext, ".mdu") || \ |
40 | 40 |
cli_strbcasestr(ext, ".ndb") || \ |
41 | 41 |
cli_strbcasestr(ext, ".ndu") || \ |
42 |
+ cli_strbcasestr(ext, ".ldb") || \ |
|
43 |
+ cli_strbcasestr(ext, ".ldu") || \ |
|
42 | 44 |
cli_strbcasestr(ext, ".sdb") || \ |
43 | 45 |
cli_strbcasestr(ext, ".zmd") || \ |
44 | 46 |
cli_strbcasestr(ext, ".rmd") || \ |
... | ... |
@@ -273,7 +273,7 @@ int regex_list_match(struct regex_matcher* matcher,char* real_url,const char* di |
273 | 273 |
buffer[buffer_len]=0; |
274 | 274 |
cli_dbgmsg("Looking up in regex_list: %s\n", buffer); |
275 | 275 |
|
276 |
- if((rc = cli_ac_initdata(&mdata, 0, AC_DEFAULT_TRACKLEN))) |
|
276 |
+ if((rc = cli_ac_initdata(&mdata, 0, 0, AC_DEFAULT_TRACKLEN))) |
|
277 | 277 |
return rc; |
278 | 278 |
|
279 | 279 |
bufrev = cli_strdup(buffer); |