Browse code

clamd: add support for DazukoFS (bb#1691) Patch from John Ogness <dazukocode*ogness.net>

Tomasz Kojm authored on 2009/09/22 05:06:49
Showing 10 changed files
... ...
@@ -1,3 +1,8 @@
1
+Mon Sep 21 22:05:38 CEST 2009 (tk)
2
+----------------------------------
3
+ * clamd: add support for DazukoFS (bb#1691)
4
+	  Patch from John Ogness <dazukocode*ogness.net>
5
+
1 6
 Fri Sep 18 20:02:06 CEST 2009 (tk)
2 7
 ----------------------------------
3 8
  * libclamav/matcher-bm.c: use mpool in BM's offset mode
... ...
@@ -48,12 +48,16 @@ clamd_SOURCES = \
48 48
     others.h \
49 49
     clamuko.c \
50 50
     clamuko.h \
51
+    clamukofs.c \
52
+    clamukofs.h \
51 53
     dazukoio_compat12.c \
52 54
     dazukoio_compat12.h \
53 55
     dazukoio.c \
54 56
     dazukoio.h \
55 57
     dazuko_xp.h \
56 58
     dazukoio_xp.h \
59
+    dazukofs.c \
60
+    dazukofs.h \
57 61
     shared.h
58 62
 
59 63
 endif
... ...
@@ -82,9 +82,9 @@ am__clamd_SOURCES_DIST = $(top_srcdir)/shared/output.c \
82 82
 	$(top_srcdir)/shared/network.h clamd.c tcpserver.c tcpserver.h \
83 83
 	localserver.c localserver.h session.c session.h thrmgr.c \
84 84
 	thrmgr.h server-th.c server.h scanner.c scanner.h others.c \
85
-	others.h clamuko.c clamuko.h dazukoio_compat12.c \
86
-	dazukoio_compat12.h dazukoio.c dazukoio.h dazuko_xp.h \
87
-	dazukoio_xp.h shared.h
85
+	others.h clamuko.c clamuko.h clamukofs.c clamukofs.h \
86
+	dazukoio_compat12.c dazukoio_compat12.h dazukoio.c dazukoio.h \
87
+	dazuko_xp.h dazukoio_xp.h dazukofs.c dazukofs.h shared.h
88 88
 @BUILD_CLAMD_TRUE@am_clamd_OBJECTS = output.$(OBJEXT) \
89 89
 @BUILD_CLAMD_TRUE@	optparser.$(OBJEXT) getopt.$(OBJEXT) \
90 90
 @BUILD_CLAMD_TRUE@	misc.$(OBJEXT) network.$(OBJEXT) \
... ...
@@ -93,7 +93,9 @@ am__clamd_SOURCES_DIST = $(top_srcdir)/shared/output.c \
93 93
 @BUILD_CLAMD_TRUE@	thrmgr.$(OBJEXT) server-th.$(OBJEXT) \
94 94
 @BUILD_CLAMD_TRUE@	scanner.$(OBJEXT) others.$(OBJEXT) \
95 95
 @BUILD_CLAMD_TRUE@	clamuko.$(OBJEXT) \
96
+@BUILD_CLAMD_TRUE@	clamukofs.$(OBJEXT) \
96 97
 @BUILD_CLAMD_TRUE@	dazukoio_compat12.$(OBJEXT) \
98
+@BUILD_CLAMD_TRUE@	dazukofs.$(OBJEXT) \
97 99
 @BUILD_CLAMD_TRUE@	dazukoio.$(OBJEXT)
98 100
 clamd_OBJECTS = $(am_clamd_OBJECTS)
99 101
 clamd_LDADD = $(LDADD)
... ...
@@ -316,12 +318,16 @@ top_srcdir = @top_srcdir@
316 316
 @BUILD_CLAMD_TRUE@    others.h \
317 317
 @BUILD_CLAMD_TRUE@    clamuko.c \
318 318
 @BUILD_CLAMD_TRUE@    clamuko.h \
319
+@BUILD_CLAMD_TRUE@    clamukofs.c \
320
+@BUILD_CLAMD_TRUE@    clamukofs.h \
319 321
 @BUILD_CLAMD_TRUE@    dazukoio_compat12.c \
320 322
 @BUILD_CLAMD_TRUE@    dazukoio_compat12.h \
321 323
 @BUILD_CLAMD_TRUE@    dazukoio.c \
322 324
 @BUILD_CLAMD_TRUE@    dazukoio.h \
323 325
 @BUILD_CLAMD_TRUE@    dazuko_xp.h \
324 326
 @BUILD_CLAMD_TRUE@    dazukoio_xp.h \
327
+@BUILD_CLAMD_TRUE@    dazukofs.c \
328
+@BUILD_CLAMD_TRUE@    dazukofs.h \
325 329
 @BUILD_CLAMD_TRUE@    shared.h
326 330
 
327 331
 AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/shared -I$(top_srcdir)/libclamav
... ...
@@ -435,8 +441,10 @@ distclean-compile:
435 435
 
436 436
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clamd.Po@am__quote@
437 437
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clamuko.Po@am__quote@
438
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clamukofs.Po@am__quote@
438 439
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dazukoio.Po@am__quote@
439 440
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dazukoio_compat12.Po@am__quote@
441
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dazukofs.Po@am__quote@
440 442
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@
441 443
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/localserver.Po@am__quote@
442 444
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@
... ...
@@ -39,6 +39,7 @@
39 39
 #include "server.h"
40 40
 #include "others.h"
41 41
 #include "dazukoio.h"
42
+#include "clamukofs.h"
42 43
 #include "clamuko.h"
43 44
 
44 45
 struct dazuko_access *acc;
... ...
@@ -62,7 +63,7 @@ static void clamuko_exit(int sig)
62 62
     pthread_exit(NULL);
63 63
 }
64 64
 
65
-void *clamukoth(void *arg)
65
+static void *clamukolegacyth(void *arg)
66 66
 {
67 67
 	struct thrarg *tharg = (struct thrarg *) arg;
68 68
 	sigset_t sigset;
... ...
@@ -200,4 +201,15 @@ void *clamukoth(void *arg)
200 200
     return NULL;
201 201
 }
202 202
 
203
+void *clamukoth(void *arg)
204
+{
205
+	struct stat s;
206
+
207
+    /* we use DazukoFS if /dev/dazukofs.ctrl exists and it is a
208
+     * character device, otherwise we use Dazuko */
209
+    if(stat("/dev/dazukofs.ctrl", &s) != 0) return clamukolegacyth(arg);
210
+    if(!S_ISCHR(s.st_mode)) return clamukolegacyth(arg);
211
+    return clamukofsth(arg);
212
+}
213
+
203 214
 #endif
204 215
new file mode 100644
... ...
@@ -0,0 +1,249 @@
0
+/*
1
+ *  Copyright (C) 2007-2009 Sourcefire, Inc.
2
+ *    Author: Tomasz Kojm
3
+ *    Author: John Ogness <dazukocode@ogness.net>
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License version 2 as
7
+ *  published by the Free Software Foundation.
8
+ *
9
+ *  This program is distributed in the hope that it will be useful,
10
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ *  GNU General Public License for more details.
13
+ *
14
+ *  You should have received a copy of the GNU General Public License
15
+ *  along with this program; if not, write to the Free Software
16
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ *  MA 02110-1301, USA.
18
+ */
19
+
20
+#if HAVE_CONFIG_H
21
+#include "clamav-config.h"
22
+#endif
23
+
24
+#ifdef CLAMUKO
25
+
26
+#include <stdio.h>
27
+#include <unistd.h>
28
+#include <sys/types.h>
29
+#include <sys/stat.h>
30
+#include <signal.h>
31
+#include <pthread.h>
32
+
33
+#include "libclamav/clamav.h"
34
+
35
+#include "shared/optparser.h"
36
+#include "shared/output.h"
37
+
38
+#include "server.h"
39
+#include "others.h"
40
+#include "dazukofs.h"
41
+#include "clamuko.h"
42
+
43
+static pthread_mutex_t running_mutex = PTHREAD_MUTEX_INITIALIZER;
44
+static dazukofs_handle_t shutdown_hndl;
45
+static pthread_cond_t shutdown_cond;
46
+
47
+static void clamuko_exit(int sig)
48
+{
49
+    pthread_cond_signal(&shutdown_cond);
50
+}
51
+
52
+static int setup_shutdown_handle(const char *groupname)
53
+{
54
+    /* is another server thread is already running? */
55
+    if(shutdown_hndl) return -1;
56
+
57
+    if(pthread_cond_init(&shutdown_cond, NULL)) return -1;
58
+
59
+    /* handle used for shutdown by signal */
60
+    shutdown_hndl = dazukofs_open(groupname, DAZUKOFS_TRACK_GROUP);
61
+    if(!shutdown_hndl) {
62
+	logg("!Clamuko: Can't register with DazukoFS\n");
63
+	return -1;
64
+    }
65
+    return 0;
66
+}
67
+
68
+static void shutdown_clamuko(void)
69
+{
70
+	dazukofs_handle_t hndl = shutdown_hndl;
71
+
72
+    /* Set shutdown_hndl before closing because the close will
73
+     * immediately cause the scan threads to be interrupted.
74
+     * But they will only abort if shutdown_hndl is NULL. */
75
+    shutdown_hndl = NULL;
76
+
77
+    if(hndl) dazukofs_close(hndl, DAZUKOFS_REMOVE_GROUP);
78
+}
79
+
80
+static void *clamuko_scanth(void *arg)
81
+{
82
+	struct thrarg *tharg = (struct thrarg *) arg;
83
+	sigset_t sigset;
84
+	short int scan;
85
+	unsigned int sizelimit = 0;
86
+	struct stat sb;
87
+	dazukofs_handle_t scan_hndl;
88
+	struct dazukofs_access acc;
89
+	const char *groupname = "ClamAV";
90
+	int skip_scan = 0;
91
+	const char *virname;
92
+	char filename[4096];
93
+
94
+    /* ignore all signals */
95
+    sigfillset(&sigset);
96
+    /* The behavior of a process is undefined after it ignores a
97
+     * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */
98
+    sigdelset(&sigset, SIGFPE);
99
+    sigdelset(&sigset, SIGILL);
100
+    sigdelset(&sigset, SIGSEGV);
101
+#ifdef SIGBUS
102
+    sigdelset(&sigset, SIGBUS);
103
+#endif
104
+    pthread_sigmask(SIG_SETMASK, &sigset, NULL);
105
+
106
+    /* register */
107
+    scan_hndl = dazukofs_open(groupname, DAZUKOFS_TRACK_GROUP);
108
+    if(!scan_hndl) {
109
+	logg("!Clamuko: Can't register with DazukoFS\n");
110
+	return NULL;
111
+    } else {
112
+	logg("Clamuko: Correctly registered with DazukoFS.\n");
113
+    }
114
+
115
+    /* access mask (not used by DazukoFS) */
116
+    if(optget(tharg->opts, "ClamukoScanOnOpen")->enabled)
117
+	logg("!Clamuko: ClamukoScanOnOpen ignored when using DazukoFS.\n");
118
+    if(optget(tharg->opts, "ClamukoScanOnClose")->enabled)
119
+	logg("!Clamuko: ClamukoScanOnClose ignored when using DazukoFS.\n");
120
+    if(optget(tharg->opts, "ClamukoScanOnExec")->enabled)
121
+	logg("!Clamuko: ClamukoScanOnExec ignored when using DazukoFS.\n");
122
+    if(optget(tharg->opts, "ClamukoIncludePath")->enabled)
123
+	logg("!Clamuko: ClamukoIncludePath ignored when using DazukoFS.\n");
124
+    if(optget(tharg->opts, "ClamukoExcludePath")->enabled)
125
+	logg("!Clamuko: ClamukoExcludePath ignored when using DazukoFS.\n");
126
+
127
+    sizelimit = optget(tharg->opts, "ClamukoMaxFileSize")->numarg;
128
+    if(sizelimit)
129
+	logg("Clamuko: Max file size limited to %u bytes.\n", sizelimit);
130
+    else
131
+	logg("Clamuko: File size limit disabled.\n");
132
+
133
+    while(1) {
134
+	if(dazukofs_get_access(scan_hndl, &acc)) {
135
+	    if(!shutdown_hndl)
136
+		break;
137
+	    continue;
138
+	}
139
+
140
+	if(!fstat(acc.fd, &sb)) {
141
+	    if(S_ISDIR(sb.st_mode)) {
142
+		/* don't try to scan directories */
143
+		skip_scan = 1;
144
+	    } else if(sb.st_size > sizelimit) {
145
+		dazukofs_get_filename(&acc, filename, sizeof(filename));
146
+		logg("*Clamuko: %s skipped (too big)\n", filename);
147
+		skip_scan = 1;
148
+	    }
149
+	}
150
+
151
+	if(skip_scan) {
152
+	    acc.deny = 0;
153
+	    /* reset skip flag */
154
+	    skip_scan = 0;
155
+	} else if(cl_scandesc(acc.fd, &virname, NULL, tharg->engine,
156
+			      tharg->options) == CL_VIRUS) {
157
+	    dazukofs_get_filename(&acc, filename, sizeof(filename));
158
+	    logg("Clamuko: %s: %s FOUND\n", filename, virname);
159
+	    /* we can not perform any special action because it will
160
+	     * trigger DazukoFS recursively */
161
+	    acc.deny = 1;
162
+	} else {
163
+	    acc.deny = 0;
164
+	}
165
+
166
+	if(dazukofs_return_access(scan_hndl, &acc)) {
167
+	    if(shutdown_hndl)
168
+	        logg("!Clamuko: Can't return access to DazukoFS.\n");
169
+	    break;
170
+	}
171
+    }
172
+
173
+    dazukofs_close(scan_hndl, 0);
174
+
175
+    if(shutdown_hndl)
176
+        logg("!Clamuko: A scanner thread has unexpectedly shutdown.\n");
177
+
178
+    return NULL;
179
+}
180
+
181
+void *clamukofsth(void *arg)
182
+{
183
+	struct thrarg *tharg = (struct thrarg *) arg;
184
+	sigset_t sigset;
185
+        struct sigaction act;
186
+	pthread_t *clamuko_pids = NULL;
187
+	const char *groupname = "ClamAV";
188
+	int count;
189
+	int started;
190
+
191
+    /* is another server thread already working? */
192
+    if(pthread_mutex_trylock(&running_mutex))
193
+	return NULL;
194
+
195
+    /* ignore all signals except SIGUSR1 */
196
+    sigfillset(&sigset);
197
+    sigdelset(&sigset, SIGUSR1);
198
+    /* The behavior of a process is undefined after it ignores a
199
+     * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */
200
+    sigdelset(&sigset, SIGFPE);
201
+    sigdelset(&sigset, SIGILL);
202
+    sigdelset(&sigset, SIGSEGV);
203
+#ifdef SIGBUS
204
+    sigdelset(&sigset, SIGBUS);
205
+#endif
206
+    pthread_sigmask(SIG_SETMASK, &sigset, NULL);
207
+
208
+    count = optget(tharg->opts, "ClamukoScannerCount")->numarg;
209
+    if(count < 1) goto out;
210
+
211
+    clamuko_pids = calloc(count, sizeof(pthread_t));
212
+    if(!clamuko_pids) goto out;
213
+
214
+    if(setup_shutdown_handle(groupname)) goto out;
215
+
216
+    act.sa_handler = clamuko_exit;
217
+    sigfillset(&(act.sa_mask));
218
+    sigaction(SIGUSR1, &act, NULL);
219
+    sigaction(SIGSEGV, &act, NULL);
220
+
221
+    for(started = 0; started < count; started++) {
222
+	pthread_attr_t clamuko_attr;
223
+
224
+	if(pthread_attr_init(&clamuko_attr)) break;
225
+	pthread_attr_setdetachstate(&clamuko_attr, PTHREAD_CREATE_JOINABLE);
226
+	if(pthread_create(&clamuko_pids[started], &clamuko_attr,
227
+			  clamuko_scanth, tharg)) break;
228
+	logg("Clamuko: Started scanner thread %d.\n", started);
229
+    }
230
+
231
+    pthread_cond_wait(&shutdown_cond, &running_mutex);
232
+    logg("Clamuko: Stop signal received.\n");
233
+
234
+    shutdown_clamuko();
235
+
236
+    for(started-- ; started >= 0; started--) {
237
+	logg("Clamuko: Waiting for scanner thread %d to finish.\n", started);
238
+	pthread_join(clamuko_pids[started], NULL);
239
+    }
240
+
241
+    logg("Clamuko: Stopped.\n");
242
+out:
243
+    if(clamuko_pids) free(clamuko_pids);
244
+    pthread_mutex_unlock(&running_mutex);
245
+    return NULL;
246
+}
247
+
248
+#endif
0 249
new file mode 100644
... ...
@@ -0,0 +1,28 @@
0
+/*
1
+ *  Copyright (C) 2009 Sourcefire, Inc.
2
+ *    Author: John Ogness <dazukocode@ogness.net>
3
+ *
4
+ *  This program is free software; you can redistribute it and/or modify
5
+ *  it under the terms of the GNU General Public License version 2 as
6
+ *  published by the Free Software Foundation.
7
+ *
8
+ *  This program is distributed in the hope that it will be useful,
9
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
+ *  GNU General Public License for more details.
12
+ *
13
+ *  You should have received a copy of the GNU General Public License
14
+ *  along with this program; if not, write to the Free Software
15
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16
+ *  MA 02110-1301, USA.
17
+ */
18
+
19
+#ifdef CLAMUKO
20
+
21
+#ifndef __CLAMUKO_H
22
+#define __CLAMUKO_H
23
+
24
+extern void *clamukofsth(void *arg);
25
+
26
+#endif
27
+#endif
0 28
new file mode 100644
... ...
@@ -0,0 +1,238 @@
0
+/* userspace library to interface with dazukofs
1
+
2
+   Copyright (C) 2008-2009 John Ogness
3
+     Author: John Ogness <dazukocode@ogness.net>
4
+
5
+   This library is free software; you can redistribute it and/or
6
+   modify it under the terms of the GNU Lesser General Public
7
+   License as published by the Free Software Foundation; either
8
+   version 2.1 of the License, or (at your option) any later version.
9
+
10
+   This library 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 Lesser General Public License for more details.
14
+
15
+   You should have received a copy of the GNU Lesser General Public
16
+   License along with this library; if not, write to the Free Software
17
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
+*/
19
+
20
+#include <stdio.h>
21
+#include <stdlib.h>
22
+#include <string.h>
23
+#include <fcntl.h>
24
+#include <unistd.h>
25
+
26
+#include <sys/types.h>
27
+#include <sys/stat.h>
28
+
29
+#include "dazukofs.h"
30
+
31
+struct dazukofs_handle
32
+{
33
+	int dev_fd;
34
+	unsigned long event_id;
35
+	char *group_name;
36
+};
37
+
38
+#define DAZUKOFS_ALLOWED_GROUPCHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
39
+static int check_group_name(const char *gname)
40
+{
41
+	size_t len = strlen(gname);
42
+	const char *p;
43
+
44
+	if (len > 20)
45
+		return -1;
46
+
47
+	for (p = gname; *p; p++) {
48
+		if (strchr(DAZUKOFS_ALLOWED_GROUPCHARS, *p) == NULL)
49
+			return -1;
50
+	}
51
+
52
+	return 0;
53
+}
54
+
55
+dazukofs_handle_t dazukofs_open(const char *gname, int flags)
56
+{
57
+	struct dazukofs_handle *hndl = NULL;
58
+	char key[25];
59
+	char buf[256];
60
+	char *p;
61
+	int gid;
62
+	int fd;
63
+
64
+	if (check_group_name(gname) != 0)
65
+		goto error_out;
66
+
67
+	fd = open("/dev/dazukofs.ctrl", O_RDWR);
68
+	if (fd == -1) {
69
+		/* try to read at least
70
+		 * (maybe the group already exists) */
71
+		fd = open("/dev/dazukofs.ctrl", O_RDONLY);
72
+		if (fd == -1)
73
+			goto error_out;
74
+	} else {
75
+		memset(buf, 0, sizeof(buf));
76
+
77
+		if (flags & DAZUKOFS_TRACK_GROUP)
78
+			snprintf(buf, sizeof(buf) - 1, "addtrack=%s", gname);
79
+		else
80
+			snprintf(buf, sizeof(buf) - 1, "add=%s", gname);
81
+
82
+		if (write(fd, buf, strlen(buf)) == -1)
83
+			goto error_out_close;
84
+
85
+		lseek(fd, 0, SEEK_SET);
86
+	}
87
+
88
+	memset(buf, 0, sizeof(buf));
89
+	if (read(fd, buf, sizeof(buf)-1) == -1)
90
+		goto error_out_close;
91
+
92
+	memset(key, 0, sizeof(key));
93
+	snprintf(key, sizeof(key) - 1, ":%s\n", gname);
94
+
95
+	p = strstr(buf, key);
96
+	if (!p || p == buf)
97
+		goto error_out_close;
98
+
99
+	p--;
100
+	gid = *p - '0';
101
+	if (gid < 0 || gid > 9)
102
+		goto error_out_close;
103
+
104
+	hndl = malloc(sizeof(struct dazukofs_handle));
105
+	if (!hndl)
106
+		goto error_out_close;
107
+	memset(hndl, 0, sizeof(struct dazukofs_handle));
108
+
109
+	hndl->group_name = strdup(gname);
110
+	if (!hndl->group_name)
111
+		goto error_out_free;
112
+
113
+	memset(key, 0, sizeof(key));
114
+	snprintf(key, sizeof(key) - 1, "/dev/dazukofs.%d", gid);
115
+
116
+	hndl->dev_fd = open(key, O_RDWR);
117
+	if (hndl->dev_fd == -1)
118
+		goto error_out_free;
119
+
120
+	close(fd);
121
+
122
+	return hndl;
123
+
124
+error_out_free:
125
+	if (hndl->group_name)
126
+		free(hndl->group_name);
127
+	free(hndl);
128
+	hndl = NULL;
129
+error_out_close:
130
+	close(fd);
131
+error_out:
132
+	return hndl;
133
+}
134
+
135
+int dazukofs_close(dazukofs_handle_t hndl, int flags)
136
+{
137
+	char buf[48];
138
+	int fd;
139
+	int ret = -1;
140
+
141
+	if (flags & DAZUKOFS_REMOVE_GROUP) {
142
+		fd = open("/dev/dazukofs.ctrl", O_WRONLY);
143
+		if (fd == -1)
144
+			goto error_out;
145
+
146
+		memset(buf, 0, sizeof(buf));
147
+		snprintf(buf, sizeof(buf) - 1, "del=%s", hndl->group_name);
148
+
149
+		if (write(fd, buf, strlen(buf)) == -1) {
150
+			close(fd);
151
+			goto error_out;
152
+		}
153
+
154
+		close(fd);
155
+	}
156
+
157
+	ret = close(hndl->dev_fd);
158
+	if (ret != 0)
159
+		goto error_out;
160
+
161
+	free(hndl->group_name);
162
+	free(hndl);
163
+
164
+	return 0;
165
+
166
+error_out:
167
+	return ret;
168
+}
169
+
170
+int dazukofs_get_access(dazukofs_handle_t hndl, struct dazukofs_access *acc)
171
+{
172
+	char buf[48];
173
+	char *p;
174
+	int err = -1;
175
+
176
+	memset(buf, 0, sizeof(buf));
177
+	if (read(hndl->dev_fd, buf, sizeof(buf)-1) == -1)
178
+		goto out;
179
+
180
+	p = strstr(buf, "id=");
181
+	if (!p)
182
+		goto out;
183
+	p += 3;
184
+	hndl->event_id = strtoul(p, &p, 10);
185
+
186
+	p = strstr(p, "fd=");
187
+	if (!p)
188
+		goto out;
189
+	p += 3;
190
+	acc->fd = (int)strtol(p, &p, 10);
191
+
192
+	p = strstr(p, "pid=");
193
+	if (!p)
194
+		goto out;
195
+	p += 4;
196
+	acc->pid = strtoul(p, NULL, 10);
197
+
198
+	acc->deny = 0;
199
+
200
+	err = 0;
201
+out:
202
+	return err;
203
+}
204
+
205
+int dazukofs_return_access(dazukofs_handle_t hndl, struct dazukofs_access *acc)
206
+{
207
+	char buf[48];
208
+	int err = -1;
209
+
210
+	if (close(acc->fd) != 0)
211
+		goto out;
212
+	snprintf(buf, sizeof(buf)-1, "id=%lu r=%d", hndl->event_id,
213
+		 acc->deny ? 1 : 0);
214
+	buf[sizeof(buf)-1] = 0;
215
+
216
+	if (write(hndl->dev_fd, buf, strlen(buf)) == -1)
217
+		goto out;
218
+	lseek(hndl->dev_fd, 0, SEEK_SET);
219
+	err = 0;
220
+out:
221
+	return err;
222
+}
223
+
224
+int dazukofs_get_filename(struct dazukofs_access *acc, char *buf, size_t bufsiz)
225
+{
226
+	char proc[48];
227
+	int ret;
228
+
229
+	memset(proc, 0, sizeof(proc));
230
+	snprintf(proc, sizeof(proc) - 1, "/proc/self/fd/%d", acc->fd);
231
+	ret = readlink(proc, buf, bufsiz - 1);
232
+	buf[bufsiz - 1] = 0;
233
+	if (ret > 0)
234
+		buf[ret] = 0;
235
+
236
+	return ret;
237
+}
0 238
new file mode 100644
... ...
@@ -0,0 +1,48 @@
0
+/* userspace library to interface with dazukofs
1
+
2
+   Copyright (C) 2008 John Ogness
3
+     Author: John Ogness <dazukocode@ogness.net>
4
+
5
+   This library is free software; you can redistribute it and/or
6
+   modify it under the terms of the GNU Lesser General Public
7
+   License as published by the Free Software Foundation; either
8
+   version 2.1 of the License, or (at your option) any later version.
9
+
10
+   This library 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 Lesser General Public License for more details.
14
+
15
+   You should have received a copy of the GNU Lesser General Public
16
+   License along with this library; if not, write to the Free Software
17
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
+*/
19
+
20
+#ifndef __DAZUKOFS_H
21
+#define __DAZUKOFS_H
22
+
23
+#include <stdio.h>
24
+
25
+/* dazukofs_open() flags */
26
+#define DAZUKOFS_TRACK_GROUP 1
27
+
28
+/* dazukofs_close() flags */
29
+#define DAZUKOFS_REMOVE_GROUP 1
30
+
31
+struct dazukofs_handle;
32
+typedef struct dazukofs_handle * dazukofs_handle_t;
33
+
34
+struct dazukofs_access
35
+{
36
+	int fd;
37
+	int deny;
38
+	unsigned long pid;
39
+};
40
+
41
+dazukofs_handle_t dazukofs_open(const char *gname, int flags);
42
+int dazukofs_get_access(dazukofs_handle_t hndl, struct dazukofs_access *acc);
43
+int dazukofs_return_access(dazukofs_handle_t hndl, struct dazukofs_access *acc);
44
+int dazukofs_close(dazukofs_handle_t hndl, int flags);
45
+int dazukofs_get_filename(struct dazukofs_access *acc, char *buf, size_t bufsiz);
46
+
47
+#endif /* __DAZUKOFS_H */
... ...
@@ -403,15 +403,26 @@ LocalSocket /tmp/clamd.socket
403 403
 
404 404
 ##
405 405
 ## Clamuko settings
406
-## WARNING: This is experimental software. It is very likely it will hang
407
-##	    up your system!!!
408 406
 ##
409 407
 
410
-# Enable Clamuko. Dazuko (/dev/dazuko) must be configured and running.
408
+# Enable Clamuko. Dazuko must be configured and running. Clamuko supports
409
+# both Dazuko (/dev/dazuko) and DazukoFS (/dev/dazukofs.ctrl). DazukoFS
410
+# is the preferred option. For more information please visit www.dazuko.org
411 411
 # Default: no
412 412
 #ClamukoScanOnAccess yes
413 413
 
414
-# Set access mask for Clamuko.
414
+# The number of scanner threads that will be started (DazukoFS only).
415
+# Having multiple scanner threads allows Clamuko to serve multiple
416
+# processes simultaneously. This is particularly beneficial on SMP machines.
417
+# Default: 3
418
+#ClamukoScannerCount 3
419
+
420
+# Don't scan files larger than ClamukoMaxFileSize
421
+# Value of 0 disables the limit.
422
+# Default: 5M
423
+#ClamukoMaxFileSize 10M
424
+
425
+# Set access mask for Clamuko (Dazuko only).
415 426
 # Default: no
416 427
 #ClamukoScanOnOpen yes
417 428
 #ClamukoScanOnClose yes
... ...
@@ -419,16 +430,11 @@ LocalSocket /tmp/clamd.socket
419 419
 
420 420
 # Set the include paths (all files inside them will be scanned). You can have
421 421
 # multiple ClamukoIncludePath directives but each directory must be added
422
-# in a seperate line.
422
+# in a seperate line. (Dazuko only)
423 423
 # Default: disabled
424 424
 #ClamukoIncludePath /home
425 425
 #ClamukoIncludePath /students
426 426
 
427
-# Set the exclude paths. All subdirectories are also excluded.
427
+# Set the exclude paths. All subdirectories are also excluded. (Dazuko only)
428 428
 # Default: disabled
429 429
 #ClamukoExcludePath /home/bofh
430
-
431
-# Don't scan files larger than ClamukoMaxFileSize
432
-# Value of 0 disables the limit.
433
-# Default: 5M
434
-#ClamukoMaxFileSize 10M
... ...
@@ -289,6 +289,8 @@ const struct clam_option clam_options[] = {
289 289
 
290 290
     { "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" },
291 291
 
292
+    { "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" },
293
+
292 294
     { "ClamukoScanOnOpen", NULL, 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD, "Scan files when they get opened by the system.", "yes" },
293 295
 
294 296
     { "ClamukoScanOnClose", NULL, 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD, "Scan files when they get closed by the system.", "yes" },