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 /* Querying time is harmless; used for log timestamps and internally to
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
);
57 ptrace_sandbox_permit_umask(p_sandbox
);
58 /* Since we're in a chroot(), we can just blanket allow filesystem readonly
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
);
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
,
106 ptrace_sandbox_permit_bind(p_sandbox
);
107 /* Yes, reuse of the connect validator is intentional. */
108 ptrace_sandbox_set_bind_validator(p_sandbox
,
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
,
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
);
163 socket_validator(struct pt_sandbox
* p_sandbox
, void* p_arg
)
166 struct vsf_session
* p_sess
= (struct vsf_session
*) p_arg
;
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
);
179 ret
= ptrace_sandbox_get_socketcall_arg(p_sandbox
, 1, &arg2
);
184 if (arg1
!= expected_family
|| arg2
!= SOCK_STREAM
)
192 connect_validator(struct pt_sandbox
* p_sandbox
, void* p_arg
)
195 struct vsf_session
* p_sess
= (struct vsf_session
*) p_arg
;
198 unsigned long expected_family
= AF_INET
;
199 unsigned long expected_len
= sizeof(struct sockaddr_in
);
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
);
213 ret
= ptrace_sandbox_get_socketcall_arg(p_sandbox
, 2, &arg3
);
218 if (arg3
!= expected_len
)
222 p_buf
= vsf_sysutil_malloc((int) expected_len
);
223 ret
= ptrace_sandbox_get_buf(p_sandbox
, arg2
, expected_len
, p_buf
);
226 vsf_sysutil_free(p_buf
);
229 p_sockaddr
= (struct sockaddr
*) p_buf
;
230 if (p_sockaddr
->sa_family
!= expected_family
)
232 vsf_sysutil_free(p_buf
);
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
);
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
);
256 vsf_sysutil_free(p_buf
);
261 getsockopt_validator(struct pt_sandbox
* p_sandbox
, void* p_arg
)
267 ret
= ptrace_sandbox_get_socketcall_arg(p_sandbox
, 1, &arg2
);
272 ret
= ptrace_sandbox_get_socketcall_arg(p_sandbox
, 2, &arg3
);
277 if (arg2
!= SOL_SOCKET
|| arg3
!= SO_ERROR
)
285 setsockopt_validator(struct pt_sandbox
* p_sandbox
, void* p_arg
)
291 ret
= ptrace_sandbox_get_socketcall_arg(p_sandbox
, 1, &arg2
);
296 ret
= ptrace_sandbox_get_socketcall_arg(p_sandbox
, 2, &arg3
);
301 if (arg2
== SOL_SOCKET
)
303 if (arg3
!= SO_KEEPALIVE
&&
304 arg3
!= SO_REUSEADDR
&&
305 arg3
!= SO_OOBINLINE
&&
311 else if (arg2
== IPPROTO_TCP
)
313 if (arg3
!= TCP_NODELAY
)
318 else if (arg2
== IPPROTO_IP
)