... | ... |
@@ -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" }, |