Browse code

freshclam: DatabaseCustomURL: add support for If-Modified-Since and signature counter

Tomasz Kojm authored on 2010/10/30 00:55:54
Showing 4 changed files
... ...
@@ -1,3 +1,8 @@
1
+Fri Oct 29 17:55:10 CEST 2010 (tk)
2
+----------------------------------
3
+ * freshclam: DatabaseCustomURL: add support for If-Modified-Since
4
+	      and signature counter
5
+
1 6
 Thu Oct 28 16:23:47 CEST 2010 (tk)
2 7
 ----------------------------------
3 8
  * freshclam: add initial support for DatabaseCustomURL
... ...
@@ -106,6 +106,11 @@ By default freshclam will keep the local databases (.cld) uncompressed to make t
106 106
 .br 
107 107
 Default: no
108 108
 .TP 
109
+\fBDatabaseCustomURL STR\fR
110
+With this option you can provide custom sources (http:// or file://) for database files. This option can be used multiple times.
111
+.br 
112
+Default: no custom URLs
113
+.TP 
109 114
 \fBHTTPProxyServer STR\fR, \fBHTTPProxyPort NUMBER\fR
110 115
 Use given proxy server and TCP port for database downloads.
111 116
 .TP 
... ...
@@ -87,6 +87,12 @@ DatabaseMirror database.clamav.net
87 87
 # Default: no
88 88
 #CompressLocalDatabase no
89 89
 
90
+# With this option you can provide custom sources (http:// or file://) for
91
+# database files. This option can be used multiple times.
92
+# Default: no custom URLs
93
+#DatabaseCustomURL http://myserver.com/mysigs.ndb
94
+#DatabaseCustomURL file:///mnt/nfs/local.hdb
95
+
90 96
 # Number of database checks per day.
91 97
 # Default: 12 (every two hours)
92 98
 #Checks 24
... ...
@@ -1016,14 +1016,14 @@ static struct cl_cvd *remote_cvdhead(const char *cvdfile, const char *localfile,
1016 1016
     return cvd;
1017 1017
 }
1018 1018
 
1019
-static int getfile(const char *srcfile, const char *destfile, const char *hostname, char *ip, const char *localip, const char *proxy, int port, const char *user, const char *pass, const char *uas, int ctimeout, int rtimeout, struct mirdat *mdat, int logerr, unsigned int can_whitelist)
1019
+static int getfile(const char *srcfile, const char *destfile, const char *hostname, char *ip, const char *localip, const char *proxy, int port, const char *user, const char *pass, const char *uas, int ctimeout, int rtimeout, struct mirdat *mdat, int logerr, unsigned int can_whitelist, const char *ims)
1020 1020
 {
1021 1021
 	char cmd[512], uastr[128], buffer[FILEBUFF], *ch;
1022 1022
 	int bread, fd, totalsize = 0,  rot = 0, totaldownloaded = 0,
1023 1023
 	    percentage = 0, sd;
1024 1024
 	unsigned int i;
1025 1025
 	char *remotename = NULL, *authorization = NULL, *headerline, ipaddr[46];
1026
-	const char *rotation = "|/-\\";
1026
+	const char *rotation = "|/-\\", *fname;
1027 1027
 
1028 1028
 
1029 1029
     if(proxy) {
... ...
@@ -1043,6 +1043,9 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
1043 1043
 	}
1044 1044
     }
1045 1045
 
1046
+    if(ims)
1047
+	logg("*If-Modified-Since: %s\n", ims);
1048
+
1046 1049
     if(uas)
1047 1050
 	strncpy(uastr, uas, sizeof(uastr));
1048 1051
     else
... ...
@@ -1057,7 +1060,8 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
1057 1057
 	"Cache-Control: no-cache\r\n"
1058 1058
 #endif
1059 1059
 	"Connection: close\r\n"
1060
-	"\r\n", (remotename != NULL) ? remotename : "", srcfile, hostname, (authorization != NULL) ? authorization : "", uastr);
1060
+	"%s%s%s"
1061
+	"\r\n", (remotename != NULL) ? remotename : "", srcfile, hostname, (authorization != NULL) ? authorization : "", uastr, ims ? "If-Modified-Since: " : "", ims ? ims : "", ims ? "\r\n": "");
1061 1062
 
1062 1063
     if(remotename)
1063 1064
 	free(remotename);
... ...
@@ -1122,6 +1126,14 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
1122 1122
 	return 58;
1123 1123
     }
1124 1124
 
1125
+    /* If-Modified-Since */
1126
+    if(strstr(buffer, "HTTP/1.1 304") || strstr(buffer, "HTTP/1.0 304")) { 
1127
+	if(mdat)
1128
+	    mirman_update(mdat->currip, mdat->af, mdat, 0);
1129
+	closesocket(sd);
1130
+	return 1;
1131
+    }
1132
+
1125 1133
     if(!strstr(buffer, "HTTP/1.1 200") && !strstr(buffer, "HTTP/1.0 200") &&
1126 1134
        !strstr(buffer, "HTTP/1.1 206") && !strstr(buffer, "HTTP/1.0 206")) {
1127 1135
 	logg("%cgetfile: Unknown response from remote server (IP: %s)\n", logerr ? '!' : '^', ipaddr);
... ...
@@ -1157,6 +1169,11 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
1157 1157
 	return 57;
1158 1158
     }
1159 1159
 
1160
+    if((fname = strrchr(srcfile, '/')))
1161
+	fname++;
1162
+    else
1163
+	fname = srcfile;
1164
+
1160 1165
 #ifdef SO_ERROR
1161 1166
     while((bread = wait_recv(sd, buffer, FILEBUFF, 0, rtimeout)) > 0) {
1162 1167
 #else
... ...
@@ -1176,9 +1193,9 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
1176 1176
 
1177 1177
         if(!mprintf_quiet) {
1178 1178
             if(totalsize > 0) {
1179
-                mprintf("Downloading %s [%3i%%]\r", srcfile, percentage);
1179
+                mprintf("Downloading %s [%3i%%]\r", fname, percentage);
1180 1180
             } else {
1181
-                mprintf("Downloading %s [%c]\r", srcfile, rotation[rot]);
1181
+                mprintf("Downloading %s [%c]\r", fname, rotation[rot]);
1182 1182
                 rot++;
1183 1183
                 rot %= 4;
1184 1184
             }
... ...
@@ -1199,9 +1216,9 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
1199 1199
 	return 53;
1200 1200
 
1201 1201
     if(totalsize > 0)
1202
-        logg("Downloading %s [%i%%]\n", srcfile, percentage);
1202
+        logg("Downloading %s [100%%]\n", fname);
1203 1203
     else
1204
-        logg("Downloading %s [*]\n", srcfile);
1204
+        logg("Downloading %s [*]\n", fname);
1205 1205
 
1206 1206
     if(mdat)
1207 1207
 	mirman_update(mdat->currip, mdat->af, mdat, 0);
... ...
@@ -1215,7 +1232,7 @@ static int getcvd(const char *cvdfile, const char *newfile, const char *hostname
1215 1215
 
1216 1216
 
1217 1217
     logg("*Retrieving http://%s/%s\n", hostname, cvdfile);
1218
-    if((ret = getfile(cvdfile, newfile, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat, logerr, can_whitelist))) {
1218
+    if((ret = getfile(cvdfile, newfile, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat, logerr, can_whitelist, NULL))) {
1219 1219
         logg("%cCan't download %s from %s\n", logerr ? '!' : '^', cvdfile, hostname);
1220 1220
         unlink(newfile);
1221 1221
         return ret;
... ...
@@ -1298,7 +1315,7 @@ static int getpatch(const char *dbname, const char *tmpdir, int version, const c
1298 1298
     snprintf(patch, sizeof(patch), "%s-%d.cdiff", dbname, version);
1299 1299
 
1300 1300
     logg("*Retrieving http://%s/%s\n", hostname, patch);
1301
-    if((ret = getfile(patch, tempname, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat, logerr, can_whitelist))) {
1301
+    if((ret = getfile(patch, tempname, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat, logerr, can_whitelist, NULL))) {
1302 1302
 	if(ret == 53)
1303 1303
 	    logg("Empty script %s, need to download entire database\n", patch);
1304 1304
 	else
... ...
@@ -1850,13 +1867,14 @@ static int updatedb(const char *dbname, const char *hostname, char *ip, int *sig
1850 1850
 static int updatecustomdb(const char *url, int *signo, const struct optstruct *opts, char *localip, int logerr)
1851 1851
 {
1852 1852
 	const struct optstruct *opt;
1853
-	unsigned int port = 0, newsigs = 0;
1853
+	unsigned int port = 0, newsigs = 0, sigs = 0;
1854 1854
 	int ret;
1855
-	char *pt, *host, urlcpy[256], *newfile = NULL, *newfile2, newdb[32];
1855
+	char *pt, *host, urlcpy[256], *newfile = NULL, mtime[36], *newfile2;
1856 1856
 	const char *proxy = NULL, *user = NULL, *pass = NULL, *uas = NULL, *rpath, *dbname;
1857 1857
 	int ctimeout, rtimeout;
1858 1858
 	struct cl_engine *engine;
1859
-
1859
+	struct stat sb;
1860
+	struct cl_cvd *cvd;
1860 1861
 
1861 1862
     if(!strncasecmp(url, "http://", 7)) {
1862 1863
 	strncpy(urlcpy, url, sizeof(urlcpy));
... ...
@@ -1899,24 +1917,24 @@ static int updatecustomdb(const char *url, int *signo, const struct optstruct *o
1899 1899
 	ctimeout = optget(opts, "ConnectTimeout")->numarg;
1900 1900
 	rtimeout = optget(opts, "ReceiveTimeout")->numarg;
1901 1901
 
1902
+	*mtime = 0;
1903
+	if(stat(dbname, &sb) != -1)
1904
+	    Rfc2822DateTime(mtime, sb.st_mtime);
1905
+
1902 1906
 	newfile = cli_gentemp(updtmpdir);
1903
-	if((ret = getfile(rpath, newfile, host, NULL, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, NULL, logerr, 0))) {
1907
+	ret = getfile(rpath, newfile, host, NULL, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, NULL, logerr, 0, *mtime ? mtime : NULL);
1908
+	if(ret == 1) {
1909
+	    logg("%s is up to date (version: custom database)\n", dbname);
1910
+	    unlink(newfile);
1911
+	    free(newfile);
1912
+	    return 1;
1913
+	} else if(ret > 1) {
1904 1914
 	    logg("%cCan't download %s from %s\n", logerr ? '!' : '^', dbname, host);
1905 1915
 	    unlink(newfile);
1906 1916
 	    free(newfile);
1907 1917
 	    return ret;
1908 1918
 	}
1909 1919
 
1910
-	/* FIXME: add IMS support
1911
-	if(!nodb && (current->version >= newver)) {
1912
-	    logg("%s is up to date (version: %d, sigs: %d, f-level: %d, builder: %s)\n", localname, current->version, current->sigs, current->fl, current->builder);
1913
-
1914
-	    *signo += current->sigs;
1915
-	    cl_cvdfree(current);
1916
-	    return 1;
1917
-	}
1918
-	*/
1919
-
1920 1920
     } else if(!strncasecmp(url, "file://", 7)) {
1921 1921
 	rpath = &url[7];
1922 1922
 #ifdef _WIN32
... ...
@@ -1983,7 +2001,7 @@ static int updatecustomdb(const char *url, int *signo, const struct optstruct *o
1983 1983
 	    cl_engine_free(engine);
1984 1984
 	    return 55;
1985 1985
 	}
1986
-	logg("*Properly loaded %u signatures from new %s\n", newsigs, newdb);
1986
+	logg("*Properly loaded %u signatures from new (custom) %s\n", newsigs, dbname);
1987 1987
 	if(engine->domainlist_matcher && engine->domainlist_matcher->sha256_pfx_set.keys)
1988 1988
 	    cli_hashset_destroy(&engine->domainlist_matcher->sha256_pfx_set);
1989 1989
 	cl_engine_free(engine);
... ...
@@ -1991,7 +2009,7 @@ static int updatecustomdb(const char *url, int *signo, const struct optstruct *o
1991 1991
 
1992 1992
 #ifdef _WIN32
1993 1993
     if(!access(dbname, R_OK) && unlink(dbname)) {
1994
-	logg("!Can't unlink %s. Please fix the problem manually and try again.\n", newdb);
1994
+	logg("!Can't unlink %s. Please fix the problem manually and try again.\n", dbname);
1995 1995
 	unlink(newfile);
1996 1996
 	free(newfile);
1997 1997
 	return 53;
... ...
@@ -2005,9 +2023,20 @@ static int updatecustomdb(const char *url, int *signo, const struct optstruct *o
2005 2005
 	return 57;
2006 2006
     }
2007 2007
     free(newfile);
2008
-    logg("%s updated (version: custom database)\n", dbname);
2009 2008
 
2010
-    /* FIXME *signo += current->sigs; */
2009
+    if(cli_strbcasestr(dbname, ".cld") || cli_strbcasestr(dbname, ".cvd")) {
2010
+	if((cvd = cl_cvdhead(dbname))) {
2011
+	    sigs = cvd->sigs;
2012
+	    cl_cvdfree(cvd);
2013
+	}
2014
+    } else if(cli_strbcasestr(dbname, ".cbc")) {
2015
+	sigs = 1;
2016
+    } else {
2017
+	sigs = countlines(dbname);
2018
+    }
2019
+
2020
+    logg("%s updated (version: custom database, sigs: %u)\n", dbname, sigs);
2021
+    *signo += sigs;
2011 2022
     return 0;
2012 2023
 }
2013 2024