vsftpd 3.0.2
[tomato/tomato-dir865l.git] / release / src / router / vsftpd / oneprocess.c
bloba3cbfe6555d80c7ace60498459285bc64c369bc5
1 /*
2 * Part of Very Secure FTPd
3 * Licence: GPL v2
4 * Author: Chris Evans
5 * oneprocess.c
7 * Code for the "one process" security model. The one process security model
8 * is born for the purposes of raw speed at the expense of compromising the
9 * purity of the security model.
10 * The one process model will typically be disabled, for security reasons.
11 * Only sites with huge numbers of concurrent users are likely to feel the
12 * pain of two processes per session.
15 #include "prelogin.h"
16 #include "postlogin.h"
17 #include "privops.h"
18 #include "session.h"
19 #include "secutil.h"
20 #include "str.h"
21 #include "tunables.h"
22 #include "utility.h"
23 #include "sysstr.h"
24 #include "sysdeputil.h"
25 #include "sysutil.h"
26 #include "ptracesandbox.h"
27 #include "ftppolicy.h"
28 #include "seccompsandbox.h"
30 static void one_process_start(void* p_arg);
32 void
33 vsf_one_process_start(struct vsf_session* p_sess)
35 if (tunable_ptrace_sandbox)
37 struct pt_sandbox* p_sandbox = ptrace_sandbox_alloc();
38 if (p_sandbox == 0)
40 die("could not allocate sandbox (only works for 32-bit builds)");
42 policy_setup(p_sandbox, p_sess);
43 if (ptrace_sandbox_launch_process(p_sandbox,
44 one_process_start,
45 (void*) p_sess) <= 0)
47 die("could not launch sandboxed child");
49 /* TODO - could drop privs here. For now, run as root as the attack surface
50 * is negligible, and running as root permits us to correctly deliver the
51 * parent death signal upon unexpected crash.
53 (void) ptrace_sandbox_run_processes(p_sandbox);
54 ptrace_sandbox_free(p_sandbox);
55 vsf_sysutil_exit(0);
57 else
59 one_process_start((void*) p_sess);
63 static void
64 one_process_start(void* p_arg)
66 struct vsf_session* p_sess = (struct vsf_session*) p_arg;
67 unsigned int caps = 0;
68 if (tunable_chown_uploads)
70 caps |= kCapabilityCAP_CHOWN;
72 if (tunable_connect_from_port_20)
74 caps |= kCapabilityCAP_NET_BIND_SERVICE;
77 struct mystr user_name = INIT_MYSTR;
78 struct mystr chdir_str = INIT_MYSTR;
79 if (tunable_ftp_username)
81 str_alloc_text(&user_name, tunable_ftp_username);
83 if (tunable_anon_root)
85 str_alloc_text(&chdir_str, tunable_anon_root);
87 if (tunable_run_as_launching_user)
89 if (!str_isempty(&chdir_str))
91 str_chdir(&chdir_str);
94 else
96 vsf_secutil_change_credentials(&user_name, 0, &chdir_str, caps,
97 VSF_SECUTIL_OPTION_CHROOT |
98 VSF_SECUTIL_OPTION_USE_GROUPS |
99 VSF_SECUTIL_OPTION_NO_PROCS);
101 str_free(&user_name);
102 str_free(&chdir_str);
104 if (tunable_ptrace_sandbox)
106 ptrace_sandbox_attach_point();
108 seccomp_sandbox_init();
109 seccomp_sandbox_setup_postlogin(p_sess);
110 seccomp_sandbox_lockdown();
111 init_connection(p_sess);
114 void
115 vsf_one_process_login(struct vsf_session* p_sess,
116 const struct mystr* p_pass_str)
118 enum EVSFPrivopLoginResult login_result =
119 vsf_privop_do_login(p_sess, p_pass_str);
120 switch (login_result)
122 case kVSFLoginFail:
123 return;
124 break;
125 case kVSFLoginAnon:
126 p_sess->is_anonymous = 1;
127 process_post_login(p_sess);
128 break;
129 case kVSFLoginNull:
130 /* Fall through. */
131 case kVSFLoginReal:
132 /* Fall through. */
133 default:
134 bug("bad state in vsf_one_process_login");
135 break;
140 vsf_one_process_get_priv_data_sock(struct vsf_session* p_sess)
142 unsigned short port = vsf_sysutil_sockaddr_get_port(p_sess->p_port_sockaddr);
143 return vsf_privop_get_ftp_port_sock(p_sess, port, 1);
146 void
147 vsf_one_process_pasv_cleanup(struct vsf_session* p_sess)
149 vsf_privop_pasv_cleanup(p_sess);
153 vsf_one_process_pasv_active(struct vsf_session* p_sess)
155 return vsf_privop_pasv_active(p_sess);
158 unsigned short
159 vsf_one_process_listen(struct vsf_session* p_sess)
161 return vsf_privop_pasv_listen(p_sess);
165 vsf_one_process_get_pasv_fd(struct vsf_session* p_sess)
167 return vsf_privop_accept_pasv(p_sess);
170 void
171 vsf_one_process_chown_upload(struct vsf_session* p_sess, int fd)
173 vsf_privop_do_file_chown(p_sess, fd);