Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / vsftpd / ftppolicy.c
blobdb282c9e092ae83826a7509e6ce12337bf43d5de
1 /*
2 * Part of Very Secure FTPd
3 * Licence: GPL v2
4 * Author: Chris Evans
5 * ftppolicy.c
7 * Code to build a sandbox policy based on current session options.
8 */
10 #include "ftppolicy.h"
11 #include "ptracesandbox.h"
12 #include "tunables.h"
13 #include "session.h"
14 #include "sysutil.h"
16 /* For AF_INET etc. network constants. */
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <netinet/in_systm.h>
20 #include <netinet/in.h>
21 #include <netinet/ip.h>
22 #include <netinet/tcp.h>
24 static int socket_validator(struct pt_sandbox* p_sandbox, void* p_arg);
25 static int connect_validator(struct pt_sandbox* p_sandbox, void* p_arg);
26 static int getsockopt_validator(struct pt_sandbox* p_sandbox, void* p_arg);
27 static int setsockopt_validator(struct pt_sandbox* p_sandbox, void* p_arg);
29 void
30 policy_setup(struct pt_sandbox* p_sandbox, const struct vsf_session* p_sess)
32 int is_anon = p_sess->is_anonymous;
33 /* Always need to be able to exit! */
34 ptrace_sandbox_permit_exit(p_sandbox);
35 /* Needed for memory management. */
36 ptrace_sandbox_permit_mmap(p_sandbox);
37 ptrace_sandbox_permit_mprotect(p_sandbox);
38 ptrace_sandbox_permit_brk(p_sandbox);
39 /* Simple reads and writes are required. Permitting write does not imply
40 * filesystem write access because access control is done at open time.
42 ptrace_sandbox_permit_read(p_sandbox);
43 ptrace_sandbox_permit_write(p_sandbox);
44 /* Querying time is harmless; used for log timestamps and internally to
45 * OpenSSL
47 ptrace_sandbox_permit_query_time(p_sandbox);
48 /* Stat'ing is needed for downloading and directory listings. Can blanket
49 * enable for any filename thanks to the chroot().
51 ptrace_sandbox_permit_file_stats(p_sandbox);
52 ptrace_sandbox_permit_fd_stats(p_sandbox);
53 /* Querying and changing directory. */
54 ptrace_sandbox_permit_getcwd(p_sandbox);
55 ptrace_sandbox_permit_chdir(p_sandbox);
56 /* Setting umask. */
57 ptrace_sandbox_permit_umask(p_sandbox);
58 /* Since we're in a chroot(), we can just blanket allow filesystem readonly
59 * open.
61 ptrace_sandbox_permit_open(p_sandbox, 0);
62 ptrace_sandbox_permit_close(p_sandbox);
63 /* High-speed transfers... */
64 ptrace_sandbox_permit_sendfile(p_sandbox);
65 /* Reading directories. */
66 ptrace_sandbox_permit_getdents(p_sandbox);
67 /* Reading symlink targets. */
68 ptrace_sandbox_permit_readlink(p_sandbox);
69 /* File locking. */
70 ptrace_sandbox_permit_fcntl(p_sandbox);
71 /* Seeking for REST. */
72 ptrace_sandbox_permit_seek(p_sandbox);
73 /* Select for data connection readyness. */
74 ptrace_sandbox_permit_select(p_sandbox);
75 /* Always need ability to take signals (SIGPIPE) */
76 ptrace_sandbox_permit_sigreturn(p_sandbox);
77 /* Sleeping (bandwidth limit, connect retires, anon login fails) */
78 ptrace_sandbox_permit_sleep(p_sandbox);
79 /* May need ability to install signal handlers. */
80 if (tunable_async_abor_enable ||
81 tunable_idle_session_timeout > 0 ||
82 tunable_data_connection_timeout > 0)
84 ptrace_sandbox_permit_sigaction(p_sandbox);
86 /* May need ability to set up timeout alarms. */
87 if (tunable_idle_session_timeout > 0 || tunable_data_connection_timeout > 0)
89 ptrace_sandbox_permit_alarm(p_sandbox);
91 /* TODO - Grrrr! nscd cache access is leaking into child. Need to find out
92 * out how to disable that. Also means that text_userdb_names loads values
93 * from the real system data.
95 if (tunable_text_userdb_names)
97 ptrace_sandbox_permit_mremap(p_sandbox);
99 /* Set up network permissions according to config and session. */
100 ptrace_sandbox_permit_recv(p_sandbox);
101 ptrace_sandbox_permit_shutdown(p_sandbox);
102 ptrace_sandbox_permit_socket(p_sandbox);
103 ptrace_sandbox_set_socket_validator(p_sandbox,
104 socket_validator,
105 (void*) p_sess);
106 ptrace_sandbox_permit_bind(p_sandbox);
107 /* Yes, reuse of the connect validator is intentional. */
108 ptrace_sandbox_set_bind_validator(p_sandbox,
109 connect_validator,
110 (void*) p_sess);
111 ptrace_sandbox_permit_setsockopt(p_sandbox);
112 ptrace_sandbox_set_setsockopt_validator(p_sandbox, setsockopt_validator, 0);
113 ptrace_sandbox_permit_shutdown(p_sandbox);
114 if (tunable_port_enable)
116 ptrace_sandbox_permit_connect(p_sandbox);
117 ptrace_sandbox_set_connect_validator(p_sandbox,
118 connect_validator,
119 (void*) p_sess);
120 ptrace_sandbox_permit_getsockopt(p_sandbox);
121 ptrace_sandbox_set_getsockopt_validator(p_sandbox, getsockopt_validator, 0);
123 if (tunable_pasv_enable)
125 ptrace_sandbox_permit_listen(p_sandbox);
126 ptrace_sandbox_permit_accept(p_sandbox);
128 /* Set up write permissions according to config and session. */
129 if (tunable_write_enable)
131 if (!is_anon || tunable_anon_upload_enable)
133 ptrace_sandbox_permit_open(p_sandbox, 1);
135 if (!is_anon || tunable_anon_mkdir_write_enable)
137 ptrace_sandbox_permit_mkdir(p_sandbox);
139 if (!is_anon || tunable_anon_other_write_enable)
141 ptrace_sandbox_permit_unlink(p_sandbox);
142 ptrace_sandbox_permit_rmdir(p_sandbox);
143 ptrace_sandbox_permit_rename(p_sandbox);
144 ptrace_sandbox_permit_ftruncate(p_sandbox);
145 if (tunable_mdtm_write)
147 ptrace_sandbox_permit_utime(p_sandbox);
150 if (!is_anon && tunable_chmod_enable)
152 ptrace_sandbox_permit_chmod(p_sandbox);
154 if (is_anon && tunable_chown_uploads)
156 ptrace_sandbox_permit_fchmod(p_sandbox);
157 ptrace_sandbox_permit_fchown(p_sandbox);
162 static int
163 socket_validator(struct pt_sandbox* p_sandbox, void* p_arg)
165 int ret;
166 struct vsf_session* p_sess = (struct vsf_session*) p_arg;
167 unsigned long arg1;
168 unsigned long arg2;
169 unsigned long expected_family = AF_INET;
170 if (vsf_sysutil_sockaddr_is_ipv6(p_sess->p_local_addr))
172 expected_family = AF_INET6;
174 ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 0, &arg1);
175 if (ret != 0)
177 return ret;
179 ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 1, &arg2);
180 if (ret != 0)
182 return ret;
184 if (arg1 != expected_family || arg2 != SOCK_STREAM)
186 return -1;
188 return 0;
191 static int
192 connect_validator(struct pt_sandbox* p_sandbox, void* p_arg)
194 int ret;
195 struct vsf_session* p_sess = (struct vsf_session*) p_arg;
196 unsigned long arg2;
197 unsigned long arg3;
198 unsigned long expected_family = AF_INET;
199 unsigned long expected_len = sizeof(struct sockaddr_in);
200 void* p_buf = 0;
201 struct sockaddr* p_sockaddr;
202 static struct vsf_sysutil_sockaddr* p_sockptr;
203 if (vsf_sysutil_sockaddr_is_ipv6(p_sess->p_local_addr))
205 expected_family = AF_INET6;
206 expected_len = sizeof(struct sockaddr_in6);
208 ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 1, &arg2);
209 if (ret != 0)
211 return ret;
213 ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 2, &arg3);
214 if (ret != 0)
216 return ret;
218 if (arg3 != expected_len)
220 return -1;
222 p_buf = vsf_sysutil_malloc((int) expected_len);
223 ret = ptrace_sandbox_get_buf(p_sandbox, arg2, expected_len, p_buf);
224 if (ret != 0)
226 vsf_sysutil_free(p_buf);
227 return -2;
229 p_sockaddr = (struct sockaddr*) p_buf;
230 if (p_sockaddr->sa_family != expected_family)
232 vsf_sysutil_free(p_buf);
233 return -3;
235 if (expected_family == AF_INET)
237 struct sockaddr_in* p_sockaddr_in = (struct sockaddr_in*) p_sockaddr;
238 vsf_sysutil_sockaddr_alloc_ipv4(&p_sockptr);
239 vsf_sysutil_sockaddr_set_ipv4addr(p_sockptr,
240 (const unsigned char*)
241 &p_sockaddr_in->sin_addr);
243 else
245 struct sockaddr_in6* p_sockaddr_in6 = (struct sockaddr_in6*) p_sockaddr;
246 vsf_sysutil_sockaddr_alloc_ipv6(&p_sockptr);
247 vsf_sysutil_sockaddr_set_ipv6addr(p_sockptr,
248 (const unsigned char*)
249 &p_sockaddr_in6->sin6_addr);
251 if (!vsf_sysutil_sockaddr_addr_equal(p_sess->p_remote_addr, p_sockptr))
253 vsf_sysutil_free(p_buf);
254 return -4;
256 vsf_sysutil_free(p_buf);
257 return 0;
260 static int
261 getsockopt_validator(struct pt_sandbox* p_sandbox, void* p_arg)
263 int ret;
264 unsigned long arg2;
265 unsigned long arg3;
266 (void) p_arg;
267 ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 1, &arg2);
268 if (ret != 0)
270 return ret;
272 ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 2, &arg3);
273 if (ret != 0)
275 return ret;
277 if (arg2 != SOL_SOCKET || arg3 != SO_ERROR)
279 return -1;
281 return 0;
284 static int
285 setsockopt_validator(struct pt_sandbox* p_sandbox, void* p_arg)
287 int ret;
288 unsigned long arg2;
289 unsigned long arg3;
290 (void) p_arg;
291 ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 1, &arg2);
292 if (ret != 0)
294 return ret;
296 ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 2, &arg3);
297 if (ret != 0)
299 return ret;
301 if (arg2 == SOL_SOCKET)
303 if (arg3 != SO_KEEPALIVE &&
304 arg3 != SO_REUSEADDR &&
305 arg3 != SO_OOBINLINE &&
306 arg3 != SO_LINGER)
308 return -1;
311 else if (arg2 == IPPROTO_TCP)
313 if (arg3 != TCP_NODELAY)
315 return -2;
318 else if (arg2 == IPPROTO_IP)
320 if (arg3 != IP_TOS)
322 return -3;
325 else
327 return -4;
329 return 0;