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