Browse code

freshclam: add support for ExtraDatabase (bb#781)

Tomasz Kojm authored on 2010/03/19 22:37:51
Showing 4 changed files
... ...
@@ -1,3 +1,7 @@
1
+Fri Mar 19 14:37:18 CET 2010 (tk)
2
+---------------------------------
3
+ * freshclam: add support for ExtraDatabase (bb#781)
4
+
1 5
 Tue Mar 16 04:11:02 CET 2010 (acab)
2 6
 -----------------------------------
3 7
  * win32: add sigtool upon request from 3rd party sigmakers
... ...
@@ -49,7 +49,8 @@ char *txtquery(const char *domain, unsigned int *ttl)
49 49
 	unsigned int cttl, size, txtlen = 0;
50 50
 
51 51
 
52
-    *ttl = 0;
52
+    if(ttl)
53
+	*ttl = 0;
53 54
     if(res_init() < 0) {
54 55
 	logg("^res_init failed\n");
55 56
 	return NULL;
... ...
@@ -136,7 +137,8 @@ char *txtquery(const char *domain, unsigned int *ttl)
136 136
 
137 137
     memcpy(txt, pt+1, txtlen);
138 138
     txt[txtlen] = 0;
139
-    *ttl = cttl;
139
+    if(ttl)
140
+	*ttl = cttl;
140 141
 
141 142
     return txt;
142 143
 }
... ...
@@ -1456,13 +1456,14 @@ static int buildcld(const char *tmpdir, const char *dbname, const char *newfile,
1456 1456
     return 0;
1457 1457
 }
1458 1458
 
1459
-static int updatedb(const char *dbname, const char *hostname, char *ip, int *signo, const struct optstruct *opts, const char *dnsreply, char *localip, int outdated, struct mirdat *mdat, int logerr)
1459
+static int updatedb(const char *dbname, const char *hostname, char *ip, int *signo, const struct optstruct *opts, const char *dnsreply, char *localip, int outdated, struct mirdat *mdat, int logerr, int extra)
1460 1460
 {
1461 1461
 	struct cl_cvd *current, *remote;
1462 1462
 	const struct optstruct *opt;
1463 1463
 	unsigned int nodb = 0, currver = 0, newver = 0, port = 0, i, j;
1464 1464
 	int ret, ims = -1;
1465 1465
 	char *pt, cvdfile[32], localname[32], *tmpdir = NULL, *newfile, newdb[32], cwd[512];
1466
+	char extradbinfo[64], *extradnsreply = NULL;
1466 1467
 	const char *proxy = NULL, *user = NULL, *pass = NULL, *uas = NULL;
1467 1468
 	unsigned int flevel = cl_retflevel(), remote_flevel = 0, maxattempts;
1468 1469
 	unsigned int can_whitelist = 0;
... ...
@@ -1477,7 +1478,7 @@ static int updatedb(const char *dbname, const char *hostname, char *ip, int *sig
1477 1477
 	mdat->dbflevel = current->fl;
1478 1478
     }
1479 1479
 
1480
-    if(!nodb && dnsreply) {
1480
+    if(!nodb && !extra && dnsreply) {
1481 1481
 	    int field = 0;
1482 1482
 
1483 1483
 	if(!strcmp(dbname, "main")) {
... ...
@@ -1506,8 +1507,43 @@ static int updatedb(const char *dbname, const char *hostname, char *ip, int *sig
1506 1506
 	    logg("^Invalid DNS reply. Falling back to HTTP mode.\n");
1507 1507
 	}
1508 1508
     }
1509
+#ifdef HAVE_RESOLV_H
1510
+    else if(!nodb && extra && !optget(opts, "no-dns")->enabled) {
1511
+	snprintf(extradbinfo, sizeof(extradbinfo), "%s.cvd.clamav.net", dbname);
1512
+	if((extradnsreply = txtquery(extradbinfo, NULL))) {
1513
+	    if((pt = cli_strtok(extradnsreply, 1, ":"))) {
1514
+		    int rt;
1515
+		    time_t ct;
1516
+
1517
+		rt = atoi(pt);
1518
+		free(pt);
1519
+		time(&ct);
1520
+		if((int) ct - rt > 10800) {
1521
+		    logg("^DNS record is older than 3 hours.\n");
1522
+		    free(extradnsreply);
1523
+		    extradnsreply = NULL;
1524
+		}
1525
+	    } else {
1526
+		logg("^No timestamp in TXT record for %s\n", cvdfile);
1527
+		free(extradnsreply);
1528
+		extradnsreply = NULL;
1529
+	    }
1530
+	    if((pt = cli_strtok(extradnsreply, 0, ":"))) {
1531
+		if(!cli_isnumber(pt)) {
1532
+		    logg("^Broken database version in TXT record for %s\n", cvdfile);
1533
+		} else {
1534
+		    newver = atoi(pt);
1535
+		    logg("*%s version from DNS: %d\n", cvdfile, newver);
1536
+		}
1537
+		free(pt);
1538
+	    } else {
1539
+		logg("^Invalid DNS reply. Falling back to HTTP mode.\n");
1540
+	    }
1541
+	}
1542
+    }
1543
+#endif
1509 1544
 
1510
-    if(dnsreply) {
1545
+    if(dnsreply && !extra) {
1511 1546
 	if((pt = cli_strtok(dnsreply, 5, ":"))) {
1512 1547
 	    remote_flevel = atoi(pt);
1513 1548
 	    free(pt);
... ...
@@ -1814,7 +1850,7 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch
1814 1814
 
1815 1815
     memset(ipaddr, 0, sizeof(ipaddr));
1816 1816
 
1817
-    if((ret = updatedb("main", hostname, ipaddr, &signo, opts, dnsreply, localip, outdated, &mdat, logerr)) > 50) {
1817
+    if((ret = updatedb("main", hostname, ipaddr, &signo, opts, dnsreply, localip, outdated, &mdat, logerr, 0)) > 50) {
1818 1818
 	if(dnsreply)
1819 1819
 	    free(dnsreply);
1820 1820
 
... ...
@@ -1828,7 +1864,7 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch
1828 1828
 	updated = 1;
1829 1829
 
1830 1830
     /* if ipaddr[0] != 0 it will use it to connect to the web host */
1831
-    if((ret = updatedb("daily", hostname, ipaddr, &signo, opts, dnsreply, localip, outdated, &mdat, logerr)) > 50) {
1831
+    if((ret = updatedb("daily", hostname, ipaddr, &signo, opts, dnsreply, localip, outdated, &mdat, logerr, 0)) > 50) {
1832 1832
 	if(dnsreply)
1833 1833
 	    free(dnsreply);
1834 1834
 
... ...
@@ -1856,7 +1892,7 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch
1856 1856
 	    else
1857 1857
 		logg("*%s removed\n", safedb);
1858 1858
 	}
1859
-    } else if((ret = updatedb("safebrowsing", hostname, ipaddr, &signo, opts, dnsreply, localip, outdated, &mdat, logerr)) > 50) {
1859
+    } else if((ret = updatedb("safebrowsing", hostname, ipaddr, &signo, opts, dnsreply, localip, outdated, &mdat, logerr, 0)) > 50) {
1860 1860
 	if(dnsreply)
1861 1861
 	    free(dnsreply);
1862 1862
 
... ...
@@ -1882,7 +1918,7 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch
1882 1882
 	    else
1883 1883
 		logg("*%s removed\n", dbname);
1884 1884
 	}
1885
-    } else if((ret = updatedb("bytecode", hostname, ipaddr, &signo, opts, dnsreply, localip, outdated, &mdat, logerr)) > 50) {
1885
+    } else if((ret = updatedb("bytecode", hostname, ipaddr, &signo, opts, dnsreply, localip, outdated, &mdat, logerr, 0)) > 50) {
1886 1886
 	if(dnsreply)
1887 1887
 	    free(dnsreply);
1888 1888
 
... ...
@@ -1896,6 +1932,20 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch
1896 1896
     if(dnsreply)
1897 1897
 	free(dnsreply);
1898 1898
 
1899
+    /* handle extra dbs */
1900
+    if((opt = optget(opts, "ExtraDatabase"))->enabled) {
1901
+	while(opt) {
1902
+	    if((ret = updatedb(opt->strarg, hostname, ipaddr, &signo, opts, NULL, localip, outdated, &mdat, logerr, 1)) > 50) {
1903
+		if(newver)
1904
+		    free(newver);
1905
+		mirman_write("mirrors.dat", &mdat);
1906
+		return ret;
1907
+	    } else if(ret == 0)
1908
+		updated = 1;
1909
+	    opt = opt->nextarg;
1910
+	}
1911
+    }
1912
+
1899 1913
     mirman_write("mirrors.dat", &mdat);
1900 1914
 
1901 1915
     if(updated) {
... ...
@@ -346,6 +346,8 @@ const struct clam_option __clam_options[] = {
346 346
 
347 347
     { "CompressLocalDatabase", NULL, 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM, "By default freshclam will keep the local databases (.cld) uncompressed to\nmake their handling faster. With this option you can enable the compression.\nThe change will take effect with the next database update.", "" },
348 348
 
349
+    { "ExtraDatabase", NULL, 0, TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_FRESHCLAM, "Download additional database. This option can be used multiple times.", "dbname1\ndbname2" },
350
+
349 351
     { "HTTPProxyServer", NULL, 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_FRESHCLAM, "If you're behind a proxy, please enter its address here.", "your-proxy" },
350 352
 
351 353
     { "HTTPProxyPort", NULL, 0, TYPE_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_FRESHCLAM, "HTTP proxy's port", "8080" },