1/* 2 * Part of Very Secure FTPd 3 * Licence: GPL v2 4 * Author: Chris Evans 5 * secutil.c 6 */ 7 8#include "secutil.h" 9#include "str.h" 10#include "sysutil.h" 11#include "sysstr.h" 12#include "utility.h" 13#include "sysdeputil.h" 14 15void 16vsf_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) 20{ 21 struct vsf_sysutil_user* p_user; 22 if (!vsf_sysutil_running_as_root()) 23 { 24 bug("vsf_secutil_change_credentials: not running as root"); 25 } 26 27 p_user = str_getpwnam(p_user_str); 28 29 if (p_user == 0) 30 { 31 die2("cannot locate user entry:", str_getbuf(p_user_str)); 32 } 33 { 34 35 struct mystr dir_str = INIT_MYSTR; 36 /* Work out where the chroot() jail is */ 37 if (p_dir_str == 0 || str_isempty(p_dir_str)) 38 { 39 str_alloc_text(&dir_str, vsf_sysutil_user_get_homedir(p_user)); 40 } 41 else 42 { 43 str_copy(&dir_str, p_dir_str); 44 } 45 46 /* Sort out supplementary groups before the chroot(). We need to access 47 * /etc/groups 48 */ 49 if (options & VSF_SECUTIL_OPTION_USE_GROUPS) 50 { 51 vsf_sysutil_initgroups(p_user); 52 } 53 else 54 { 55 vsf_sysutil_clear_supp_groups(); 56 } 57 58 /* Always do the chdir() regardless of whether we are chroot()'ing */ 59 { 60 /* Do chdir() with the target effective IDs to cater for NFS mounted 61 * home directories. 62 */ 63 int saved_euid = 0; 64 int saved_egid = 0; 65 int retval; 66 if (options & VSF_SECUTIL_OPTION_CHANGE_EUID) 67 { 68 saved_euid = vsf_sysutil_geteuid(); 69 saved_egid = vsf_sysutil_getegid(); 70 vsf_sysutil_setegid(p_user); 71 vsf_sysutil_seteuid(p_user); 72 } 73 74 retval = str_chdir(&dir_str); 75 76 if (retval != 0) 77 { 78 die2("cannot change directory:", str_getbuf(&dir_str)); 79 } 80 if (p_ext_dir_str && !str_isempty(p_ext_dir_str)) 81 { 82 retval = str_chdir(p_ext_dir_str); 83 84 /* Failure on the extra directory is OK as long as we're not in 85 * chroot() mode 86 */ 87 if (retval != 0 && !(options & VSF_SECUTIL_OPTION_CHROOT)) 88 { 89 retval = 0; 90 } 91 } 92 93 if (retval != 0) 94 { 95 die2("cannot change directory:", str_getbuf(p_ext_dir_str)); 96 } 97 if (options & VSF_SECUTIL_OPTION_CHANGE_EUID) 98 { 99 vsf_sysutil_seteuid_numeric(saved_euid); 100 vsf_sysutil_setegid_numeric(saved_egid); 101 } 102 103// 2007.05 James { 104 /* Do the chroot() if required */ 105 //if (options & VSF_SECUTIL_OPTION_CHROOT) 106 //{ 107 // vsf_sysutil_chroot("."); 108 //} 109// 2007.05 James } 110 } 111 str_free(&dir_str); 112 } 113 /* Handle capabilities */ 114 if (caps) 115 { 116 if (!vsf_sysdep_has_capabilities()) 117 { 118 /* Need privilege but OS has no capabilities - have to keep root */ 119 return; 120 } 121 if (!vsf_sysdep_has_capabilities_as_non_root()) 122 { 123 vsf_sysdep_adopt_capabilities(caps); 124 return; 125 } 126 vsf_sysdep_keep_capabilities(); 127 } 128 129 /* Set group id */ 130 vsf_sysutil_setgid(p_user); 131 /* Finally set user id */ 132 vsf_sysutil_setuid(p_user); 133 134 if (caps) 135 { 136 vsf_sysdep_adopt_capabilities(caps); 137 } 138} 139 140