vsftpd 2.0.7 - initial checkin.
[tomato.git] / release / src / router / vsftpd / secutil.c
blob3506bb807d7dc964825f30df46f06e6632754e37
1 /*
2 * Part of Very Secure FTPd
3 * Licence: GPL v2
4 * Author: Chris Evans
5 * secutil.c
6 */
8 #include "secutil.h"
9 #include "str.h"
10 #include "sysutil.h"
11 #include "sysstr.h"
12 #include "utility.h"
13 #include "sysdeputil.h"
15 void
16 vsf_secutil_change_credentials(const struct mystr* p_user_str,
17 const struct mystr* p_dir_str,
18 const struct mystr* p_ext_dir_str,
19 unsigned int caps, unsigned int options)
21 struct vsf_sysutil_user* p_user;
22 if (!vsf_sysutil_running_as_root())
24 bug("vsf_secutil_change_credentials: not running as root");
26 p_user = str_getpwnam(p_user_str);
27 if (p_user == 0)
29 die2("cannot locate user entry:", str_getbuf(p_user_str));
32 struct mystr dir_str = INIT_MYSTR;
33 /* Work out where the chroot() jail is */
34 if (p_dir_str == 0 || str_isempty(p_dir_str))
36 str_alloc_text(&dir_str, vsf_sysutil_user_get_homedir(p_user));
38 else
40 str_copy(&dir_str, p_dir_str);
42 /* Sort out supplementary groups before the chroot(). We need to access
43 * /etc/groups
45 if (options & VSF_SECUTIL_OPTION_USE_GROUPS)
47 vsf_sysutil_initgroups(p_user);
49 else
51 vsf_sysutil_clear_supp_groups();
53 /* Always do the chdir() regardless of whether we are chroot()'ing */
55 /* Do chdir() with the target effective IDs to cater for NFS mounted
56 * home directories.
58 int saved_euid = 0;
59 int saved_egid = 0;
60 int retval;
61 if (options & VSF_SECUTIL_OPTION_CHANGE_EUID)
63 saved_euid = vsf_sysutil_geteuid();
64 saved_egid = vsf_sysutil_getegid();
65 vsf_sysutil_setegid(p_user);
66 vsf_sysutil_seteuid(p_user);
68 retval = str_chdir(&dir_str);
69 if (retval != 0)
71 die2("cannot change directory:", str_getbuf(&dir_str));
73 if (p_ext_dir_str && !str_isempty(p_ext_dir_str))
75 retval = str_chdir(p_ext_dir_str);
76 /* Failure on the extra directory is OK as long as we're not in
77 * chroot() mode
79 if (retval != 0 && !(options & VSF_SECUTIL_OPTION_CHROOT))
81 retval = 0;
84 if (retval != 0)
86 die2("cannot change directory:", str_getbuf(p_ext_dir_str));
88 if (options & VSF_SECUTIL_OPTION_CHANGE_EUID)
90 vsf_sysutil_seteuid_numeric(saved_euid);
91 vsf_sysutil_setegid_numeric(saved_egid);
93 /* Do the chroot() if required */
94 if (options & VSF_SECUTIL_OPTION_CHROOT)
96 vsf_sysutil_chroot(".");
99 str_free(&dir_str);
101 /* Handle capabilities */
102 if (caps)
104 if (!vsf_sysdep_has_capabilities())
106 /* Need privilege but OS has no capabilities - have to keep root */
107 return;
109 if (!vsf_sysdep_has_capabilities_as_non_root())
111 vsf_sysdep_adopt_capabilities(caps);
112 return;
114 vsf_sysdep_keep_capabilities();
116 /* Set group id */
117 vsf_sysutil_setgid(p_user);
118 /* Finally set user id */
119 vsf_sysutil_setuid(p_user);
120 if (caps)
122 vsf_sysdep_adopt_capabilities(caps);