1139804Simp/* $Id: platform.c,v 1.22 2014/07/18 04:11:26 djm Exp $ */
21541Srgrimes
31541Srgrimes/*
41541Srgrimes * Copyright (c) 2006 Darren Tucker.  All rights reserved.
51541Srgrimes *
61541Srgrimes * Permission to use, copy, modify, and distribute this software for any
71541Srgrimes * purpose with or without fee is hereby granted, provided that the above
81541Srgrimes * copyright notice and this permission notice appear in all copies.
91541Srgrimes *
101541Srgrimes * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
111541Srgrimes * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
121541Srgrimes * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
131541Srgrimes * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
141541Srgrimes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
151541Srgrimes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
161541Srgrimes * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
171541Srgrimes */
181541Srgrimes
191541Srgrimes#include "includes.h"
201541Srgrimes
211541Srgrimes#include <sys/types.h>
221541Srgrimes
231541Srgrimes#include <stdarg.h>
241541Srgrimes#include <unistd.h>
251541Srgrimes
261541Srgrimes#include "log.h"
271541Srgrimes#include "buffer.h"
281541Srgrimes#include "misc.h"
291541Srgrimes#include "servconf.h"
301541Srgrimes#include "key.h"
311541Srgrimes#include "hostfile.h"
32116182Sobrien#include "auth.h"
33116182Sobrien#include "auth-pam.h"
34116182Sobrien#include "platform.h"
3531778Seivind
3631778Seivind#include "openbsd-compat/openbsd-compat.h"
371541Srgrimes
381541Srgrimesextern int use_privsep;
3912221Sbdeextern ServerOptions options;
401541Srgrimes
41164033Srwatsonvoid
421541Srgrimesplatform_pre_listen(void)
4382717Sdillon{
4482717Sdillon#ifdef LINUX_OOM_ADJUST
45186570Sed	/* Adjust out-of-memory killer so listening process is not killed */
461541Srgrimes	oom_adjust_setup();
471549Srgrimes#endif
481541Srgrimes}
49186570Sed
508876Srgrimesvoid
51130344Sphkplatform_pre_fork(void)
521541Srgrimes{
5312221Sbde#ifdef USE_SOLARIS_PROCESS_CONTRACTS
541541Srgrimes	solaris_contract_pre_fork();
551541Srgrimes#endif
561541Srgrimes}
571541Srgrimes
5812221Sbdevoid
591541Srgrimesplatform_pre_restart(void)
601549Srgrimes{
6183366Sjulian#ifdef LINUX_OOM_ADJUST
6283366Sjulian	oom_adjust_restore();
631541Srgrimes#endif
641541Srgrimes}
6512171Sphk
6638517Sdfrvoid
671541Srgrimesplatform_post_fork_parent(pid_t child_pid)
6812171Sphk{
6912171Sphk#ifdef USE_SOLARIS_PROCESS_CONTRACTS
70186564Sed	solaris_contract_post_fork_parent(child_pid);
71186564Sed#endif
721541Srgrimes}
731541Srgrimes
7412221Sbdevoid
751541Srgrimesplatform_post_fork_child(void)
761541Srgrimes{
771541Srgrimes#ifdef USE_SOLARIS_PROCESS_CONTRACTS
781541Srgrimes	solaris_contract_post_fork_child();
7912221Sbde#endif
801541Srgrimes#ifdef LINUX_OOM_ADJUST
811549Srgrimes	oom_adjust_restore();
8283366Sjulian#endif
8383366Sjulian}
841541Srgrimes
851541Srgrimes/* return 1 if we are running with privilege to swap UIDs, 0 otherwise */
8612171Sphkint
871541Srgrimesplatform_privileged_uidswap(void)
8812171Sphk{
8912171Sphk#ifdef HAVE_CYGWIN
90186564Sed	/* uid 0 is not special on Cygwin so always try */
91186564Sed	return 1;
921541Srgrimes#else
931541Srgrimes	return (getuid() == 0 || geteuid() == 0);
9412221Sbde#endif
9512200Sbde}
961541Srgrimes
971541Srgrimes/*
9812221Sbde * This gets called before switching UIDs, and is called even when sshd is
991541Srgrimes * not running as root.
1001549Srgrimes */
10183366Sjulianvoid
10283366Sjulianplatform_setusercontext(struct passwd *pw)
10312200Sbde{
1041541Srgrimes#ifdef WITH_SELINUX
105193066Sjamie	/* Cache selinux status for later use */
106193066Sjamie	(void)ssh_selinux_enabled();
1071541Srgrimes#endif
108193066Sjamie
109193066Sjamie#ifdef USE_SOLARIS_PROJECTS
110193066Sjamie	/* if solaris projects were detected, set the default now */
111193066Sjamie	if (getuid() == 0 || geteuid() == 0)
1121541Srgrimes		solaris_set_default_project(pw);
113130344Sphk#endif
1141541Srgrimes
1151541Srgrimes#if defined(HAVE_LOGIN_CAP) && defined (__bsdi__)
11612221Sbde	if (getuid() == 0 || geteuid() == 0)
11712200Sbde		setpgid(0, 0);
1181541Srgrimes# endif
1191541Srgrimes
12012221Sbde#if defined(HAVE_LOGIN_CAP) && defined(USE_PAM)
1211541Srgrimes	/*
1221549Srgrimes	 * If we have both LOGIN_CAP and PAM, we want to establish creds
12383366Sjulian	 * before calling setusercontext (in session.c:do_setusercontext).
12483366Sjulian	 */
12512200Sbde	if (getuid() == 0 || geteuid() == 0) {
1261541Srgrimes		if (options.use_pam) {
127193066Sjamie			do_pam_setcred(use_privsep);
1281541Srgrimes		}
129193066Sjamie	}
130193066Sjamie# endif /* USE_PAM */
131193066Sjamie
132193066Sjamie#if !defined(HAVE_LOGIN_CAP) && defined(HAVE_GETLUID) && defined(HAVE_SETLUID)
1331541Srgrimes	if (getuid() == 0 || geteuid() == 0) {
1341541Srgrimes		/* Sets login uid for accounting */
1351549Srgrimes		if (getluid() == -1 && setluid(pw->pw_uid) == -1)
13683366Sjulian			error("setluid: %s", strerror(errno));
13783366Sjulian	}
13812200Sbde#endif
1391541Srgrimes}
140167232Srwatson
1411541Srgrimes/*
1421541Srgrimes * This gets called after we've established the user's groups, and is only
143186570Sed * called if sshd is running as root.
144186570Sed */
145186570Sedvoid
146186570Sedplatform_setusercontext_post_groups(struct passwd *pw)
147186570Sed{
148186570Sed#if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM)
149186570Sed	/*
150186570Sed	 * PAM credentials may take the form of supplementary groups.
151186570Sed	 * These will have been wiped by the above initgroups() call.
152186570Sed	 * Reestablish them here.
153186570Sed	 */
154186570Sed	if (options.use_pam) {
155186570Sed		do_pam_setcred(use_privsep);
156186570Sed	}
157186570Sed#endif /* USE_PAM */
158186570Sed
159186570Sed#if !defined(HAVE_LOGIN_CAP) && (defined(WITH_IRIX_PROJECT) || \
160186570Sed    defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY))
161186570Sed	irix_setusercontext(pw);
162186570Sed#endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */
163186570Sed
164186570Sed#ifdef _AIX
165186570Sed	aix_usrinfo(pw);
166186570Sed#endif /* _AIX */
167186570Sed
168186570Sed#ifdef HAVE_SETPCRED
169186570Sed	/*
170186570Sed	 * If we have a chroot directory, we set all creds except real
171186570Sed	 * uid which we will need for chroot.  If we don't have a
172186570Sed	 * chroot directory, we don't override anything.
173186570Sed	 */
174186570Sed	{
175186570Sed		char **creds = NULL, *chroot_creds[] =
176186570Sed		    { "REAL_USER=root", NULL };
177186570Sed
178186570Sed		if (options.chroot_directory != NULL &&
179186570Sed		    strcasecmp(options.chroot_directory, "none") != 0)
180186570Sed			creds = chroot_creds;
181186570Sed
182186570Sed		if (setpcred(pw->pw_name, creds) == -1)
183186570Sed			fatal("Failed to set process credentials");
184186570Sed	}
185186570Sed#endif /* HAVE_SETPCRED */
186186570Sed#ifdef WITH_SELINUX
187186570Sed	ssh_selinux_setup_exec_context(pw->pw_name);
188186570Sed#endif
189186570Sed}
190186570Sed
191186570Sedchar *
192186570Sedplatform_krb5_get_principal_name(const char *pw_name)
193186570Sed{
194186570Sed#ifdef USE_AIX_KRB_NAME
195186570Sed	return aix_krb5_get_principal_name(pw_name);
196186570Sed#else
197186570Sed	return NULL;
198186570Sed#endif
199186570Sed}
200186570Sed
201186570Sed/*
202186570Sed * return 1 if the specified uid is a uid that may own a system directory
203186570Sed * otherwise 0.
204186570Sed */
205186570Sedint
206186570Sedplatform_sys_dir_uid(uid_t uid)
207186570Sed{
208186570Sed	if (uid == 0)
209186570Sed		return 1;
210186570Sed#ifdef PLATFORM_SYS_DIR_UID
211186570Sed	if (uid == PLATFORM_SYS_DIR_UID)
212186570Sed		return 1;
213186570Sed#endif
214186570Sed	return 0;
215186570Sed}
216186570Sed