... | ... |
@@ -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 |
|