Browse code

sigtool: add support for building unsigned dbs (--unsigned) libclamav: handle unsigned db files (.cud)

Tomasz Kojm authored on 2011/05/11 04:29:49
Showing 9 changed files
... ...
@@ -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")) {
... ...
@@ -57,6 +57,7 @@
57 57
 	cli_strbcasestr(ext, ".cfg")   ||	\
58 58
 	cli_strbcasestr(ext, ".cvd")   ||	\
59 59
 	cli_strbcasestr(ext, ".cld")   ||	\
60
+	cli_strbcasestr(ext, ".cud")   ||	\
60 61
 	cli_strbcasestr(ext, ".cdb")   ||	\
61 62
 	cli_strbcasestr(ext, ".idb")		\
62 63
     )
... ...
@@ -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");