1/* 2 * This program is free software; you can redistribute it and/or 3 * modify it under the terms of the GNU General Public License as 4 * published by the Free Software Foundation; either version 2 of 5 * the License, or (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software 14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 15 * MA 02111-1307 USA 16 */ 17/* 18 * Part of Very Secure FTPd 19 * Licence: GPL v2 20 * Author: Chris Evans 21 * secutil.c 22 */ 23 24#include "secutil.h" 25#include "str.h" 26#include "sysutil.h" 27#include "sysstr.h" 28#include "utility.h" 29#include "sysdeputil.h" 30 31void 32vsf_secutil_change_credentials(const struct mystr* p_user_str, 33 const struct mystr* p_dir_str, 34 const struct mystr* p_ext_dir_str, 35 unsigned int caps, unsigned int options) 36{ 37 struct vsf_sysutil_user* p_user; 38 if (!vsf_sysutil_running_as_root()) 39 { 40 bug("vsf_secutil_change_credentials: not running as root"); 41 } 42 43 p_user = str_getpwnam(p_user_str); 44 45 if (p_user == 0) 46 { 47 die2("cannot locate user entry:", str_getbuf(p_user_str)); 48 } 49 { 50 51 struct mystr dir_str = INIT_MYSTR; 52 /* Work out where the chroot() jail is */ 53 if (p_dir_str == 0 || str_isempty(p_dir_str)) 54 { 55 str_alloc_text(&dir_str, vsf_sysutil_user_get_homedir(p_user)); 56 } 57 else 58 { 59 str_copy(&dir_str, p_dir_str); 60 } 61 62 /* Sort out supplementary groups before the chroot(). We need to access 63 * /etc/groups 64 */ 65 if (options & VSF_SECUTIL_OPTION_USE_GROUPS) 66 { 67 vsf_sysutil_initgroups(p_user); 68 } 69 else 70 { 71 vsf_sysutil_clear_supp_groups(); 72 } 73 74 /* Always do the chdir() regardless of whether we are chroot()'ing */ 75 { 76 /* Do chdir() with the target effective IDs to cater for NFS mounted 77 * home directories. 78 */ 79 int saved_euid = 0; 80 int saved_egid = 0; 81 int retval; 82 if (options & VSF_SECUTIL_OPTION_CHANGE_EUID) 83 { 84 saved_euid = vsf_sysutil_geteuid(); 85 saved_egid = vsf_sysutil_getegid(); 86 vsf_sysutil_setegid(p_user); 87 vsf_sysutil_seteuid(p_user); 88 } 89 90 retval = str_chdir(&dir_str); 91 92 if (retval != 0) 93 { 94 die2("cannot change directory:", str_getbuf(&dir_str)); 95 } 96 if (p_ext_dir_str && !str_isempty(p_ext_dir_str)) 97 { 98 retval = str_chdir(p_ext_dir_str); 99 100 /* Failure on the extra directory is OK as long as we're not in 101 * chroot() mode 102 */ 103 if (retval != 0 && !(options & VSF_SECUTIL_OPTION_CHROOT)) 104 { 105 retval = 0; 106 } 107 } 108 109 if (retval != 0) 110 { 111 die2("cannot change directory:", str_getbuf(p_ext_dir_str)); 112 } 113 if (options & VSF_SECUTIL_OPTION_CHANGE_EUID) 114 { 115 vsf_sysutil_seteuid_numeric(saved_euid); 116 vsf_sysutil_setegid_numeric(saved_egid); 117 } 118 119// 2007.05 James { 120 /* Do the chroot() if required */ 121 //if (options & VSF_SECUTIL_OPTION_CHROOT) 122 //{ 123 // vsf_sysutil_chroot("."); 124 //} 125// 2007.05 James } 126 } 127 str_free(&dir_str); 128 } 129 /* Handle capabilities */ 130 if (caps) 131 { 132 if (!vsf_sysdep_has_capabilities()) 133 { 134 /* Need privilege but OS has no capabilities - have to keep root */ 135 return; 136 } 137 if (!vsf_sysdep_has_capabilities_as_non_root()) 138 { 139 vsf_sysdep_adopt_capabilities(caps); 140 return; 141 } 142 vsf_sysdep_keep_capabilities(); 143 } 144 145 /* Set group id */ 146 vsf_sysutil_setgid(p_user); 147 /* Finally set user id */ 148 vsf_sysutil_setuid(p_user); 149 150 if (caps) 151 { 152 vsf_sysdep_adopt_capabilities(caps); 153 } 154} 155 156