1 /* $Id: platform.c,v 1.22 2014/07/18 04:11:26 djm Exp $ */ 2 3 /* 4 * Copyright (c) 2006 Darren Tucker. All rights reserved. 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include "includes.h" 20 21 #include <stdarg.h> 22 #include <unistd.h> 23 24 #include "log.h" 25 #include "buffer.h" 26 #include "misc.h" 27 #include "servconf.h" 28 #include "key.h" 29 #include "hostfile.h" 30 #include "auth.h" 31 #include "auth-pam.h" 32 #include "platform.h" 33 34 #include "openbsd-compat/openbsd-compat.h" 35 36 extern int use_privsep; 37 extern ServerOptions options; 38 39 void 40 platform_pre_listen(void) 41 { 42 #ifdef LINUX_OOM_ADJUST 43 /* Adjust out-of-memory killer so listening process is not killed */ 44 oom_adjust_setup(); 45 #endif 46 } 47 48 void 49 platform_pre_fork(void) 50 { 51 #ifdef USE_SOLARIS_PROCESS_CONTRACTS 52 solaris_contract_pre_fork(); 53 #endif 54 } 55 56 void 57 platform_pre_restart(void) 58 { 59 #ifdef LINUX_OOM_ADJUST 60 oom_adjust_restore(); 61 #endif 62 } 63 64 void 65 platform_post_fork_parent(pid_t child_pid) 66 { 67 #ifdef USE_SOLARIS_PROCESS_CONTRACTS 68 solaris_contract_post_fork_parent(child_pid); 69 #endif 70 } 71 72 void 73 platform_post_fork_child(void) 74 { 75 #ifdef USE_SOLARIS_PROCESS_CONTRACTS 76 solaris_contract_post_fork_child(); 77 #endif 78 #ifdef LINUX_OOM_ADJUST 79 oom_adjust_restore(); 80 #endif 81 } 82 83 /* return 1 if we are running with privilege to swap UIDs, 0 otherwise */ 84 int 85 platform_privileged_uidswap(void) 86 { 87 #ifdef HAVE_CYGWIN 88 /* uid 0 is not special on Cygwin so always try */ 89 return 1; 90 #else 91 return (getuid() == 0 || geteuid() == 0); 92 #endif 93 } 94 95 /* 96 * This gets called before switching UIDs, and is called even when sshd is 97 * not running as root. 98 */ 99 void 100 platform_setusercontext(struct passwd *pw) 101 { 102 #ifdef WITH_SELINUX 103 /* Cache selinux status for later use */ 104 (void)ssh_selinux_enabled(); 105 #endif 106 107 #ifdef USE_SOLARIS_PROJECTS 108 /* 109 * If solaris projects were detected, set the default now, unless 110 * we are using PAM in which case it is the responsibility of the 111 * PAM stack. 112 */ 113 if (!options.use_pam && (getuid() == 0 || geteuid() == 0)) 114 solaris_set_default_project(pw); 115 #endif 116 117 #if defined(HAVE_LOGIN_CAP) && defined (__bsdi__) 118 if (getuid() == 0 || geteuid() == 0) 119 setpgid(0, 0); 120 # endif 121 122 #if defined(HAVE_LOGIN_CAP) && defined(USE_PAM) 123 /* 124 * If we have both LOGIN_CAP and PAM, we want to establish creds 125 * before calling setusercontext (in session.c:do_setusercontext). 126 */ 127 if (getuid() == 0 || geteuid() == 0) { 128 if (options.use_pam) { 129 do_pam_setcred(use_privsep); 130 } 131 } 132 # endif /* USE_PAM */ 133 134 #if !defined(HAVE_LOGIN_CAP) && defined(HAVE_GETLUID) && defined(HAVE_SETLUID) 135 if (getuid() == 0 || geteuid() == 0) { 136 /* Sets login uid for accounting */ 137 if (getluid() == -1 && setluid(pw->pw_uid) == -1) 138 error("setluid: %s", strerror(errno)); 139 } 140 #endif 141 } 142 143 /* 144 * This gets called after we've established the user's groups, and is only 145 * called if sshd is running as root. 146 */ 147 void 148 platform_setusercontext_post_groups(struct passwd *pw) 149 { 150 #if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM) 151 /* 152 * PAM credentials may take the form of supplementary groups. 153 * These will have been wiped by the above initgroups() call. 154 * Reestablish them here. 155 */ 156 if (options.use_pam) { 157 do_pam_setcred(use_privsep); 158 } 159 #endif /* USE_PAM */ 160 161 #if !defined(HAVE_LOGIN_CAP) && (defined(WITH_IRIX_PROJECT) || \ 162 defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY)) 163 irix_setusercontext(pw); 164 #endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */ 165 166 #ifdef _AIX 167 aix_usrinfo(pw); 168 #endif /* _AIX */ 169 170 #ifdef HAVE_SETPCRED 171 /* 172 * If we have a chroot directory, we set all creds except real 173 * uid which we will need for chroot. If we don't have a 174 * chroot directory, we don't override anything. 175 */ 176 { 177 char **creds = NULL, *chroot_creds[] = 178 { "REAL_USER=root", NULL }; 179 180 if (options.chroot_directory != NULL && 181 strcasecmp(options.chroot_directory, "none") != 0) 182 creds = chroot_creds; 183 184 if (setpcred(pw->pw_name, creds) == -1) 185 fatal("Failed to set process credentials"); 186 } 187 #endif /* HAVE_SETPCRED */ 188 #ifdef WITH_SELINUX 189 ssh_selinux_setup_exec_context(pw->pw_name); 190 #endif 191 } 192 193 char * 194 platform_krb5_get_principal_name(const char *pw_name) 195 { 196 #ifdef USE_AIX_KRB_NAME 197 return aix_krb5_get_principal_name(pw_name); 198 #else 199 return NULL; 200 #endif 201 } 202 203 /* 204 * return 1 if the specified uid is a uid that may own a system directory 205 * otherwise 0. 206 */ 207 int 208 platform_sys_dir_uid(uid_t uid) 209 { 210 if (uid == 0) 211 return 1; 212 #ifdef PLATFORM_SYS_DIR_UID 213 if (uid == PLATFORM_SYS_DIR_UID) 214 return 1; 215 #endif 216 return 0; 217 } 218