git-svn: trunk@2207
Nigel Horne authored on 2006/08/25 19:23:51... | ... |
@@ -1,3 +1,11 @@ |
1 |
+Fri Aug 25 11:22:24 BST 2006 (njh) |
|
2 |
+---------------------------------- |
|
3 |
+ * clamav-milter: Start a separate thread for each load balancing server |
|
4 |
+ that is being queried |
|
5 |
+ When not in internal mode, don't send headers to clamd |
|
6 |
+ that it will discard (cf usefulHeaders() in |
|
7 |
+ libclamav/mbox.c) |
|
8 |
+ |
|
1 | 9 |
Wed Aug 23 07:54:15 BST 2006 (njh) |
2 | 10 |
---------------------------------- |
3 | 11 |
* clamav-milter: --report-phish didn't work with --quarantine-dir |
... | ... |
@@ -23,9 +23,9 @@ |
23 | 23 |
* |
24 | 24 |
* For installation instructions see the file INSTALL that came with this file |
25 | 25 |
*/ |
26 |
-static char const rcsid[] = "$Id: clamav-milter.c,v 1.280 2006/08/23 06:52:53 njh Exp $"; |
|
26 |
+static char const rcsid[] = "$Id: clamav-milter.c,v 1.281 2006/08/25 10:21:54 njh Exp $"; |
|
27 | 27 |
|
28 |
-#define CM_VERSION "devel-230806" |
|
28 |
+#define CM_VERSION "devel-250806" |
|
29 | 29 |
|
30 | 30 |
#if HAVE_CONFIG_H |
31 | 31 |
#include "clamav-config.h" |
... | ... |
@@ -252,6 +252,13 @@ struct privdata { |
252 | 252 |
static int createSession(unsigned int s); |
253 | 253 |
#else |
254 | 254 |
static int pingServer(int serverNumber); |
255 |
+static void *try_server(void *var); |
|
256 |
+struct try_server_struct { |
|
257 |
+ int sock; |
|
258 |
+ int rc; |
|
259 |
+ struct sockaddr_in *server; |
|
260 |
+ int server_index; |
|
261 |
+}; |
|
255 | 262 |
#endif |
256 | 263 |
static int findServer(void); |
257 | 264 |
static sfsistat clamfi_connect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr); |
... | ... |
@@ -520,6 +527,7 @@ static void mx(void); |
520 | 520 |
static void resolve(const char *host); |
521 | 521 |
#endif |
522 | 522 |
static sfsistat black_hole(const struct privdata *privdata); |
523 |
+static int useful_header(const char *cmd); |
|
523 | 524 |
|
524 | 525 |
extern short logg_time, logg_lock, logg_verbose, logg_foreground; |
525 | 526 |
extern int logg_size; |
... | ... |
@@ -2105,9 +2113,11 @@ static int |
2105 | 2105 |
findServer(void) |
2106 | 2106 |
{ |
2107 | 2107 |
struct sockaddr_in *servers, *server; |
2108 |
- int *socks, maxsock = -1, i, j; |
|
2108 |
+ int maxsock, i, j; |
|
2109 | 2109 |
fd_set rfds; |
2110 | 2110 |
int retval; |
2111 |
+ pthread_t *tids; |
|
2112 |
+ struct try_server_struct *socks; |
|
2111 | 2113 |
|
2112 | 2114 |
assert(tcpSocket != 0); |
2113 | 2115 |
assert(numServers > 0); |
... | ... |
@@ -2118,9 +2128,7 @@ findServer(void) |
2118 | 2118 |
servers = (struct sockaddr_in *)cli_calloc(numServers, sizeof(struct sockaddr_in)); |
2119 | 2119 |
if(servers == NULL) |
2120 | 2120 |
return 0; |
2121 |
- socks = (int *)cli_malloc(numServers * sizeof(int)); |
|
2122 |
- |
|
2123 |
- FD_ZERO(&rfds); |
|
2121 |
+ socks = (struct try_server_struct *)cli_malloc(numServers * sizeof(struct try_server_struct)); |
|
2124 | 2122 |
|
2125 | 2123 |
if(max_children > 0) { |
2126 | 2124 |
assert(n_children > 0); |
... | ... |
@@ -2139,6 +2147,11 @@ findServer(void) |
2139 | 2139 |
*/ |
2140 | 2140 |
j = cli_rndnum(numServers); |
2141 | 2141 |
|
2142 |
+ tids = cli_malloc(numServers * sizeof(pthread_t)); |
|
2143 |
+ |
|
2144 |
+ for(i = 0; i < numServers; i++) |
|
2145 |
+ socks[i].sock = -1; |
|
2146 |
+ |
|
2142 | 2147 |
for(i = 0, server = servers; i < numServers; i++, server++) { |
2143 | 2148 |
int sock; |
2144 | 2149 |
int server_index = (i + j) % numServers; |
... | ... |
@@ -2149,45 +2162,53 @@ findServer(void) |
2149 | 2149 |
|
2150 | 2150 |
logg("*findServer: try server %d\n", server_index); |
2151 | 2151 |
|
2152 |
- sock = socks[i] = socket(AF_INET, SOCK_STREAM, 0); |
|
2152 |
+ sock = socks[i].sock = socket(AF_INET, SOCK_STREAM, 0); |
|
2153 | 2153 |
|
2154 | 2154 |
if(sock < 0) { |
2155 | 2155 |
perror("socket"); |
2156 |
- do |
|
2157 |
- if(socks[i] >= 0) |
|
2158 |
- close(socks[i]); |
|
2159 |
- while(--i >= 0); |
|
2156 |
+ do { |
|
2157 |
+ if(socks[i].sock >= 0) |
|
2158 |
+ close(socks[i].sock); |
|
2159 |
+ pthread_join(tids[i], NULL); |
|
2160 |
+ } while(--i >= 0); |
|
2160 | 2161 |
free(socks); |
2161 | 2162 |
free(servers); |
2162 | 2163 |
return 0; /* Use the first server on failure */ |
2163 | 2164 |
} |
2164 | 2165 |
|
2165 |
- if((connect(sock, (struct sockaddr *)server, sizeof(struct sockaddr)) < 0) || |
|
2166 |
- (send(sock, "PING\n", 5, 0) < 5)) { |
|
2167 |
-#ifdef MAXHOSTNAMELEN |
|
2168 |
- char hostname[MAXHOSTNAMELEN + 1]; |
|
2166 |
+ socks[i].server = server; |
|
2167 |
+ socks[i].server_index = server_index; |
|
2169 | 2168 |
|
2170 |
- cli_strtokbuf(serverHostNames, server_index, ":", hostname); |
|
2171 |
- if(strcmp(hostname, "127.0.0.1") == 0) |
|
2172 |
- gethostname(hostname, sizeof(hostname)); |
|
2173 |
-#else |
|
2174 |
- char *hostname = cli_strtok(serverHostNames, server_index, ":"); |
|
2175 |
-#endif |
|
2176 |
- logg(_("^Check clamd server %s - it may be down\n"), hostname); |
|
2177 |
- close(sock); |
|
2178 |
-#ifndef MAXHOSTNAMELEN |
|
2179 |
- free(hostname); |
|
2180 |
-#endif |
|
2181 |
- broadcast(_("Check clamd server - it may be down\n")); |
|
2182 |
- socks[i] = -1; |
|
2183 |
- continue; |
|
2169 |
+ if(pthread_create(&tids[i], NULL, try_server, &socks[i]) != 0) { |
|
2170 |
+ perror("pthread_create"); |
|
2171 |
+ do { |
|
2172 |
+ if(socks[i].sock >= 0) |
|
2173 |
+ close(socks[i].sock); |
|
2174 |
+ pthread_join(tids[i], NULL); |
|
2175 |
+ } while(--i >= 0); |
|
2176 |
+ free(socks); |
|
2177 |
+ free(servers); |
|
2178 |
+ return 0; /* Use the first server on failure */ |
|
2184 | 2179 |
} |
2180 |
+ } |
|
2181 |
+ |
|
2182 |
+ maxsock = -1; |
|
2183 |
+ FD_ZERO(&rfds); |
|
2185 | 2184 |
|
2186 |
- shutdown(sock, SHUT_WR); |
|
2185 |
+ for(i = 0; i < numServers; i++) { |
|
2186 |
+ struct try_server_struct *rc; |
|
2187 | 2187 |
|
2188 |
- FD_SET(sock, &rfds); |
|
2189 |
- if(sock > maxsock) |
|
2190 |
- maxsock = sock; |
|
2188 |
+ pthread_join(tids[i], &rc); |
|
2189 |
+ assert(rc->sock == socks[i].sock); |
|
2190 |
+ if(rc->rc == 0) { |
|
2191 |
+ close(rc->sock); |
|
2192 |
+ socks[i].sock = -1; |
|
2193 |
+ } else { |
|
2194 |
+ shutdown(rc->sock, SHUT_WR); |
|
2195 |
+ FD_SET(rc->sock, &rfds); |
|
2196 |
+ if(rc->sock > maxsock) |
|
2197 |
+ maxsock = rc->sock; |
|
2198 |
+ } |
|
2191 | 2199 |
} |
2192 | 2200 |
|
2193 | 2201 |
free(servers); |
... | ... |
@@ -2208,8 +2229,8 @@ findServer(void) |
2208 | 2208 |
perror("select"); |
2209 | 2209 |
|
2210 | 2210 |
for(i = 0; i < numServers; i++) |
2211 |
- if(socks[i] >= 0) |
|
2212 |
- close(socks[i]); |
|
2211 |
+ if(socks[i].sock >= 0) |
|
2212 |
+ close(socks[i].sock); |
|
2213 | 2213 |
|
2214 | 2214 |
if(retval == 0) { |
2215 | 2215 |
free(socks); |
... | ... |
@@ -2217,13 +2238,12 @@ findServer(void) |
2217 | 2217 |
return 0; |
2218 | 2218 |
} else if(retval < 0) { |
2219 | 2219 |
free(socks); |
2220 |
- if(use_syslog) |
|
2221 |
- syslog(LOG_ERR, _("findServer: select failed")); |
|
2220 |
+ logg(_("^findServer: select failed (maxsock = %d)\n"), maxsock); |
|
2222 | 2221 |
return 0; |
2223 | 2222 |
} |
2224 | 2223 |
|
2225 | 2224 |
for(i = 0; i < numServers; i++) |
2226 |
- if((socks[i] >= 0) && (FD_ISSET(socks[i], &rfds))) { |
|
2225 |
+ if((socks[i].sock >= 0) && (FD_ISSET(socks[i].sock, &rfds))) { |
|
2227 | 2226 |
const int s = (i + j) % numServers; |
2228 | 2227 |
|
2229 | 2228 |
free(socks); |
... | ... |
@@ -2235,6 +2255,49 @@ findServer(void) |
2235 | 2235 |
logg(_("^findServer: No response from any server\n")); |
2236 | 2236 |
return 0; |
2237 | 2237 |
} |
2238 |
+ |
|
2239 |
+/* |
|
2240 |
+ * Connecting to remote servers can take some time, so let's connect to |
|
2241 |
+ * them in parallel. This routine is started as a thread |
|
2242 |
+ */ |
|
2243 |
+static void * |
|
2244 |
+try_server(void *var) |
|
2245 |
+{ |
|
2246 |
+ struct try_server_struct *s = (struct try_server_struct *)var; |
|
2247 |
+ int sock = s->sock; |
|
2248 |
+ struct sockaddr *server = (struct sockaddr *)s->server; |
|
2249 |
+ int server_index = s->server_index; |
|
2250 |
+ |
|
2251 |
+ logg("*try_server: sock %d\n", sock); |
|
2252 |
+ |
|
2253 |
+ if(connect(sock, server, sizeof(struct sockaddr)) < 0) { |
|
2254 |
+ perror("connect"); |
|
2255 |
+ s->rc = 0; |
|
2256 |
+ } else if(send(sock, "PING\n", 5, 0) < 5) { |
|
2257 |
+ perror("send"); |
|
2258 |
+ s->rc = 0; |
|
2259 |
+ } else |
|
2260 |
+ s->rc = 1; |
|
2261 |
+ |
|
2262 |
+ if(s->rc == 0) { |
|
2263 |
+#ifdef MAXHOSTNAMELEN |
|
2264 |
+ char hostname[MAXHOSTNAMELEN + 1]; |
|
2265 |
+ |
|
2266 |
+ cli_strtokbuf(serverHostNames, server_index, ":", hostname); |
|
2267 |
+ if(strcmp(hostname, "127.0.0.1") == 0) |
|
2268 |
+ gethostname(hostname, sizeof(hostname)); |
|
2269 |
+#else |
|
2270 |
+ char *hostname = cli_strtok(serverHostNames, server_index, ":"); |
|
2271 |
+#endif |
|
2272 |
+ logg(_("^Check clamd server %s - it may be down\n"), hostname); |
|
2273 |
+#ifndef MAXHOSTNAMELEN |
|
2274 |
+ free(hostname); |
|
2275 |
+#endif |
|
2276 |
+ broadcast(_("Check clamd server - it may be down\n")); |
|
2277 |
+ } |
|
2278 |
+ |
|
2279 |
+ return var; |
|
2280 |
+} |
|
2238 | 2281 |
#endif |
2239 | 2282 |
|
2240 | 2283 |
/* |
... | ... |
@@ -2472,7 +2535,7 @@ clamfi_envfrom(SMFICTX *ctx, char **argv) |
2472 | 2472 |
struct privdata *privdata; |
2473 | 2473 |
const char *mailaddr = argv[0]; |
2474 | 2474 |
|
2475 |
- logg("*clamfi_envfrom: %s", argv[0]); |
|
2475 |
+ logg("*clamfi_envfrom: %s\n", argv[0]); |
|
2476 | 2476 |
|
2477 | 2477 |
if(strcmp(argv[0], "<>") == 0) { |
2478 | 2478 |
mailaddr = smfi_getsymval(ctx, "{mail_addr}"); |
... | ... |
@@ -2657,9 +2720,9 @@ clamfi_header(SMFICTX *ctx, char *headerf, char *headerv) |
2657 | 2657 |
if(debug_level >= 9) |
2658 | 2658 |
logg("*clamfi_header: %s: %s\n", headerf, headerv); |
2659 | 2659 |
else |
2660 |
- logg("*clamfi_header\n"); |
|
2660 |
+ logg("*clamfi_header: %s\n", headerf); |
|
2661 | 2661 |
#else |
2662 |
- logg("*clamfi_header\n"); |
|
2662 |
+ logg("*clamfi_header: %s\n", headerf); |
|
2663 | 2663 |
#endif |
2664 | 2664 |
|
2665 | 2665 |
/* |
... | ... |
@@ -2667,20 +2730,6 @@ clamfi_header(SMFICTX *ctx, char *headerf, char *headerv) |
2667 | 2667 |
*/ |
2668 | 2668 |
privdata->rejectCode = "554"; |
2669 | 2669 |
|
2670 |
- if(privdata->dataSocket == -1) |
|
2671 |
- /* |
|
2672 |
- * First header - make connection with clamd |
|
2673 |
- */ |
|
2674 |
- if(!connect2clamd(privdata)) { |
|
2675 |
- clamfi_cleanup(ctx); |
|
2676 |
- return cl_error; |
|
2677 |
- } |
|
2678 |
- |
|
2679 |
- if(clamfi_send(privdata, 0, "%s: %s\n", headerf, headerv) <= 0) { |
|
2680 |
- clamfi_cleanup(ctx); |
|
2681 |
- return cl_error; |
|
2682 |
- } |
|
2683 |
- |
|
2684 | 2670 |
if(hflag) |
2685 | 2671 |
header_list_add(privdata->headers, headerf, headerv); |
2686 | 2672 |
else if((strcasecmp(headerf, "Received") == 0) && |
... | ... |
@@ -2708,6 +2757,25 @@ clamfi_header(SMFICTX *ctx, char *headerf, char *headerv) |
2708 | 2708 |
privdata->sender = strdup(headerv); |
2709 | 2709 |
} |
2710 | 2710 |
|
2711 |
+ if(!useful_header(headerf)) { |
|
2712 |
+ logg("*Discarded the header\n"); |
|
2713 |
+ return SMFIS_CONTINUE; |
|
2714 |
+ } |
|
2715 |
+ |
|
2716 |
+ if(privdata->dataSocket == -1) |
|
2717 |
+ /* |
|
2718 |
+ * First header - make connection with clamd |
|
2719 |
+ */ |
|
2720 |
+ if(!connect2clamd(privdata)) { |
|
2721 |
+ clamfi_cleanup(ctx); |
|
2722 |
+ return cl_error; |
|
2723 |
+ } |
|
2724 |
+ |
|
2725 |
+ if(clamfi_send(privdata, 0, "%s: %s\n", headerf, headerv) <= 0) { |
|
2726 |
+ clamfi_cleanup(ctx); |
|
2727 |
+ return cl_error; |
|
2728 |
+ } |
|
2729 |
+ |
|
2711 | 2730 |
return SMFIS_CONTINUE; |
2712 | 2731 |
} |
2713 | 2732 |
|
... | ... |
@@ -5443,6 +5511,7 @@ verifyIncomingSocketName(const char *sockName) |
5443 | 5443 |
* TODO: Allow regular expressions in the addresses |
5444 | 5444 |
* TODO: Syntax check the contents of the files |
5445 | 5445 |
* TODO: Allow emails of the form "name <address>" |
5446 |
+ * TODO: Allow emails not of the form "<address>" |
|
5446 | 5447 |
* TODO: Assume that if a '@' is missing from the address, that all emails |
5447 | 5448 |
* to that domain are to be whitelisted |
5448 | 5449 |
*/ |
... | ... |
@@ -5793,3 +5862,23 @@ black_hole(const struct privdata *privdata) |
5793 | 5793 |
} |
5794 | 5794 |
return SMFIS_CONTINUE; |
5795 | 5795 |
} |
5796 |
+ |
|
5797 |
+/* See also libclamav/mbox.c */ |
|
5798 |
+static int |
|
5799 |
+useful_header(const char *cmd) |
|
5800 |
+{ |
|
5801 |
+ if(strcasecmp(cmd, "From") == 0) |
|
5802 |
+ return 1; |
|
5803 |
+ if(strcasecmp(cmd, "Received") == 0) |
|
5804 |
+ return 1; |
|
5805 |
+ if(strcasecmp(cmd, "Content-Type") == 0) |
|
5806 |
+ return 1; |
|
5807 |
+ if(strcasecmp(cmd, "Content-Transfer-Encoding") == 0) |
|
5808 |
+ return 1; |
|
5809 |
+ if(strcasecmp(cmd, "Content-Disposition") == 0) |
|
5810 |
+ return 1; |
|
5811 |
+ if(strcasecmp(cmd, "De") == 0) |
|
5812 |
+ return 1; |
|
5813 |
+ |
|
5814 |
+ return 0; |
|
5815 |
+} |