Subversion Repositories vsftpd-clamav

Rev

Rev 2 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 madcat 1
#! /bin/sh /usr/share/dpatch/dpatch-run
2
## clamav-integration.dpatch by  <marco@debiansqueeze64>
3
##
4
## All lines beginning with `## DP:' are a description of the patch.
5
## DP: No description.
6
 
7
@DPATCH@
8
 
1 madcat 9
Add support for scanning uploaded files with clamav. Not all features are
10
implemented (ex. file inclusion/exclusion for scanning). Every uploaded file is
11
saved in random named file, and moved to destination file after scanning. Side
12
effects: when uploaded *new* file was infected, 0-size file left.
13
 
14
Written by Marek Marczykowski <m.marczykowski@fiok.pl>
15
 
16
Downloaded from: http://cvs.pld-linux.org/cgi-bin/cvsweb.cgi/packages/vsftpd/vsftpd-clamav.patch
17
 
18
diff -Naru vsftpd-2.2.2.orig/Makefile vsftpd-2.2.2/Makefile
19
--- vsftpd-2.2.2.orig/Makefile  2009-05-22 21:44:52.000000000 +0200
20
+++ vsftpd-2.2.2/Makefile       2010-04-29 19:46:54.435448038 +0200
3 madcat 21
@@ -19,7 +19,7 @@
1 madcat 22
     ascii.o oneprocess.o twoprocess.o privops.o standalone.o hash.o \
23
     tcpwrap.o ipaddrparse.o access.o features.o readwrite.o opts.o \
3 madcat 24
     ssl.o sslslave.o ptracesandbox.o ftppolicy.o sysutil.o sysdeputil.o \
25
-    seccompsandbox.o
26
+    seccompsandbox.o clamav.o
1 madcat 27
 
28
 
29
 .c.o:
30
diff -Naru vsftpd-2.2.2.orig/clamav.c vsftpd-2.2.2/clamav.c
31
--- vsftpd-2.2.2.orig/clamav.c  1970-01-01 01:00:00.000000000 +0100
32
+++ vsftpd-2.2.2/clamav.c       2010-04-29 19:46:54.435448038 +0200
33
@@ -0,0 +1,221 @@
34
+#include <sys/types.h>
35
+#include <regex.h>
36
+#include <sys/socket.h>
37
+#include <linux/un.h>
38
+#include <arpa/inet.h>
39
+#include <netdb.h>
40
+#include <sys/socket.h>
41
+#include <stdio.h>
42
+#include "clamav.h"
43
+#include "tunables.h"
44
+#include "utility.h"
45
+#include "sysutil.h"
46
+#include "logging.h"
47
+#include "sysstr.h"
48
+
49
+regex_t av_include_files_regex, av_exclude_files_regex;
50
+
51
+int av_init() {
52
+       int ret;
53
+
54
+       if (tunable_av_enable) {
55
+               if (tunable_av_include_files) {
56
+                       if ((ret=regcomp(&av_include_files_regex, tunable_av_include_files, REG_NOSUB)) != 0)
57
+                               die("regex compilation failed for AvIncludeFiles");
58
+               }
59
+               if (tunable_av_exclude_files) {
60
+                       if ((ret=regcomp(&av_exclude_files_regex, tunable_av_exclude_files, REG_NOSUB)) != 0)
61
+                               die("regex compilation failed for AvExcludeFiles");
62
+               }
63
+       }
64
+       return 0;
65
+}
66
+
67
+int av_will_scan(const char *filename) {
68
+       if (!tunable_av_enable)
69
+               return 0;
70
+       if (tunable_av_include_files && (regexec(&av_include_files_regex, filename, 0, 0, 0)!=0))
71
+               return 0;
72
+       if (tunable_av_exclude_files && (regexec(&av_exclude_files_regex, filename, 0, 0, 0)==0))
73
+               return 0;
74
+       return 1;
75
+}
76
+
77
+int av_init_scanner (struct vsf_session* p_sess) {
78
+       struct mystr debug_str = INIT_MYSTR;
79
+
80
+       if (p_sess->clamd_sock < 0) {
81
+               
82
+               /* connect to clamd through local unix socket */
83
+               if (tunable_av_clamd_socket) {
84
+                       struct sockaddr_un server_local;
85
+
86
+                       vsf_sysutil_memclr((char*)&server_local, sizeof(server_local));
87
+
88
+                       server_local.sun_family = AF_UNIX;
89
+                       vsf_sysutil_strcpy(server_local.sun_path, tunable_av_clamd_socket, sizeof(server_local.sun_path));
90
+                       if ((p_sess->clamd_sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
91
+                               str_alloc_text(&debug_str, "av: error opening unix socket");
92
+                               vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
93
+                               p_sess->clamd_sock = -2;
94
+                               return 0;
95
+                       }
96
+
97
+                       if (connect(p_sess->clamd_sock, (struct sockaddr *)&server_local, sizeof(struct sockaddr_un)) < 0) {
98
+                               str_alloc_text(&debug_str, "av: error connecting to clamd");
99
+                               vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
100
+                               p_sess->clamd_sock = -2;
101
+                               return 0;
102
+                       }
103
+
104
+               } else if (tunable_av_clamd_host) {
105
+                       struct sockaddr_in server_inet;
106
+                       struct hostent *he;
107
+
108
+                       vsf_sysutil_memclr((char*)&server_inet, sizeof(server_inet));
109
+
110
+                       /* Remote Socket */
111
+                       server_inet.sin_family = AF_INET;
112
+                       server_inet.sin_port = htons(tunable_av_clamd_port);
113
+
114
+                       if ((p_sess->clamd_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
115
+                               str_alloc_text(&debug_str, "av: error opening inet socket");
116
+                               vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
117
+                               p_sess->clamd_sock = -2;
118
+                               return 0;
119
+                       }
120
+
121
+                       if ((he = gethostbyname(tunable_av_clamd_host)) == 0) {
122
+                               str_alloc_text(&debug_str, "av: unable to locate clamd host");
123
+                               vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
124
+                               vsf_sysutil_close_failok(p_sess->clamd_sock);
125
+                               p_sess->clamd_sock = -2;
126
+                               return 0;
127
+                       }
128
+
129
+                       server_inet.sin_addr = *(struct in_addr *) he->h_addr_list[0];
130
+
131
+                       if (connect(p_sess->clamd_sock, (struct sockaddr *)&server_inet, sizeof(struct sockaddr_in)) < 0) {
132
+                               str_alloc_text(&debug_str, "av: error connecting to clamd host");
133
+                               vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
134
+                               vsf_sysutil_close_failok(p_sess->clamd_sock);
135
+                               p_sess->clamd_sock = -2;
136
+                               return 0;
137
+                       }
138
+               }
139
+
140
+               if (vsf_sysutil_write(p_sess->clamd_sock, "nIDSESSION\n", 11) <= 0) {
141
+                       str_alloc_text(&debug_str, "av: error starting clamd session");
142
+                       vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
143
+                       vsf_sysutil_close_failok(p_sess->clamd_sock);
144
+                       p_sess->clamd_sock = -2;
145
+                       return 0;
146
+               }
147
+       }
148
+
149
+       return 1;
150
+}
151
+
152
+int av_scan_file(struct vsf_session* p_sess, struct mystr *filename, struct mystr *virname) {
153
+       struct mystr cwd = INIT_MYSTR;
154
+       struct mystr clamcmd = INIT_MYSTR;
155
+       struct mystr response = INIT_MYSTR;
156
+       char recv_buff[4096];
157
+       int recv_count;
158
+       struct str_locate_result locate_res;
159
+       struct mystr debug_str = INIT_MYSTR;
160
+       int retry = 0;
161
+
162
+init_scan:
163
+       if (av_init_scanner(p_sess)) {
164
+
165
+               str_alloc_text(&clamcmd, "nSCAN ");
166
+               if (!str_isempty(&p_sess->chroot_str)) {
167
+                       str_append_str(&clamcmd, &p_sess->chroot_str);
168
+               }
169
+               if (str_get_char_at(filename, 0) != '/') {
170
+                       str_getcwd(&cwd);
171
+                       str_append_str(&clamcmd, &cwd);
172
+               }
173
+               if (str_get_char_at(&clamcmd, str_getlen(&clamcmd) - 1) != '/') { 
174
+                       str_append_char(&clamcmd, '/');
175
+               }
176
+               str_append_str(&clamcmd, filename);
177
+               str_append_char(&clamcmd, '\n');
178
+
179
+//             sprintf(recv_buff, "sockfd: %d", p_sess->clamd_sock);
180
+//             str_alloc_text(&debug_str, recv_buff);
181
+//             vsf_log_line(p_sess, kVSFLogEntryDebug, &p_sess->chroot_str);
182
+//             vsf_log_line(p_sess, kVSFLogEntryDebug, &clamcmd);
183
+
184
+               if (vsf_sysutil_write(p_sess->clamd_sock, str_getbuf(&clamcmd), str_getlen(&clamcmd)) <= 0) {
185
+                       str_alloc_text(&debug_str, "av: failed to scan file");
186
+                       vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
187
+                       vsf_sysutil_close_failok(p_sess->clamd_sock);
188
+                       p_sess->clamd_sock = -2;
189
+                       return 2;
190
+               }
191
+
192
+               str_free(&clamcmd);
193
+
194
+               /* receive and interpret answer */
195
+               while ((recv_count=vsf_sysutil_read(p_sess->clamd_sock, recv_buff, 4095)) > 0) {
196
+                       recv_buff[recv_count]=0;
197
+                       str_append_text(&response, recv_buff);
198
+                       if (recv_buff[recv_count-1] == '\n')
199
+                               break;
200
+               }
201
+               if (recv_count < 0 || str_getlen(&response) == 0) {
202
+                       if (!retry) {
203
+                               retry = 1;
204
+                               vsf_sysutil_close_failok(p_sess->clamd_sock);
205
+                               p_sess->clamd_sock = -2;
206
+                               goto init_scan;
207
+                       } else {
208
+                               str_alloc_text(&debug_str, "av: failed to scan file (read failed)");
209
+                               vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
210
+                               vsf_sysutil_close(p_sess->clamd_sock);
211
+                               p_sess->clamd_sock = -2;
212
+                               return 2;
213
+                       }
214
+               }
215
+               
216
+               if (str_equal_text(&response, "COMMAND READ TIMED OUT\n")) {
217
+                       if (!retry) {
218
+                               retry = 1;
219
+                               vsf_sysutil_close_failok(p_sess->clamd_sock);
220
+                               p_sess->clamd_sock = -2;
221
+                               goto init_scan;
222
+                       } else {
223
+                               str_alloc_text(&debug_str, "av: got: ");
224
+                               str_append_str(&debug_str, &response);
225
+                               vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
226
+                               return 2;
227
+                       }
228
+               }
229
+
230
+
231
+
232
+               locate_res = str_locate_text(&response, " FOUND\n");
233
+               /* virus found */
234
+               if (locate_res.found) {
235
+                       str_trunc(&response, locate_res.index);
236
+                       str_split_text_reverse(&response, virname, ": ");
237
+                       return 1;
238
+               }
239
+               locate_res = str_locate_text(&response, " ERROR\n");
240
+               if (locate_res.found) {
241
+                       str_alloc_text(&debug_str, "av: got: ");
242
+                       str_append_str(&debug_str, &response);
243
+                       vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
244
+                       return 2;
245
+               }
246
+               return 0;
247
+       }
248
+
249
+       return 2;
250
+}
251
+
252
+
253
+
254
+
255
diff -Naru vsftpd-2.2.2.orig/clamav.h vsftpd-2.2.2/clamav.h
256
--- vsftpd-2.2.2.orig/clamav.h  1970-01-01 01:00:00.000000000 +0100
257
+++ vsftpd-2.2.2/clamav.h       2010-04-29 19:46:54.435448038 +0200
258
@@ -0,0 +1,12 @@
259
+#ifndef _CLAMAV_H
260
+#define _CLAMAV_H
261
+
262
+#include "str.h"
263
+#include "session.h"
264
+
265
+extern int av_init();
266
+extern int av_will_scan(const char *filename);
267
+extern int av_init_scanner (struct vsf_session* p_sess);
268
+extern int av_scan_file(struct vsf_session* p_sess, struct mystr *filename, struct mystr *virname);
269
+
270
+#endif
271
diff -Naru vsftpd-2.2.2.orig/main.c vsftpd-2.2.2/main.c
272
--- vsftpd-2.2.2.orig/main.c    2009-07-18 07:55:53.000000000 +0200
273
+++ vsftpd-2.2.2/main.c 2010-04-29 19:46:54.435448038 +0200
2 madcat 274
@@ -66,7 +66,9 @@
1 madcat 275
     /* Secure connection state */
276
     0, 0, 0, 0, 0, INIT_MYSTR, 0, -1, -1,
277
     /* Login fails */
278
-    0
279
+    0,
280
+       /* av */
281
+       -1, INIT_MYSTR
282
   };
283
   int config_loaded = 0;
284
   int i;
285
diff -Naru vsftpd-2.2.2.orig/parseconf.c vsftpd-2.2.2/parseconf.c
286
--- vsftpd-2.2.2.orig/parseconf.c       2009-08-07 20:46:40.000000000 +0200
287
+++ vsftpd-2.2.2/parseconf.c    2010-04-29 19:46:54.435448038 +0200
2 madcat 288
@@ -101,6 +101,7 @@
1 madcat 289
   { "delete_failed_uploads", &tunable_delete_failed_uploads },
290
   { "implicit_ssl", &tunable_implicit_ssl },
3 madcat 291
   { "ptrace_sandbox", &tunable_ptrace_sandbox },
1 madcat 292
+  { "av_enable", &tunable_av_enable },
293
   { "require_ssl_reuse", &tunable_require_ssl_reuse },
294
   { "isolate", &tunable_isolate },
295
   { "isolate_network", &tunable_isolate_network },
3 madcat 296
@@ -138,6 +139,7 @@
1 madcat 297
   { "delay_successful_login", &tunable_delay_successful_login },
298
   { "max_login_fails", &tunable_max_login_fails },
299
   { "chown_upload_mode", &tunable_chown_upload_mode },
300
+  { "av_clamd_port", &tunable_av_clamd_port },
301
   { 0, 0 }
302
 };
303
 
3 madcat 304
@@ -180,6 +182,10 @@
1 madcat 305
   { "dsa_private_key_file", &tunable_dsa_private_key_file },
306
   { "ca_certs_file", &tunable_ca_certs_file },
307
   { "cmds_denied", &tunable_cmds_denied },
308
+  { "av_clamd_socket", &tunable_av_clamd_socket },
309
+  { "av_clamd_host", &tunable_av_clamd_host },
310
+  { "av_include_files", &tunable_av_include_files },
311
+  { "av_exclude_files", &tunable_av_exclude_files },
312
   { 0, 0 }
313
 };
314
 
315
diff -Naru vsftpd-2.2.2.orig/postlogin.c vsftpd-2.2.2/postlogin.c
316
--- vsftpd-2.2.2.orig/postlogin.c       2009-11-07 05:55:12.000000000 +0100
317
+++ vsftpd-2.2.2/postlogin.c    2010-04-29 19:46:54.438781445 +0200
318
@@ -27,6 +27,7 @@
319
 #include "ssl.h"
320
 #include "vsftpver.h"
321
 #include "opts.h"
322
+#include "clamav.h"
323
 
324
 /* Private local functions */
325
 static void handle_pwd(struct vsf_session* p_sess);
3 madcat 326
@@ -1009,12 +1010,15 @@
1 madcat 327
   static struct vsf_sysutil_statbuf* s_p_statbuf;
328
   static struct mystr s_filename;
329
   struct mystr* p_filename;
330
+  struct mystr tmp_filename = INIT_MYSTR;
331
   struct vsf_transfer_ret trans_ret;
332
   int new_file_fd;
333
+  int av_orig_file_fd = -1;
334
   int remote_fd;
335
   int success = 0;
336
   int created = 0;
337
   int do_truncate = 0;
338
+  int do_av = 0;
339
   filesize_t offset = p_sess->restart_pos;
340
   p_sess->restart_pos = 0;
341
   if (!data_transfer_checks_ok(p_sess))
3 madcat 342
@@ -1028,6 +1032,7 @@
1 madcat 343
     get_unique_filename(&s_filename, p_filename);
344
     p_filename = &s_filename;
345
   }
346
+
347
   vsf_log_start_entry(p_sess, kVSFLogEntryUpload);
348
   str_copy(&p_sess->log_str, &p_sess->ftp_arg_str);
349
   prepend_path_to_filename(&p_sess->log_str);
3 madcat 350
@@ -1059,6 +1064,24 @@
1 madcat 351
     return;
352
   }
353
   created = 1;
354
+
355
+  if (av_will_scan(str_getbuf(p_filename))) {
356
+       do_av = 1;
357
+       str_copy(&tmp_filename, p_filename);
358
+       str_append_text(&tmp_filename, ".XXXXXX");
359
+       av_orig_file_fd = new_file_fd;
360
+       /* FIXME: various permissions issues... ex. writable file in non-writable directory */
361
+       new_file_fd = mkstemp(str_getbuf(&tmp_filename));
362
+       if (vsf_sysutil_retval_is_error(new_file_fd))
363
+       {
364
+         vsf_sysutil_close(av_orig_file_fd);
365
+         vsf_cmdio_write(p_sess, FTP_UPLOADFAIL, "Could not create temp file.");
366
+         return;
367
+       }
368
+       /* mkstemp creates file with 0600 */
369
+       vsf_sysutil_fchmod(new_file_fd, 0666 &(~vsf_sysutil_get_umask()));
370
+  }
371
+
372
   vsf_sysutil_fstat(new_file_fd, &s_p_statbuf);
373
   if (vsf_sysutil_statbuf_is_regfile(s_p_statbuf))
374
   {
3 madcat 375
@@ -1084,6 +1107,8 @@
1 madcat 376
   if (tunable_lock_upload_files)
377
   {
378
     vsf_sysutil_lock_file_write(new_file_fd);
379
+       if (do_av)
380
+               vsf_sysutil_lock_file_write(av_orig_file_fd);
381
   }
382
   /* Must truncate the file AFTER locking it! */
383
   if (do_truncate)
3 madcat 384
@@ -1091,6 +1116,22 @@
1 madcat 385
     vsf_sysutil_ftruncate(new_file_fd);
386
     vsf_sysutil_lseek_to(new_file_fd, 0);
387
   }
388
+  if (do_av && (is_append || offset != 0)) {
389
+       char buf[4096];
390
+       int count;
391
+
392
+       /* copy original file */
393
+       vsf_sysutil_lseek_to(av_orig_file_fd, 0);
394
+       while ((count=vsf_sysutil_read(av_orig_file_fd, buf, 4096)) > 0) {
395
+         if (vsf_sysutil_write_loop(new_file_fd, buf, count) < 0) {
396
+               vsf_cmdio_write(p_sess, FTP_UPLOADFAIL, "Could not copy temp file.");
397
+               vsf_sysutil_close(new_file_fd);
398
+               vsf_sysutil_close(av_orig_file_fd);
399
+               vsf_sysutil_unlink(str_getbuf(&tmp_filename));
400
+               return;
401
+         }
402
+       }
403
+  }
404
   if (!is_append && offset != 0)
405
   {
406
     /* XXX - warning, allows seek past end of file! Check for seek > size? */
3 madcat 407
@@ -1114,6 +1155,7 @@
1 madcat 408
   }
409
   if (vsf_sysutil_retval_is_error(remote_fd))
410
   {
411
+       vsf_sysutil_unlink(str_getbuf(&tmp_filename));
412
     goto port_pasv_cleanup_out;
413
   }
414
   if (tunable_ascii_upload_enable && p_sess->is_ascii)
3 madcat 415
@@ -1134,7 +1176,6 @@
1 madcat 416
   if (trans_ret.retval == 0)
417
   {
418
     success = 1;
419
-    vsf_log_do_log(p_sess, 1);
420
   }
421
   if (trans_ret.retval == -1)
422
   {
3 madcat 423
@@ -1150,7 +1191,43 @@
1 madcat 424
   }
425
   else
426
   {
427
-    vsf_cmdio_write(p_sess, FTP_TRANSFEROK, "Transfer complete.");
428
+       if (do_av) {
429
+         struct mystr virname = INIT_MYSTR;
430
+         struct mystr resp_str = INIT_MYSTR;
431
+
432
+         switch (av_scan_file(p_sess, &tmp_filename, &virname)) {
433
+               case 1:
434
+                 str_alloc_text(&resp_str, "Virus found: ");
435
+                 str_append_str(&resp_str, &virname);
436
+                 vsf_log_line(p_sess, kVSFLogEntryUpload, &resp_str);
437
+                 vsf_cmdio_write(p_sess, FTP_UPLOADFAIL, str_getbuf(&resp_str));
438
+                 str_free(&resp_str);
439
+
440
+                 str_unlink(&tmp_filename);
441
+                 break;
442
+               case 2:
443
+                 vsf_cmdio_write(p_sess, FTP_BADSENDFILE, "Failure scanning file.");
444
+                 str_unlink(&tmp_filename);
445
+                 break;
446
+               default:
447
+                 /* FIXME: race condition */
448
+                 if (vsf_sysutil_rename(str_getbuf(&tmp_filename), str_getbuf(p_filename)) < 0) {
449
+                       vsf_cmdio_write(p_sess, FTP_BADSENDFILE, "Failure writing to local file .");
450
+                       str_unlink(&tmp_filename);
451
+                 } 
452
+                 else 
453
+                 {
454
+                       vsf_log_do_log(p_sess, 1);
455
+                       vsf_cmdio_write(p_sess, FTP_TRANSFEROK, "File receive OK.");
456
+                 }
457
+                 break;
458
+         }
459
+       } 
460
+       else 
461
+       {
462
+         vsf_log_do_log(p_sess, 1);
463
+         vsf_cmdio_write(p_sess, FTP_TRANSFEROK, "File receive OK.");
464
+       }
465
   }
466
   check_abor(p_sess);
467
 port_pasv_cleanup_out:
3 madcat 468
@@ -1158,9 +1235,15 @@
1 madcat 469
   pasv_cleanup(p_sess);
470
   if (tunable_delete_failed_uploads && created && !success)
471
   {
472
-    str_unlink(p_filename);
473
+       if (do_av) {
474
+         str_unlink(&tmp_filename);
475
+       } else {
476
+         str_unlink(p_filename);
477
+       }
478
   }
479
   vsf_sysutil_close(new_file_fd);
480
+  if (do_av)
481
+       vsf_sysutil_close(av_orig_file_fd);
482
 }
483
 
484
 static void
485
diff -Naru vsftpd-2.2.2.orig/secutil.c vsftpd-2.2.2/secutil.c
486
--- vsftpd-2.2.2.orig/secutil.c 2009-05-27 08:20:36.000000000 +0200
487
+++ vsftpd-2.2.2/secutil.c      2010-04-29 19:46:54.438781445 +0200
488
@@ -34,6 +34,7 @@
489
     if (p_dir_str == 0 || str_isempty(p_dir_str))
490
     {
491
       str_alloc_text(&dir_str, vsf_sysutil_user_get_homedir(p_user));
492
+         str_copy(p_dir_str, &dir_str);
493
     }
494
     else
495
     {
496
diff -Naru vsftpd-2.2.2.orig/session.h vsftpd-2.2.2/session.h
497
--- vsftpd-2.2.2.orig/session.h 2008-02-12 03:39:38.000000000 +0100
498
+++ vsftpd-2.2.2/session.h      2010-04-29 19:46:54.438781445 +0200
3 madcat 499
@@ -99,6 +99,10 @@
1 madcat 500
   int ssl_slave_fd;
501
   int ssl_consumer_fd;
502
   unsigned int login_fails;
503
+
504
+  /* data for av scanner */
505
+  int clamd_sock;
506
+  struct mystr chroot_str;
507
 };
508
 
509
 #endif /* VSF_SESSION_H */
510
diff -Naru vsftpd-2.2.2.orig/tunables.c vsftpd-2.2.2/tunables.c
511
--- vsftpd-2.2.2.orig/tunables.c        2009-07-15 22:08:27.000000000 +0200
512
+++ vsftpd-2.2.2/tunables.c     2010-04-29 19:48:44.265437093 +0200
3 madcat 513
@@ -89,6 +89,7 @@
2 madcat 514
 int tunable_http_enable;
3 madcat 515
 int tunable_seccomp_sandbox;
516
 int tunable_allow_writeable_chroot;
517
+int tunable_av_enable;
1 madcat 518
 
519
 unsigned int tunable_accept_timeout;
520
 unsigned int tunable_connect_timeout;
3 madcat 521
@@ -110,6 +111,7 @@
1 madcat 522
 unsigned int tunable_delay_successful_login;
523
 unsigned int tunable_max_login_fails;
524
 unsigned int tunable_chown_upload_mode;
525
+unsigned int tunable_av_clamd_port;
526
 
527
 const char* tunable_secure_chroot_dir;
528
 const char* tunable_ftp_username;
3 madcat 529
@@ -144,6 +147,11 @@
1 madcat 530
 const char* tunable_dsa_private_key_file;
531
 const char* tunable_ca_certs_file;
532
 
533
+const char* tunable_av_clamd_socket;
534
+const char* tunable_av_clamd_host;
535
+const char* tunable_av_include_files;
536
+const char* tunable_av_exclude_files;
537
+
538
 static void install_str_setting(const char* p_value, const char** p_storage);
539
 
540
 void
3 madcat 541
@@ -225,11 +227,12 @@
542
   tunable_ptrace_sandbox = 0;
1 madcat 543
   tunable_require_ssl_reuse = 1;
544
   tunable_isolate = 1;
545
-  tunable_isolate_network = 1;
546
+  tunable_isolate_network = 0;
547
   tunable_ftp_enable = 1;
548
   tunable_http_enable = 0;
3 madcat 549
   tunable_seccomp_sandbox = 1;
550
   tunable_allow_writeable_chroot = 0;
1 madcat 551
+  tunable_av_enable = 0;
552
 
553
   tunable_accept_timeout = 60;
554
   tunable_connect_timeout = 60;
3 madcat 555
@@ -255,6 +263,7 @@
1 madcat 556
   tunable_max_login_fails = 3;
557
   /* -rw------- */
558
   tunable_chown_upload_mode = 0600;
559
+  tunable_av_clamd_port = 3310;
560
 
2 madcat 561
   install_str_setting("/var/run/vsftpd/empty", &tunable_secure_chroot_dir);
1 madcat 562
   install_str_setting("ftp", &tunable_ftp_username);
3 madcat 563
@@ -290,6 +299,11 @@
1 madcat 564
   install_str_setting(0, &tunable_rsa_private_key_file);
565
   install_str_setting(0, &tunable_dsa_private_key_file);
566
   install_str_setting(0, &tunable_ca_certs_file);
567
+
568
+  install_str_setting(0, &tunable_av_clamd_socket);
569
+  install_str_setting("127.0.0.1", &tunable_av_clamd_host);
570
+  install_str_setting(0, &tunable_av_include_files);
571
+  install_str_setting(0, &tunable_av_exclude_files);
572
 }
573
 
574
 void
575
diff -Naru vsftpd-2.2.2.orig/tunables.h vsftpd-2.2.2/tunables.h
576
--- vsftpd-2.2.2.orig/tunables.h        2009-07-07 03:37:28.000000000 +0200
577
+++ vsftpd-2.2.2/tunables.h     2010-04-29 19:46:54.438781445 +0200
2 madcat 578
@@ -84,6 +84,7 @@
1 madcat 579
 extern int tunable_implicit_ssl;              /* Use implicit SSL protocol */
3 madcat 580
 extern int tunable_ptrace_sandbox;            /* DEPRECATED ptrace sandbox */
1 madcat 581
 extern int tunable_require_ssl_reuse;         /* Require re-used data conn */
582
+extern int tunable_av_enable;                 /* Scan av incomming files */
583
 extern int tunable_isolate;                   /* Use container clone() flags */
584
 extern int tunable_isolate_network;           /* Use CLONE_NEWNET */
2 madcat 585
 extern int tunable_ftp_enable;                /* Allow FTP protocol */
3 madcat 586
@@ -112,6 +113,7 @@
1 madcat 587
 extern unsigned int tunable_delay_successful_login;
588
 extern unsigned int tunable_max_login_fails;
589
 extern unsigned int tunable_chown_upload_mode;
590
+extern unsigned int tunable_av_clamd_port;
591
 
592
 /* String defines */
593
 extern const char* tunable_secure_chroot_dir;
3 madcat 594
@@ -146,6 +148,10 @@
1 madcat 595
 extern const char* tunable_dsa_private_key_file;
596
 extern const char* tunable_ca_certs_file;
597
 extern const char* tunable_cmds_denied;
598
+extern const char* tunable_av_clamd_socket;
599
+extern const char* tunable_av_clamd_host;
600
+extern const char* tunable_av_include_files;
601
+extern const char* tunable_av_exclude_files;
602
 
603
 #endif /* VSF_TUNABLES_H */
604
 
605
diff -Naru vsftpd-2.2.2.orig/twoprocess.c vsftpd-2.2.2/twoprocess.c
606
--- vsftpd-2.2.2.orig/twoprocess.c      2009-07-18 07:56:44.000000000 +0200
607
+++ vsftpd-2.2.2/twoprocess.c   2010-04-29 19:46:54.438781445 +0200
3 madcat 608
@@ -457,6 +457,13 @@
1 madcat 609
                         p_user_str, p_orig_user_str);
610
     vsf_secutil_change_credentials(p_user_str, &userdir_str, &chroot_str,
611
                                    0, secutil_option);
612
+
613
+       if (do_chroot) {
614
+               str_copy(&p_sess->chroot_str, &userdir_str);
615
+       } else {
616
+               str_empty(&p_sess->chroot_str);
617
+       }
618
+
619
     if (!str_isempty(&chdir_str))
620
     {
621
       (void) str_chdir(&chdir_str);
622
diff -Naru vsftpd-2.2.2.orig/vsftpd.conf.5 vsftpd-2.2.2/vsftpd.conf.5
623
--- vsftpd-2.2.2.orig/vsftpd.conf.5     2009-10-19 04:46:30.000000000 +0200
624
+++ vsftpd-2.2.2/vsftpd.conf.5  2010-04-29 19:46:54.438781445 +0200
625
@@ -105,6 +105,11 @@
626
 
627
 Default: NO
628
 .TP
629
+.B av_enable
630
+If enabled, all uploaded files are scanned with clamav (through clamd).
631
+
632
+Default: NO
633
+.TP
634
 .B background
635
 When enabled, and vsftpd is started in "listen" mode, vsftpd will background
636
 the listener process. i.e. control will immediately be returned to the shell
637
@@ -643,6 +648,11 @@
638
 
639
 Default: 077
640
 .TP
641
+.B av_clamd_port
642
+Port number where clamd listen on.
643
+
644
+Default: 3310
645
+.TP
646
 .B chown_upload_mode
647
 The file mode to force for chown()ed anonymous uploads. (Added in v2.0.6).
648
 
649
@@ -758,6 +768,18 @@
650
 
651
 Default: (none)
652
 .TP
653
+.B av_clamd_host
654
+IP where clamd listen. It must be on the same host (or have access to same
655
+filesystem).
656
+
657
+Default: 127.0.0.1
658
+.TP
659
+.B av_clamd_socket
660
+UNIX socket of clamd. Warning: When using chroot you should use TCP instead of
661
+UNIX socket.
662
+
663
+Default: (none)
664
+.TP
665
 .B banned_email_file
666
 This option is the name of a file containing a list of anonymous e-mail
667
 passwords which are not permitted. This file is consulted if the option