1 /* $Id: platform.c,v 1.19 2013/03/12 00:31:05 dtucker 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 <sys/types.h> 22 23 #include <stdarg.h> 24 #include <unistd.h> 25 26 #include "log.h" 27 #include "buffer.h" 28 #include "servconf.h" 29 #include "key.h" 30 #include "hostfile.h" 31 #include "auth.h" 32 #include "auth-pam.h" 33 #include "platform.h" 34 35 #include "openbsd-compat/openbsd-compat.h" 36 37 extern int use_privsep; 38 extern ServerOptions options; 39 40 void 41 platform_pre_listen(void) 42 { 43 #ifdef LINUX_OOM_ADJUST 44 /* Adjust out-of-memory killer so listening process is not killed */ 45 oom_adjust_setup(); 46 #endif 47 } 48 49 void 50 platform_pre_fork(void) 51 { 52 #ifdef USE_SOLARIS_PROCESS_CONTRACTS 53 solaris_contract_pre_fork(); 54 #endif 55 } 56 57 void 58 platform_post_fork_parent(pid_t child_pid) 59 { 60 #ifdef USE_SOLARIS_PROCESS_CONTRACTS 61 solaris_contract_post_fork_parent(child_pid); 62 #endif 63 } 64 65 void 66 platform_post_fork_child(void) 67 { 68 #ifdef USE_SOLARIS_PROCESS_CONTRACTS 69 solaris_contract_post_fork_child(); 70 #endif 71 #ifdef LINUX_OOM_ADJUST 72 oom_adjust_restore(); 73 #endif 74 } 75 76 /* return 1 if we are running with privilege to swap UIDs, 0 otherwise */ 77 int 78 platform_privileged_uidswap(void) 79 { 80 #ifdef HAVE_CYGWIN 81 /* uid 0 is not special on Cygwin so always try */ 82 return 1; 83 #else 84 return (getuid() == 0 || geteuid() == 0); 85 #endif 86 } 87 88 /* 89 * This gets called before switching UIDs, and is called even when sshd is 90 * not running as root. 91 */ 92 void 93 platform_setusercontext(struct passwd *pw) 94 { 95 #ifdef WITH_SELINUX 96 /* Cache selinux status for later use */ 97 (void)ssh_selinux_enabled(); 98 #endif 99 100 #ifdef USE_SOLARIS_PROJECTS 101 /* if solaris projects were detected, set the default now */ 102 if (getuid() == 0 || geteuid() == 0) 103 solaris_set_default_project(pw); 104 #endif 105 106 #if defined(HAVE_LOGIN_CAP) && defined (__bsdi__) 107 if (getuid() == 0 || geteuid() == 0) 108 setpgid(0, 0); 109 # endif 110 111 #if defined(HAVE_LOGIN_CAP) && defined(USE_PAM) 112 /* 113 * If we have both LOGIN_CAP and PAM, we want to establish creds 114 * before calling setusercontext (in session.c:do_setusercontext). 115 */ 116 if (getuid() == 0 || geteuid() == 0) { 117 if (options.use_pam) { 118 do_pam_setcred(use_privsep); 119 } 120 } 121 # endif /* USE_PAM */ 122 123 #if !defined(HAVE_LOGIN_CAP) && defined(HAVE_GETLUID) && defined(HAVE_SETLUID) 124 if (getuid() == 0 || geteuid() == 0) { 125 /* Sets login uid for accounting */ 126 if (getluid() == -1 && setluid(pw->pw_uid) == -1) 127 error("setluid: %s", strerror(errno)); 128 } 129 #endif 130 } 131 132 /* 133 * This gets called after we've established the user's groups, and is only 134 * called if sshd is running as root. 135 */ 136 void 137 platform_setusercontext_post_groups(struct passwd *pw) 138 { 139 #if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM) 140 /* 141 * PAM credentials may take the form of supplementary groups. 142 * These will have been wiped by the above initgroups() call. 143 * Reestablish them here. 144 */ 145 if (options.use_pam) { 146 do_pam_setcred(use_privsep); 147 } 148 #endif /* USE_PAM */ 149 150 #if !defined(HAVE_LOGIN_CAP) && (defined(WITH_IRIX_PROJECT) || \ 151 defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY)) 152 irix_setusercontext(pw); 153 #endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */ 154 155 #ifdef _AIX 156 aix_usrinfo(pw); 157 #endif /* _AIX */ 158 159 #if !defined(HAVE_LOGIN_CAP) && defined(USE_LIBIAF) 160 if (set_id(pw->pw_name) != 0) { 161 exit(1); 162 } 163 # endif /* USE_LIBIAF */ 164 165 #ifdef HAVE_SETPCRED 166 /* 167 * If we have a chroot directory, we set all creds except real 168 * uid which we will need for chroot. If we don't have a 169 * chroot directory, we don't override anything. 170 */ 171 { 172 char **creds = NULL, *chroot_creds[] = 173 { "REAL_USER=root", NULL }; 174 175 if (options.chroot_directory != NULL && 176 strcasecmp(options.chroot_directory, "none") != 0) 177 creds = chroot_creds; 178 179 if (setpcred(pw->pw_name, creds) == -1) 180 fatal("Failed to set process credentials"); 181 } 182 #endif /* HAVE_SETPCRED */ 183 #ifdef WITH_SELINUX 184 ssh_selinux_setup_exec_context(pw->pw_name); 185 #endif 186 } 187 188 char * 189 platform_krb5_get_principal_name(const char *pw_name) 190 { 191 #ifdef USE_AIX_KRB_NAME 192 return aix_krb5_get_principal_name(pw_name); 193 #else 194 return NULL; 195 #endif 196 } 197 198 /* 199 * return 1 if the specified uid is a uid that may own a system directory 200 * otherwise 0. 201 */ 202 int 203 platform_sys_dir_uid(uid_t uid) 204 { 205 if (uid == 0) 206 return 1; 207 #ifdef PLATFORM_SYS_DIR_UID 208 if (uid == PLATFORM_SYS_DIR_UID) 209 return 1; 210 #endif 211 return 0; 212 } 213