... | ... |
@@ -36,14 +36,14 @@ clamonacc_SOURCES = \ |
36 | 36 |
$(top_srcdir)/shared/getopt.h \ |
37 | 37 |
$(top_srcdir)/shared/actions.c \ |
38 | 38 |
$(top_srcdir)/shared/actions.h \ |
39 |
- $(top_srcdir)/shared/clamdcom.c \ |
|
40 |
- $(top_srcdir)/shared/clamdcom.h \ |
|
41 | 39 |
$(top_srcdir)/shared/priv-fts.h \ |
42 | 40 |
clamonacc.c \ |
43 | 41 |
./client/onaccess_client.c \ |
44 | 42 |
./client/onaccess_client.h \ |
45 | 43 |
./client/onaccess_proto.c \ |
46 | 44 |
./client/onaccess_proto.h \ |
45 |
+ ./client/onaccess_com.c \ |
|
46 |
+ ./client/onaccess_com.h \ |
|
47 | 47 |
./inotif/onaccess_ddd.c \ |
48 | 48 |
./inotif/onaccess_ddd.h \ |
49 | 49 |
./fanotif/onaccess_fan.c \ |
... | ... |
@@ -64,8 +64,8 @@ AM_CFLAGS=@WERR_CFLAGS@ |
64 | 64 |
endif |
65 | 65 |
|
66 | 66 |
DEFS = @DEFS@ -DCL_NOLIBCLAMAV |
67 |
-LIBS = $(top_builddir)/libclamav/libclamav_internal_utils.la @CLAMONACC_LIBS@ @THREAD_LIBS@ |
|
68 |
-AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/clamd -I$(top_srcdir)/shared -I$(top_srcdir)/libclamav @SSL_CPPFLAGS@ @CLAMONACC_CPPFLAGS@ @JSON_CPPFLAGS@ @PCRE_CPPFLAGS@ |
|
67 |
+LIBS = $(top_builddir)/libclamav/libclamav_internal_utils.la @CURL_LDFLAGS@ @CURL_LIBS@ @CLAMONACC_LIBS@ @THREAD_LIBS@ |
|
68 |
+AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/clamd -I$(top_srcdir)/shared -I$(top_srcdir)/libclamav @CURL_CPPFLAGS@ @SSL_CPPFLAGS@ @CLAMONACC_CPPFLAGS@ @JSON_CPPFLAGS@ @PCRE_CPPFLAGS@ |
|
69 | 69 |
|
70 | 70 |
AM_INSTALLCHECK_STD_OPTIONS_EXEMPT=clamonacc$(EXEEXT) |
71 | 71 |
CLEANFILES=*.gcda *.gcno |
... | ... |
@@ -159,11 +159,12 @@ struct onas_context *onas_init_context(void) { |
159 | 159 |
|
160 | 160 |
cl_error_t onas_check_client_connection(struct onas_context **ctx) { |
161 | 161 |
|
162 |
+ cl_error_t err = CL_SUCCESS; |
|
162 | 163 |
errno = 0; |
163 | 164 |
|
164 | 165 |
/* 0 local, non-zero remote, errno set on error */ |
165 |
- (*ctx)->isremote = onas_check_remote(ctx); |
|
166 |
- if (errno == 0) { |
|
166 |
+ (*ctx)->isremote = onas_check_remote(ctx, &err); |
|
167 |
+ if (errno == 0 && CL_SUCCESS == err ) { |
|
167 | 168 |
logg("*Clamonacc: "); |
168 | 169 |
(*ctx)->isremote ? logg("*daemon is remote\n") : logg("*daemon is local\n"); |
169 | 170 |
} |
... | ... |
@@ -225,6 +226,9 @@ void* onas_context_cleanup(struct onas_context *ctx) { |
225 | 225 |
close(ctx->fan_fd); |
226 | 226 |
optfree((struct optstruct *) ctx->opts); |
227 | 227 |
optfree((struct optstruct *) ctx->clamdopts); |
228 |
+ if (ctx->portstr) { |
|
229 |
+ free(ctx->portstr); |
|
230 |
+ } |
|
228 | 231 |
ctx->opts = NULL; |
229 | 232 |
ctx->clamdopts = NULL; |
230 | 233 |
free(ctx); |
... | ... |
@@ -24,6 +24,16 @@ |
24 | 24 |
|
25 | 25 |
#include "libclamav/clamav.h" |
26 | 26 |
|
27 |
+#ifndef HAVE_ATTRIB_PACKED |
|
28 |
+#define __attribute__(x) |
|
29 |
+#endif |
|
30 |
+#ifdef HAVE_PRAGMA_PACK |
|
31 |
+#pragma pack(1) |
|
32 |
+#endif |
|
33 |
+#ifdef HAVE_PRAGMA_PACK_HPPA |
|
34 |
+#pragma pack 1 |
|
35 |
+#endif |
|
36 |
+ |
|
27 | 37 |
struct onas_context { |
28 | 38 |
const struct optstruct *opts; |
29 | 39 |
const struct optstruct *clamdopts; |
... | ... |
@@ -45,8 +55,16 @@ struct onas_context { |
45 | 45 |
int scantype; |
46 | 46 |
int isremote; |
47 | 47 |
int session; |
48 |
-}; |
|
49 | 48 |
|
49 |
+ char *portstr; |
|
50 |
+} __attribute__((packed)); |
|
51 |
+ |
|
52 |
+#ifdef HAVE_PRAGMA_PACK |
|
53 |
+#pragma pack() |
|
54 |
+#endif |
|
55 |
+#ifdef HAVE_PRAGMA_PACK_HPPA |
|
56 |
+#pragma pack |
|
57 |
+#endif |
|
50 | 58 |
|
51 | 59 |
struct onas_context* onas_init_context(void); |
52 | 60 |
void* onas_cleanup(struct onas_context *ctx); |
... | ... |
@@ -25,6 +25,7 @@ |
25 | 25 |
|
26 | 26 |
#include <stdio.h> |
27 | 27 |
#include <stdlib.h> |
28 |
+#include <curl/curl.h> |
|
28 | 29 |
#ifdef HAVE_UNISTD_H |
29 | 30 |
#include <unistd.h> |
30 | 31 |
#endif |
... | ... |
@@ -56,11 +57,12 @@ |
56 | 56 |
#include "shared/output.h" |
57 | 57 |
#include "shared/misc.h" |
58 | 58 |
#include "shared/actions.h" |
59 |
-#include "shared/clamdcom.h" |
|
60 | 59 |
|
61 | 60 |
#include "libclamav/str.h" |
62 | 61 |
#include "libclamav/others.h" |
63 | 62 |
|
63 |
+ |
|
64 |
+#include "onaccess_com.h" |
|
64 | 65 |
#include "onaccess_client.h" |
65 | 66 |
#include "onaccess_proto.h" |
66 | 67 |
|
... | ... |
@@ -80,97 +82,124 @@ static void print_server_version(struct onas_context **ctx) |
80 | 80 |
|
81 | 81 |
/* Inits the communication layer |
82 | 82 |
* Returns 0 if clamd is local, non zero if clamd is remote */ |
83 |
-int onas_check_remote(struct onas_context **ctx) { |
|
84 |
- int s, ret; |
|
85 |
- const struct optstruct *opt; |
|
86 |
- char *ipaddr = NULL; |
|
87 |
- char port[10]; |
|
88 |
- struct addrinfo hints, *info, *p; |
|
89 |
- int res; |
|
83 |
+int onas_check_remote(struct onas_context **ctx, cl_error_t *err) { |
|
84 |
+ int s, ret; |
|
85 |
+ const struct optstruct *opt; |
|
86 |
+ CURL *curl; |
|
87 |
+ CURLcode curlcode; |
|
88 |
+ char *ipaddr = NULL; |
|
89 |
+ char port[10]; |
|
90 |
+ struct addrinfo hints, *info, *p; |
|
91 |
+ int res; |
|
92 |
+ |
|
93 |
+ *err = CL_SUCCESS; |
|
90 | 94 |
|
91 | 95 |
#ifndef _WIN32 |
92 |
- if((opt = optget((*ctx)->clamdopts, "LocalSocket"))->enabled) { |
|
93 |
- memset((void *)&nixsock, 0, sizeof(nixsock)); |
|
94 |
- nixsock.sun_family = AF_UNIX; |
|
95 |
- strncpy(nixsock.sun_path, opt->strarg, sizeof(nixsock.sun_path)); |
|
96 |
- nixsock.sun_path[sizeof(nixsock.sun_path)-1]='\0'; |
|
97 |
- return 0; |
|
98 |
- } |
|
96 |
+ if((opt = optget((*ctx)->clamdopts, "LocalSocket"))->enabled) { |
|
97 |
+ return 0; |
|
98 |
+ } |
|
99 | 99 |
#endif |
100 |
- if(!(opt = optget((*ctx)->clamdopts, "TCPSocket"))->enabled) |
|
101 |
- return 0; |
|
100 |
+ if(!(opt = optget((*ctx)->clamdopts, "TCPSocket"))->enabled) { |
|
101 |
+ return 0; |
|
102 |
+ } |
|
102 | 103 |
|
103 |
- snprintf(port, sizeof(port), "%lld", optget((*ctx)->clamdopts, "TCPSocket")->numarg); |
|
104 |
+ snprintf(port, sizeof(port), "%lld", optget((*ctx)->clamdopts, "TCPSocket")->numarg); |
|
104 | 105 |
|
105 |
- opt = optget((*ctx)->clamdopts, "TCPAddr"); |
|
106 |
- while (opt) { |
|
106 |
+ if ((*ctx)->portstr) { |
|
107 |
+ free((*ctx)->portstr); |
|
108 |
+ } |
|
107 | 109 |
|
108 |
- if (opt->strarg) |
|
109 |
- ipaddr = (!strcmp(opt->strarg, "any") ? NULL : opt->strarg); |
|
110 |
+ (*ctx)->portstr = cli_strdup(port); |
|
111 |
+ if ( NULL == (*ctx)->portstr ) { |
|
112 |
+ *err = CL_EARG; |
|
113 |
+ return 0; |
|
114 |
+ } |
|
110 | 115 |
|
111 |
- memset(&hints, 0x00, sizeof(struct addrinfo)); |
|
112 |
- hints.ai_family = AF_UNSPEC; |
|
113 |
- hints.ai_socktype = SOCK_STREAM; |
|
114 |
- hints.ai_flags = AI_PASSIVE; |
|
116 |
+ opt = optget((*ctx)->clamdopts, "TCPAddr"); |
|
117 |
+ while (opt) { |
|
118 |
+ |
|
119 |
+ if (opt->strarg) { |
|
120 |
+ ipaddr = (!strcmp(opt->strarg, "any") ? NULL : opt->strarg); |
|
121 |
+ } |
|
122 |
+ |
|
123 |
+ if (NULL == ipaddr) { |
|
124 |
+ logg("!ClamClient: Clamonacc does not support binding to INADDR_ANY, \ |
|
125 |
+ please specify an address with TCPAddr in your clamd.conf config file\n"); |
|
126 |
+ *err = CL_EARG; |
|
127 |
+ return 1; |
|
128 |
+ } |
|
129 |
+ |
|
130 |
+ curlcode = onas_curl_init(&curl, ipaddr, port); |
|
131 |
+ if (CURLE_OK != curlcode) { |
|
132 |
+ logg("!ClamClient: could not init curl, %s\n", curl_easy_strerror(curlcode)); |
|
133 |
+ *err = CL_EARG; |
|
134 |
+ return 1; |
|
135 |
+ } |
|
136 |
+ |
|
137 |
+ curlcode = curl_easy_perform(curl); |
|
138 |
+ if (CURLE_OK != curlcode) { |
|
139 |
+ logg("!ClamClient: could not connect to remote clam daemon, %s\n", curl_easy_strerror(curlcode)); |
|
140 |
+ *err = CL_EARG; |
|
141 |
+ return 1; |
|
142 |
+ } |
|
143 |
+ |
|
144 |
+ curl_easy_cleanup(curl); |
|
145 |
+ |
|
146 |
+ opt = opt->nextarg; |
|
147 |
+ } |
|
115 | 148 |
|
116 |
- if ((res = getaddrinfo(ipaddr, port, &hints, &info))) { |
|
117 |
- logg("!Can't lookup clamd hostname: %s\n", gai_strerror(res)); |
|
118 |
- opt = opt->nextarg; |
|
119 |
- continue; |
|
120 |
- } |
|
149 |
+ if (*err == CL_SUCCESS) { |
|
150 |
+ return 1; |
|
151 |
+ } else { |
|
152 |
+ return 0; |
|
153 |
+ } |
|
154 |
+} |
|
121 | 155 |
|
122 |
- for (p = info; p != NULL; p = p->ai_next) { |
|
123 |
- if((s = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) { |
|
124 |
- logg("isremote: socket() returning: %s.\n", strerror(errno)); |
|
125 |
- continue; |
|
126 |
- } |
|
127 |
- |
|
128 |
- switch (p->ai_family) { |
|
129 |
- case AF_INET: |
|
130 |
- ((struct sockaddr_in *)(p->ai_addr))->sin_port = htons(INADDR_ANY); |
|
131 |
- break; |
|
132 |
- case AF_INET6: |
|
133 |
- ((struct sockaddr_in6 *)(p->ai_addr))->sin6_port = htons(INADDR_ANY); |
|
134 |
- break; |
|
135 |
- default: |
|
136 |
- break; |
|
137 |
- } |
|
138 |
- |
|
139 |
- ret = bind(s, p->ai_addr, p->ai_addrlen); |
|
140 |
- if (ret) { |
|
141 |
- if (errno == EADDRINUSE) { |
|
142 |
- /* |
|
143 |
- * If we can't bind, then either we're attempting to listen on an IP that isn't |
|
144 |
- * ours or that clamd is already listening on. |
|
145 |
- */ |
|
146 |
- closesocket(s); |
|
147 |
- freeaddrinfo(info); |
|
148 |
- return 0; |
|
149 |
- } |
|
150 |
- |
|
151 |
- closesocket(s); |
|
152 |
- freeaddrinfo(info); |
|
153 |
- return 1; |
|
154 |
- } |
|
155 |
- |
|
156 |
- closesocket(s); |
|
156 |
+CURLcode onas_curl_init(CURL **curl, char *ipaddr, char *port) { |
|
157 |
+ |
|
158 |
+ CURLcode curlcode = CURLE_OK; |
|
159 |
+ |
|
160 |
+ if (!curl || !(*curl) || !ipaddr || !port) { |
|
161 |
+ logg("!ClamClient: invalid (NULL) args passed to onas_curl_init\n"); |
|
162 |
+ return CURLE_FAILED_INIT; |
|
163 |
+ } |
|
164 |
+ |
|
165 |
+ *curl = curl_easy_init(); |
|
166 |
+ |
|
167 |
+ curlcode = curl_easy_setopt(*curl, CURLOPT_PORT, port); |
|
168 |
+ if (CURLE_OK != curlcode) { |
|
169 |
+ logg("!ClamClient: could not setup curl with tcp port, %s\n", curl_easy_strerror(curlcode)); |
|
170 |
+ curl_easy_cleanup(*curl); |
|
171 |
+ return curlcode; |
|
157 | 172 |
} |
158 | 173 |
|
159 |
- freeaddrinfo(info); |
|
174 |
+ curlcode = curl_easy_setopt(*curl, CURLOPT_URL, ipaddr); |
|
175 |
+ if (CURLE_OK != curlcode) { |
|
176 |
+ logg("!ClamClient: could not setup curl with tcp address, %s\n", curl_easy_strerror(curlcode)); |
|
177 |
+ curl_easy_cleanup(*curl); |
|
178 |
+ return curlcode; |
|
179 |
+ } |
|
160 | 180 |
|
161 |
- opt = opt->nextarg; |
|
162 |
- } |
|
181 |
+ /* we implement our own transfer protocol via send and recv, so we only need to connect */ |
|
182 |
+ curlcode = curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L); |
|
183 |
+ if (CURLE_OK != curlcode) { |
|
184 |
+ logg("!ClamClient: could not setup curl to connect only, %s\n", curl_easy_strerror(curlcode)); |
|
185 |
+ curl_easy_cleanup(*curl); |
|
186 |
+ return curlcode; |
|
187 |
+ } |
|
163 | 188 |
|
164 |
- return 0; |
|
189 |
+ return curlcode; |
|
165 | 190 |
} |
166 | 191 |
|
167 | 192 |
cl_error_t onas_setup_client (struct onas_context **ctx) { |
168 | 193 |
|
169 | 194 |
const struct optstruct *opts; |
170 | 195 |
const struct optstruct *opt; |
171 |
- errno = 0; |
|
196 |
+ cl_error_t err; |
|
172 | 197 |
int remote; |
173 | 198 |
|
199 |
+ errno = 0; |
|
200 |
+ |
|
174 | 201 |
opts = (*ctx)->opts; |
175 | 202 |
|
176 | 203 |
if(optget(opts, "verbose")->enabled) { |
... | ... |
@@ -200,16 +229,20 @@ cl_error_t onas_setup_client (struct onas_context **ctx) { |
200 | 200 |
logg("!ClamClient: problem with internal logger\n"); |
201 | 201 |
return CL_EARG; |
202 | 202 |
} |
203 |
- } else |
|
203 |
+ } else { |
|
204 | 204 |
logg_file = NULL; |
205 |
+ } |
|
205 | 206 |
|
206 | 207 |
if(actsetup(opts)) { |
207 | 208 |
return CL_EARG; |
208 | 209 |
} |
209 | 210 |
|
210 |
- if (onas_check_remote(ctx)) { |
|
211 |
- (*ctx)->isremote = 1; |
|
212 |
- } else if (errno == EADDRINUSE) { |
|
211 |
+ if (curl_global_init(CURL_GLOBAL_NOTHING)) { |
|
212 |
+ return CL_EARG; |
|
213 |
+ } |
|
214 |
+ |
|
215 |
+ (*ctx)->isremote = onas_check_remote(ctx, &err); |
|
216 |
+ if (err) { |
|
213 | 217 |
return CL_EARG; |
214 | 218 |
} |
215 | 219 |
|
... | ... |
@@ -275,21 +308,51 @@ static char *onas_make_absolute(const char *basepath) { |
275 | 275 |
int onas_get_clamd_version(struct onas_context **ctx) |
276 | 276 |
{ |
277 | 277 |
char *buff; |
278 |
+ CURL *curl; |
|
279 |
+ CURLcode curlcode; |
|
280 |
+ cl_error_t err = CL_SUCCESS; |
|
281 |
+ int b_remote; |
|
278 | 282 |
int len, sockd; |
279 | 283 |
struct RCVLN rcv; |
280 | 284 |
|
281 |
- onas_check_remote(ctx); |
|
282 |
- if((sockd = onas_dconnect(ctx)) < 0) { |
|
283 |
- return 2; |
|
285 |
+ b_remote = onas_check_remote(ctx, &err); |
|
286 |
+ if (CL_SUCCESS != err) { |
|
287 |
+ logg("!ClamClient: could not check to see if daemon was remote\n"); |
|
288 |
+ return 2; |
|
289 |
+ } |
|
290 |
+ |
|
291 |
+ if (!b_remote) { |
|
292 |
+ curl = curl_easy_init(); |
|
293 |
+ curlcode = curl_easy_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, optget((*ctx)->clamdopts, "LocalSocket")->strarg); |
|
294 |
+ if (CURLE_OK != curlcode) { |
|
295 |
+ logg("!ClamClient: could not setup curl with local unix socket, %s\n", curl_easy_strerror(curlcode)); |
|
296 |
+ curl_easy_cleanup(curl); |
|
297 |
+ return 2; |
|
298 |
+ } |
|
299 |
+ } else { |
|
300 |
+ curlcode = onas_curl_init(&curl, optget((*ctx)->clamdopts, "TCPAddr")->strarg, (*ctx)->portstr); |
|
301 |
+ if (CURLE_OK != curlcode) { |
|
302 |
+ logg("!ClamClient: could not setup curl with tcp address and port, %s\n", curl_easy_strerror(curlcode)); |
|
303 |
+ /* curl cleanup done in ons_curl_init on error */ |
|
304 |
+ return 2; |
|
305 |
+ } |
|
284 | 306 |
} |
285 |
- recvlninit(&rcv, sockd); |
|
286 | 307 |
|
287 |
- if(sendln(sockd, "zVERSION", 9)) { |
|
288 |
- closesocket(sockd); |
|
308 |
+ onas_recvlninit(&rcv, curl); |
|
309 |
+ |
|
310 |
+ curlcode = curl_easy_perform(curl); |
|
311 |
+ if (CURLE_OK != curlcode) { |
|
312 |
+ logg("!ClamClient: could not connect to clam daemon, %s\n", curl_easy_strerror(curlcode)); |
|
313 |
+ return 2; |
|
314 |
+ } |
|
315 |
+ |
|
316 |
+ |
|
317 |
+ if(onas_sendln(curl, "zVERSION", 9)) { |
|
318 |
+ curl_easy_close(curl); |
|
289 | 319 |
return 2; |
290 | 320 |
} |
291 | 321 |
|
292 |
- while((len = recvln(&rcv, &buff, NULL))) { |
|
322 |
+ while((len = onas_recvln(&rcv, &buff, NULL))) { |
|
293 | 323 |
if(len == -1) { |
294 | 324 |
logg("*ClamClient: clamd did not respond with version information\n"); |
295 | 325 |
break; |
... | ... |
@@ -297,12 +360,14 @@ int onas_get_clamd_version(struct onas_context **ctx) |
297 | 297 |
printf("%s\n", buff); |
298 | 298 |
} |
299 | 299 |
|
300 |
- closesocket(sockd); |
|
300 |
+ curl_easy_close(curl); |
|
301 | 301 |
return 0; |
302 | 302 |
} |
303 | 303 |
|
304 | 304 |
int onas_client_scan(struct onas_context **ctx, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code) |
305 | 305 |
{ |
306 |
+ CURL *curl = NULL; |
|
307 |
+ CURLcode curlcode = CURLE_OK; |
|
306 | 308 |
int scantype, errors = 0; |
307 | 309 |
int sockd, ret; |
308 | 310 |
|
... | ... |
@@ -314,19 +379,32 @@ int onas_client_scan(struct onas_context **ctx, const char *fname, STATBUF sb, i |
314 | 314 |
scantype = (*ctx)->scantype; |
315 | 315 |
} |
316 | 316 |
|
317 |
+ curlcode = onas_curl_init(&curl, optget((*ctx)->clamdopts, "TCPAddr")->strarg, (*ctx)->portstr); |
|
318 |
+ if (CURLE_OK != curlcode) { |
|
319 |
+ logg("!ClamClient: could not setup curl with tcp address and port, %s\n", curl_easy_strerror(curlcode)); |
|
320 |
+ /* curl cleanup done in ons_curl_init on error */ |
|
321 |
+ return 2; |
|
322 |
+ } |
|
323 |
+ |
|
317 | 324 |
/* logg here is noisy even for debug, enable only for dev work if something has gone very wrong. */ |
318 | 325 |
//logg("*ClamClient: connecting to daemon ...\n"); |
319 |
- if((sockd = onas_dconnect(ctx)) >= 0 && (ret = onas_dsresult(ctx, sockd, scantype, fname, &ret, err, ret_code)) >= 0) { |
|
326 |
+ curlcode = curl_easy_perform(curl); |
|
327 |
+ if (CURLE_OK != curlcode) { |
|
328 |
+ logg("!ClamClient: could not establish connection, %s\n", curl_easy_strerror(curlcode)); |
|
329 |
+ return 2; |
|
330 |
+ } |
|
331 |
+ |
|
332 |
+ |
|
333 |
+ if((ret = onas_dsresult(ctx, curl, scantype, fname, &ret, err, ret_code)) >= 0) { |
|
320 | 334 |
*infected = ret; |
321 | 335 |
} else { |
322 | 336 |
logg("*ClamClient: connection could not be established ... return code %d\n", *ret_code); |
323 | 337 |
errors = 1; |
324 | 338 |
} |
325 |
- if(sockd >= 0) { |
|
326 |
- /* logg here is noisy even for debug, enable only for dev work if something has gone very wrong. */ |
|
327 |
- //logg("*ClamClient: done, closing connection ...\n"); |
|
328 |
- closesocket(sockd); |
|
329 |
- } |
|
339 |
+ /* logg here is noisy even for debug, enable only for dev work if something has gone very wrong. */ |
|
340 |
+ //logg("*ClamClient: done, closing connection ...\n"); |
|
330 | 341 |
|
342 |
+ curl_easy_cleanup(curl); |
|
331 | 343 |
return *infected ? 1 : (errors ? 2 : 0); |
332 | 344 |
} |
345 |
+ |
... | ... |
@@ -22,6 +22,8 @@ |
22 | 22 |
#ifndef __ONAS_CLIENT_H |
23 | 23 |
#define __ONAS_CLIENT_H |
24 | 24 |
|
25 |
+#include <curl/curl.h> |
|
26 |
+ |
|
25 | 27 |
#include "shared/optparser.h" |
26 | 28 |
#include "../clamonacc.h" |
27 | 29 |
|
... | ... |
@@ -36,8 +38,9 @@ enum { |
36 | 36 |
|
37 | 37 |
|
38 | 38 |
int onas_client_scan(struct onas_context **ctx, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code); |
39 |
+CURLcode onas_curl_init(CURL **curl, char *ipaddr, char *port); |
|
39 | 40 |
int onas_get_clamd_version(struct onas_context **ctx); |
40 | 41 |
cl_error_t onas_setup_client(struct onas_context **ctx); |
41 |
-int onas_check_remote(struct onas_context **ctx); |
|
42 |
+int onas_check_remote(struct onas_context **ctx, cl_error_t *err); |
|
42 | 43 |
|
43 | 44 |
#endif |
44 | 45 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,156 @@ |
0 |
+/* |
|
1 |
+ * Copyright (C) 2015 Cisco Systems, Inc. and/or its affiliates. All rights reserved. |
|
2 |
+ * Copyright (C) 2009-2010 Sourcefire, Inc. |
|
3 |
+ * |
|
4 |
+ * Author: aCaB |
|
5 |
+ * |
|
6 |
+ * This program is free software; you can redistribute it and/or modify |
|
7 |
+ * it under the terms of the GNU General Public License version 2 as |
|
8 |
+ * published by the Free Software Foundation. |
|
9 |
+ * |
|
10 |
+ * This program is distributed in the hope that it will be useful, |
|
11 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
13 |
+ * GNU General Public License for more details. |
|
14 |
+ * |
|
15 |
+ * You should have received a copy of the GNU General Public License |
|
16 |
+ * along with this program; if not, write to the Free Software |
|
17 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|
18 |
+ * MA 02110-1301, USA. |
|
19 |
+ */ |
|
20 |
+ |
|
21 |
+#if HAVE_CONFIG_H |
|
22 |
+#include "clamav-config.h" |
|
23 |
+#endif |
|
24 |
+ |
|
25 |
+#include <stdio.h> |
|
26 |
+#include <string.h> |
|
27 |
+#include <sys/types.h> |
|
28 |
+#include <sys/stat.h> |
|
29 |
+#include <curl/curl.h> |
|
30 |
+#if HAVE_UNISTD_H |
|
31 |
+#include <unistd.h> |
|
32 |
+#endif |
|
33 |
+#include <fcntl.h> |
|
34 |
+#include <errno.h> |
|
35 |
+ |
|
36 |
+#if !defined(_WIN32) |
|
37 |
+#include <sys/socket.h> |
|
38 |
+#endif |
|
39 |
+ |
|
40 |
+#include "shared/output.h" |
|
41 |
+ |
|
42 |
+#include "onaccess_com.h" |
|
43 |
+ |
|
44 |
+/* Sends bytes over a socket |
|
45 |
+ * Returns 0 on success */ |
|
46 |
+int onas_sendln(CURL *curl, const char *line, unsigned int len) { |
|
47 |
+ unsigned int sent = 0; |
|
48 |
+ CURLcode curlcode; |
|
49 |
+ |
|
50 |
+ while(len) { |
|
51 |
+ |
|
52 |
+ curlcode = curl_easy_send(curl, line, len, &sent); |
|
53 |
+ if(sent <= 0) { |
|
54 |
+ if(sent && errno == EINTR) { |
|
55 |
+ continue; |
|
56 |
+ } else { |
|
57 |
+ logg("!Can't send to clamd: %s\n", strerror(errno)); |
|
58 |
+ } |
|
59 |
+ |
|
60 |
+ return 1; |
|
61 |
+ } |
|
62 |
+ |
|
63 |
+ line += sent; |
|
64 |
+ len -= sent; |
|
65 |
+ } |
|
66 |
+ |
|
67 |
+ return 0; |
|
68 |
+} |
|
69 |
+ |
|
70 |
+/* Inits a RECVLN struct before it can be used in recvln() - see below */ |
|
71 |
+void onas_recvlninit(struct RCVLN *s, CURL *curl) { |
|
72 |
+ rcv_data->curl = curl; |
|
73 |
+ rcv_data->curl_code = CURLE_OK; |
|
74 |
+ rcv_data->lnstart = rcv_data->curr = rcv_data->buf; |
|
75 |
+ rcv_data->bytes_recvd = 0; |
|
76 |
+} |
|
77 |
+ |
|
78 |
+/* Receives a full (terminated with \0) line from a socket |
|
79 |
+ * Sets ret_bol to the begin of the received line, and optionally |
|
80 |
+ * ret_eol to the end of line. |
|
81 |
+ * Should be called repeatedly until all input is consumed |
|
82 |
+ * Returns: |
|
83 |
+ * - the length of the line (a positive number) on success |
|
84 |
+ * - 0 if the connection is closed |
|
85 |
+ * - -1 on error |
|
86 |
+ */ |
|
87 |
+int onas_recvln(struct RCVLN *rcv_data, char **ret_bol, char **ret_eol) { |
|
88 |
+ char *eol; |
|
89 |
+ int ret = 0; |
|
90 |
+ |
|
91 |
+ while(1) { |
|
92 |
+ if (!rcv_data->bytes_recvd) { |
|
93 |
+ rcv_data->curl_code = easy_curl_recv(rcv_data->curl, rcv_data->curr, |
|
94 |
+ sizeof(rcv_data->buf) - (rcv_data->curr - rcv_data->buf), &(rcv_data->bytes_recvd)); |
|
95 |
+ |
|
96 |
+ if (rcv_data->bytes_recvd<=0) { |
|
97 |
+ if (rcv_data->bytes_recvd && errno == EINTR) { |
|
98 |
+ rcv_data->bytes_recvd = 0; |
|
99 |
+ continue; |
|
100 |
+ } |
|
101 |
+ |
|
102 |
+ if (rcv_data->bytes_recvd || rcv_data->curr!=rcv_data->buf) { |
|
103 |
+ *rcv_data->curr = '\0'; |
|
104 |
+ |
|
105 |
+ if (strcmp(rcv_data->buf, "UNKNOWN COMMAND\n")) { |
|
106 |
+ logg("!Communication error\n"); |
|
107 |
+ } else { |
|
108 |
+ logg("!Command rejected by clamd (wrong clamd version?)\n"); |
|
109 |
+ } |
|
110 |
+ |
|
111 |
+ return -1; |
|
112 |
+ } |
|
113 |
+ |
|
114 |
+ return 0; |
|
115 |
+ } |
|
116 |
+ } |
|
117 |
+ |
|
118 |
+ if ((eol = memchr(rcv_data->curr, 0, rcv_data->bytes_recvd))) { |
|
119 |
+ eol++; |
|
120 |
+ rcv_data->bytes_recvd -= eol - rcv_data->curr; |
|
121 |
+ |
|
122 |
+ *ret_bol = rcv_data->lnstart; |
|
123 |
+ if (ret_eol) { |
|
124 |
+ *ret_eol = eol; |
|
125 |
+ } |
|
126 |
+ |
|
127 |
+ ret = eol - rcv_data->lnstart; |
|
128 |
+ if (rcv_data->bytes_recvd) { |
|
129 |
+ rcv_data->lnstart = rcv_data->curr = eol; |
|
130 |
+ } else { |
|
131 |
+ rcv_data->lnstart = rcv_data->curr = rcv_data->buf; |
|
132 |
+ } |
|
133 |
+ |
|
134 |
+ return ret; |
|
135 |
+ } |
|
136 |
+ |
|
137 |
+ rcv_data->bytes_recvd += rcv_data->curr - rcv_data->lnstart; |
|
138 |
+ |
|
139 |
+ if (!eol && rcv_data->bytes_recvd==sizeof(rcv_data->buf)) { |
|
140 |
+ logg("!Overlong reply from clamd\n"); |
|
141 |
+ return -1; |
|
142 |
+ } |
|
143 |
+ |
|
144 |
+ if (!eol) { |
|
145 |
+ if(rcv_data->buf != rcv_data->lnstart) { /* old memmove sux */ |
|
146 |
+ memmove(rcv_data->buf, rcv_data->lnstart, rcv_data->bytes_recvd); |
|
147 |
+ rcv_data->lnstart = rcv_data->buf; |
|
148 |
+ } |
|
149 |
+ |
|
150 |
+ rcv_data->curr = &rcv_data->lnstart[rcv_data->bytes_recvd]; |
|
151 |
+ rcv_data->bytes_recvd = 0; |
|
152 |
+ } |
|
153 |
+ } |
|
154 |
+} |
|
155 |
+ |
0 | 156 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,48 @@ |
0 |
+/* |
|
1 |
+ * Copyright (C) 2015 Cisco Systems, Inc. and/or its affiliates. All rights reserved. |
|
2 |
+ * Copyright (C) 2009-2010 Sourcefire, Inc. |
|
3 |
+ * |
|
4 |
+ * Author: aCaB |
|
5 |
+ * |
|
6 |
+ * This program is free software; you can redistribute it and/or modify |
|
7 |
+ * it under the terms of the GNU General Public License version 2 as |
|
8 |
+ * published by the Free Software Foundation. |
|
9 |
+ * |
|
10 |
+ * This program is distributed in the hope that it will be useful, |
|
11 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
13 |
+ * GNU General Public License for more details. |
|
14 |
+ * |
|
15 |
+ * You should have received a copy of the GNU General Public License |
|
16 |
+ * along with this program; if not, write to the Free Software |
|
17 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|
18 |
+ * MA 02110-1301, USA. |
|
19 |
+ */ |
|
20 |
+ |
|
21 |
+#ifndef ONAS_COM_H |
|
22 |
+#define ONAS_COM_H |
|
23 |
+ |
|
24 |
+#if HAVE_CONFIG_H |
|
25 |
+#include "clamav-config.h" |
|
26 |
+#endif |
|
27 |
+ |
|
28 |
+#if HAVE_SYS_PARAM_H |
|
29 |
+#include <sys/param.h> |
|
30 |
+#endif |
|
31 |
+ |
|
32 |
+#include "shared/misc.h" |
|
33 |
+ |
|
34 |
+struct RCVLN { |
|
35 |
+ char buf[PATH_MAX+1024]; /* FIXME must match that in clamd - bb1349 */ |
|
36 |
+ CURL *curl; |
|
37 |
+ CURLcode curlcode; |
|
38 |
+ int retlen; |
|
39 |
+ char *curr; |
|
40 |
+ char *lnstart; |
|
41 |
+}; |
|
42 |
+ |
|
43 |
+int onas_sendln(CURL *curl, const char *line, unsigned int len); |
|
44 |
+void onas_recvlninit(struct RCVLN *s, CURL *curl); |
|
45 |
+int onas_recvln(struct RCVLN *rcv_data, char **ret_bol, char **ret_eol); |
|
46 |
+ |
|
47 |
+#endif |
... | ... |
@@ -32,6 +32,7 @@ |
32 | 32 |
/* must be first because it may define _XOPEN_SOURCE */ |
33 | 33 |
#include "shared/fdpassing.h" |
34 | 34 |
#include <stdio.h> |
35 |
+#include <curl/curl.h> |
|
35 | 36 |
#ifdef HAVE_UNISTD_H |
36 | 37 |
#include <unistd.h> |
37 | 38 |
#endif |
... | ... |
@@ -57,8 +58,8 @@ |
57 | 57 |
#include "shared/actions.h" |
58 | 58 |
#include "shared/output.h" |
59 | 59 |
#include "shared/misc.h" |
60 |
-#include "shared/clamdcom.h" |
|
61 | 60 |
|
61 |
+#include "onaccess_com.h" |
|
62 | 62 |
#include "onaccess_proto.h" |
63 | 63 |
#include "onaccess_client.h" |
64 | 64 |
|
... | ... |
@@ -72,7 +73,7 @@ static const char *scancmd[] = { "CONTSCAN", "MULTISCAN", "INSTREAM", "FILDES", |
72 | 72 |
|
73 | 73 |
/* Connects to clamd |
74 | 74 |
* Returns a FD or -1 on error */ |
75 |
-int onas_dconnect(struct onas_context **ctx) { |
|
75 |
+/*int onas_dconnect(struct onas_context **ctx) { |
|
76 | 76 |
int sockd, res; |
77 | 77 |
const struct optstruct *opt; |
78 | 78 |
struct addrinfo hints, *info, *p; |
... | ... |
@@ -134,11 +135,11 @@ int onas_dconnect(struct onas_context **ctx) { |
134 | 134 |
} |
135 | 135 |
|
136 | 136 |
return -1; |
137 |
-} |
|
137 |
+}*/ |
|
138 | 138 |
|
139 | 139 |
/* Issues an INSTREAM command to clamd and streams the given file |
140 | 140 |
* Returns >0 on success, 0 soft fail, -1 hard fail */ |
141 |
-static int onas_send_stream(struct onas_context **ctx, int sockd, const char *filename) { |
|
141 |
+static int onas_send_stream(struct onas_context **ctx, CURL *curl, const char *filename) { |
|
142 | 142 |
uint32_t buf[BUFSIZ/sizeof(uint32_t)]; |
143 | 143 |
int fd, len; |
144 | 144 |
unsigned long int todo = (*ctx)->maxstream; |
... | ... |
@@ -150,7 +151,7 @@ static int onas_send_stream(struct onas_context **ctx, int sockd, const char *fi |
150 | 150 |
} |
151 | 151 |
} else fd = 0; |
152 | 152 |
|
153 |
- if(sendln(sockd, "zINSTREAM", 10)) { |
|
153 |
+ if(onas_sendln(curl, "zINSTREAM", 10)) { |
|
154 | 154 |
close(fd); |
155 | 155 |
return -1; |
156 | 156 |
} |
... | ... |
@@ -158,7 +159,7 @@ static int onas_send_stream(struct onas_context **ctx, int sockd, const char *fi |
158 | 158 |
while((len = read(fd, &buf[1], sizeof(buf) - sizeof(uint32_t))) > 0) { |
159 | 159 |
if((unsigned int)len > todo) len = todo; |
160 | 160 |
buf[0] = htonl(len); |
161 |
- if(sendln(sockd, (const char *)buf, len+sizeof(uint32_t))) { |
|
161 |
+ if (onas_sendln(curl, (const char *)buf, len+sizeof(uint32_t))) { |
|
162 | 162 |
close(fd); |
163 | 163 |
return -1; |
164 | 164 |
} |
... | ... |
@@ -174,14 +175,15 @@ static int onas_send_stream(struct onas_context **ctx, int sockd, const char *fi |
174 | 174 |
return 0; |
175 | 175 |
} |
176 | 176 |
*buf=0; |
177 |
- sendln(sockd, (const char *)buf, 4); |
|
177 |
+ onas_sendln(curl, (const char *)buf, 4); |
|
178 | 178 |
return 1; |
179 | 179 |
} |
180 | 180 |
|
181 | 181 |
#ifdef HAVE_FD_PASSING |
182 | 182 |
/* Issues a FILDES command and pass a FD to clamd |
183 | 183 |
* Returns >0 on success, 0 soft fail, -1 hard fail */ |
184 |
-static int onas_send_fdpass(int sockd, const char *filename) { |
|
184 |
+static int onas_send_fdpass(CURL *curl, const char *filename) { |
|
185 |
+ CURLcode result; |
|
185 | 186 |
struct iovec iov[1]; |
186 | 187 |
struct msghdr msg; |
187 | 188 |
struct cmsghdr *cmsg; |
... | ... |
@@ -195,7 +197,8 @@ static int onas_send_fdpass(int sockd, const char *filename) { |
195 | 195 |
return 0; |
196 | 196 |
} |
197 | 197 |
} else fd = 0; |
198 |
- if(sendln(sockd, "zFILDES", 8)) { |
|
198 |
+ if(result = onas_sendln(curl, "zFILDES", 8)) { |
|
199 |
+ logg("*ClamProto: error sending w/ curl, %s\n", curl_easy_strerror(result)); |
|
199 | 200 |
close(fd); |
200 | 201 |
return -1; |
201 | 202 |
} |
... | ... |
@@ -212,7 +215,7 @@ static int onas_send_fdpass(int sockd, const char *filename) { |
212 | 212 |
cmsg->cmsg_level = SOL_SOCKET; |
213 | 213 |
cmsg->cmsg_type = SCM_RIGHTS; |
214 | 214 |
*(int *)CMSG_DATA(cmsg) = fd; |
215 |
- if(sendmsg(sockd, &msg, 0) == -1) { |
|
215 |
+ if(onas_sendln(curl, &msg, 0) == -1) { |
|
216 | 216 |
logg("!FD send failed: %s\n", strerror(errno)); |
217 | 217 |
close(fd); |
218 | 218 |
return -1; |
... | ... |
@@ -244,7 +247,7 @@ static int chkpath(struct onas_context **ctx, const char *path) |
244 | 244 |
* This is used only in non IDSESSION mode |
245 | 245 |
* Returns the number of infected files or -1 on error |
246 | 246 |
* NOTE: filename may be NULL for STREAM scantype. */ |
247 |
-int onas_dsresult(struct onas_context **ctx, int sockd, int scantype, const char *filename, int *printok, int *errors, cl_error_t *ret_code) { |
|
247 |
+int onas_dsresult(struct onas_context **ctx, CURL *curl, int scantype, const char *filename, int *printok, int *errors, cl_error_t *ret_code) { |
|
248 | 248 |
int infected = 0, len = 0, beenthere = 0; |
249 | 249 |
char *bol, *eol; |
250 | 250 |
struct RCVLN rcv; |
... | ... |
@@ -252,7 +255,8 @@ int onas_dsresult(struct onas_context **ctx, int sockd, int scantype, const char |
252 | 252 |
|
253 | 253 |
if(filename && chkpath(ctx, filename)) |
254 | 254 |
return 0; |
255 |
- recvlninit(&rcv, sockd); |
|
255 |
+ |
|
256 |
+ onas_recvlninit(&rcv, curl); |
|
256 | 257 |
|
257 | 258 |
if (ret_code) { |
258 | 259 |
*ret_code = CL_SUCCESS; |
... | ... |
@@ -278,7 +282,7 @@ int onas_dsresult(struct onas_context **ctx, int sockd, int scantype, const char |
278 | 278 |
return -1; |
279 | 279 |
} |
280 | 280 |
sprintf(bol, "z%s %s", scancmd[scantype], filename); |
281 |
- if(sendln(sockd, bol, len)) { |
|
281 |
+ if(onas_sendln(curl, bol, len)) { |
|
282 | 282 |
if (ret_code) { |
283 | 283 |
*ret_code = CL_EWRITE; |
284 | 284 |
} |
... | ... |
@@ -290,12 +294,12 @@ int onas_dsresult(struct onas_context **ctx, int sockd, int scantype, const char |
290 | 290 |
|
291 | 291 |
case STREAM: |
292 | 292 |
/* NULL filename safe in send_stream() */ |
293 |
- len = onas_send_stream(ctx, sockd, filename); |
|
293 |
+ len = onas_send_stream(ctx, curl, filename); |
|
294 | 294 |
break; |
295 | 295 |
#ifdef HAVE_FD_PASSING |
296 | 296 |
case FILDES: |
297 | 297 |
/* NULL filename safe in send_fdpass() */ |
298 |
- len = onas_send_fdpass(sockd, filename); |
|
298 |
+ len = onas_send_fdpass(curl, filename); |
|
299 | 299 |
break; |
300 | 300 |
#endif |
301 | 301 |
} |
... | ... |
@@ -307,7 +311,7 @@ int onas_dsresult(struct onas_context **ctx, int sockd, int scantype, const char |
307 | 307 |
return len; |
308 | 308 |
} |
309 | 309 |
|
310 |
- while((len = recvln(&rcv, &bol, &eol))) { |
|
310 |
+ while((len = onas_recvln(&rcv, &bol, &eol))) { |
|
311 | 311 |
if(len == -1) { |
312 | 312 |
if (ret_code) { |
313 | 313 |
*ret_code = CL_EREAD; |
... | ... |
@@ -21,9 +21,12 @@ |
21 | 21 |
|
22 | 22 |
#ifndef ONAS_PROTO_H |
23 | 23 |
#define ONAS_PROTO_H |
24 |
+ |
|
25 |
+#include <curl/curl.h> |
|
26 |
+ |
|
24 | 27 |
#include "shared/misc.h" |
25 | 28 |
#include "../clamonacc.h" |
26 | 29 |
|
27 |
-int onas_dconnect(struct onas_context **ctx) ; |
|
28 |
-int onas_dsresult(struct onas_context **ctx, int sockd, int scantype, const char *filename, int *printok, int *errors, cl_error_t *ret_code); |
|
30 |
+/*int onas_dconnect(struct onas_context **ctx);*/ |
|
31 |
+int onas_dsresult(struct onas_context **ctx, CURL *curl, int scantype, const char *filename, int *printok, int *errors, cl_error_t *ret_code); |
|
29 | 32 |
#endif |
... | ... |
@@ -70,10 +70,10 @@ extern pthread_t ddd_pid; |
70 | 70 |
logg("ClamFanotif: stopped\n"); |
71 | 71 |
}*/ |
72 | 72 |
|
73 |
-static int onas_fan_scanfile(const char *fname, struct fanotify_event_metadata *fmd, STATBUF sb, int scan, struct onas_context **ctx) |
|
73 |
+/* TODO: rework this to feed multithreading consumer queue |
|
74 |
+ * static int onas_fan_scanfile(const char *fname, struct fanotify_event_metadata *fmd, STATBUF sb, int scan, struct onas_context **ctx) |
|
74 | 75 |
{ |
75 | 76 |
struct fanotify_response res; |
76 |
- const char *virname = NULL; |
|
77 | 77 |
int infected = 0; |
78 | 78 |
int err = 0; |
79 | 79 |
int ret = 0; |
... | ... |
@@ -102,7 +102,7 @@ static int onas_fan_scanfile(const char *fname, struct fanotify_event_metadata * |
102 | 102 |
} |
103 | 103 |
|
104 | 104 |
return ret; |
105 |
-} |
|
105 |
+}*/ |
|
106 | 106 |
|
107 | 107 |
cl_error_t onas_setup_fanotif(struct onas_context **ctx) { |
108 | 108 |
|
... | ... |
@@ -255,11 +255,12 @@ int onas_fan_eloop(struct onas_context **ctx) { |
255 | 255 |
} |
256 | 256 |
} |
257 | 257 |
|
258 |
+ /* TODO: rework to feed consumer queue |
|
258 | 259 |
if (onas_fan_scanfile(fname, fmd, sb, scan, ctx) == -1) { |
259 | 260 |
close(fmd->fd); |
260 | 261 |
logg("!ClamFanotif: error when stating and/or scanning??\n"); |
261 | 262 |
return 2; |
262 |
- } |
|
263 |
+ }*/ |
|
263 | 264 |
|
264 | 265 |
if (close(fmd->fd) == -1) { |
265 | 266 |
printf("!ClamFanotif: internal error (close(%d) failed)\n", fmd->fd); |
... | ... |
@@ -69,7 +69,7 @@ static void onas_ddd_handle_in_moved_to(struct onas_context *ctx, const char *pa |
69 | 69 |
static void onas_ddd_handle_in_create(struct onas_context *ctx, const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask); |
70 | 70 |
static void onas_ddd_handle_in_moved_from(struct onas_context *ctx, const char *path, const char *child_path, const struct inotify_event *event, int wd); |
71 | 71 |
static void onas_ddd_handle_in_delete(struct onas_context *ctx, const char *path, const char *child_path, const struct inotify_event *event, int wd); |
72 |
-static void onas_ddd_handle_extra_scanning(struct onas_context *ctx, const char *pathname, int extra_options); |
|
72 |
+/*static void onas_ddd_handle_extra_scanning(struct onas_context *ctx, const char *pathname, int extra_options);*/ |
|
73 | 73 |
|
74 | 74 |
static void onas_ddd_exit(int sig); |
75 | 75 |
|
... | ... |
@@ -684,8 +684,8 @@ static void onas_ddd_handle_in_moved_to(struct onas_context *ctx, |
684 | 684 |
return; |
685 | 685 |
} |
686 | 686 |
|
687 |
- |
|
688 |
-static void onas_ddd_handle_extra_scanning(struct onas_context *ctx, const char *pathname, int extra_options) { |
|
687 |
+/* TODO: rework this to use consumer queue when making multithreading changes */ |
|
688 |
+/*static void onas_ddd_handle_extra_scanning(struct onas_context *ctx, const char *pathname, int extra_options) { |
|
689 | 689 |
|
690 | 690 |
int thread_started = 1; |
691 | 691 |
struct scth_thrarg *scth_tharg = NULL; |
... | ... |
@@ -694,10 +694,10 @@ static void onas_ddd_handle_extra_scanning(struct onas_context *ctx, const char |
694 | 694 |
|
695 | 695 |
do { |
696 | 696 |
if (pthread_attr_init(&scth_attr)) break; |
697 |
- pthread_attr_setdetachstate(&scth_attr, PTHREAD_CREATE_JOINABLE); |
|
697 |
+ pthread_attr_setdetachstate(&scth_attr, PTHREAD_CREATE_JOINABLE);*/ |
|
698 | 698 |
|
699 | 699 |
/* Allocate memory for arguments. Thread is responsible for freeing it. */ |
700 |
- if (!(scth_tharg = (struct scth_thrarg *)calloc(sizeof(struct scth_thrarg), 1))) break; |
|
700 |
+ /* (!(scth_tharg = (struct scth_thrarg *) calloc(sizeof(struct scth_thrarg), 1))) break; |
|
701 | 701 |
if (!(scth_tharg->options = (struct cl_scan_options *)calloc(sizeof(struct cl_scan_options), 1))) break; |
702 | 702 |
|
703 | 703 |
|
... | ... |
@@ -708,9 +708,9 @@ static void onas_ddd_handle_extra_scanning(struct onas_context *ctx, const char |
708 | 708 |
thread_started = pthread_create(&scth_pid, &scth_attr, onas_scan_th, scth_tharg); |
709 | 709 |
} while (0); |
710 | 710 |
|
711 |
- if (0 != thread_started) { |
|
711 |
+ if (0 != thread_started) {*/ |
|
712 | 712 |
/* Failed to create thread. Free anything we may have allocated. */ |
713 |
- logg("!ClamInotif: Unable to kick off extra scanning.\n"); |
|
713 |
+ /*logg("!ClamInotif: Unable to kick off extra scanning.\n"); |
|
714 | 714 |
if (NULL != scth_tharg) { |
715 | 715 |
if (NULL != scth_tharg->pathname) { |
716 | 716 |
free(scth_tharg->pathname); |
... | ... |
@@ -726,7 +726,7 @@ static void onas_ddd_handle_extra_scanning(struct onas_context *ctx, const char |
726 | 726 |
} |
727 | 727 |
|
728 | 728 |
return; |
729 |
-} |
|
729 |
+}*/ |
|
730 | 730 |
|
731 | 731 |
static void onas_ddd_exit(int sig) { |
732 | 732 |
logg("*ClamInotif: onas_ddd_exit(), signal %d\n", sig); |
... | ... |
@@ -47,8 +47,6 @@ |
47 | 47 |
#include "../clamonacc.h" |
48 | 48 |
#include "../client/onaccess_client.h" |
49 | 49 |
|
50 |
-static pthread_mutex_t onas_scan_lock = PTHREAD_MUTEX_INITIALIZER; |
|
51 |
- |
|
52 | 50 |
int onas_fan_checkowner(int pid, const struct optstruct *opts) |
53 | 51 |
{ |
54 | 52 |
char path[32]; |
... | ... |
@@ -99,7 +97,9 @@ int onas_fan_checkowner(int pid, const struct optstruct *opts) |
99 | 99 |
/** |
100 | 100 |
* Thread-safe scan wrapper to ensure there's no processs contention over use of the socket. |
101 | 101 |
*/ |
102 |
-int onas_scan(struct onas_context **ctx, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code) |
|
102 |
+ |
|
103 |
+/* TODO: remove this |
|
104 |
+ * int onas_scan(struct onas_context **ctx, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code) |
|
103 | 105 |
{ |
104 | 106 |
int ret = 0; |
105 | 107 |
int i = 0; |
... | ... |
@@ -113,7 +113,6 @@ int onas_scan(struct onas_context **ctx, const char *fname, STATBUF sb, int *inf |
113 | 113 |
|
114 | 114 |
logg("*ClamMisc: internal issue (daemon could not access directory/file %s)\n", fname); |
115 | 115 |
break; |
116 |
- /* TODO: handle other errors */ |
|
117 | 116 |
case CL_EPARSE: |
118 | 117 |
case CL_EREAD: |
119 | 118 |
case CL_EWRITE: |
... | ... |
@@ -135,12 +134,13 @@ int onas_scan(struct onas_context **ctx, const char *fname, STATBUF sb, int *inf |
135 | 135 |
} |
136 | 136 |
} |
137 | 137 |
return ret; |
138 |
-} |
|
138 |
+}*/ |
|
139 | 139 |
|
140 | 140 |
/** |
141 | 141 |
* Thread-safe scan wrapper to ensure there's no processs contention over use of the socket. |
142 | 142 |
*/ |
143 |
-int onas_scan_safe(struct onas_context **ctx, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code) |
|
143 |
+/* TODO: remove this |
|
144 |
+ * int onas_scan_safe(struct onas_context **ctx, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code) |
|
144 | 145 |
{ |
145 | 146 |
int ret = 0; |
146 | 147 |
|
... | ... |
@@ -151,7 +151,7 @@ int onas_scan_safe(struct onas_context **ctx, const char *fname, STATBUF sb, int |
151 | 151 |
pthread_mutex_unlock(&onas_scan_lock); |
152 | 152 |
|
153 | 153 |
return ret; |
154 |
- } |
|
154 |
+}*/ |
|
155 | 155 |
|
156 | 156 |
char **onas_get_opt_list(const char *fname, int *num_entries, cl_error_t *err) |
157 | 157 |
{ |
... | ... |
@@ -32,8 +32,8 @@ typedef enum { |
32 | 32 |
} cli_check_t; |
33 | 33 |
|
34 | 34 |
int onas_fan_checkowner(int pid, const struct optstruct *opts); |
35 |
-int onas_scan(struct onas_context **ctx, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code); |
|
36 |
-int onas_scan_safe(struct onas_context **ctx, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code); |
|
35 |
+//int onas_scan(struct onas_context **ctx, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code); |
|
36 |
+//int onas_scan_safe(struct onas_context **ctx, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code); |
|
37 | 37 |
char **onas_get_opt_list(const char *fname, int *num_entries, cl_error_t *err); |
38 | 38 |
void free_opt_list(char** opt_list, int entries); |
39 | 39 |
|
... | ... |
@@ -30,6 +30,7 @@ |
30 | 30 |
#include <fcntl.h> |
31 | 31 |
#include <signal.h> |
32 | 32 |
#include <pthread.h> |
33 |
+#include <sys/fanotify.h> |
|
33 | 34 |
|
34 | 35 |
#include "shared/optparser.h" |
35 | 36 |
#include "shared/output.h" |
... | ... |
@@ -37,14 +38,19 @@ |
37 | 37 |
#include "libclamav/others.h" |
38 | 38 |
#include "../misc/priv_fts.h" |
39 | 39 |
#include "../misc/onaccess_others.h" |
40 |
+#include "../client/onaccess_client.h" |
|
40 | 41 |
#include "onaccess_scth.h" |
41 | 42 |
//#include "onaccess_others.h" |
42 | 43 |
|
43 | 44 |
#include "libclamav/clamav.h" |
44 | 45 |
|
45 |
-static int onas_scth_scanfile(const char *fname, int fd, int extinfo, struct scth_thrarg *tharg); |
|
46 |
-static int onas_scth_handle_dir(const char *pathname, struct scth_thrarg *tharg); |
|
47 |
-static int onas_scth_handle_file(const char *pathname, struct scth_thrarg *tharg); |
|
46 |
+static pthread_mutex_t onas_scan_lock = PTHREAD_MUTEX_INITIALIZER; |
|
47 |
+ |
|
48 |
+static int onas_scan(struct onas_context **ctx, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code); |
|
49 |
+static int onas_scan_safe(struct onas_context **ctx, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code); |
|
50 |
+static int onas_scth_scanfile(struct onas_context **ctx, const char *fname, STATBUF sb, struct onas_scan_event *event_data, int *infected, int *err, cl_error_t *ret_code); |
|
51 |
+static int onas_scth_handle_dir(struct onas_context **ctx, const char *pathname, struct onas_scan_event *event_data); |
|
52 |
+static int onas_scth_handle_file(struct onas_context **ctx, const char *pathname, struct onas_scan_event *event_data); |
|
48 | 53 |
|
49 | 54 |
static void onas_scth_exit(int sig); |
50 | 55 |
|
... | ... |
@@ -55,67 +61,168 @@ static void onas_scth_exit(int sig) |
55 | 55 |
pthread_exit(NULL); |
56 | 56 |
} |
57 | 57 |
|
58 |
-static int onas_scth_scanfile(const char *fname, int fd, int extinfo, struct scth_thrarg *tharg) |
|
58 |
+/** |
|
59 |
+ * Scan wrapper, used by both inotify and fanotify threads. Owned by scanthread to force multithreaded client archtiecture |
|
60 |
+ * which better avoids kernel level deadlocks from fanotify blocking/prevention |
|
61 |
+ */ |
|
62 |
+static int onas_scan(struct onas_context **ctx, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code) |
|
59 | 63 |
{ |
60 | 64 |
int ret = 0; |
61 |
- const char *virname = NULL; |
|
65 |
+ int i = 0; |
|
66 |
+ |
|
67 |
+ ret = onas_scan_safe(ctx, fname, sb, infected, err, ret_code); |
|
68 |
+ |
|
69 |
+ if (*err) { |
|
70 |
+ switch (*ret_code) { |
|
71 |
+ case CL_EACCES: |
|
72 |
+ case CL_ESTAT: |
|
73 |
+ |
|
74 |
+ logg("*ClamMisc: internal issue (daemon could not access directory/file %s)\n", fname); |
|
75 |
+ break; |
|
76 |
+ /* TODO: handle other errors */ |
|
77 |
+ case CL_EPARSE: |
|
78 |
+ case CL_EREAD: |
|
79 |
+ case CL_EWRITE: |
|
80 |
+ case CL_EMEM: |
|
81 |
+ case CL_ENULLARG: |
|
82 |
+ default: |
|
83 |
+ logg("~ClamMisc: internal issue (client failed to scan)\n"); |
|
84 |
+ } |
|
85 |
+ if ((*ctx)->retry_on_error) { |
|
86 |
+ logg("*ClamMisc: reattempting scan ... \n"); |
|
87 |
+ while (err) { |
|
88 |
+ ret = onas_scan_safe(ctx, fname, sb, infected, err, ret_code); |
|
89 |
+ |
|
90 |
+ i++; |
|
91 |
+ if (*err && i == (*ctx)->retry_attempts) { |
|
92 |
+ *err = 0; |
|
93 |
+ } |
|
94 |
+ } |
|
95 |
+ } |
|
96 |
+ } |
|
62 | 97 |
|
63 |
- //return onas_scan(fname, fd, &virname, tharg->engine, tharg->options, extinfo); |
|
64 | 98 |
return ret; |
65 | 99 |
} |
66 | 100 |
|
67 |
-static int onas_scth_handle_dir(const char *pathname, struct scth_thrarg *tharg) |
|
101 |
+/** |
|
102 |
+ * Thread-safe scan wrapper to ensure there's no processs contention over use of the socket. |
|
103 |
+ */ |
|
104 |
+static int onas_scan_safe(struct onas_context **ctx, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code) |
|
68 | 105 |
{ |
106 |
+ int ret = 0; |
|
107 |
+ |
|
108 |
+ pthread_mutex_lock(&onas_scan_lock); |
|
109 |
+ |
|
110 |
+ ret = onas_client_scan(ctx, fname, sb, infected, err, ret_code); |
|
111 |
+ |
|
112 |
+ pthread_mutex_unlock(&onas_scan_lock); |
|
113 |
+ |
|
114 |
+ return ret; |
|
115 |
+} |
|
116 |
+ |
|
117 |
+static int onas_scth_scanfile(struct onas_context **ctx, const char *fname, STATBUF sb, struct onas_scan_event *event_data, int *infected, int *err, cl_error_t *ret_code) |
|
118 |
+{ |
|
119 |
+ struct fanotify_response res; |
|
120 |
+ int ret = 0; |
|
121 |
+ int i = 0; |
|
122 |
+ |
|
123 |
+ if (event_data->b_fanotify) { |
|
124 |
+ res.fd = event_data->fmd->fd; |
|
125 |
+ res.response = FAN_ALLOW; |
|
126 |
+ } |
|
127 |
+ |
|
128 |
+ if (event_data->b_scan) { |
|
129 |
+ ret = onas_scan(ctx, fname, sb, infected, err, ret_code); |
|
130 |
+ |
|
131 |
+ if (err && ret_code != CL_SUCCESS) { |
|
132 |
+ logg("*Clamonacc: scan failed with error code %d\n", *ret_code); |
|
133 |
+ } |
|
134 |
+ |
|
135 |
+ |
|
136 |
+ if (event_data->b_fanotify) { |
|
137 |
+ if ((err && ret_code && (*ctx)->deny_on_error) || infected) { |
|
138 |
+ res.response = FAN_DENY; |
|
139 |
+ } |
|
140 |
+ } |
|
141 |
+ } |
|
142 |
+ |
|
143 |
+ |
|
144 |
+ if (event_data->b_fanotify) { |
|
145 |
+ if(event_data->fmd->mask & FAN_ALL_PERM_EVENTS) { |
|
146 |
+ ret = write((*ctx)->fan_fd, &res, sizeof(res)); |
|
147 |
+ if(ret == -1) |
|
148 |
+ logg("!Clamonacc: internal error (can't write to fanotify)\n"); |
|
149 |
+ } |
|
150 |
+ } |
|
151 |
+ |
|
152 |
+ return ret; |
|
153 |
+} |
|
154 |
+ |
|
155 |
+static int onas_scth_handle_dir(struct onas_context **ctx, const char *pathname, struct onas_scan_event *event_data) { |
|
69 | 156 |
FTS *ftsp = NULL; |
70 |
- int fd; |
|
71 |
- int ftspopts = FTS_PHYSICAL | FTS_XDEV; |
|
72 |
- int extinfo; |
|
73 |
- int ret; |
|
157 |
+ int32_t ftspopts = FTS_PHYSICAL | FTS_XDEV; |
|
158 |
+ int32_t infected = 0; |
|
159 |
+ int32_t err = 0; |
|
160 |
+ cl_error_t ret_code = CL_SUCCESS; |
|
161 |
+ int32_t ret = 0; |
|
162 |
+ int32_t fres = 0; |
|
74 | 163 |
FTSENT *curr = NULL; |
75 |
- |
|
76 |
- extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled; |
|
164 |
+ STATBUF sb; |
|
77 | 165 |
|
78 | 166 |
char *const pathargv[] = {(char *)pathname, NULL}; |
79 | 167 |
if (!(ftsp = _priv_fts_open(pathargv, ftspopts, NULL))) return CL_EOPEN; |
80 | 168 |
|
81 | 169 |
while ((curr = _priv_fts_read(ftsp))) { |
82 | 170 |
if (curr->fts_info != FTS_D) { |
83 |
- if ((fd = safe_open(curr->fts_path, O_RDONLY | O_BINARY)) == -1) |
|
84 |
- return CL_EOPEN; |
|
85 | 171 |
|
86 |
- if (onas_scth_scanfile(curr->fts_path, fd, extinfo, tharg) == CL_VIRUS) |
|
87 |
- ; |
|
88 |
- ret = CL_VIRUS; |
|
172 |
+ fres = CLAMSTAT(curr->fts_path, &sb); |
|
173 |
+ |
|
174 |
+ if ((*ctx)->sizelimit) { |
|
175 |
+ if (fres != 0 || sb.st_size > (*ctx)->sizelimit) { |
|
176 |
+ //okay to skip, directory from inotify events (probably) won't block w/ protection enabled |
|
177 |
+ //log here later |
|
178 |
+ continue; |
|
179 |
+ } |
|
180 |
+ } |
|
89 | 181 |
|
90 |
- close(fd); |
|
182 |
+ ret = onas_scth_scanfile(ctx, curr->fts_path, sb, event_data, &infected, &err, &ret_code); |
|
183 |
+ // probs need to error check here later, or at least log |
|
91 | 184 |
} |
92 | 185 |
} |
93 | 186 |
|
94 | 187 |
return ret; |
95 | 188 |
} |
96 | 189 |
|
97 |
-static int onas_scth_handle_file(const char *pathname, struct scth_thrarg *tharg) |
|
98 |
-{ |
|
99 |
- int fd; |
|
100 |
- int extinfo; |
|
101 |
- int ret; |
|
190 |
+static int onas_scth_handle_file(struct onas_context **ctx, const char *pathname, struct onas_scan_event *event_data) { |
|
102 | 191 |
|
103 |
- if (!pathname) return CL_ENULLARG; |
|
192 |
+ STATBUF sb; |
|
193 |
+ int32_t infected = 0; |
|
194 |
+ int32_t err = 0; |
|
195 |
+ cl_error_t ret_code = CL_SUCCESS; |
|
196 |
+ int fres = 0; |
|
197 |
+ int ret = 0; |
|
104 | 198 |
|
105 |
- extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled; |
|
199 |
+ if (!pathname) return CL_ENULLARG; |
|
106 | 200 |
|
107 |
- if ((fd = safe_open(pathname, O_RDONLY | O_BINARY)) == -1) |
|
108 |
- return CL_EOPEN; |
|
109 |
- ret = onas_scth_scanfile(pathname, fd, extinfo, tharg); |
|
201 |
+ fres = CLAMSTAT(pathname, &sb); |
|
202 |
+ if ((*ctx)->sizelimit) { |
|
203 |
+ if (fres != 0 || sb.st_size > (*ctx)->sizelimit) { |
|
204 |
+ /* don't skip so we avoid lockups, but don't scan either */ |
|
205 |
+ event_data->b_scan = 0; |
|
206 |
+ } |
|
207 |
+ } |
|
110 | 208 |
|
111 |
- close(fd); |
|
209 |
+ ret = onas_scth_scanfile(ctx, pathname, sb, event_data, &infected, &err, &ret_code); |
|
210 |
+ // probs need to error check here later, or at least log |
|
112 | 211 |
|
113 | 212 |
return ret; |
114 | 213 |
} |
115 | 214 |
|
116 |
-void *onas_scan_th(void *arg) |
|
117 |
-{ |
|
215 |
+void *onas_scan_th(void *arg) { |
|
216 |
+ |
|
118 | 217 |
struct scth_thrarg *tharg = (struct scth_thrarg *)arg; |
218 |
+ struct onas_scan_event *event_data = NULL; |
|
219 |
+ struct onas_context **ctx = NULL; |
|
119 | 220 |
sigset_t sigset; |
120 | 221 |
struct sigaction act; |
121 | 222 |
|
... | ... |
@@ -126,7 +233,7 @@ void *onas_scan_th(void *arg) |
126 | 126 |
* SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */ |
127 | 127 |
sigdelset(&sigset, SIGFPE); |
128 | 128 |
sigdelset(&sigset, SIGILL); |
129 |
- sigdelset(&sigset, SIGSEGV); |
|
129 |
+ //sigdelset(&sigset, SIGSEGV); |
|
130 | 130 |
#ifdef SIGBUS |
131 | 131 |
sigdelset(&sigset, SIGBUS); |
132 | 132 |
#endif |
... | ... |
@@ -137,29 +244,45 @@ void *onas_scan_th(void *arg) |
137 | 137 |
sigaction(SIGUSR1, &act, NULL); |
138 | 138 |
sigaction(SIGSEGV, &act, NULL); |
139 | 139 |
|
140 |
- if (NULL == tharg || NULL == tharg->pathname || NULL == tharg->opts || NULL == tharg->engine) { |
|
140 |
+ if (NULL == tharg || NULL == tharg->ctx || NULL == tharg->event_data || NULL == tharg->event_data->pathname || NULL == (*(tharg->ctx))->opts) { |
|
141 | 141 |
logg("ScanOnAccess: Invalid thread arguments for extra scanning\n"); |
142 | 142 |
goto done; |
143 | 143 |
} |
144 | 144 |
|
145 |
- if (tharg->extra_options & ONAS_SCTH_ISDIR) { |
|
146 |
- logg("*ScanOnAccess: Performing additional scanning on directory '%s'\n", tharg->pathname); |
|
147 |
- onas_scth_handle_dir(tharg->pathname, tharg); |
|
148 |
- } else if (tharg->extra_options & ONAS_SCTH_ISFILE) { |
|
149 |
- logg("*ScanOnAccess: Performing additional scanning on file '%s'\n", tharg->pathname); |
|
150 |
- onas_scth_handle_file(tharg->pathname, tharg); |
|
145 |
+ /* this event_data is ours and ours alone */ |
|
146 |
+ event_data = tharg->event_data; |
|
147 |
+ |
|
148 |
+ /* we share this context globally--it's not ours to touch/edit */ |
|
149 |
+ ctx = tharg->ctx; |
|
150 |
+ |
|
151 |
+ if (event_data->b_inotify) { |
|
152 |
+ if (event_data->extra_options & ONAS_SCTH_ISDIR) { |
|
153 |
+ logg("*ScanOnAccess: Performing additional scanning on directory '%s'\n", event_data->pathname); |
|
154 |
+ onas_scth_handle_dir(ctx, event_data->pathname, event_data); |
|
155 |
+ } else if (event_data->extra_options & ONAS_SCTH_ISFILE) { |
|
156 |
+ logg("*ScanOnAccess: Performing additional scanning on file '%s'\n", event_data->pathname); |
|
157 |
+ onas_scth_handle_file(ctx, event_data->pathname, event_data); |
|
158 |
+ } |
|
159 |
+ } else if (event_data->b_fanotify) { |
|
160 |
+ logg("*ScanOnAccess: Performing scanning on file '%s'\n", event_data->pathname); |
|
161 |
+ onas_scth_handle_file(ctx, event_data->pathname, event_data); |
|
151 | 162 |
} |
163 |
+ /* TODO: else something went wrong and we should error out here */ |
|
152 | 164 |
|
153 | 165 |
done: |
154 |
- if (NULL != tharg->pathname) { |
|
155 |
- free(tharg->pathname); |
|
156 |
- tharg->pathname = NULL; |
|
166 |
+ /* our job to cleanup event data: worker queue just kicks us off, drops the event object |
|
167 |
+ * from the queue and forgets about us. */ |
|
168 |
+ |
|
169 |
+ if (NULL != tharg) { |
|
170 |
+ if (NULL != tharg->event_data) { |
|
171 |
+ if (NULL != tharg->event_data->pathname) { |
|
172 |
+ free(tharg->event_data->pathname); |
|
173 |
+ event_data->pathname = NULL; |
|
157 | 174 |
} |
158 |
- if (NULL != tharg->options) { |
|
159 |
- free(tharg->options); |
|
160 |
- tharg->options = NULL; |
|
175 |
+ free(tharg->event_data); |
|
176 |
+ tharg->event_data = NULL; |
|
161 | 177 |
} |
162 |
- if (NULL != tharg) { |
|
178 |
+ /* don't free context, cleanup for context is handled at the highest layer */ |
|
163 | 179 |
free(tharg); |
164 | 180 |
} |
165 | 181 |
|
... | ... |
@@ -21,18 +21,26 @@ |
21 | 21 |
#ifndef __ONAS_SCTH_H |
22 | 22 |
#define __ONAS_SCTH_H |
23 | 23 |
|
24 |
+ |
|
25 |
+#include <sys/fanotify.h> |
|
24 | 26 |
#include "shared/optparser.h" |
25 | 27 |
#include "libclamav/clamav.h" |
26 | 28 |
|
27 | 29 |
#define ONAS_SCTH_ISDIR 0x01 |
28 | 30 |
#define ONAS_SCTH_ISFILE 0x02 |
29 | 31 |
|
30 |
-struct scth_thrarg { |
|
31 |
- uint32_t extra_options; |
|
32 |
- struct cl_scan_options *options; |
|
33 |
- const struct optstruct *opts; |
|
34 |
- const struct cl_engine *engine; |
|
32 |
+struct onas_scan_event { |
|
35 | 33 |
char *pathname; |
34 |
+ struct fanotify_event_metadata *fmd; |
|
35 |
+ int16_t b_inotify; |
|
36 |
+ int16_t b_fanotify; |
|
37 |
+ int16_t b_scan; |
|
38 |
+ uint32_t extra_options; |
|
39 |
+}; |
|
40 |
+ |
|
41 |
+struct scth_thrarg { |
|
42 |
+ struct onas_scan_event *event_data; |
|
43 |
+ struct onas_context **ctx; |
|
36 | 44 |
}; |
37 | 45 |
|
38 | 46 |
void *onas_scan_th(void *arg); |