1295367Sdes/* $Id: platform.c,v 1.22 2014/07/18 04:11:26 djm Exp $ */
2162852Sdes
3162852Sdes/*
4162852Sdes * Copyright (c) 2006 Darren Tucker.  All rights reserved.
5162852Sdes *
6162852Sdes * Permission to use, copy, modify, and distribute this software for any
7162852Sdes * purpose with or without fee is hereby granted, provided that the above
8162852Sdes * copyright notice and this permission notice appear in all copies.
9162852Sdes *
10162852Sdes * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11162852Sdes * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12162852Sdes * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13162852Sdes * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14162852Sdes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15162852Sdes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16162852Sdes * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17162852Sdes */
18162852Sdes
19221420Sdes#include "includes.h"
20221420Sdes
21221420Sdes#include <stdarg.h>
22221420Sdes#include <unistd.h>
23221420Sdes
24221420Sdes#include "log.h"
25221420Sdes#include "buffer.h"
26295367Sdes#include "misc.h"
27221420Sdes#include "servconf.h"
28221420Sdes#include "key.h"
29221420Sdes#include "hostfile.h"
30221420Sdes#include "auth.h"
31221420Sdes#include "auth-pam.h"
32162852Sdes#include "platform.h"
33162852Sdes
34162852Sdes#include "openbsd-compat/openbsd-compat.h"
35162852Sdes
36221420Sdesextern int use_privsep;
37221420Sdesextern ServerOptions options;
38221420Sdes
39162852Sdesvoid
40204917Sdesplatform_pre_listen(void)
41204917Sdes{
42204917Sdes#ifdef LINUX_OOM_ADJUST
43204917Sdes	/* Adjust out-of-memory killer so listening process is not killed */
44204917Sdes	oom_adjust_setup();
45204917Sdes#endif
46204917Sdes}
47204917Sdes
48204917Sdesvoid
49162852Sdesplatform_pre_fork(void)
50162852Sdes{
51162852Sdes#ifdef USE_SOLARIS_PROCESS_CONTRACTS
52162852Sdes	solaris_contract_pre_fork();
53162852Sdes#endif
54162852Sdes}
55162852Sdes
56162852Sdesvoid
57262566Sdesplatform_pre_restart(void)
58262566Sdes{
59262566Sdes#ifdef LINUX_OOM_ADJUST
60262566Sdes	oom_adjust_restore();
61262566Sdes#endif
62262566Sdes}
63262566Sdes
64262566Sdesvoid
65162852Sdesplatform_post_fork_parent(pid_t child_pid)
66162852Sdes{
67162852Sdes#ifdef USE_SOLARIS_PROCESS_CONTRACTS
68162852Sdes	solaris_contract_post_fork_parent(child_pid);
69162852Sdes#endif
70162852Sdes}
71162852Sdes
72162852Sdesvoid
73162852Sdesplatform_post_fork_child(void)
74162852Sdes{
75162852Sdes#ifdef USE_SOLARIS_PROCESS_CONTRACTS
76162852Sdes	solaris_contract_post_fork_child();
77162852Sdes#endif
78204917Sdes#ifdef LINUX_OOM_ADJUST
79204917Sdes	oom_adjust_restore();
80204917Sdes#endif
81162852Sdes}
82204917Sdes
83221420Sdes/* return 1 if we are running with privilege to swap UIDs, 0 otherwise */
84221420Sdesint
85221420Sdesplatform_privileged_uidswap(void)
86221420Sdes{
87221420Sdes#ifdef HAVE_CYGWIN
88221420Sdes	/* uid 0 is not special on Cygwin so always try */
89221420Sdes	return 1;
90221420Sdes#else
91221420Sdes	return (getuid() == 0 || geteuid() == 0);
92221420Sdes#endif
93221420Sdes}
94221420Sdes
95221420Sdes/*
96221420Sdes * This gets called before switching UIDs, and is called even when sshd is
97221420Sdes * not running as root.
98221420Sdes */
99221420Sdesvoid
100221420Sdesplatform_setusercontext(struct passwd *pw)
101221420Sdes{
102221420Sdes#ifdef WITH_SELINUX
103221420Sdes	/* Cache selinux status for later use */
104221420Sdes	(void)ssh_selinux_enabled();
105221420Sdes#endif
106221420Sdes
107221420Sdes#ifdef USE_SOLARIS_PROJECTS
108323124Sdes	/*
109323124Sdes	 * If solaris projects were detected, set the default now, unless
110323124Sdes	 * we are using PAM in which case it is the responsibility of the
111323124Sdes	 * PAM stack.
112323124Sdes	 */
113323124Sdes	if (!options.use_pam && (getuid() == 0 || geteuid() == 0))
114221420Sdes		solaris_set_default_project(pw);
115221420Sdes#endif
116221420Sdes
117221420Sdes#if defined(HAVE_LOGIN_CAP) && defined (__bsdi__)
118221420Sdes	if (getuid() == 0 || geteuid() == 0)
119221420Sdes		setpgid(0, 0);
120221420Sdes# endif
121221420Sdes
122221420Sdes#if defined(HAVE_LOGIN_CAP) && defined(USE_PAM)
123221420Sdes	/*
124221420Sdes	 * If we have both LOGIN_CAP and PAM, we want to establish creds
125221420Sdes	 * before calling setusercontext (in session.c:do_setusercontext).
126221420Sdes	 */
127221420Sdes	if (getuid() == 0 || geteuid() == 0) {
128221420Sdes		if (options.use_pam) {
129221420Sdes			do_pam_setcred(use_privsep);
130221420Sdes		}
131221420Sdes	}
132221420Sdes# endif /* USE_PAM */
133221420Sdes
134221420Sdes#if !defined(HAVE_LOGIN_CAP) && defined(HAVE_GETLUID) && defined(HAVE_SETLUID)
135221420Sdes	if (getuid() == 0 || geteuid() == 0) {
136221420Sdes		/* Sets login uid for accounting */
137221420Sdes		if (getluid() == -1 && setluid(pw->pw_uid) == -1)
138221420Sdes			error("setluid: %s", strerror(errno));
139221420Sdes	}
140221420Sdes#endif
141221420Sdes}
142221420Sdes
143221420Sdes/*
144221420Sdes * This gets called after we've established the user's groups, and is only
145221420Sdes * called if sshd is running as root.
146221420Sdes */
147221420Sdesvoid
148221420Sdesplatform_setusercontext_post_groups(struct passwd *pw)
149221420Sdes{
150221420Sdes#if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM)
151221420Sdes	/*
152221420Sdes	 * PAM credentials may take the form of supplementary groups.
153221420Sdes	 * These will have been wiped by the above initgroups() call.
154221420Sdes	 * Reestablish them here.
155221420Sdes	 */
156221420Sdes	if (options.use_pam) {
157221420Sdes		do_pam_setcred(use_privsep);
158221420Sdes	}
159221420Sdes#endif /* USE_PAM */
160221420Sdes
161221420Sdes#if !defined(HAVE_LOGIN_CAP) && (defined(WITH_IRIX_PROJECT) || \
162221420Sdes    defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY))
163221420Sdes	irix_setusercontext(pw);
164221420Sdes#endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */
165221420Sdes
166221420Sdes#ifdef _AIX
167221420Sdes	aix_usrinfo(pw);
168221420Sdes#endif /* _AIX */
169221420Sdes
170221420Sdes#ifdef HAVE_SETPCRED
171221420Sdes	/*
172221420Sdes	 * If we have a chroot directory, we set all creds except real
173221420Sdes	 * uid which we will need for chroot.  If we don't have a
174221420Sdes	 * chroot directory, we don't override anything.
175221420Sdes	 */
176221420Sdes	{
177221420Sdes		char **creds = NULL, *chroot_creds[] =
178221420Sdes		    { "REAL_USER=root", NULL };
179221420Sdes
180221420Sdes		if (options.chroot_directory != NULL &&
181221420Sdes		    strcasecmp(options.chroot_directory, "none") != 0)
182221420Sdes			creds = chroot_creds;
183221420Sdes
184221420Sdes		if (setpcred(pw->pw_name, creds) == -1)
185221420Sdes			fatal("Failed to set process credentials");
186221420Sdes	}
187221420Sdes#endif /* HAVE_SETPCRED */
188221420Sdes#ifdef WITH_SELINUX
189221420Sdes	ssh_selinux_setup_exec_context(pw->pw_name);
190221420Sdes#endif
191221420Sdes}
192221420Sdes
193204917Sdeschar *
194204917Sdesplatform_krb5_get_principal_name(const char *pw_name)
195204917Sdes{
196204917Sdes#ifdef USE_AIX_KRB_NAME
197204917Sdes	return aix_krb5_get_principal_name(pw_name);
198204917Sdes#else
199204917Sdes	return NULL;
200204917Sdes#endif
201204917Sdes}
202248619Sdes
203248619Sdes/*
204248619Sdes * return 1 if the specified uid is a uid that may own a system directory
205248619Sdes * otherwise 0.
206248619Sdes */
207248619Sdesint
208248619Sdesplatform_sys_dir_uid(uid_t uid)
209248619Sdes{
210248619Sdes	if (uid == 0)
211248619Sdes		return 1;
212248619Sdes#ifdef PLATFORM_SYS_DIR_UID
213248619Sdes	if (uid == PLATFORM_SYS_DIR_UID)
214248619Sdes		return 1;
215248619Sdes#endif
216248619Sdes	return 0;
217248619Sdes}
218