2 * Part of Very Secure FTPd
7 * Code to build a sandbox policy based on current session options.
10 #include "ftppolicy.h"
11 #include "ptracesandbox.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
);
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
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
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);
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
,
107 ptrace_sandbox_permit_bind(p_sandbox
);
108 /* Yes, reuse of the connect validator is intentional. */
109 ptrace_sandbox_set_bind_validator(p_sandbox
,
112 if (tunable_port_enable
)
114 ptrace_sandbox_permit_connect(p_sandbox
);
115 ptrace_sandbox_set_connect_validator(p_sandbox
,
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
);
161 socket_validator(struct pt_sandbox
* p_sandbox
, void* p_arg
)
164 struct vsf_session
* p_sess
= (struct vsf_session
*) p_arg
;
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
);
177 ret
= ptrace_sandbox_get_socketcall_arg(p_sandbox
, 1, &arg2
);
182 if (arg1
!= expected_family
|| arg2
!= SOCK_STREAM
)
190 connect_validator(struct pt_sandbox
* p_sandbox
, void* p_arg
)
193 struct vsf_session
* p_sess
= (struct vsf_session
*) p_arg
;
196 unsigned long expected_family
= AF_INET
;
197 unsigned long expected_len
= sizeof(struct sockaddr_in
);
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
);
211 ret
= ptrace_sandbox_get_socketcall_arg(p_sandbox
, 2, &arg3
);
216 if (arg3
!= expected_len
)
220 p_buf
= vsf_sysutil_malloc((int) expected_len
);
221 ret
= ptrace_sandbox_get_buf(p_sandbox
, arg2
, expected_len
, p_buf
);
224 vsf_sysutil_free(p_buf
);
227 p_sockaddr
= (struct sockaddr
*) p_buf
;
228 if (p_sockaddr
->sa_family
!= expected_family
)
230 vsf_sysutil_free(p_buf
);
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
);
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
);
254 vsf_sysutil_free(p_buf
);
259 getsockopt_validator(struct pt_sandbox
* p_sandbox
, void* p_arg
)
265 ret
= ptrace_sandbox_get_socketcall_arg(p_sandbox
, 1, &arg2
);
270 ret
= ptrace_sandbox_get_socketcall_arg(p_sandbox
, 2, &arg3
);
275 if (arg2
!= SOL_SOCKET
|| arg3
!= SO_ERROR
)
283 setsockopt_validator(struct pt_sandbox
* p_sandbox
, void* p_arg
)
289 ret
= ptrace_sandbox_get_socketcall_arg(p_sandbox
, 1, &arg2
);
294 ret
= ptrace_sandbox_get_socketcall_arg(p_sandbox
, 2, &arg3
);
299 if (arg2
== SOL_SOCKET
)
301 if (arg3
!= SO_KEEPALIVE
&&
302 arg3
!= SO_REUSEADDR
&&
303 arg3
!= SO_OOBINLINE
&&
309 else if (arg2
== IPPROTO_TCP
)
311 if (arg3
!= TCP_NODELAY
)
316 else if (arg2
== IPPROTO_IP
)