... | ... |
@@ -1,3 +1,8 @@ |
1 |
+Tue May 10 21:25:37 CEST 2011 (tk) |
|
2 |
+---------------------------------- |
|
3 |
+ * sigtool: add support for building unsigned dbs (--unsigned) |
|
4 |
+ * libclamav: handle unsigned db files (.cud) |
|
5 |
+ |
|
1 | 6 |
Sat May 7 18:05:23 EEST 2011 (edwin) |
2 | 7 |
------------------------------------- |
3 | 8 |
* libclamav/pdf.c: better detection for encrypted PDFs (bb #2448) |
... | ... |
@@ -57,6 +57,12 @@ Print a CVD information and verify MD5 and a digital signature. |
57 | 57 |
\fB\-b, \-\-build\fR |
58 | 58 |
Build a CVD file. \-s, \-\-server is required. |
59 | 59 |
.TP |
60 |
+\fB\-b, \-\-no\-cdiff\fR |
|
61 |
+Don't create a .cdiff file when building a new database file. |
|
62 |
+.TP |
|
63 |
+\fB\-b, \-\-unsigned\fR |
|
64 |
+Create a database file without digital signatures (.cua). |
|
65 |
+.TP |
|
60 | 66 |
\fB\-\-server\fR |
61 | 67 |
ClamAV Signing Service address (for virus database maintainers only). |
62 | 68 |
.TP |
... | ... |
@@ -94,6 +94,7 @@ typedef enum { |
94 | 94 |
#define CL_DB_BYTECODE 0x2000 |
95 | 95 |
#define CL_DB_SIGNED 0x4000 /* internal */ |
96 | 96 |
#define CL_DB_BYTECODE_UNSIGNED 0x8000 |
97 |
+#define CL_DB_UNSIGNED 0x10000 /* internal */ |
|
97 | 98 |
|
98 | 99 |
/* recommended db settings */ |
99 | 100 |
#define CL_DB_STDOPT (CL_DB_PHISHING | CL_DB_PHISHING_URLS | CL_DB_BYTECODE) |
... | ... |
@@ -488,7 +488,7 @@ void cl_cvdfree(struct cl_cvd *cvd) |
488 | 488 |
free(cvd); |
489 | 489 |
} |
490 | 490 |
|
491 |
-static int cli_cvdverify(FILE *fs, struct cl_cvd *cvdpt, unsigned int cld) |
|
491 |
+static int cli_cvdverify(FILE *fs, struct cl_cvd *cvdpt, unsigned int skipsig) |
|
492 | 492 |
{ |
493 | 493 |
struct cl_cvd *cvd; |
494 | 494 |
char *md5, head[513]; |
... | ... |
@@ -510,7 +510,7 @@ static int cli_cvdverify(FILE *fs, struct cl_cvd *cvdpt, unsigned int cld) |
510 | 510 |
if(cvdpt) |
511 | 511 |
memcpy(cvdpt, cvd, sizeof(struct cl_cvd)); |
512 | 512 |
|
513 |
- if(cld) { |
|
513 |
+ if(skipsig) { |
|
514 | 514 |
cl_cvdfree(cvd); |
515 | 515 |
return CL_SUCCESS; |
516 | 516 |
} |
... | ... |
@@ -562,7 +562,7 @@ int cl_cvdverify(const char *file) |
562 | 562 |
return ret; |
563 | 563 |
} |
564 | 564 |
|
565 |
-int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, unsigned int cld, const char *filename, unsigned int chkonly) |
|
565 |
+int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, unsigned int dbtype, const char *filename, unsigned int chkonly) |
|
566 | 566 |
{ |
567 | 567 |
struct cl_cvd cvd, dupcvd; |
568 | 568 |
FILE *dupfs; |
... | ... |
@@ -576,32 +576,34 @@ int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigne |
576 | 576 |
cli_dbgmsg("in cli_cvdload()\n"); |
577 | 577 |
|
578 | 578 |
/* verify */ |
579 |
- if((ret = cli_cvdverify(fs, &cvd, cld))) |
|
579 |
+ if((ret = cli_cvdverify(fs, &cvd, dbtype))) |
|
580 | 580 |
return ret; |
581 | 581 |
|
582 |
- /* check for duplicate db */ |
|
583 |
- dupname = cli_strdup(filename); |
|
584 |
- if(!dupname) |
|
585 |
- return CL_EMEM; |
|
586 |
- dupname[strlen(dupname) - 2] = (cld ? 'v' : 'l'); |
|
587 |
- if(!access(dupname, R_OK) && (dupfs = fopen(dupname, "rb"))) { |
|
588 |
- if((ret = cli_cvdverify(dupfs, &dupcvd, !cld))) { |
|
582 |
+ if(dbtype <= 1) { |
|
583 |
+ /* check for duplicate db */ |
|
584 |
+ dupname = cli_strdup(filename); |
|
585 |
+ if(!dupname) |
|
586 |
+ return CL_EMEM; |
|
587 |
+ dupname[strlen(dupname) - 2] = (dbtype == 1 ? 'v' : 'l'); |
|
588 |
+ if(!access(dupname, R_OK) && (dupfs = fopen(dupname, "rb"))) { |
|
589 |
+ if((ret = cli_cvdverify(dupfs, &dupcvd, !dbtype))) { |
|
590 |
+ fclose(dupfs); |
|
591 |
+ free(dupname); |
|
592 |
+ return ret; |
|
593 |
+ } |
|
589 | 594 |
fclose(dupfs); |
590 |
- free(dupname); |
|
591 |
- return ret; |
|
592 |
- } |
|
593 |
- fclose(dupfs); |
|
594 |
- if(dupcvd.version > cvd.version) { |
|
595 |
- cli_warnmsg("Detected duplicate databases %s and %s. The %s database is older and will not be loaded, you should manually remove it from the database directory.\n", filename, dupname, filename); |
|
596 |
- free(dupname); |
|
597 |
- return CL_SUCCESS; |
|
598 |
- } else if(dupcvd.version == cvd.version && !cld) { |
|
599 |
- cli_warnmsg("Detected duplicate databases %s and %s, please manually remove one of them\n", filename, dupname); |
|
600 |
- free(dupname); |
|
601 |
- return CL_SUCCESS; |
|
595 |
+ if(dupcvd.version > cvd.version) { |
|
596 |
+ cli_warnmsg("Detected duplicate databases %s and %s. The %s database is older and will not be loaded, you should manually remove it from the database directory.\n", filename, dupname, filename); |
|
597 |
+ free(dupname); |
|
598 |
+ return CL_SUCCESS; |
|
599 |
+ } else if(dupcvd.version == cvd.version && !dbtype) { |
|
600 |
+ cli_warnmsg("Detected duplicate databases %s and %s, please manually remove one of them\n", filename, dupname); |
|
601 |
+ free(dupname); |
|
602 |
+ return CL_SUCCESS; |
|
603 |
+ } |
|
602 | 604 |
} |
605 |
+ free(dupname); |
|
603 | 606 |
} |
604 |
- free(dupname); |
|
605 | 607 |
|
606 | 608 |
if(strstr(filename, "daily.")) { |
607 | 609 |
time(&s_time); |
... | ... |
@@ -631,7 +633,10 @@ int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigne |
631 | 631 |
|
632 | 632 |
cfd = fileno(fs); |
633 | 633 |
dbio.chkonly = 0; |
634 |
- ret = cli_tgzload(cfd, engine, signo, options | CL_DB_OFFICIAL, &dbio, NULL); |
|
634 |
+ if(dbtype == 2) |
|
635 |
+ ret = cli_tgzload(cfd, engine, signo, options | CL_DB_UNSIGNED, &dbio, NULL); |
|
636 |
+ else |
|
637 |
+ ret = cli_tgzload(cfd, engine, signo, options | CL_DB_OFFICIAL, &dbio, NULL); |
|
635 | 638 |
if(ret != CL_SUCCESS) |
636 | 639 |
return ret; |
637 | 640 |
|
... | ... |
@@ -645,8 +650,12 @@ int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigne |
645 | 645 |
return CL_EMALFDB; |
646 | 646 |
|
647 | 647 |
dbio.chkonly = chkonly; |
648 |
- options |= CL_DB_SIGNED; |
|
649 |
- ret = cli_tgzload(cfd, engine, signo, options | CL_DB_OFFICIAL, &dbio, dbinfo); |
|
648 |
+ if(dbtype == 2) |
|
649 |
+ options |= CL_DB_UNSIGNED; |
|
650 |
+ else |
|
651 |
+ options |= CL_DB_SIGNED | CL_DB_OFFICIAL; |
|
652 |
+ |
|
653 |
+ ret = cli_tgzload(cfd, engine, signo, options, &dbio, dbinfo); |
|
650 | 654 |
|
651 | 655 |
while(engine->dbinfo) { |
652 | 656 |
dbinfo = engine->dbinfo; |
... | ... |
@@ -37,7 +37,7 @@ struct cli_dbio { |
37 | 37 |
SHA256_CTX sha256ctx; |
38 | 38 |
}; |
39 | 39 |
|
40 |
-int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, unsigned int cld, const char *filename, unsigned int chkonly); |
|
40 |
+int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, unsigned int dbtype, const char *filename, unsigned int chkonly); |
|
41 | 41 |
int cli_cvdunpack(const char *file, const char *dir); |
42 | 42 |
|
43 | 43 |
#endif |
... | ... |
@@ -1696,7 +1696,7 @@ static int cli_loadinfo(FILE *fs, struct cl_engine *engine, unsigned int options |
1696 | 1696 |
sha256_init(&ctx); |
1697 | 1697 |
while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) { |
1698 | 1698 |
line++; |
1699 |
- if(!strncmp(buffer, "DSIG:", 5)) { |
|
1699 |
+ if(!(options & CL_DB_UNSIGNED) && !strncmp(buffer, "DSIG:", 5)) { |
|
1700 | 1700 |
dsig = 1; |
1701 | 1701 |
sha256_final(&ctx, hash); |
1702 | 1702 |
if(cli_versig2(hash, buffer + 5, INFO_NSTR, INFO_ESTR) != CL_SUCCESS) { |
... | ... |
@@ -1775,7 +1775,7 @@ static int cli_loadinfo(FILE *fs, struct cl_engine *engine, unsigned int options |
1775 | 1775 |
last = new; |
1776 | 1776 |
} |
1777 | 1777 |
|
1778 |
- if(!dsig) { |
|
1778 |
+ if(!(options & CL_DB_UNSIGNED) && !dsig) { |
|
1779 | 1779 |
cli_errmsg("cli_loadinfo: Digital signature not found\n"); |
1780 | 1780 |
return CL_EMALFDB; |
1781 | 1781 |
} |
... | ... |
@@ -2382,6 +2382,9 @@ int cli_load(const char *filename, struct cl_engine *engine, unsigned int *signo |
2382 | 2382 |
} else if(cli_strbcasestr(dbname, ".cld")) { |
2383 | 2383 |
ret = cli_cvdload(fs, engine, signo, options, 1, filename, 0); |
2384 | 2384 |
|
2385 |
+ } else if(cli_strbcasestr(dbname, ".cud")) { |
|
2386 |
+ ret = cli_cvdload(fs, engine, signo, options, 2, filename, 0); |
|
2387 |
+ |
|
2385 | 2388 |
} else if(cli_strbcasestr(dbname, ".hdb") || cli_strbcasestr(dbname, ".hsb")) { |
2386 | 2389 |
ret = cli_loadhash(fs, engine, signo, MD5_HDB, options, dbio, dbname); |
2387 | 2390 |
} else if(cli_strbcasestr(dbname, ".hdu") || cli_strbcasestr(dbname, ".hsu")) { |
... | ... |
@@ -104,6 +104,7 @@ const struct clam_option __clam_options[] = { |
104 | 104 |
{ NULL, "html-normalise", 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" }, |
105 | 105 |
{ NULL, "utf16-decode", 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" }, |
106 | 106 |
{ NULL, "build", 'b', TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" }, |
107 |
+ { NULL, "unsigned", 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", "" }, |
|
107 | 108 |
{ NULL, "no-cdiff", 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", "" }, |
108 | 109 |
{ NULL, "server", 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" }, |
109 | 110 |
{ NULL, "unpack", 'u', TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" }, |
... | ... |
@@ -24,6 +24,8 @@ |
24 | 24 |
#include "clamav-config.h" |
25 | 25 |
#endif |
26 | 26 |
|
27 |
+#define _GNU_SOURCE |
|
28 |
+ |
|
27 | 29 |
#include <stdio.h> |
28 | 30 |
#include <stdlib.h> |
29 | 31 |
#include <string.h> |
... | ... |
@@ -116,7 +118,7 @@ static char *getdbname(const char *str, char *dst, int dstlen) |
116 | 116 |
{ |
117 | 117 |
int len = strlen(str); |
118 | 118 |
|
119 |
- if(cli_strbcasestr(str, ".cvd") || cli_strbcasestr(str, ".cld")) |
|
119 |
+ if(cli_strbcasestr(str, ".cvd") || cli_strbcasestr(str, ".cld") || cli_strbcasestr(str, ".cud")) |
|
120 | 120 |
len -= 4; |
121 | 121 |
|
122 | 122 |
if(dst) { |
... | ... |
@@ -474,18 +476,20 @@ static int writeinfo(const char *dbname, const char *builder, const char *header |
474 | 474 |
} |
475 | 475 |
} |
476 | 476 |
} |
477 |
- rewind(fh); |
|
478 |
- sha256_init(&ctx); |
|
479 |
- while((bytes = fread(buffer, 1, sizeof(buffer), fh))) |
|
480 |
- sha256_update(&ctx, buffer, bytes); |
|
481 |
- sha256_final(&ctx, digest); |
|
482 |
- if(!(pt = getdsig(optget(opts, "server")->strarg, builder, digest, 32, 3))) { |
|
483 |
- mprintf("!writeinfo: Can't get digital signature from remote server\n"); |
|
484 |
- fclose(fh); |
|
485 |
- return -1; |
|
477 |
+ if(!optget(opts, "unsigned")->enabled) { |
|
478 |
+ rewind(fh); |
|
479 |
+ sha256_init(&ctx); |
|
480 |
+ while((bytes = fread(buffer, 1, sizeof(buffer), fh))) |
|
481 |
+ sha256_update(&ctx, buffer, bytes); |
|
482 |
+ sha256_final(&ctx, digest); |
|
483 |
+ if(!(pt = getdsig(optget(opts, "server")->strarg, builder, digest, 32, 3))) { |
|
484 |
+ mprintf("!writeinfo: Can't get digital signature from remote server\n"); |
|
485 |
+ fclose(fh); |
|
486 |
+ return -1; |
|
487 |
+ } |
|
488 |
+ fprintf(fh, "DSIG:%s\n", pt); |
|
489 |
+ free(pt); |
|
486 | 490 |
} |
487 |
- fprintf(fh, "DSIG:%s\n", pt); |
|
488 |
- free(pt); |
|
489 | 491 |
fclose(fh); |
490 | 492 |
return 0; |
491 | 493 |
} |
... | ... |
@@ -643,7 +647,7 @@ static int build(const struct optstruct *opts) |
643 | 643 |
free(x[i]); \ |
644 | 644 |
free(x); |
645 | 645 |
|
646 |
- if(!optget(opts, "server")->enabled) { |
|
646 |
+ if(!optget(opts, "server")->enabled && !optget(opts, "unsigned")->enabled) { |
|
647 | 647 |
mprintf("!build: --server is required for --build\n"); |
648 | 648 |
return -1; |
649 | 649 |
} |
... | ... |
@@ -741,11 +745,11 @@ static int build(const struct optstruct *opts) |
741 | 741 |
|
742 | 742 |
/* try to read cvd header of current database */ |
743 | 743 |
if(opts->filename) { |
744 |
- if(cli_strbcasestr(opts->filename[0], ".cvd") || cli_strbcasestr(opts->filename[0], ".cld")) { |
|
744 |
+ if(cli_strbcasestr(opts->filename[0], ".cvd") || cli_strbcasestr(opts->filename[0], ".cld") || cli_strbcasestr(opts->filename[0], ".cud")) { |
|
745 | 745 |
strncpy(olddb, opts->filename[0], sizeof(olddb)); |
746 | 746 |
olddb[sizeof(olddb)-1]='\0'; |
747 | 747 |
} else { |
748 |
- mprintf("!build: Not a CVD/CLD file\n"); |
|
748 |
+ mprintf("!build: Not a CVD/CLD/CUD file\n"); |
|
749 | 749 |
FREE_LS(dblist2); |
750 | 750 |
return -1; |
751 | 751 |
} |
... | ... |
@@ -755,6 +759,8 @@ static int build(const struct optstruct *opts) |
755 | 755 |
snprintf(olddb, sizeof(olddb), "%s"PATHSEP"%s.cvd", localdbdir ? localdbdir : pt, dbname); |
756 | 756 |
if(access(olddb, R_OK)) |
757 | 757 |
snprintf(olddb, sizeof(olddb), "%s"PATHSEP"%s.cld", localdbdir ? localdbdir : pt, dbname); |
758 |
+ if(access(olddb, R_OK)) |
|
759 |
+ snprintf(olddb, sizeof(olddb), "%s"PATHSEP"%s.cud", localdbdir ? localdbdir : pt, dbname); |
|
758 | 760 |
free(pt); |
759 | 761 |
} |
760 | 762 |
|
... | ... |
@@ -916,15 +922,19 @@ static int build(const struct optstruct *opts) |
916 | 916 |
sprintf(header + strlen(header), "%s:", pt); |
917 | 917 |
free(pt); |
918 | 918 |
|
919 |
- if(!(pt = getdsig(optget(opts, "server")->strarg, builder, buffer, 16, 1))) { |
|
920 |
- mprintf("!build: Can't get digital signature from remote server\n"); |
|
921 |
- fclose(fh); |
|
922 |
- unlink(tarfile); |
|
923 |
- free(tarfile); |
|
924 |
- return -1; |
|
919 |
+ if(!optget(opts, "unsigned")->enabled) { |
|
920 |
+ if(!(pt = getdsig(optget(opts, "server")->strarg, builder, buffer, 16, 1))) { |
|
921 |
+ mprintf("!build: Can't get digital signature from remote server\n"); |
|
922 |
+ fclose(fh); |
|
923 |
+ unlink(tarfile); |
|
924 |
+ free(tarfile); |
|
925 |
+ return -1; |
|
926 |
+ } |
|
927 |
+ sprintf(header + strlen(header), "%s:", pt); |
|
928 |
+ free(pt); |
|
929 |
+ } else { |
|
930 |
+ sprintf(header + strlen(header), "X:"); |
|
925 | 931 |
} |
926 |
- sprintf(header + strlen(header), "%s:", pt); |
|
927 |
- free(pt); |
|
928 | 932 |
|
929 | 933 |
/* add builder */ |
930 | 934 |
strcat(header, builder); |
... | ... |
@@ -982,6 +992,9 @@ static int build(const struct optstruct *opts) |
982 | 982 |
|
983 | 983 |
mprintf("Created %s\n", newcvd); |
984 | 984 |
|
985 |
+ if(optget(opts, "unsigned")->enabled) |
|
986 |
+ return 0; |
|
987 |
+ |
|
985 | 988 |
if(!oldcvd || optget(opts, "no-cdiff")->enabled) { |
986 | 989 |
mprintf("Skipping .cdiff creation\n"); |
987 | 990 |
return 0; |
... | ... |
@@ -2726,6 +2739,7 @@ static void help(void) |
2726 | 2726 |
mprintf(" --info=FILE -i FILE print database information\n"); |
2727 | 2727 |
mprintf(" --build=NAME [cvd] -b NAME build a CVD file\n"); |
2728 | 2728 |
mprintf(" --no-cdiff Don't generate .cdiff file\n"); |
2729 |
+ mprintf(" --unsigned Create unsigned database file (.cud)\n"); |
|
2729 | 2730 |
mprintf(" --server=ADDR ClamAV Signing Service address\n"); |
2730 | 2731 |
mprintf(" --datadir=DIR Use DIR as default database directory\n"); |
2731 | 2732 |
mprintf(" --unpack=FILE -u FILE Unpack a CVD/CLD file\n"); |