Browse code

Whitelisting infrastructure

git-svn: trunk@4529

aCaB authored on 2008/12/05 01:27:04
Showing 6 changed files
... ...
@@ -33,6 +33,8 @@ clamav_milter_SOURCES = \
33 33
     $(top_srcdir)/shared/misc.h \
34 34
     $(top_srcdir)/shared/options.c \
35 35
     $(top_srcdir)/shared/options.h \
36
+    whitelist.c \
37
+    whitelist.h \
36 38
     connpool.c \
37 39
     connpool.h \
38 40
     netcode.c \
... ...
@@ -77,14 +77,16 @@ am__clamav_milter_SOURCES_DIST = $(top_srcdir)/shared/cfgparser.c \
77 77
 	$(top_srcdir)/shared/output.h $(top_srcdir)/shared/getopt.c \
78 78
 	$(top_srcdir)/shared/getopt.h $(top_srcdir)/shared/misc.c \
79 79
 	$(top_srcdir)/shared/misc.h $(top_srcdir)/shared/options.c \
80
-	$(top_srcdir)/shared/options.h connpool.c connpool.h netcode.c \
81
-	netcode.h clamfi.c clamfi.h clamav-milter.c
80
+	$(top_srcdir)/shared/options.h whitelist.c whitelist.h \
81
+	connpool.c connpool.h netcode.c netcode.h clamfi.c clamfi.h \
82
+	clamav-milter.c
82 83
 @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@am_clamav_milter_OBJECTS =  \
83 84
 @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@	cfgparser.$(OBJEXT) \
84 85
 @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@	output.$(OBJEXT) \
85 86
 @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@	getopt.$(OBJEXT) \
86 87
 @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@	misc.$(OBJEXT) \
87 88
 @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@	options.$(OBJEXT) \
89
+@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@	whitelist.$(OBJEXT) \
88 90
 @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@	connpool.$(OBJEXT) \
89 91
 @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@	netcode.$(OBJEXT) \
90 92
 @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@	clamfi.$(OBJEXT) \
... ...
@@ -279,6 +281,8 @@ top_srcdir = @top_srcdir@
279 279
 @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@    $(top_srcdir)/shared/misc.h \
280 280
 @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@    $(top_srcdir)/shared/options.c \
281 281
 @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@    $(top_srcdir)/shared/options.h \
282
+@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@    whitelist.c \
283
+@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@    whitelist.h \
282 284
 @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@    connpool.c \
283 285
 @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@    connpool.h \
284 286
 @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@    netcode.c \
... ...
@@ -387,6 +391,7 @@ distclean-compile:
387 387
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netcode.Po@am__quote@
388 388
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@
389 389
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/output.Po@am__quote@
390
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/whitelist.Po@am__quote@
390 391
 
391 392
 .c.o:
392 393
 @am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
... ...
@@ -42,7 +42,7 @@
42 42
 #include "connpool.h"
43 43
 #include "netcode.h"
44 44
 #include "clamfi.h"
45
-
45
+#include "whitelist.h"
46 46
 
47 47
 struct smfiDesc descr = {
48 48
     "ClamAV", 		/* filter name */
... ...
@@ -214,6 +214,12 @@ int main(int argc, char **argv) {
214 214
 	return 1;
215 215
     }
216 216
 
217
+    if((cpt = cfgopt(copt, "Whitelist"))->enabled && whitelist_init(cpt->strarg)) {
218
+	localnets_free();
219
+	logg_close();
220
+	freecfg(copt);
221
+	return 1;
222
+    }
217 223
 
218 224
     /* FIXME: find a place for these:
219 225
      * maxthreads = cfgopt(copt, "MaxThreads")->numarg;
... ...
@@ -239,18 +245,24 @@ int main(int argc, char **argv) {
239 239
     umask(0007);
240 240
     if(!(my_socket = cfgopt(copt, "MilterSocket")->strarg)) {
241 241
 	logg("!Please configure the MilterSocket directive\n");
242
+	localnets_free();
243
+	whitelist_free();
242 244
 	logg_close();
243 245
 	freecfg(copt);
244 246
 	return 1;
245 247
     }
246 248
     if(smfi_setconn(my_socket) == MI_FAILURE) {
247 249
 	logg("!smfi_setconn failed\n");
250
+	localnets_free();
251
+	whitelist_free();
248 252
 	logg_close();
249 253
 	freecfg(copt);
250 254
 	return 1;
251 255
     }
252 256
     if(smfi_register(descr) == MI_FAILURE) {
253 257
 	logg("!smfi_register failed\n");
258
+	localnets_free();
259
+	whitelist_free();
254 260
 	logg_close();
255 261
 	freecfg(copt);
256 262
 	return 1;
... ...
@@ -258,6 +270,8 @@ int main(int argc, char **argv) {
258 258
     cpt = cfgopt(copt, "FixStaleSocket");
259 259
     if(smfi_opensocket(cpt->enabled) == MI_FAILURE) {
260 260
 	logg("!Failed to create socket %s\n", my_socket);
261
+	localnets_free();
262
+	whitelist_free();
261 263
 	logg_close();
262 264
 	freecfg(copt);
263 265
 	return 1;
... ...
@@ -269,6 +283,8 @@ int main(int argc, char **argv) {
269 269
     cpool_init(copt);
270 270
     if (!cp) {
271 271
 	logg("!Failed to init the socket pool\n");
272
+	localnets_free();
273
+	whitelist_free();
272 274
 	logg_close();
273 275
 	freecfg(copt);
274 276
 	return 1;
... ...
@@ -277,6 +293,8 @@ int main(int argc, char **argv) {
277 277
     if(!cfgopt(copt, "Foreground")->enabled) {
278 278
 	if(daemonize() == -1) {
279 279
 	    logg("!daemonize() failed\n");
280
+	    localnets_free();
281
+	    whitelist_free();
280 282
 	    cpool_free();
281 283
 	    logg_close();
282 284
 	    return 1;
... ...
@@ -293,8 +311,11 @@ int main(int argc, char **argv) {
293 293
     logg_close();
294 294
     cpool_free();
295 295
     localnets_free();
296
+    whitelist_free();
297
+
296 298
     return ret;
297 299
 }
300
+
298 301
 /*
299 302
  * Local Variables:
300 303
  * mode: c
301 304
new file mode 100644
... ...
@@ -0,0 +1,124 @@
0
+/*
1
+ *  Copyright (C)2008 Sourcefire, Inc.
2
+ *
3
+ *  Author: aCaB <acab@clamav.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
+#include <stdio.h>
25
+#include <string.h>
26
+#include <sys/types.h>
27
+#include <regex.h>
28
+
29
+#include "shared/output.h"
30
+
31
+struct WHLST {
32
+    regex_t preg;
33
+    struct WHLST *next;
34
+};
35
+
36
+struct WHLST *wfrom = NULL;
37
+struct WHLST *wto = NULL;
38
+
39
+void whitelist_free(void) {
40
+    struct WHLST *w;
41
+    while(wfrom) {
42
+	w = wfrom->next;
43
+	regfree(&wfrom->preg);
44
+	free(wfrom);
45
+	wfrom = w;
46
+    }
47
+    while(wto) {
48
+	w = wfrom->next;
49
+	regfree(&wto->preg);
50
+	free(wto);
51
+	wto = w;
52
+    }
53
+}
54
+
55
+int whitelist_init(const char *fname) {
56
+    char buf[2048];
57
+    FILE *f;
58
+    struct WHLST *w;
59
+
60
+    if(!(f = fopen(fname, "r"))) {
61
+	logg("!Cannot open whitelist file\n");
62
+	return 1;
63
+    }
64
+
65
+    while(fgets(buf, sizeof(buf), f) != NULL) {
66
+	struct WHLST **addto = &wto;
67
+	char *ptr = buf;
68
+	int len;
69
+
70
+	if(*buf == '#' || *buf == ':' || *buf == '!')
71
+	    continue;
72
+
73
+	if(!strncasecmp("From:", buf, 5)) {
74
+	    ptr+=5;
75
+	    addto = &wfrom;
76
+	} else if (!strncasecmp("To:", buf, 3))
77
+	    ptr+=3;
78
+
79
+	len = strlen(ptr) - 1;
80
+	for(;len>=0; len--) {
81
+	    if(buf[len] != '\n' && buf[len] != '\r') break;
82
+	    buf[len] = '\0';
83
+	}
84
+	if(!len) continue;
85
+	if (!(w = (struct WHLST *)malloc(sizeof(*w)))) {
86
+	    logg("!Out of memory loading whitelist\n");
87
+	    whitelist_free();
88
+	    return 1;
89
+	}
90
+	w->next = (*addto)->next;
91
+	(*addto) = w;
92
+	if (regcomp(&w->preg, ptr, REG_ICASE|REG_NOSUB)) {
93
+	    logg("!Failed to compile regex '%s'\n", ptr);
94
+	    whitelist_free();
95
+	    return 1;
96
+	}
97
+    }
98
+    return 0;
99
+}
100
+
101
+
102
+int whitelisted(const char *e, int from) {
103
+    struct WHLST *w;
104
+
105
+    if(from) w = wfrom;
106
+    else w = wto;
107
+    while(w) {
108
+	if(!regexec(&w->preg, e, 0, NULL, 0))
109
+	    return 1;
110
+	w = w->next;
111
+    }
112
+    return 0;
113
+}
114
+
115
+
116
+/*
117
+ * Local Variables:
118
+ * mode: c
119
+ * c-basic-offset: 4
120
+ * tab-width: 8
121
+ * End: 
122
+ * vim: set cindent smartindent autoindent softtabstop=4 shiftwidth=4 tabstop=8: 
123
+ */
0 124
new file mode 100644
... ...
@@ -0,0 +1,7 @@
0
+#ifndef _WHITELIST_H
1
+#define _WHITELIST_H
2
+
3
+int whitelist_init(const char *fname);
4
+void whitelist_free(void);
5
+
6
+#endif
... ...
@@ -16,39 +16,48 @@ Example
16 16
 # [[unix|local]:]/path/to/file - to specify a unix domain socket
17 17
 # inet:port@[hostname|ip-address] - to specify an ipv4 socket
18 18
 # inet6:port@[hostname|ip-address] - to specify an ipv6 socket
19
-#Default: no default
19
+#
20
+# Default: no default
20 21
 ##MilterSocket /tmp/clamav-milter.socket
21 22
 ##MilterSocket inet:7357
22 23
 
23 24
 # Remove stale socket after unclean shutdown.
25
+#
24 26
 # Default: yes
25 27
 ##FixStaleSocket yes
26 28
 
27 29
 # Maximum number of threads running at the same time.
30
+#
28 31
 # Default: 10
29 32
 ##MaxThreads 20
30 33
 
31 34
 # Run as another user (clamav-milter must be started by root for this option to work)
32
-# Default: don't drop privileges
35
+#
36
+# Default: unset (don't drop privileges)
33 37
 ##User clamav
34 38
 
35 39
 # Initialize supplementary group access (clamd must be started by root).
40
+#
36 41
 # Default: no
37 42
 ##AllowSupplementaryGroups no
38 43
 
39 44
 # Waiting for data from clamd will timeout after this time (seconds).
40 45
 # Value of 0 disables the timeout.
46
+#
41 47
 # Default: 120
42 48
 ##ReadTimeout 300
43 49
 
44 50
 # Don't fork into background.
51
+#
45 52
 # Default: no
46 53
 ##Foreground yes
47 54
 
48 55
 # Chroot to the specified directory.
49 56
 # Chrooting is performed just after reading the config file and before dropping privileges.
57
+#
50 58
 # Default: unset (don't chroot)
51
-#Chroot /newroot
59
+##Chroot /newroot
60
+
52 61
 
53 62
 ##
54 63
 ## Clamd options
... ...
@@ -88,11 +97,23 @@ Example
88 88
 # This option takes a host(name)/mask pair in CIRD notation and can be
89 89
 # repeated several times. If "/mask" is omitted, a host is assumed.
90 90
 # To specify a locally orignated, non-smtp, email use the keyword "local"
91
+#
91 92
 # Default: unset (scan everything regardless of the origin)
92 93
 #LocalNet local
93 94
 #LocalNet 192.168.0.0/24
94 95
 #LocalNet 1111:2222:3333::/48
95 96
 
97
+# This option specifies a file which contains a list of e-mail addresses.
98
+# E-mails sent to or from these addresses will NOT be checked.
99
+# The file consists of a list of addresses, each address on a line enclosed
100
+# in angle brackets (e.g. <foo@bar.com>).
101
+# Optionally each line can start with the string "To:" or "From:" indicating
102
+# if it is the sender or recipient that is to be whitelisted. If the field
103
+# is missing, the default is "To:". Lines starting with #, : or ! are ignored.
104
+#
105
+# Default unset (no exclusion applied)
106
+#Whitelist /etc/whitelisted_addresses
107
+
96 108
 
97 109
 ##
98 110
 ## Actions
... ...
@@ -142,12 +163,14 @@ Example
142 142
 # Uncomment this option to enable logging.
143 143
 # LogFile must be writable for the user running daemon.
144 144
 # A full path is required.
145
+#
145 146
 # Default: disabled
146 147
 ##LogFile /tmp/clamav-milter.log
147 148
 
148 149
 # By default the log file is locked for writing - the lock protects against
149 150
 # running clamav-milter multiple times.
150 151
 # This option disables log file locking.
152
+#
151 153
 # Default: no
152 154
 ##LogFileUnlock yes
153 155
 
... ...
@@ -156,28 +179,34 @@ Example
156 156
 # You may use 'M' or 'm' for megabytes (1M = 1m = 1048576 bytes)
157 157
 # and 'K' or 'k' for kilobytes (1K = 1k = 1024 bytes). To specify the size
158 158
 # in bytes just don't use modifiers.
159
+#
159 160
 # Default: 1M
160 161
 ##LogFileMaxSize 2M
161 162
 
162 163
 # Log time with each message.
164
+#
163 165
 # Default: no
164 166
 ##LogTime yes
165 167
 
166 168
 # Also log clean files. Useful in debugging but drastically increases the
167 169
 # log size.
170
+#
168 171
 # Default: no
169 172
 ##LogClean yes
170 173
 
171 174
 # Use system logger (can work together with LogFile).
175
+#
172 176
 # Default: no
173 177
 ##LogSyslog yes
174 178
 
175 179
 # Specify the type of syslog messages - please refer to 'man syslog'
176 180
 # for facility names.
181
+#
177 182
 # Default: LOG_LOCAL6
178 183
 ##LogFacility LOG_MAIL
179 184
 
180 185
 # Enable verbose logging.
186
+#
181 187
 # Default: no
182 188
 ##LogVerbose yes
183 189
 
... ...
@@ -225,7 +254,7 @@ Example
225 225
 
226 226
 
227 227
 #Todo
228
-#-C --chroot
228
+##-C --chroot
229 229
 #-D --debug
230 230
 #-i --pidfile
231 231
 ##-I --ignore