Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / vsftpd / postprivparent.c
blobc2a0c9339bfd097b7c6bfb28706e61dc3dfae61f
1 /*
2 * Part of Very Secure FTPd
3 * Licence: GPL v2
4 * Author: Chris Evans
5 * postprivparent.c
7 * This file contains all privileged parent services offered after logging
8 * in. This includes e.g. chown() of uploaded files, issuing of port 20
9 * sockets.
12 #include "postprivparent.h"
13 #include "session.h"
14 #include "privops.h"
15 #include "privsock.h"
16 #include "utility.h"
17 #include "tunables.h"
18 #include "defs.h"
19 #include "sysutil.h"
20 #include "str.h"
21 #include "secutil.h"
22 #include "sysstr.h"
23 #include "sysdeputil.h"
25 static void minimize_privilege(struct vsf_session* p_sess);
26 static void process_post_login_req(struct vsf_session* p_sess);
27 static void cmd_process_chown(struct vsf_session* p_sess);
28 static void cmd_process_get_data_sock(struct vsf_session* p_sess);
29 static void cmd_process_pasv_cleanup(struct vsf_session* p_sess);
30 static void cmd_process_pasv_active(struct vsf_session* p_sess);
31 static void cmd_process_pasv_listen(struct vsf_session* p_sess);
32 static void cmd_process_pasv_accept(struct vsf_session* p_sess);
34 void
35 vsf_priv_parent_postlogin(struct vsf_session* p_sess)
37 minimize_privilege(p_sess);
38 /* We're still here... */
39 while (1)
41 process_post_login_req(p_sess);
45 static void
46 process_post_login_req(struct vsf_session* p_sess)
48 char cmd;
49 /* Blocks */
50 cmd = priv_sock_get_cmd(p_sess->parent_fd);
51 if (tunable_chown_uploads && cmd == PRIV_SOCK_CHOWN)
53 cmd_process_chown(p_sess);
55 else if (cmd == PRIV_SOCK_GET_DATA_SOCK)
57 cmd_process_get_data_sock(p_sess);
59 else if (cmd == PRIV_SOCK_PASV_CLEANUP)
61 cmd_process_pasv_cleanup(p_sess);
63 else if (cmd == PRIV_SOCK_PASV_ACTIVE)
65 cmd_process_pasv_active(p_sess);
67 else if (cmd == PRIV_SOCK_PASV_LISTEN)
69 cmd_process_pasv_listen(p_sess);
71 else if (cmd == PRIV_SOCK_PASV_ACCEPT)
73 cmd_process_pasv_accept(p_sess);
75 else
77 die("bad request in process_post_login_req");
81 static void
82 minimize_privilege(struct vsf_session* p_sess)
84 /* So, we logged in and forked a totally unprivileged child. Our job
85 * now is to minimize the privilege we need in order to act as a helper
86 * to the child.
88 if (!p_sess->is_anonymous && tunable_session_support)
90 /* Need to hang around to update logs, utmp, wtmp etc. on logout.
91 * Need to keep privs to do this. */
92 return;
95 unsigned int caps = 0;
96 struct mystr user_str = INIT_MYSTR;
97 struct mystr dir_str = INIT_MYSTR;
98 str_alloc_text(&user_str, tunable_nopriv_user);
99 str_alloc_text(&dir_str, tunable_secure_chroot_dir);
100 if (tunable_chown_uploads)
102 caps |= kCapabilityCAP_CHOWN;
104 if (tunable_connect_from_port_20)
106 caps |= kCapabilityCAP_NET_BIND_SERVICE;
108 vsf_secutil_change_credentials(&user_str, &dir_str, 0, caps,
109 VSF_SECUTIL_OPTION_CHROOT);
110 str_free(&user_str);
111 str_free(&dir_str);
115 static void
116 cmd_process_chown(struct vsf_session* p_sess)
118 int the_fd = priv_sock_recv_fd(p_sess->parent_fd);
119 vsf_privop_do_file_chown(p_sess, the_fd);
120 vsf_sysutil_close(the_fd);
121 priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK);
124 static void
125 cmd_process_get_data_sock(struct vsf_session* p_sess)
127 unsigned short port = (unsigned short) priv_sock_get_int(p_sess->parent_fd);
128 int sock_fd = vsf_privop_get_ftp_port_sock(p_sess, port, 0);
129 if (sock_fd == -1)
131 priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_BAD);
132 return;
134 priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK);
135 priv_sock_send_fd(p_sess->parent_fd, sock_fd);
136 vsf_sysutil_close(sock_fd);
139 static void
140 cmd_process_pasv_cleanup(struct vsf_session* p_sess)
142 vsf_privop_pasv_cleanup(p_sess);
143 priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK);
146 static void
147 cmd_process_pasv_active(struct vsf_session* p_sess)
149 int active = vsf_privop_pasv_active(p_sess);
150 priv_sock_send_int(p_sess->parent_fd, active);
153 static void
154 cmd_process_pasv_listen(struct vsf_session* p_sess)
156 unsigned short port = vsf_privop_pasv_listen(p_sess);
157 priv_sock_send_int(p_sess->parent_fd, port);
160 static void
161 cmd_process_pasv_accept(struct vsf_session* p_sess)
163 int fd = vsf_privop_accept_pasv(p_sess);
164 if (fd < 0)
166 priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_BAD);
167 priv_sock_send_int(p_sess->parent_fd, fd);
168 return;
170 priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK);
171 priv_sock_send_fd(p_sess->parent_fd, fd);
172 vsf_sysutil_close(fd);