vsftpd 3.0.2
[tomato/tomato-dir865l.git] / release / src / router / vsftpd / ftppolicy.c
blob9aea20b5aaacf5552b418e7ad7f2bb435a830910
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 /* Reading FTP commands from the network. */
45 ptrace_sandbox_permit_recv(p_sandbox);
46 /* Querying time is harmless; used for log timestamps and internally to
47 * OpenSSL
49 ptrace_sandbox_permit_query_time(p_sandbox);
51 /* Typically post-login things follow. */
52 /* Since we're in a chroot(), we can just blanket allow filesystem readonly
53 * open.
55 ptrace_sandbox_permit_open(p_sandbox, 0);
56 ptrace_sandbox_permit_close(p_sandbox);
57 /* Other pathname-based metadata queries. */
58 ptrace_sandbox_permit_file_stats(p_sandbox);
59 ptrace_sandbox_permit_readlink(p_sandbox);
60 /* Querying, reading and changing directory. */
61 ptrace_sandbox_permit_getcwd(p_sandbox);
62 ptrace_sandbox_permit_chdir(p_sandbox);
63 ptrace_sandbox_permit_getdents(p_sandbox);
64 /* Simple fd-based operations. */
65 ptrace_sandbox_permit_fd_stats(p_sandbox);
66 ptrace_sandbox_permit_seek(p_sandbox);
67 ptrace_sandbox_permit_shutdown(p_sandbox);
68 ptrace_sandbox_permit_fcntl(p_sandbox);
69 ptrace_sandbox_permit_setsockopt(p_sandbox);
70 ptrace_sandbox_set_setsockopt_validator(p_sandbox, setsockopt_validator, 0);
71 /* Misc */
72 /* Setting umask. */
73 ptrace_sandbox_permit_umask(p_sandbox);
74 /* Select for data connection readyness. */
75 ptrace_sandbox_permit_select(p_sandbox);
76 /* Always need ability to take signals (SIGPIPE) */
77 ptrace_sandbox_permit_sigreturn(p_sandbox);
78 /* Sleeping (bandwidth limit, connect retires, anon login fails) */
79 ptrace_sandbox_permit_sleep(p_sandbox);
80 /* High-speed transfers... */
81 ptrace_sandbox_permit_sendfile(p_sandbox);
82 /* TODO - Grrrr! nscd cache access is leaking into child. Need to find out
83 * out how to disable that. Also means that text_userdb_names loads values
84 * from the real system data.
86 if (tunable_text_userdb_names)
88 ptrace_sandbox_permit_mremap(p_sandbox);
90 /* May need ability to install signal handlers. */
91 if (tunable_async_abor_enable ||
92 tunable_idle_session_timeout > 0 ||
93 tunable_data_connection_timeout > 0)
95 ptrace_sandbox_permit_sigaction(p_sandbox);
97 /* May need ability to set up timeout alarms. */
98 if (tunable_idle_session_timeout > 0 || tunable_data_connection_timeout > 0)
100 ptrace_sandbox_permit_alarm(p_sandbox);
102 /* Set up network permissions according to config and session. */
103 ptrace_sandbox_permit_socket(p_sandbox);
104 ptrace_sandbox_set_socket_validator(p_sandbox,
105 socket_validator,
106 (void*) p_sess);
107 ptrace_sandbox_permit_bind(p_sandbox);
108 /* Yes, reuse of the connect validator is intentional. */
109 ptrace_sandbox_set_bind_validator(p_sandbox,
110 connect_validator,
111 (void*) p_sess);
112 if (tunable_port_enable)
114 ptrace_sandbox_permit_connect(p_sandbox);
115 ptrace_sandbox_set_connect_validator(p_sandbox,
116 connect_validator,
117 (void*) p_sess);
118 ptrace_sandbox_permit_getsockopt(p_sandbox);
119 ptrace_sandbox_set_getsockopt_validator(p_sandbox, getsockopt_validator, 0);
121 if (tunable_pasv_enable)
123 ptrace_sandbox_permit_listen(p_sandbox);
124 ptrace_sandbox_permit_accept(p_sandbox);
126 /* Set up write permissions according to config and session. */
127 if (tunable_write_enable)
129 if (!is_anon || tunable_anon_upload_enable)
131 ptrace_sandbox_permit_open(p_sandbox, 1);
133 if (!is_anon || tunable_anon_mkdir_write_enable)
135 ptrace_sandbox_permit_mkdir(p_sandbox);
137 if (!is_anon || tunable_anon_other_write_enable)
139 ptrace_sandbox_permit_unlink(p_sandbox);
140 ptrace_sandbox_permit_rmdir(p_sandbox);
141 ptrace_sandbox_permit_rename(p_sandbox);
142 ptrace_sandbox_permit_ftruncate(p_sandbox);
143 if (tunable_mdtm_write)
145 ptrace_sandbox_permit_utime(p_sandbox);
148 if (!is_anon && tunable_chmod_enable)
150 ptrace_sandbox_permit_chmod(p_sandbox);
152 if (is_anon && tunable_chown_uploads)
154 ptrace_sandbox_permit_fchmod(p_sandbox);
155 ptrace_sandbox_permit_fchown(p_sandbox);
160 static int
161 socket_validator(struct pt_sandbox* p_sandbox, void* p_arg)
163 int ret;
164 struct vsf_session* p_sess = (struct vsf_session*) p_arg;
165 unsigned long arg1;
166 unsigned long arg2;
167 unsigned long expected_family = AF_INET;
168 if (vsf_sysutil_sockaddr_is_ipv6(p_sess->p_local_addr))
170 expected_family = AF_INET6;
172 ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 0, &arg1);
173 if (ret != 0)
175 return ret;
177 ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 1, &arg2);
178 if (ret != 0)
180 return ret;
182 if (arg1 != expected_family || arg2 != SOCK_STREAM)
184 return -1;
186 return 0;
189 static int
190 connect_validator(struct pt_sandbox* p_sandbox, void* p_arg)
192 int ret;
193 struct vsf_session* p_sess = (struct vsf_session*) p_arg;
194 unsigned long arg2;
195 unsigned long arg3;
196 unsigned long expected_family = AF_INET;
197 unsigned long expected_len = sizeof(struct sockaddr_in);
198 void* p_buf = 0;
199 struct sockaddr* p_sockaddr;
200 static struct vsf_sysutil_sockaddr* p_sockptr;
201 if (vsf_sysutil_sockaddr_is_ipv6(p_sess->p_local_addr))
203 expected_family = AF_INET6;
204 expected_len = sizeof(struct sockaddr_in6);
206 ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 1, &arg2);
207 if (ret != 0)
209 return ret;
211 ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 2, &arg3);
212 if (ret != 0)
214 return ret;
216 if (arg3 != expected_len)
218 return -1;
220 p_buf = vsf_sysutil_malloc((int) expected_len);
221 ret = ptrace_sandbox_get_buf(p_sandbox, arg2, expected_len, p_buf);
222 if (ret != 0)
224 vsf_sysutil_free(p_buf);
225 return -2;
227 p_sockaddr = (struct sockaddr*) p_buf;
228 if (p_sockaddr->sa_family != expected_family)
230 vsf_sysutil_free(p_buf);
231 return -3;
233 if (expected_family == AF_INET)
235 struct sockaddr_in* p_sockaddr_in = (struct sockaddr_in*) p_sockaddr;
236 vsf_sysutil_sockaddr_alloc_ipv4(&p_sockptr);
237 vsf_sysutil_sockaddr_set_ipv4addr(p_sockptr,
238 (const unsigned char*)
239 &p_sockaddr_in->sin_addr);
241 else
243 struct sockaddr_in6* p_sockaddr_in6 = (struct sockaddr_in6*) p_sockaddr;
244 vsf_sysutil_sockaddr_alloc_ipv6(&p_sockptr);
245 vsf_sysutil_sockaddr_set_ipv6addr(p_sockptr,
246 (const unsigned char*)
247 &p_sockaddr_in6->sin6_addr);
249 if (!vsf_sysutil_sockaddr_addr_equal(p_sess->p_remote_addr, p_sockptr))
251 vsf_sysutil_free(p_buf);
252 return -4;
254 vsf_sysutil_free(p_buf);
255 return 0;
258 static int
259 getsockopt_validator(struct pt_sandbox* p_sandbox, void* p_arg)
261 int ret;
262 unsigned long arg2;
263 unsigned long arg3;
264 (void) p_arg;
265 ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 1, &arg2);
266 if (ret != 0)
268 return ret;
270 ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 2, &arg3);
271 if (ret != 0)
273 return ret;
275 if (arg2 != SOL_SOCKET || arg3 != SO_ERROR)
277 return -1;
279 return 0;
282 static int
283 setsockopt_validator(struct pt_sandbox* p_sandbox, void* p_arg)
285 int ret;
286 unsigned long arg2;
287 unsigned long arg3;
288 (void) p_arg;
289 ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 1, &arg2);
290 if (ret != 0)
292 return ret;
294 ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 2, &arg3);
295 if (ret != 0)
297 return ret;
299 if (arg2 == SOL_SOCKET)
301 if (arg3 != SO_KEEPALIVE &&
302 arg3 != SO_REUSEADDR &&
303 arg3 != SO_OOBINLINE &&
304 arg3 != SO_LINGER)
306 return -1;
309 else if (arg2 == IPPROTO_TCP)
311 if (arg3 != TCP_NODELAY)
313 return -2;
316 else if (arg2 == IPPROTO_IP)
318 if (arg3 != IP_TOS)
320 return -3;
323 else
325 return -4;
327 return 0;