... | ... |
@@ -1066,7 +1066,7 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna |
1066 | 1066 |
free(authorization); |
1067 | 1067 |
|
1068 | 1068 |
memset(ipaddr, 0, sizeof(ipaddr)); |
1069 |
- if(ip[0]) /* use ip to connect */ |
|
1069 |
+ if(ip && ip[0]) /* use ip to connect */ |
|
1070 | 1070 |
sd = wwwconnect(ip, proxy, port, ipaddr, localip, ctimeout, mdat, logerr, can_whitelist); |
1071 | 1071 |
else |
1072 | 1072 |
sd = wwwconnect(hostname, proxy, port, ipaddr, localip, ctimeout, mdat, logerr, can_whitelist); |
... | ... |
@@ -1077,7 +1077,7 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna |
1077 | 1077 |
logg("*Trying to download http://%s/%s (IP: %s)\n", hostname, srcfile, ipaddr); |
1078 | 1078 |
} |
1079 | 1079 |
|
1080 |
- if(!ip[0]) |
|
1080 |
+ if(ip && !ip[0]) |
|
1081 | 1081 |
strcpy(ip, ipaddr); |
1082 | 1082 |
|
1083 | 1083 |
if(send(sd, cmd, strlen(cmd), 0) < 0) { |
... | ... |
@@ -1097,7 +1097,8 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna |
1097 | 1097 |
if((i >= sizeof(buffer) - 1) || recv(sd, buffer + i, 1, 0) == -1) { |
1098 | 1098 |
#endif |
1099 | 1099 |
logg("%cgetfile: Error while reading database from %s (IP: %s): %s\n", logerr ? '!' : '^', hostname, ipaddr, strerror(errno)); |
1100 |
- mirman_update(mdat->currip, mdat->af, mdat, 1); |
|
1100 |
+ if(mdat) |
|
1101 |
+ mirman_update(mdat->currip, mdat->af, mdat, 1); |
|
1101 | 1102 |
closesocket(sd); |
1102 | 1103 |
return 52; |
1103 | 1104 |
} |
... | ... |
@@ -1115,7 +1116,8 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna |
1115 | 1115 |
/* check whether the resource actually existed or not */ |
1116 | 1116 |
if((strstr(buffer, "HTTP/1.1 404")) != NULL || (strstr(buffer, "HTTP/1.0 404")) != NULL) { |
1117 | 1117 |
logg("^getfile: %s not found on remote server (IP: %s)\n", srcfile, ipaddr); |
1118 |
- mirman_update(mdat->currip, mdat->af, mdat, 2); |
|
1118 |
+ if(mdat) |
|
1119 |
+ mirman_update(mdat->currip, mdat->af, mdat, 2); |
|
1119 | 1120 |
closesocket(sd); |
1120 | 1121 |
return 58; |
1121 | 1122 |
} |
... | ... |
@@ -1123,7 +1125,8 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna |
1123 | 1123 |
if(!strstr(buffer, "HTTP/1.1 200") && !strstr(buffer, "HTTP/1.0 200") && |
1124 | 1124 |
!strstr(buffer, "HTTP/1.1 206") && !strstr(buffer, "HTTP/1.0 206")) { |
1125 | 1125 |
logg("%cgetfile: Unknown response from remote server (IP: %s)\n", logerr ? '!' : '^', ipaddr); |
1126 |
- mirman_update(mdat->currip, mdat->af, mdat, 1); |
|
1126 |
+ if(mdat) |
|
1127 |
+ mirman_update(mdat->currip, mdat->af, mdat, 1); |
|
1127 | 1128 |
closesocket(sd); |
1128 | 1129 |
return 58; |
1129 | 1130 |
} |
... | ... |
@@ -1187,7 +1190,8 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna |
1187 | 1187 |
|
1188 | 1188 |
if(bread == -1) { |
1189 | 1189 |
logg("%cgetfile: Download interrupted: %s (IP: %s)\n", logerr ? '!' : '^', strerror(errno), ipaddr); |
1190 |
- mirman_update(mdat->currip, mdat->af, mdat, 2); |
|
1190 |
+ if(mdat) |
|
1191 |
+ mirman_update(mdat->currip, mdat->af, mdat, 2); |
|
1191 | 1192 |
return 52; |
1192 | 1193 |
} |
1193 | 1194 |
|
... | ... |
@@ -1199,7 +1203,8 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna |
1199 | 1199 |
else |
1200 | 1200 |
logg("Downloading %s [*]\n", srcfile); |
1201 | 1201 |
|
1202 |
- mirman_update(mdat->currip, mdat->af, mdat, 0); |
|
1202 |
+ if(mdat) |
|
1203 |
+ mirman_update(mdat->currip, mdat->af, mdat, 0); |
|
1203 | 1204 |
return 0; |
1204 | 1205 |
} |
1205 | 1206 |
|
... | ... |
@@ -1842,6 +1847,170 @@ static int updatedb(const char *dbname, const char *hostname, char *ip, int *sig |
1842 | 1842 |
return 0; |
1843 | 1843 |
} |
1844 | 1844 |
|
1845 |
+static int updatecustomdb(const char *url, int *signo, const struct optstruct *opts, char *localip, int logerr) |
|
1846 |
+{ |
|
1847 |
+ const struct optstruct *opt; |
|
1848 |
+ unsigned int port = 0, newsigs = 0; |
|
1849 |
+ int ret; |
|
1850 |
+ char *pt, *host, urlcpy[256], *newfile = NULL, *newfile2, newdb[32]; |
|
1851 |
+ const char *proxy = NULL, *user = NULL, *pass = NULL, *uas = NULL, *rpath, *dbname; |
|
1852 |
+ int ctimeout, rtimeout; |
|
1853 |
+ struct cl_engine *engine; |
|
1854 |
+ |
|
1855 |
+ |
|
1856 |
+ if(!strncasecmp(url, "http://", 7)) { |
|
1857 |
+ strncpy(urlcpy, url, sizeof(urlcpy)); |
|
1858 |
+ host = &urlcpy[7]; |
|
1859 |
+ if(!(pt = strchr(host, '/'))) { |
|
1860 |
+ logg("!DatabaseCustomURL: Incorrect URL\n"); |
|
1861 |
+ return 70; |
|
1862 |
+ } |
|
1863 |
+ *pt = 0; |
|
1864 |
+ rpath = &url[pt - urlcpy]; |
|
1865 |
+ dbname = strrchr(url, '/') + 1; |
|
1866 |
+ if(!dbname || strlen(dbname) < 4) { |
|
1867 |
+ logg("DatabaseCustomURL: Incorrect URL\n"); |
|
1868 |
+ return 70; |
|
1869 |
+ } |
|
1870 |
+ |
|
1871 |
+ /* Initialize proxy settings */ |
|
1872 |
+ if((opt = optget(opts, "HTTPProxyServer"))->enabled) { |
|
1873 |
+ proxy = opt->strarg; |
|
1874 |
+ if(strncasecmp(proxy, "http://", 7) == 0) |
|
1875 |
+ proxy += 7; |
|
1876 |
+ |
|
1877 |
+ if((opt = optget(opts, "HTTPProxyUsername"))->enabled) { |
|
1878 |
+ user = opt->strarg; |
|
1879 |
+ if((opt = optget(opts, "HTTPProxyPassword"))->enabled) { |
|
1880 |
+ pass = opt->strarg; |
|
1881 |
+ } else { |
|
1882 |
+ logg("HTTPProxyUsername requires HTTPProxyPassword\n"); |
|
1883 |
+ return 56; |
|
1884 |
+ } |
|
1885 |
+ } |
|
1886 |
+ if((opt = optget(opts, "HTTPProxyPort"))->enabled) |
|
1887 |
+ port = opt->numarg; |
|
1888 |
+ logg("Connecting via %s\n", proxy); |
|
1889 |
+ } |
|
1890 |
+ |
|
1891 |
+ if((opt = optget(opts, "HTTPUserAgent"))->enabled) |
|
1892 |
+ uas = opt->strarg; |
|
1893 |
+ |
|
1894 |
+ ctimeout = optget(opts, "ConnectTimeout")->numarg; |
|
1895 |
+ rtimeout = optget(opts, "ReceiveTimeout")->numarg; |
|
1896 |
+ |
|
1897 |
+ newfile = cli_gentemp(updtmpdir); |
|
1898 |
+ if((ret = getfile(rpath, newfile, host, NULL, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, NULL, logerr, 0))) { |
|
1899 |
+ logg("%cCan't download %s from %s\n", logerr ? '!' : '^', dbname, host); |
|
1900 |
+ unlink(newfile); |
|
1901 |
+ free(newfile); |
|
1902 |
+ return ret; |
|
1903 |
+ } |
|
1904 |
+ |
|
1905 |
+ /* FIXME: add IMS support |
|
1906 |
+ if(!nodb && (current->version >= newver)) { |
|
1907 |
+ 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); |
|
1908 |
+ |
|
1909 |
+ *signo += current->sigs; |
|
1910 |
+ cl_cvdfree(current); |
|
1911 |
+ return 1; |
|
1912 |
+ } |
|
1913 |
+ */ |
|
1914 |
+ |
|
1915 |
+ } else if(!strncasecmp(url, "file://", 7)) { |
|
1916 |
+ rpath = &url[7]; |
|
1917 |
+#ifdef _WIN32 |
|
1918 |
+ dbname = strrchr(rpath, '\\'); |
|
1919 |
+#else |
|
1920 |
+ dbname = strrchr(rpath, '/'); |
|
1921 |
+#endif |
|
1922 |
+ if(!dbname || strlen(dbname++) < 5) { |
|
1923 |
+ logg("DatabaseCustomURL: Incorrect URL\n"); |
|
1924 |
+ return 70; |
|
1925 |
+ } |
|
1926 |
+ |
|
1927 |
+ newfile = cli_gentemp(updtmpdir); |
|
1928 |
+ if(!newfile) |
|
1929 |
+ return 70; |
|
1930 |
+ |
|
1931 |
+ /* FIXME: preserve file permissions, calculate % */ |
|
1932 |
+ logg("Downloading %s [ 0%%]\r", dbname); |
|
1933 |
+ if(cli_filecopy(rpath, newfile) == -1) { |
|
1934 |
+ logg("DatabaseCustomURL: Can't copy file %s into database directory\n", rpath); |
|
1935 |
+ free(newfile); |
|
1936 |
+ return 70; |
|
1937 |
+ } |
|
1938 |
+ logg("Downloading %s [100%%]\n", dbname); |
|
1939 |
+ } else { |
|
1940 |
+ logg("!DatabaseCustomURL: Not supported protocol\n"); |
|
1941 |
+ return 70; |
|
1942 |
+ } |
|
1943 |
+ |
|
1944 |
+ if(optget(opts, "TestDatabases")->enabled && strlen(newfile) > 4) { |
|
1945 |
+ newfile2 = malloc(strlen(newfile) + strlen(dbname) + 1); |
|
1946 |
+ if(!newfile2) { |
|
1947 |
+ unlink(newfile); |
|
1948 |
+ free(newfile); |
|
1949 |
+ return 55; |
|
1950 |
+ } |
|
1951 |
+ sprintf(newfile2, "%s%s", newfile, dbname); |
|
1952 |
+ newfile2[strlen(newfile) + strlen(dbname)] = 0; |
|
1953 |
+ if(rename(newfile, newfile2) == -1) { |
|
1954 |
+ logg("!Can't rename %s to %s: %s\n", newfile, newfile2, strerror(errno)); |
|
1955 |
+ unlink(newfile); |
|
1956 |
+ free(newfile); |
|
1957 |
+ free(newfile2); |
|
1958 |
+ return 57; |
|
1959 |
+ } |
|
1960 |
+ free(newfile); |
|
1961 |
+ newfile = newfile2; |
|
1962 |
+ if(!(engine = cl_engine_new())) { |
|
1963 |
+ unlink(newfile); |
|
1964 |
+ free(newfile); |
|
1965 |
+ return 55; |
|
1966 |
+ } |
|
1967 |
+ if((ret = cl_load(newfile, engine, &newsigs, CL_DB_PHISHING | CL_DB_PHISHING_URLS | CL_DB_BYTECODE | CL_DB_PUA)) != CL_SUCCESS) { |
|
1968 |
+ logg("!Failed to load new database: %s\n", cl_strerror(ret)); |
|
1969 |
+ unlink(newfile); |
|
1970 |
+ free(newfile); |
|
1971 |
+ cl_engine_free(engine); |
|
1972 |
+ return 55; |
|
1973 |
+ } |
|
1974 |
+ if(optget(opts, "Bytecode")->enabled && (ret = cli_bytecode_prepare2(engine, &engine->bcs, engine->dconf->bytecode/*FIXME: dconf has no sense here*/))) { |
|
1975 |
+ logg("!Failed to compile/load bytecode: %s\n", cl_strerror(ret)); |
|
1976 |
+ unlink(newfile); |
|
1977 |
+ free(newfile); |
|
1978 |
+ cl_engine_free(engine); |
|
1979 |
+ return 55; |
|
1980 |
+ } |
|
1981 |
+ logg("*Properly loaded %u signatures from new %s\n", newsigs, newdb); |
|
1982 |
+ if(engine->domainlist_matcher && engine->domainlist_matcher->sha256_pfx_set.keys) |
|
1983 |
+ cli_hashset_destroy(&engine->domainlist_matcher->sha256_pfx_set); |
|
1984 |
+ cl_engine_free(engine); |
|
1985 |
+ } |
|
1986 |
+ |
|
1987 |
+#ifdef _WIN32 |
|
1988 |
+ if(!access(dbname, R_OK) && unlink(dbname)) { |
|
1989 |
+ logg("!Can't unlink %s. Please fix the problem manually and try again.\n", newdb); |
|
1990 |
+ unlink(newfile); |
|
1991 |
+ free(newfile); |
|
1992 |
+ return 53; |
|
1993 |
+ } |
|
1994 |
+#endif |
|
1995 |
+ |
|
1996 |
+ if(rename(newfile, dbname) == -1) { |
|
1997 |
+ logg("!Can't rename %s to %s: %s\n", newfile, dbname, strerror(errno)); |
|
1998 |
+ unlink(newfile); |
|
1999 |
+ free(newfile); |
|
2000 |
+ return 57; |
|
2001 |
+ } |
|
2002 |
+ free(newfile); |
|
2003 |
+ logg("%s updated (custom database)\n", dbname); |
|
2004 |
+ |
|
2005 |
+ /* FIXME *signo += current->sigs; */ |
|
2006 |
+ return 0; |
|
2007 |
+} |
|
2008 |
+ |
|
1845 | 2009 |
int downloadmanager(const struct optstruct *opts, const char *hostname, const char *dbdir, int logerr) |
1846 | 2010 |
{ |
1847 | 2011 |
time_t currtime; |
... | ... |
@@ -2046,11 +2215,20 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch |
2046 | 2046 |
} |
2047 | 2047 |
} |
2048 | 2048 |
|
2049 |
+ /* custom dbs */ |
|
2050 |
+ if((opt = optget(opts, "DatabaseCustomURL"))->enabled) { |
|
2051 |
+ while(opt) { |
|
2052 |
+ if(updatecustomdb(opt->strarg, &signo, opts, localip, logerr) == 0) |
|
2053 |
+ updated = 1; |
|
2054 |
+ opt = opt->nextarg; |
|
2055 |
+ } |
|
2056 |
+ } |
|
2057 |
+ |
|
2049 | 2058 |
mirman_write("mirrors.dat", &mdat); |
2050 | 2059 |
cli_rmdirs(updtmpdir); |
2051 | 2060 |
|
2052 | 2061 |
if(updated) { |
2053 |
- if(optget(opts, "HTTPProxyServer")->enabled) { |
|
2062 |
+ if(optget(opts, "HTTPProxyServer")->enabled || !ipaddr[0]) { |
|
2054 | 2063 |
logg("Database updated (%d signatures) from %s\n", signo, hostname); |
2055 | 2064 |
} else { |
2056 | 2065 |
logg("Database updated (%d signatures) from %s (IP: %s)\n", signo, hostname, ipaddr); |
... | ... |
@@ -360,6 +360,8 @@ const struct clam_option __clam_options[] = { |
360 | 360 |
|
361 | 361 |
{ "ExtraDatabase", NULL, 0, TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_FRESHCLAM, "Download additional database. This option can be used multiple times.", "dbname1\ndbname2" }, |
362 | 362 |
|
363 |
+ { "DatabaseCustomURL", NULL, 0, TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_FRESHCLAM, "With this option you can provide custom sources (http:// or file://) for database files.\nThis option can be used multiple times.", "http://myserver.com/mysigs.ndb\nfile:///mnt/nfs/local.hdb" }, |
|
364 |
+ |
|
363 | 365 |
{ "HTTPProxyServer", NULL, 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_FRESHCLAM, "If you're behind a proxy, please enter its address here.", "your-proxy" }, |
364 | 366 |
|
365 | 367 |
{ "HTTPProxyPort", NULL, 0, TYPE_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_FRESHCLAM, "HTTP proxy's port", "8080" }, |