vsftpd 2.0.7 - initial checkin.
[tomato.git] / release / src / router / vsftpd / postprivparent.c
blobd47f99eaba3b8af2e2dc5bada00ed6bc3b7df205
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);
30 void
31 vsf_priv_parent_postlogin(struct vsf_session* p_sess)
33 minimize_privilege(p_sess);
34 /* We're still here... */
35 while (1)
37 process_post_login_req(p_sess);
41 static void
42 process_post_login_req(struct vsf_session* p_sess)
44 char cmd;
45 vsf_sysutil_unblock_sig(kVSFSysUtilSigCHLD);
46 /* Blocks */
47 cmd = priv_sock_get_cmd(p_sess->parent_fd);
48 vsf_sysutil_block_sig(kVSFSysUtilSigCHLD);
49 if (tunable_chown_uploads && cmd == PRIV_SOCK_CHOWN)
51 cmd_process_chown(p_sess);
53 else if (tunable_connect_from_port_20 && cmd == PRIV_SOCK_GET_DATA_SOCK)
55 cmd_process_get_data_sock(p_sess);
57 else
59 die("bad request in process_post_login_req");
63 static void
64 minimize_privilege(struct vsf_session* p_sess)
66 /* So, we logged in and forked a totally unprivileged child. Our job
67 * now is to minimize the privilege we need in order to act as a helper
68 * to the child.
70 * In some happy circumstances, we can exit and be done with root
71 * altogether.
73 if (!p_sess->is_anonymous && tunable_session_support)
75 /* Need to hang around to update logs, utmp, wtmp etc. on logout.
76 * Need to keep privs to do this. */
77 return;
79 if (!tunable_chown_uploads && !tunable_connect_from_port_20 &&
80 !tunable_max_per_ip && !tunable_max_clients)
82 /* Cool. We're outta here. */
83 vsf_sysutil_exit(0);
86 unsigned int caps = 0;
87 struct mystr user_str = INIT_MYSTR;
88 struct mystr dir_str = INIT_MYSTR;
89 str_alloc_text(&user_str, tunable_nopriv_user);
90 str_alloc_text(&dir_str, tunable_secure_chroot_dir);
91 if (tunable_chown_uploads)
93 caps |= kCapabilityCAP_CHOWN;
95 if (tunable_connect_from_port_20)
97 caps |= kCapabilityCAP_NET_BIND_SERVICE;
99 vsf_secutil_change_credentials(&user_str, &dir_str, 0, caps,
100 VSF_SECUTIL_OPTION_CHROOT);
101 str_free(&user_str);
102 str_free(&dir_str);
106 static void
107 cmd_process_chown(struct vsf_session* p_sess)
109 int the_fd = priv_sock_recv_fd(p_sess->parent_fd);
110 vsf_privop_do_file_chown(p_sess, the_fd);
111 vsf_sysutil_close(the_fd);
112 priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK);
115 static void
116 cmd_process_get_data_sock(struct vsf_session* p_sess)
118 int sock_fd = vsf_privop_get_ftp_port_sock(p_sess);
119 priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK);
120 priv_sock_send_fd(p_sess->parent_fd, sock_fd);
121 vsf_sysutil_close(sock_fd);