git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@1163 77e5149b-7576-45b1-b177-96237e5ba77b
... | ... |
@@ -118,6 +118,7 @@ Thomas Lamy <Thomas.Lamy*in-online.net> |
118 | 118 |
Marty Lee <marty*maui.co.uk> |
119 | 119 |
Peter N Lewis <peter*stairways.com.au> |
120 | 120 |
Roger Lucas <roger*planbit.co.uk> |
121 |
+Richard Lyons <frob-clamav*webcentral.com.au> |
|
121 | 122 |
David S. Madole <david*madole.net> |
122 | 123 |
Joe Maimon <jmaimon*ttec.com> |
123 | 124 |
Andrey V. Malyshev <amal*krasn.ru> |
... | ... |
@@ -1,3 +1,8 @@ |
1 |
+Tue Dec 7 02:48:08 CET 2004 (tk) |
|
2 |
+--------------------------------- |
|
3 |
+ * clamd: added support for file descriptor passing (patch by Richard Lyons |
|
4 |
+ <frob-clamav*webcentral.com.au>) |
|
5 |
+ |
|
1 | 6 |
Mon Dec 6 22:33:26 GMT 2004 (njh) |
2 | 7 |
---------------------------------- |
3 | 8 |
* clamav-milter: Ensure the date is kept in the quarantine path |
... | ... |
@@ -75,12 +75,18 @@ |
75 | 75 |
/* file i/o buffer size */ |
76 | 76 |
#undef FILEBUFF |
77 | 77 |
|
78 |
+/* access rights in msghdr */ |
|
79 |
+#undef HAVE_ACCRIGHTS_IN_MSGHDR |
|
80 |
+ |
|
78 | 81 |
/* "attrib packed" */ |
79 | 82 |
#undef HAVE_ATTRIB_PACKED |
80 | 83 |
|
81 | 84 |
/* have bzip2 */ |
82 | 85 |
#undef HAVE_BZLIB_H |
83 | 86 |
|
87 |
+/* ancillary data style fd pass */ |
|
88 |
+#undef HAVE_CONTROL_IN_MSGHDR |
|
89 |
+ |
|
84 | 90 |
/* Define to 1 if you have the <dlfcn.h> header file. */ |
85 | 91 |
#undef HAVE_DLFCN_H |
86 | 92 |
|
... | ... |
@@ -153,12 +159,18 @@ |
153 | 153 |
/* readdir_r takes 3 arguments */ |
154 | 154 |
#undef HAVE_READDIR_R_3 |
155 | 155 |
|
156 |
+/* Define to 1 if you have the `recvmsg' function. */ |
|
157 |
+#undef HAVE_RECVMSG |
|
158 |
+ |
|
156 | 159 |
/* Define to 1 if you have the <regex.h> header file. */ |
157 | 160 |
#undef HAVE_REGEX_H |
158 | 161 |
|
159 | 162 |
/* have resolv.h */ |
160 | 163 |
#undef HAVE_RESOLV_H |
161 | 164 |
|
165 |
+/* Define to 1 if you have the `sendmsg' function. */ |
|
166 |
+#undef HAVE_SENDMSG |
|
167 |
+ |
|
162 | 168 |
/* Define to 1 if you have the `setgroups' function. */ |
163 | 169 |
#undef HAVE_SETGROUPS |
164 | 170 |
|
... | ... |
@@ -216,6 +228,9 @@ |
216 | 216 |
/* Define to 1 if you have the <tcpd.h> header file. */ |
217 | 217 |
#undef HAVE_TCPD_H |
218 | 218 |
|
219 |
+/* Define to 1 if you have the <uio.h> header file. */ |
|
220 |
+#undef HAVE_UIO_H |
|
221 |
+ |
|
219 | 222 |
/* Define to 1 if you have the <unistd.h> header file. */ |
220 | 223 |
#undef HAVE_UNISTD_H |
221 | 224 |
|
... | ... |
@@ -225,6 +240,9 @@ |
225 | 225 |
/* zlib installed */ |
226 | 226 |
#undef HAVE_ZLIB_H |
227 | 227 |
|
228 |
+/* Early Linux doesn't set cmsg fields */ |
|
229 |
+#undef INCOMPLETE_CMSG |
|
230 |
+ |
|
228 | 231 |
/* bzip funtions do not have bz2 prefix */ |
229 | 232 |
#undef NOBZ2PREFIX |
230 | 233 |
|
... | ... |
@@ -32,12 +32,16 @@ |
32 | 32 |
#include <sys/time.h> |
33 | 33 |
#include <sys/socket.h> |
34 | 34 |
#include <sys/ioctl.h> |
35 |
+ |
|
35 | 36 |
#if HAVE_SYS_TYPES_H |
36 | 37 |
#include <sys/types.h> |
37 | 38 |
#endif |
38 | 39 |
#if HAVE_SYS_FILIO_H |
39 | 40 |
#include <sys/filio.h> |
40 | 41 |
#endif |
42 |
+#ifdef HAVE_SYS_UIO_H |
|
43 |
+#include <sys/uio.h> |
|
44 |
+#endif |
|
41 | 45 |
|
42 | 46 |
/* submitted by breiter@wolfereiter.com: do not use poll(2) on Interix */ |
43 | 47 |
#ifdef C_INTERIX |
... | ... |
@@ -58,6 +62,7 @@ |
58 | 58 |
|
59 | 59 |
#include "memory.h" |
60 | 60 |
#include "cfgparser.h" |
61 |
+#include "session.h" |
|
61 | 62 |
|
62 | 63 |
void virusaction(const char *virname, const struct cfgstruct *copt) |
63 | 64 |
{ |
... | ... |
@@ -220,3 +225,65 @@ int writen(int fd, void *buff, unsigned int count) |
220 | 220 |
|
221 | 221 |
return count; |
222 | 222 |
} |
223 |
+ |
|
224 |
+/* Submitted by Richard Lyons <frob-clamav*webcentral.com.au> */ |
|
225 |
+ |
|
226 |
+#if defined(HAVE_RECVMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR)) && !defined(C_CYGWIN) |
|
227 |
+ |
|
228 |
+int readsock(int sockfd, char *buf, size_t size) |
|
229 |
+{ |
|
230 |
+ int fd; |
|
231 |
+ ssize_t n; |
|
232 |
+ struct msghdr msg; |
|
233 |
+ struct iovec iov[1]; |
|
234 |
+#ifdef HAVE_CONTROL_IN_MSGHDR |
|
235 |
+ struct cmsghdr *cmsg; |
|
236 |
+ char tmp[CMSG_SPACE(sizeof(fd))]; |
|
237 |
+#endif |
|
238 |
+ |
|
239 |
+ iov[0].iov_base = buf; |
|
240 |
+ iov[0].iov_len = size; |
|
241 |
+ memset(&msg, 0, sizeof(msg)); |
|
242 |
+ msg.msg_iov = iov; |
|
243 |
+ msg.msg_iovlen = 1; |
|
244 |
+#ifdef HAVE_ACCRIGHTS_IN_MSGHDR |
|
245 |
+ msg.msg_accrights = (caddr_t)&fd; |
|
246 |
+ msg.msg_accrightslen = sizeof(fd); |
|
247 |
+#endif |
|
248 |
+#ifdef HAVE_CONTROL_IN_MSGHDR |
|
249 |
+ msg.msg_control = tmp; |
|
250 |
+ msg.msg_controllen = sizeof(tmp); |
|
251 |
+#endif |
|
252 |
+ fd = -1; |
|
253 |
+ if ((n = recvmsg(sockfd, &msg, 0)) <= 0) |
|
254 |
+ return n; |
|
255 |
+ errno = EBADF; |
|
256 |
+ if (n != 1 || buf[0] != 0) |
|
257 |
+ return !strncmp(buf, CMD12, strlen(CMD12)) ? -1 : n; |
|
258 |
+#ifdef HAVE_ACCRIGHTS_IN_MSGHDR |
|
259 |
+ if (msg.msg_accrightslen != sizeof(fd)) |
|
260 |
+ return -1; |
|
261 |
+#endif |
|
262 |
+#ifdef HAVE_CONTROL_IN_MSGHDR |
|
263 |
+ cmsg = CMSG_FIRSTHDR(&msg); |
|
264 |
+ if (cmsg == NULL) |
|
265 |
+ return -1; |
|
266 |
+#ifndef INCOMPLETE_CMSG |
|
267 |
+ if (cmsg->cmsg_type != SCM_RIGHTS) |
|
268 |
+ return -1; |
|
269 |
+ if (cmsg->cmsg_len != CMSG_LEN(sizeof(fd))) |
|
270 |
+ return -1; |
|
271 |
+#endif |
|
272 |
+ fd = *(int *)CMSG_DATA(cmsg); |
|
273 |
+#endif |
|
274 |
+ if (fd < 0) |
|
275 |
+ return -1; |
|
276 |
+ n = snprintf(buf, size, "FD %d", fd); |
|
277 |
+ if (n >= size) |
|
278 |
+ return -1; |
|
279 |
+ return n; |
|
280 |
+} |
|
281 |
+ |
|
282 |
+#else |
|
283 |
+#define readsock read |
|
284 |
+#endif |
... | ... |
@@ -31,5 +31,6 @@ int poll_fd(int fd, int timeout_sec); |
31 | 31 |
int is_fd_connected(int fd); |
32 | 32 |
void virusaction(const char *virname, const struct cfgstruct *copt); |
33 | 33 |
int writen(int fd, void *buff, unsigned int count); |
34 |
+int readsock(int sockfd, char *buf, size_t size); |
|
34 | 35 |
|
35 | 36 |
#endif |
... | ... |
@@ -261,6 +261,37 @@ int scan(const char *filename, unsigned long int *scanned, const struct cl_node |
261 | 261 |
return ret; |
262 | 262 |
} |
263 | 263 |
|
264 |
+int scanfd(const int fd, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, const struct cfgstruct *copt, int odesc, short contscan) |
|
265 |
+{ |
|
266 |
+ int ret; |
|
267 |
+ const char *virname; |
|
268 |
+ struct stat statbuf; |
|
269 |
+ |
|
270 |
+ |
|
271 |
+ if(fstat(fd, &statbuf) == -1) |
|
272 |
+ return -1; |
|
273 |
+ |
|
274 |
+ if(!S_ISREG(statbuf.st_mode)) |
|
275 |
+ return -1; |
|
276 |
+ |
|
277 |
+ ret = cl_scandesc(fd, &virname, scanned, root, limits, options); |
|
278 |
+ |
|
279 |
+ if(ret == CL_VIRUS) { |
|
280 |
+ mdprintf(odesc, "fd[%d]: %s FOUND\n", fd, virname); |
|
281 |
+ logg("fd[%d]: %s FOUND\n", fd, virname); |
|
282 |
+ virusaction(virname, copt); |
|
283 |
+ } else if(ret != CL_CLEAN) { |
|
284 |
+ mdprintf(odesc, "fd[%d]: %s ERROR\n", fd, cl_strerror(ret)); |
|
285 |
+ logg("fd[%d]: %s ERROR\n", fd, cl_strerror(ret)); |
|
286 |
+ } else { |
|
287 |
+ mdprintf(odesc, "fd[%d]: OK\n", fd); |
|
288 |
+ if(logok) |
|
289 |
+ logg("fd[%d]: OK\n", fd); |
|
290 |
+ } |
|
291 |
+ |
|
292 |
+ return ret; |
|
293 |
+} |
|
294 |
+ |
|
264 | 295 |
int scanstream(int odesc, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, const struct cfgstruct *copt) |
265 | 296 |
{ |
266 | 297 |
int ret, portscan = CL_DEFAULT_MAXPORTSCAN, sockfd, port, acceptd; |
... | ... |
@@ -442,7 +473,7 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_node *root |
442 | 442 |
logg("stream: %s ERROR\n", cl_strerror(ret)); |
443 | 443 |
} else { |
444 | 444 |
mdprintf(odesc, "stream: OK\n"); |
445 |
- if (logok) |
|
445 |
+ if(logok) |
|
446 | 446 |
logg("stream: OK\n"); |
447 | 447 |
} |
448 | 448 |
|
... | ... |
@@ -27,6 +27,8 @@ int dirscan(const char *dirname, const char **virname, unsigned long int *scanne |
27 | 27 |
|
28 | 28 |
int scan(const char *filename, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, const struct cfgstruct *copt, int odesc, short contscan); |
29 | 29 |
|
30 |
+int scanfd(const int fd, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, const struct cfgstruct *copt, int odesc, short contscan); |
|
31 |
+ |
|
30 | 32 |
int scanstream(int odesc, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, const struct cfgstruct *copt); |
31 | 33 |
|
32 | 34 |
#endif |
... | ... |
@@ -44,18 +44,6 @@ |
44 | 44 |
#include "output.h" |
45 | 45 |
#include "memory.h" |
46 | 46 |
|
47 |
-#define CMD1 "SCAN" |
|
48 |
-#define CMD2 "RAWSCAN" |
|
49 |
-#define CMD3 "QUIT" /* deprecated */ |
|
50 |
-#define CMD4 "RELOAD" |
|
51 |
-#define CMD5 "PING" |
|
52 |
-#define CMD6 "CONTSCAN" |
|
53 |
-#define CMD7 "VERSION" |
|
54 |
-#define CMD8 "STREAM" |
|
55 |
-#define CMD9 "SESSION" |
|
56 |
-#define CMD10 "END" |
|
57 |
-#define CMD11 "SHUTDOWN" |
|
58 |
- |
|
59 | 47 |
pthread_mutex_t ctime_mutex = PTHREAD_MUTEX_INITIALIZER; |
60 | 48 |
|
61 | 49 |
int command(int desc, const struct cl_node *root, const struct cl_limits *limits, int options, const struct cfgstruct *copt, int timeout) |
... | ... |
@@ -77,7 +65,7 @@ int command(int desc, const struct cl_node *root, const struct cl_limits *limits |
77 | 77 |
return -1; |
78 | 78 |
} |
79 | 79 |
|
80 |
- while((bread = read(desc, buff, 1024)) == -1 && errno == EINTR); |
|
80 |
+ while((bread = readsock(desc, buff, 1024)) == -1 && errno == EINTR); |
|
81 | 81 |
|
82 | 82 |
if(!bread) |
83 | 83 |
return 0; |
... | ... |
@@ -188,6 +176,12 @@ int command(int desc, const struct cl_node *root, const struct cl_limits *limits |
188 | 188 |
} else if(!strncmp(buff, CMD11, strlen(CMD11))) { /* SHUTDOWN */ |
189 | 189 |
return COMMAND_SHUTDOWN; |
190 | 190 |
|
191 |
+ } else if(!strncmp(buff, CMD12, strlen(CMD12))) { /* FD */ |
|
192 |
+ int fd = atoi(buff + strlen(CMD12) + 1); |
|
193 |
+ |
|
194 |
+ scanfd(fd, NULL, root, limits, options, copt, desc, 0); |
|
195 |
+ close(fd); /* FIXME: should we close it here? */ |
|
196 |
+ |
|
191 | 197 |
} else { |
192 | 198 |
mdprintf(desc, "UNKNOWN COMMAND\n"); |
193 | 199 |
} |
... | ... |
@@ -23,6 +23,19 @@ |
23 | 23 |
#define COMMAND_RELOAD 2 |
24 | 24 |
#define COMMAND_END 3 |
25 | 25 |
|
26 |
+#define CMD1 "SCAN" |
|
27 |
+#define CMD2 "RAWSCAN" |
|
28 |
+#define CMD3 "QUIT" /* deprecated */ |
|
29 |
+#define CMD4 "RELOAD" |
|
30 |
+#define CMD5 "PING" |
|
31 |
+#define CMD6 "CONTSCAN" |
|
32 |
+#define CMD7 "VERSION" |
|
33 |
+#define CMD8 "STREAM" |
|
34 |
+#define CMD9 "SESSION" |
|
35 |
+#define CMD10 "END" |
|
36 |
+#define CMD11 "SHUTDOWN" |
|
37 |
+#define CMD12 "FD" |
|
38 |
+ |
|
26 | 39 |
#include <clamav.h> |
27 | 40 |
#include "cfgparser.h" |
28 | 41 |
|
... | ... |
@@ -33,6 +33,10 @@ |
33 | 33 |
#include <utime.h> |
34 | 34 |
#include <errno.h> |
35 | 35 |
|
36 |
+#ifdef HAVE_SYS_UIO_H |
|
37 |
+#include <sys/uio.h> |
|
38 |
+#endif |
|
39 |
+ |
|
36 | 40 |
#include "others.h" |
37 | 41 |
#include "defaults.h" |
38 | 42 |
#include "shared.h" |
... | ... |
@@ -50,27 +54,18 @@ |
50 | 50 |
# define SOCKET_INET AF_INET |
51 | 51 |
#endif |
52 | 52 |
|
53 |
+/* #define ENABLE_FD_PASSING FIXME: Doesn't work yet */ |
|
54 |
+ |
|
53 | 55 |
void move_infected(const char *filename, const struct optstruct *opt); |
54 | 56 |
int notremoved = 0, notmoved = 0; |
55 | 57 |
|
56 |
-int dsfile(int sockd, const char *filename, const struct optstruct *opt) |
|
58 |
+int dsresult(int sockd, const struct optstruct *opt) |
|
57 | 59 |
{ |
58 | 60 |
int infected = 0, waserror = 0; |
59 |
- char buff[4096], *scancmd, *pt; |
|
61 |
+ char buff[4096], *pt; |
|
60 | 62 |
FILE *fd; |
61 | 63 |
|
62 | 64 |
|
63 |
- scancmd = mcalloc(strlen(filename) + 20, sizeof(char)); |
|
64 |
- sprintf(scancmd, "CONTSCAN %s", filename); |
|
65 |
- |
|
66 |
- if(write(sockd, scancmd, strlen(scancmd)) <= 0) { |
|
67 |
- mprintf("@Can't write to the socket.\n"); |
|
68 |
- free(scancmd); |
|
69 |
- return -1; |
|
70 |
- } |
|
71 |
- |
|
72 |
- free(scancmd); |
|
73 |
- |
|
74 | 65 |
if((fd = fdopen(dup(sockd), "r")) == NULL) { |
75 | 66 |
mprintf("@Can't open descriptor for reading.\n"); |
76 | 67 |
return -1; |
... | ... |
@@ -99,6 +94,7 @@ int dsfile(int sockd, const char *filename, const struct optstruct *opt) |
99 | 99 |
} |
100 | 100 |
} |
101 | 101 |
} |
102 |
+ |
|
102 | 103 |
if(strstr(buff, "ERROR\n")) { |
103 | 104 |
logg("%s", buff); |
104 | 105 |
mprintf("%s", buff); |
... | ... |
@@ -108,12 +104,78 @@ int dsfile(int sockd, const char *filename, const struct optstruct *opt) |
108 | 108 |
|
109 | 109 |
fclose(fd); |
110 | 110 |
|
111 |
- if(!infected && !waserror) |
|
111 |
+ return infected ? infected : (waserror ? -1 : 0); |
|
112 |
+} |
|
113 |
+ |
|
114 |
+int dsfile(int sockd, const char *filename, const struct optstruct *opt) |
|
115 |
+{ |
|
116 |
+ int ret; |
|
117 |
+ char buff[4096], *scancmd, *pt; |
|
118 |
+ FILE *fd; |
|
119 |
+ |
|
120 |
+ |
|
121 |
+ scancmd = mcalloc(strlen(filename) + 20, sizeof(char)); |
|
122 |
+ sprintf(scancmd, "CONTSCAN %s", filename); |
|
123 |
+ |
|
124 |
+ if(write(sockd, scancmd, strlen(scancmd)) <= 0) { |
|
125 |
+ mprintf("@Can't write to the socket.\n"); |
|
126 |
+ free(scancmd); |
|
127 |
+ return -1; |
|
128 |
+ } |
|
129 |
+ |
|
130 |
+ free(scancmd); |
|
131 |
+ |
|
132 |
+ ret = dsresult(sockd, opt); |
|
133 |
+ |
|
134 |
+ if(!ret) |
|
112 | 135 |
mprintf("%s: OK\n", filename); |
113 | 136 |
|
114 |
- return infected ? infected : (waserror ? -1 : 0); |
|
137 |
+ return ret; |
|
115 | 138 |
} |
116 | 139 |
|
140 |
+#if defined(ENABLE_FD_PASSING) && defined(HAVE_SENDMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR)) && !defined(C_CYGWIN) |
|
141 |
+ |
|
142 |
+/* Submitted by Richard Lyons <frob-clamav*webcentral.com.au> */ |
|
143 |
+int dsfd(int sockfd, int fd, const struct optstruct *opt) |
|
144 |
+{ |
|
145 |
+ struct iovec iov[1]; |
|
146 |
+ struct msghdr msg; |
|
147 |
+#ifdef HAVE_CONTROL_IN_MSGHDR |
|
148 |
+ struct cmsghdr *cmsg; |
|
149 |
+ char tmp[CMSG_SPACE(sizeof(fd))]; |
|
150 |
+#endif |
|
151 |
+ |
|
152 |
+ iov[0].iov_base = ""; |
|
153 |
+ iov[0].iov_len = 1; |
|
154 |
+ memset(&msg, 0, sizeof(msg)); |
|
155 |
+ msg.msg_iov = iov; |
|
156 |
+ msg.msg_iovlen = 1; |
|
157 |
+#ifdef HAVE_CONTROL_IN_MSGHDR |
|
158 |
+ msg.msg_control = tmp; |
|
159 |
+ msg.msg_controllen = sizeof(tmp); |
|
160 |
+ cmsg = CMSG_FIRSTHDR(&msg); |
|
161 |
+ cmsg->cmsg_level = SOL_SOCKET; |
|
162 |
+ cmsg->cmsg_type = SCM_RIGHTS; |
|
163 |
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); |
|
164 |
+ *(int *)CMSG_DATA(cmsg) = fd; |
|
165 |
+#endif |
|
166 |
+#ifdef HAVE_ACCRIGHTS_IN_MSGHDR |
|
167 |
+ msg.msg_accrights = (caddr_t)&fd; |
|
168 |
+ msg.msg_accrightslen = sizeof(fd); |
|
169 |
+#endif |
|
170 |
+ if (sendmsg(sockfd, &msg, 0) != iov[0].iov_len) { |
|
171 |
+ mprintf("@Can't write to the socket.\n"); |
|
172 |
+ return -1; |
|
173 |
+ } |
|
174 |
+ return dsresult(sockfd, opt); |
|
175 |
+} |
|
176 |
+#else |
|
177 |
+int dsfd(int sockfd, int fd, const struct optstruct *opt) |
|
178 |
+{ |
|
179 |
+ return -1; |
|
180 |
+} |
|
181 |
+#endif |
|
182 |
+ |
|
117 | 183 |
int dsstream(int sockd, const struct optstruct *opt) |
118 | 184 |
{ |
119 | 185 |
int wsockd, loopw = 60, bread, port, infected = 0; |
... | ... |
@@ -122,6 +184,7 @@ int dsstream(int sockd, const struct optstruct *opt) |
122 | 122 |
int peer_size; |
123 | 123 |
char buff[4096], *pt; |
124 | 124 |
|
125 |
+ |
|
125 | 126 |
if(write(sockd, "STREAM", 6) <= 0) { |
126 | 127 |
mprintf("@Can't write to the socket.\n"); |
127 | 128 |
return 2; |
... | ... |
@@ -195,25 +258,8 @@ int dsstream(int sockd, const struct optstruct *opt) |
195 | 195 |
if(strstr(buff, "FOUND\n")) { |
196 | 196 |
infected++; |
197 | 197 |
logg("%s", buff); |
198 |
- if(optl(opt, "move")) { |
|
199 |
- pt = strrchr(buff, ':'); |
|
200 |
- *pt = 0; |
|
201 |
- move_infected(buff, opt); |
|
202 | 198 |
|
203 |
- } else if(optl(opt, "remove")) { |
|
204 |
- pt = strrchr(buff, ':'); |
|
205 |
- *pt = 0; |
|
206 |
- if(unlink(buff)) { |
|
207 |
- mprintf("%s: Can't remove.\n", buff); |
|
208 |
- logg("%s: Can't remove.\n", buff); |
|
209 |
- notremoved++; |
|
210 |
- } else { |
|
211 |
- mprintf("%s: Removed.\n", buff); |
|
212 |
- logg("%s: Removed.\n", buff); |
|
213 |
- } |
|
214 |
- } |
|
215 |
- } |
|
216 |
- if(strstr(buff, "ERROR\n")) { |
|
199 |
+ } else if(strstr(buff, "ERROR\n")) { |
|
217 | 200 |
logg("%s", buff); |
218 | 201 |
return -1; |
219 | 202 |
} |
... | ... |
@@ -354,6 +400,18 @@ int client(const struct optstruct *opt, int *infected) |
354 | 354 |
|
355 | 355 |
close(sockd); |
356 | 356 |
|
357 |
+#if defined(ENABLE_FD_PASSING) && defined(HAVE_SENDMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR)) && !defined(C_CYGWIN) |
|
358 |
+ } else if(!strcmp(opt->filename, "-")) { /* scan data from stdin */ |
|
359 |
+ if((sockd = dconnect(opt)) < 0) |
|
360 |
+ return 2; |
|
361 |
+ |
|
362 |
+ if((ret = dsfd(sockd, 0, opt)) >= 0) |
|
363 |
+ *infected += ret; |
|
364 |
+ else |
|
365 |
+ errors++; |
|
366 |
+ |
|
367 |
+ close(sockd); |
|
368 |
+#else |
|
357 | 369 |
} else if(!strcmp(opt->filename, "-")) { /* scan data from stdin */ |
358 | 370 |
if((sockd = dconnect(opt)) < 0) |
359 | 371 |
return 2; |
... | ... |
@@ -364,6 +422,7 @@ int client(const struct optstruct *opt, int *infected) |
364 | 364 |
errors++; |
365 | 365 |
|
366 | 366 |
close(sockd); |
367 |
+#endif |
|
367 | 368 |
|
368 | 369 |
} else { |
369 | 370 |
int x; |
... | ... |
@@ -8547,7 +8547,8 @@ fi |
8547 | 8547 |
|
8548 | 8548 |
|
8549 | 8549 |
|
8550 |
-for ac_header in stdint.h unistd.h sys/int_types.h dlfcn.h inttypes.h sys/inttypes.h memory.h ndir.h stdlib.h strings.h string.h sys/mman.h sys/param.h sys/stat.h sys/types.h malloc.h poll.h regex.h limits.h sys/filio.h |
|
8550 |
+ |
|
8551 |
+for ac_header in stdint.h unistd.h sys/int_types.h dlfcn.h inttypes.h sys/inttypes.h memory.h ndir.h stdlib.h strings.h string.h sys/mman.h sys/param.h sys/stat.h sys/types.h malloc.h poll.h regex.h limits.h sys/filio.h uio.h |
|
8551 | 8552 |
do |
8552 | 8553 |
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` |
8553 | 8554 |
if eval "test \"\${$as_ac_Header+set}\" = set"; then |
... | ... |
@@ -11537,6 +11538,15 @@ _ACEOF |
11537 | 11537 |
fi |
11538 | 11538 |
CLAMSCAN_LIBS="$CLAMSCAN_LIBS -lpthread" |
11539 | 11539 |
fi |
11540 |
+ case `uname -r` in |
|
11541 |
+ 1.*|2.0.*) |
|
11542 |
+ |
|
11543 |
+cat >>confdefs.h <<\_ACEOF |
|
11544 |
+#define INCOMPLETE_CMSG 1 |
|
11545 |
+_ACEOF |
|
11546 |
+ |
|
11547 |
+ ;; |
|
11548 |
+ esac |
|
11540 | 11549 |
;; |
11541 | 11550 |
cygwin*) |
11542 | 11551 |
|
... | ... |
@@ -12354,6 +12364,244 @@ fi |
12354 | 12354 |
fi |
12355 | 12355 |
|
12356 | 12356 |
|
12357 |
+ |
|
12358 |
+for ac_func in recvmsg sendmsg |
|
12359 |
+do |
|
12360 |
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` |
|
12361 |
+echo "$as_me:$LINENO: checking for $ac_func" >&5 |
|
12362 |
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 |
|
12363 |
+if eval "test \"\${$as_ac_var+set}\" = set"; then |
|
12364 |
+ echo $ECHO_N "(cached) $ECHO_C" >&6 |
|
12365 |
+else |
|
12366 |
+ cat >conftest.$ac_ext <<_ACEOF |
|
12367 |
+/* confdefs.h. */ |
|
12368 |
+_ACEOF |
|
12369 |
+cat confdefs.h >>conftest.$ac_ext |
|
12370 |
+cat >>conftest.$ac_ext <<_ACEOF |
|
12371 |
+/* end confdefs.h. */ |
|
12372 |
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. |
|
12373 |
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */ |
|
12374 |
+#define $ac_func innocuous_$ac_func |
|
12375 |
+ |
|
12376 |
+/* System header to define __stub macros and hopefully few prototypes, |
|
12377 |
+ which can conflict with char $ac_func (); below. |
|
12378 |
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since |
|
12379 |
+ <limits.h> exists even on freestanding compilers. */ |
|
12380 |
+ |
|
12381 |
+#ifdef __STDC__ |
|
12382 |
+# include <limits.h> |
|
12383 |
+#else |
|
12384 |
+# include <assert.h> |
|
12385 |
+#endif |
|
12386 |
+ |
|
12387 |
+#undef $ac_func |
|
12388 |
+ |
|
12389 |
+/* Override any gcc2 internal prototype to avoid an error. */ |
|
12390 |
+#ifdef __cplusplus |
|
12391 |
+extern "C" |
|
12392 |
+{ |
|
12393 |
+#endif |
|
12394 |
+/* We use char because int might match the return type of a gcc2 |
|
12395 |
+ builtin and then its argument prototype would still apply. */ |
|
12396 |
+char $ac_func (); |
|
12397 |
+/* The GNU C library defines this for functions which it implements |
|
12398 |
+ to always fail with ENOSYS. Some functions are actually named |
|
12399 |
+ something starting with __ and the normal name is an alias. */ |
|
12400 |
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func) |
|
12401 |
+choke me |
|
12402 |
+#else |
|
12403 |
+char (*f) () = $ac_func; |
|
12404 |
+#endif |
|
12405 |
+#ifdef __cplusplus |
|
12406 |
+} |
|
12407 |
+#endif |
|
12408 |
+ |
|
12409 |
+int |
|
12410 |
+main () |
|
12411 |
+{ |
|
12412 |
+return f != $ac_func; |
|
12413 |
+ ; |
|
12414 |
+ return 0; |
|
12415 |
+} |
|
12416 |
+_ACEOF |
|
12417 |
+rm -f conftest.$ac_objext conftest$ac_exeext |
|
12418 |
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 |
|
12419 |
+ (eval $ac_link) 2>conftest.er1 |
|
12420 |
+ ac_status=$? |
|
12421 |
+ grep -v '^ *+' conftest.er1 >conftest.err |
|
12422 |
+ rm -f conftest.er1 |
|
12423 |
+ cat conftest.err >&5 |
|
12424 |
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5 |
|
12425 |
+ (exit $ac_status); } && |
|
12426 |
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' |
|
12427 |
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 |
|
12428 |
+ (eval $ac_try) 2>&5 |
|
12429 |
+ ac_status=$? |
|
12430 |
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5 |
|
12431 |
+ (exit $ac_status); }; } && |
|
12432 |
+ { ac_try='test -s conftest$ac_exeext' |
|
12433 |
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 |
|
12434 |
+ (eval $ac_try) 2>&5 |
|
12435 |
+ ac_status=$? |
|
12436 |
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5 |
|
12437 |
+ (exit $ac_status); }; }; then |
|
12438 |
+ eval "$as_ac_var=yes" |
|
12439 |
+else |
|
12440 |
+ echo "$as_me: failed program was:" >&5 |
|
12441 |
+sed 's/^/| /' conftest.$ac_ext >&5 |
|
12442 |
+ |
|
12443 |
+eval "$as_ac_var=no" |
|
12444 |
+fi |
|
12445 |
+rm -f conftest.err conftest.$ac_objext \ |
|
12446 |
+ conftest$ac_exeext conftest.$ac_ext |
|
12447 |
+fi |
|
12448 |
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 |
|
12449 |
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 |
|
12450 |
+if test `eval echo '${'$as_ac_var'}'` = yes; then |
|
12451 |
+ cat >>confdefs.h <<_ACEOF |
|
12452 |
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 |
|
12453 |
+_ACEOF |
|
12454 |
+ |
|
12455 |
+fi |
|
12456 |
+done |
|
12457 |
+ |
|
12458 |
+echo "$as_me:$LINENO: checking for msg_accrights field in struct msghdr" >&5 |
|
12459 |
+echo $ECHO_N "checking for msg_accrights field in struct msghdr... $ECHO_C" >&6 |
|
12460 |
+if test "${ac_cv_have_accrights_in_msghdr+set}" = set; then |
|
12461 |
+ echo $ECHO_N "(cached) $ECHO_C" >&6 |
|
12462 |
+else |
|
12463 |
+ |
|
12464 |
+ if test "$cross_compiling" = yes; then |
|
12465 |
+ { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling |
|
12466 |
+See \`config.log' for more details." >&5 |
|
12467 |
+echo "$as_me: error: cannot run test program while cross compiling |
|
12468 |
+See \`config.log' for more details." >&2;} |
|
12469 |
+ { (exit 1); exit 1; }; } |
|
12470 |
+else |
|
12471 |
+ cat >conftest.$ac_ext <<_ACEOF |
|
12472 |
+/* confdefs.h. */ |
|
12473 |
+_ACEOF |
|
12474 |
+cat confdefs.h >>conftest.$ac_ext |
|
12475 |
+cat >>conftest.$ac_ext <<_ACEOF |
|
12476 |
+/* end confdefs.h. */ |
|
12477 |
+ |
|
12478 |
+#include <sys/types.h> |
|
12479 |
+#include <sys/socket.h> |
|
12480 |
+#include <sys/uio.h> |
|
12481 |
+int main() { |
|
12482 |
+#ifdef msg_accrights |
|
12483 |
+exit(1); |
|
12484 |
+#endif |
|
12485 |
+struct msghdr m; |
|
12486 |
+m.msg_accrights = 0; |
|
12487 |
+exit(0); |
|
12488 |
+} |
|
12489 |
+ |
|
12490 |
+_ACEOF |
|
12491 |
+rm -f conftest$ac_exeext |
|
12492 |
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 |
|
12493 |
+ (eval $ac_link) 2>&5 |
|
12494 |
+ ac_status=$? |
|
12495 |
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5 |
|
12496 |
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext' |
|
12497 |
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 |
|
12498 |
+ (eval $ac_try) 2>&5 |
|
12499 |
+ ac_status=$? |
|
12500 |
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5 |
|
12501 |
+ (exit $ac_status); }; }; then |
|
12502 |
+ ac_cv_have_accrights_in_msghdr="yes" |
|
12503 |
+else |
|
12504 |
+ echo "$as_me: program exited with status $ac_status" >&5 |
|
12505 |
+echo "$as_me: failed program was:" >&5 |
|
12506 |
+sed 's/^/| /' conftest.$ac_ext >&5 |
|
12507 |
+ |
|
12508 |
+( exit $ac_status ) |
|
12509 |
+ ac_cv_have_accrights_in_msghdr="no" |
|
12510 |
+ |
|
12511 |
+fi |
|
12512 |
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext |
|
12513 |
+fi |
|
12514 |
+ |
|
12515 |
+fi |
|
12516 |
+echo "$as_me:$LINENO: result: $ac_cv_have_accrights_in_msghdr" >&5 |
|
12517 |
+echo "${ECHO_T}$ac_cv_have_accrights_in_msghdr" >&6 |
|
12518 |
+if test "x$ac_cv_have_accrights_in_msghdr" = "xyes" ; then |
|
12519 |
+ |
|
12520 |
+cat >>confdefs.h <<\_ACEOF |
|
12521 |
+#define HAVE_ACCRIGHTS_IN_MSGHDR 1 |
|
12522 |
+_ACEOF |
|
12523 |
+ |
|
12524 |
+fi |
|
12525 |
+ |
|
12526 |
+echo "$as_me:$LINENO: checking for msg_control field in struct msghdr" >&5 |
|
12527 |
+echo $ECHO_N "checking for msg_control field in struct msghdr... $ECHO_C" >&6 |
|
12528 |
+if test "${ac_cv_have_control_in_msghdr+set}" = set; then |
|
12529 |
+ echo $ECHO_N "(cached) $ECHO_C" >&6 |
|
12530 |
+else |
|
12531 |
+ |
|
12532 |
+ if test "$cross_compiling" = yes; then |
|
12533 |
+ { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling |
|
12534 |
+See \`config.log' for more details." >&5 |
|
12535 |
+echo "$as_me: error: cannot run test program while cross compiling |
|
12536 |
+See \`config.log' for more details." >&2;} |
|
12537 |
+ { (exit 1); exit 1; }; } |
|
12538 |
+else |
|
12539 |
+ cat >conftest.$ac_ext <<_ACEOF |
|
12540 |
+/* confdefs.h. */ |
|
12541 |
+_ACEOF |
|
12542 |
+cat confdefs.h >>conftest.$ac_ext |
|
12543 |
+cat >>conftest.$ac_ext <<_ACEOF |
|
12544 |
+/* end confdefs.h. */ |
|
12545 |
+ |
|
12546 |
+#include <sys/types.h> |
|
12547 |
+#include <sys/socket.h> |
|
12548 |
+#include <sys/uio.h> |
|
12549 |
+int main() { |
|
12550 |
+#ifdef msg_control |
|
12551 |
+exit(1); |
|
12552 |
+#endif |
|
12553 |
+struct msghdr m; |
|
12554 |
+m.msg_control = 0; |
|
12555 |
+exit(0); |
|
12556 |
+} |
|
12557 |
+ |
|
12558 |
+_ACEOF |
|
12559 |
+rm -f conftest$ac_exeext |
|
12560 |
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 |
|
12561 |
+ (eval $ac_link) 2>&5 |
|
12562 |
+ ac_status=$? |
|
12563 |
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5 |
|
12564 |
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext' |
|
12565 |
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 |
|
12566 |
+ (eval $ac_try) 2>&5 |
|
12567 |
+ ac_status=$? |
|
12568 |
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5 |
|
12569 |
+ (exit $ac_status); }; }; then |
|
12570 |
+ ac_cv_have_control_in_msghdr="yes" |
|
12571 |
+else |
|
12572 |
+ echo "$as_me: program exited with status $ac_status" >&5 |
|
12573 |
+echo "$as_me: failed program was:" >&5 |
|
12574 |
+sed 's/^/| /' conftest.$ac_ext >&5 |
|
12575 |
+ |
|
12576 |
+( exit $ac_status ) |
|
12577 |
+ ac_cv_have_control_in_msghdr="no" |
|
12578 |
+ |
|
12579 |
+fi |
|
12580 |
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext |
|
12581 |
+fi |
|
12582 |
+ |
|
12583 |
+fi |
|
12584 |
+echo "$as_me:$LINENO: result: $ac_cv_have_control_in_msghdr" >&5 |
|
12585 |
+echo "${ECHO_T}$ac_cv_have_control_in_msghdr" >&6 |
|
12586 |
+if test "x$ac_cv_have_control_in_msghdr" = "xyes" ; then |
|
12587 |
+ |
|
12588 |
+cat >>confdefs.h <<\_ACEOF |
|
12589 |
+#define HAVE_CONTROL_IN_MSGHDR 1 |
|
12590 |
+_ACEOF |
|
12591 |
+ |
|
12592 |
+fi |
|
12593 |
+ |
|
12594 |
+ |
|
12357 | 12595 |
# Check whether --with-tcpwrappers or --without-tcpwrappers was given. |
12358 | 12596 |
if test "${with_tcpwrappers+set}" = set; then |
12359 | 12597 |
withval="$with_tcpwrappers" |
... | ... |
@@ -38,7 +38,7 @@ AC_DEFINE(SCANBUFF, 131072, [scan buffer size]) |
38 | 38 |
AC_DEFINE(FILEBUFF, 8192, [file i/o buffer size]) |
39 | 39 |
|
40 | 40 |
AC_HEADER_STDC |
41 |
-AC_CHECK_HEADERS(stdint.h unistd.h sys/int_types.h dlfcn.h inttypes.h sys/inttypes.h memory.h ndir.h stdlib.h strings.h string.h sys/mman.h sys/param.h sys/stat.h sys/types.h malloc.h poll.h regex.h limits.h sys/filio.h) |
|
41 |
+AC_CHECK_HEADERS(stdint.h unistd.h sys/int_types.h dlfcn.h inttypes.h sys/inttypes.h memory.h ndir.h stdlib.h strings.h string.h sys/mman.h sys/param.h sys/stat.h sys/types.h malloc.h poll.h regex.h limits.h sys/filio.h uio.h) |
|
42 | 42 |
AC_CHECK_HEADER(syslog.h,AC_DEFINE(USE_SYSLOG,1,[use syslog]),) |
43 | 43 |
|
44 | 44 |
AC_TYPE_OFF_T |
... | ... |
@@ -314,6 +314,11 @@ linux*) |
314 | 314 |
fi |
315 | 315 |
CLAMSCAN_LIBS="$CLAMSCAN_LIBS -lpthread" |
316 | 316 |
fi |
317 |
+ case `uname -r` in |
|
318 |
+ 1.*|2.0.*) |
|
319 |
+ AC_DEFINE(INCOMPLETE_CMSG,1,[Early Linux doesn't set cmsg fields]) |
|
320 |
+ ;; |
|
321 |
+ esac |
|
317 | 322 |
;; |
318 | 323 |
cygwin*) |
319 | 324 |
AC_DEFINE(C_CYGWIN,1,[os is cygwin]) |
... | ... |
@@ -518,6 +523,57 @@ then |
518 | 518 |
AC_PATH_PROG(SENDMAIL, sendmail, /usr/lib/sendmail, $PATH:/usr/lib:/usr/sbin:/etc:/usr/local/lib:/usr/local/sbin:/usr/bin:/usr/local/bin) |
519 | 519 |
fi |
520 | 520 |
|
521 |
+dnl Check if we can do fd passing |
|
522 |
+dnl Submitted by Richard Lyons <frob-clamav@webcentral.com.au> |
|
523 |
+AC_CHECK_FUNCS(recvmsg sendmsg) |
|
524 |
+AC_CACHE_CHECK([for msg_accrights field in struct msghdr], |
|
525 |
+ ac_cv_have_accrights_in_msghdr, [ |
|
526 |
+ AC_TRY_RUN( |
|
527 |
+ [ |
|
528 |
+#include <sys/types.h> |
|
529 |
+#include <sys/socket.h> |
|
530 |
+#include <sys/uio.h> |
|
531 |
+int main() { |
|
532 |
+#ifdef msg_accrights |
|
533 |
+exit(1); |
|
534 |
+#endif |
|
535 |
+struct msghdr m; |
|
536 |
+m.msg_accrights = 0; |
|
537 |
+exit(0); |
|
538 |
+} |
|
539 |
+ ], |
|
540 |
+ [ ac_cv_have_accrights_in_msghdr="yes" ], |
|
541 |
+ [ ac_cv_have_accrights_in_msghdr="no" ] |
|
542 |
+ ) |
|
543 |
+]) |
|
544 |
+if test "x$ac_cv_have_accrights_in_msghdr" = "xyes" ; then |
|
545 |
+ AC_DEFINE(HAVE_ACCRIGHTS_IN_MSGHDR,1,[access rights in msghdr]) |
|
546 |
+fi |
|
547 |
+ |
|
548 |
+AC_CACHE_CHECK([for msg_control field in struct msghdr], |
|
549 |
+ ac_cv_have_control_in_msghdr, [ |
|
550 |
+ AC_TRY_RUN( |
|
551 |
+ [ |
|
552 |
+#include <sys/types.h> |
|
553 |
+#include <sys/socket.h> |
|
554 |
+#include <sys/uio.h> |
|
555 |
+int main() { |
|
556 |
+#ifdef msg_control |
|
557 |
+exit(1); |
|
558 |
+#endif |
|
559 |
+struct msghdr m; |
|
560 |
+m.msg_control = 0; |
|
561 |
+exit(0); |
|
562 |
+} |
|
563 |
+ ], |
|
564 |
+ [ ac_cv_have_control_in_msghdr="yes" ], |
|
565 |
+ [ ac_cv_have_control_in_msghdr="no" ] |
|
566 |
+ ) |
|
567 |
+]) |
|
568 |
+if test "x$ac_cv_have_control_in_msghdr" = "xyes" ; then |
|
569 |
+ AC_DEFINE(HAVE_CONTROL_IN_MSGHDR,1,[ancillary data style fd pass]) |
|
570 |
+fi |
|
571 |
+ |
|
521 | 572 |
dnl tcpwrappers support |
522 | 573 |
dnl rules from http://ma.ph-freiburg.de/tng/tng-technical/2002-01/msg00094.html |
523 | 574 |
AC_ARG_WITH(tcpwrappers, |