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