... | ... |
@@ -1,3 +1,7 @@ |
1 |
+Fri Mar 2 19:48:36 CET 2012 (tk) |
|
2 |
+--------------------------------- |
|
3 |
+ * clamd: add support for on-access scanning on OS X with ClamAuth (beta) |
|
4 |
+ |
|
1 | 5 |
Wed Feb 29 17:02:18 EET 2012 (edwin) |
2 | 6 |
------------------------------------ |
3 | 7 |
* libclamav/bytecode_api*: Fix Sparc crash (bb #4324) |
... | ... |
@@ -231,4 +231,142 @@ void *clamukoth(void *arg) |
231 | 231 |
return clamukofsth(arg); |
232 | 232 |
} |
233 | 233 |
|
234 |
+#elif defined(CLAMAUTH) |
|
235 |
+ |
|
236 |
+#include <stdio.h> |
|
237 |
+#include <unistd.h> |
|
238 |
+#include <sys/types.h> |
|
239 |
+#include <sys/stat.h> |
|
240 |
+#include <sys/uio.h> |
|
241 |
+#include <fcntl.h> |
|
242 |
+#include <signal.h> |
|
243 |
+#include <pthread.h> |
|
244 |
+#include <string.h> |
|
245 |
+#include <errno.h> |
|
246 |
+ |
|
247 |
+#include "libclamav/clamav.h" |
|
248 |
+#include "libclamav/scanners.h" |
|
249 |
+ |
|
250 |
+#include "shared/optparser.h" |
|
251 |
+#include "shared/output.h" |
|
252 |
+ |
|
253 |
+#include "server.h" |
|
254 |
+#include "others.h" |
|
255 |
+#include "scanner.h" |
|
256 |
+ |
|
257 |
+#define SUPPORTED_PROTOCOL 2 |
|
258 |
+ |
|
259 |
+static int cauth_fd = -1; |
|
260 |
+ |
|
261 |
+struct ClamAuthEvent { |
|
262 |
+ unsigned int action; |
|
263 |
+ char path[1024]; |
|
264 |
+ unsigned int pid; |
|
265 |
+}; |
|
266 |
+ |
|
267 |
+static void cauth_exit(int sig) |
|
268 |
+{ |
|
269 |
+ logg("*ClamAuth: cauth_exit(), signal %d\n", sig); |
|
270 |
+ if(cauth_fd > 0) |
|
271 |
+ close(cauth_fd); |
|
272 |
+ pthread_exit(NULL); |
|
273 |
+ logg("ClamAuth: stopped\n"); |
|
274 |
+} |
|
275 |
+ |
|
276 |
+static int cauth_scanfile(const char *fname, int extinfo, struct thrarg *tharg) |
|
277 |
+{ |
|
278 |
+ struct cb_context context; |
|
279 |
+ const char *virname; |
|
280 |
+ int ret = 0, fd; |
|
281 |
+ |
|
282 |
+ context.filename = fname; |
|
283 |
+ context.virsize = 0; |
|
284 |
+ |
|
285 |
+ fd = open(fname, O_RDONLY); |
|
286 |
+ if(fd == -1) |
|
287 |
+ return -1; |
|
288 |
+ |
|
289 |
+ if(cl_scandesc_callback(fd, &virname, NULL, tharg->engine, tharg->options, &context) == CL_VIRUS) { |
|
290 |
+ if(context.virsize) |
|
291 |
+ detstats_add(virname, fname, context.virsize, context.virhash); |
|
292 |
+ if(extinfo && context.virsize) |
|
293 |
+ logg("ClamAuth: %s: %s(%s:%llu) FOUND\n", fname, virname, context.virhash, context.virsize); |
|
294 |
+ else |
|
295 |
+ logg("ClamAuth: %s: %s FOUND\n", fname, virname); |
|
296 |
+ virusaction(fname, virname, tharg->opts); |
|
297 |
+ } |
|
298 |
+ close(fd); |
|
299 |
+ return ret; |
|
300 |
+} |
|
301 |
+ |
|
302 |
+void *clamukoth(void *arg) |
|
303 |
+{ |
|
304 |
+ struct thrarg *tharg = (struct thrarg *) arg; |
|
305 |
+ sigset_t sigset; |
|
306 |
+ struct sigaction act; |
|
307 |
+ int eventcnt = 1, extinfo; |
|
308 |
+ char err[128]; |
|
309 |
+ struct ClamAuthEvent event; |
|
310 |
+ |
|
311 |
+ /* ignore all signals except SIGUSR1 */ |
|
312 |
+ sigfillset(&sigset); |
|
313 |
+ sigdelset(&sigset, SIGUSR1); |
|
314 |
+ /* The behavior of a process is undefined after it ignores a |
|
315 |
+ * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */ |
|
316 |
+ sigdelset(&sigset, SIGFPE); |
|
317 |
+ sigdelset(&sigset, SIGILL); |
|
318 |
+ sigdelset(&sigset, SIGSEGV); |
|
319 |
+#ifdef SIGBUS |
|
320 |
+ sigdelset(&sigset, SIGBUS); |
|
321 |
+#endif |
|
322 |
+ pthread_sigmask(SIG_SETMASK, &sigset, NULL); |
|
323 |
+ memset(&act, 0, sizeof(struct sigaction)); |
|
324 |
+ act.sa_handler = cauth_exit; |
|
325 |
+ sigfillset(&(act.sa_mask)); |
|
326 |
+ sigaction(SIGUSR1, &act, NULL); |
|
327 |
+ sigaction(SIGSEGV, &act, NULL); |
|
328 |
+ |
|
329 |
+ extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled; |
|
330 |
+ |
|
331 |
+ cauth_fd = open("/dev/clamauth", O_RDONLY); |
|
332 |
+ if(cauth_fd == -1) { |
|
333 |
+ logg("!ClamAuth: Can't open /dev/clamauth\n"); |
|
334 |
+ if(errno == ENOENT) |
|
335 |
+ logg("!ClamAuth: Please make sure ClamAuth.kext is loaded\n"); |
|
336 |
+ else if(errno == EACCES) |
|
337 |
+ logg("!ClamAuth: This application requires root privileges\n"); |
|
338 |
+ else |
|
339 |
+ logg("!ClamAuth: /dev/clamauth: %s\n", cli_strerror(errno, err, sizeof(err))); |
|
340 |
+ |
|
341 |
+ return NULL; |
|
342 |
+ } |
|
343 |
+ |
|
344 |
+ while(1) { |
|
345 |
+ if(read(cauth_fd, &event, sizeof(event)) > 0) { |
|
346 |
+ if(eventcnt == 1) { |
|
347 |
+ if(event.action != SUPPORTED_PROTOCOL) { |
|
348 |
+ logg("!ClamAuth: Protocol version mismatch (tool: %d, driver: %d)\n", SUPPORTED_PROTOCOL, event.action); |
|
349 |
+ close(cauth_fd); |
|
350 |
+ return NULL; |
|
351 |
+ } |
|
352 |
+ if(strncmp(event.path, "ClamAuth", 8)) { |
|
353 |
+ logg("!ClamAuth: Invalid version event\n"); |
|
354 |
+ close(cauth_fd); |
|
355 |
+ return NULL; |
|
356 |
+ } |
|
357 |
+ logg("ClamAuth: Driver version: %s, protocol version: %d\n", &event.path[9], event.action); |
|
358 |
+ } else { |
|
359 |
+ cauth_scanfile(event.path, extinfo, tharg); |
|
360 |
+ } |
|
361 |
+ eventcnt++; |
|
362 |
+ } else { |
|
363 |
+ if(errno == ENODEV) { |
|
364 |
+ printf("^ClamAuth: ClamAuth module deactivated, terminating\n"); |
|
365 |
+ close(cauth_fd); |
|
366 |
+ return NULL; |
|
367 |
+ } |
|
368 |
+ } |
|
369 |
+ usleep(200); |
|
370 |
+ } |
|
371 |
+} |
|
234 | 372 |
#endif |
... | ... |
@@ -709,7 +709,7 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi |
709 | 709 |
unsigned int selfchk; |
710 | 710 |
threadpool_t *thr_pool; |
711 | 711 |
|
712 |
-#ifdef CLAMUKO |
|
712 |
+#if defined(CLAMUKO) || defined(CLAMAUTH) |
|
713 | 713 |
pthread_t clamuko_pid; |
714 | 714 |
pthread_attr_t clamuko_attr; |
715 | 715 |
struct thrarg *tharg = NULL; /* shut up gcc */ |
... | ... |
@@ -1005,7 +1005,7 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi |
1005 | 1005 |
acceptdata.max_queue = max_queue; |
1006 | 1006 |
|
1007 | 1007 |
if(optget(opts, "ClamukoScanOnAccess")->enabled) |
1008 |
-#ifdef CLAMUKO |
|
1008 |
+#if defined(CLAMUKO) || defined(CLAMAUTH) |
|
1009 | 1009 |
{ |
1010 | 1010 |
do { |
1011 | 1011 |
if(pthread_attr_init(&clamuko_attr)) break; |
... | ... |
@@ -1284,8 +1284,8 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi |
1284 | 1284 |
pthread_mutex_lock(&reload_mutex); |
1285 | 1285 |
if(reload) { |
1286 | 1286 |
pthread_mutex_unlock(&reload_mutex); |
1287 |
-#ifdef CLAMUKO |
|
1288 |
- if(optget(opts, "ClamukoScanOnAccess")->enabled && tharg) { |
|
1287 |
+#if defined(CLAMUKO) || defined(CLAMAUTH) |
|
1288 |
+ if((optget(opts, "ClamukoScanOnAccess")->enabled || optget(opts, "ClamAuth")->enabled) && tharg) { |
|
1289 | 1289 |
logg("Stopping and restarting Clamuko.\n"); |
1290 | 1290 |
pthread_kill(clamuko_pid, SIGUSR1); |
1291 | 1291 |
pthread_join(clamuko_pid, NULL); |
... | ... |
@@ -1303,8 +1303,8 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi |
1303 | 1303 |
reload = 0; |
1304 | 1304 |
time(&reloaded_time); |
1305 | 1305 |
pthread_mutex_unlock(&reload_mutex); |
1306 |
-#ifdef CLAMUKO |
|
1307 |
- if(optget(opts, "ClamukoScanOnAccess")->enabled && tharg) { |
|
1306 |
+#if defined(CLAMUKO) || defined(CLAMAUTH) |
|
1307 |
+ if((optget(opts, "ClamukoScanOnAccess")->enabled || optget(opts, "ClamAuth")->enabled) && tharg) { |
|
1308 | 1308 |
tharg->engine = engine; |
1309 | 1309 |
pthread_create(&clamuko_pid, &clamuko_attr, clamukoth, tharg); |
1310 | 1310 |
} |
... | ... |
@@ -1330,8 +1330,8 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi |
1330 | 1330 |
*/ |
1331 | 1331 |
logg("*Waiting for all threads to finish\n"); |
1332 | 1332 |
thrmgr_destroy(thr_pool); |
1333 |
-#ifdef CLAMUKO |
|
1334 |
- if(optget(opts, "ClamukoScanOnAccess")->enabled) { |
|
1333 |
+#if defined(CLAMUKO) || defined(CLAMAUTH) |
|
1334 |
+ if(optget(opts, "ClamukoScanOnAccess")->enabled || optget(opts, "ClamAuth")->enabled) { |
|
1335 | 1335 |
logg("Stopping Clamuko.\n"); |
1336 | 1336 |
pthread_kill(clamuko_pid, SIGUSR1); |
1337 | 1337 |
pthread_join(clamuko_pid, NULL); |
... | ... |
@@ -1044,6 +1044,7 @@ darwin*) |
1044 | 1044 |
AC_DEFINE([C_BSD],1,[os is bsd flavor]) |
1045 | 1045 |
AC_DEFINE([C_DARWIN],1,[os is darwin]) |
1046 | 1046 |
AC_DEFINE([BIND_8_COMPAT],1,[enable bind8 compatibility]) |
1047 |
+ AC_DEFINE([CLAMAUTH],1,[enable ClamAuth]) |
|
1047 | 1048 |
use_netinfo="yes" |
1048 | 1049 |
;; |
1049 | 1050 |
os2*) |
... | ... |
@@ -325,6 +325,8 @@ const struct clam_option __clam_options[] = { |
325 | 325 |
|
326 | 326 |
{ "MaxFiles", "max-files", 0, TYPE_NUMBER, MATCH_NUMBER, CLI_DEFAULT_MAXFILES, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Number of files to be scanned within an archive, a document, or any other\ncontainer file.\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe\ndamage to the system.", "10000" }, |
327 | 327 |
|
328 |
+ { "ClamAuth", NULL, 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD, "This option enables on-access scanning with ClamAuth on OS X (BETA).", "no" }, |
|
329 |
+ |
|
328 | 330 |
{ "ClamukoScanOnAccess", NULL, 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD, "This option enables Clamuko. Dazuko needs to be already configured and\nrunning.", "no" }, |
329 | 331 |
|
330 | 332 |
{ "ClamukoScannerCount", NULL, 0, TYPE_NUMBER, MATCH_NUMBER, 3, NULL, 0, OPT_CLAMD, "The number of scanner threads that will be started (DazukoFS only).\nHaving multiple scanner threads allows Clamuko to serve multiple\nprocesses simultaneously. This is particularly beneficial on SMP machines.", "3" }, |