xref: /freebsd/crypto/openssh/platform.c (revision 87c1498d1a7473ff983e5c0456f30608f3f1e601)
1761efaa7SDag-Erling Smørgrav /*
2761efaa7SDag-Erling Smørgrav  * Copyright (c) 2006 Darren Tucker.  All rights reserved.
3761efaa7SDag-Erling Smørgrav  *
4761efaa7SDag-Erling Smørgrav  * Permission to use, copy, modify, and distribute this software for any
5761efaa7SDag-Erling Smørgrav  * purpose with or without fee is hereby granted, provided that the above
6761efaa7SDag-Erling Smørgrav  * copyright notice and this permission notice appear in all copies.
7761efaa7SDag-Erling Smørgrav  *
8761efaa7SDag-Erling Smørgrav  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9761efaa7SDag-Erling Smørgrav  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10761efaa7SDag-Erling Smørgrav  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11761efaa7SDag-Erling Smørgrav  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12761efaa7SDag-Erling Smørgrav  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13761efaa7SDag-Erling Smørgrav  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14761efaa7SDag-Erling Smørgrav  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15761efaa7SDag-Erling Smørgrav  */
16761efaa7SDag-Erling Smørgrav 
174a421b63SDag-Erling Smørgrav #include "includes.h"
184a421b63SDag-Erling Smørgrav 
194a421b63SDag-Erling Smørgrav #include <stdarg.h>
2019261079SEd Maste #include <stdio.h>
21*87c1498dSEd Maste #include <string.h>
224a421b63SDag-Erling Smørgrav #include <unistd.h>
234a421b63SDag-Erling Smørgrav 
244a421b63SDag-Erling Smørgrav #include "log.h"
25a0ee8cc6SDag-Erling Smørgrav #include "misc.h"
264a421b63SDag-Erling Smørgrav #include "servconf.h"
27190cef3dSDag-Erling Smørgrav #include "sshkey.h"
284a421b63SDag-Erling Smørgrav #include "hostfile.h"
294a421b63SDag-Erling Smørgrav #include "auth.h"
304a421b63SDag-Erling Smørgrav #include "auth-pam.h"
31761efaa7SDag-Erling Smørgrav #include "platform.h"
32761efaa7SDag-Erling Smørgrav 
33761efaa7SDag-Erling Smørgrav #include "openbsd-compat/openbsd-compat.h"
34761efaa7SDag-Erling Smørgrav 
354a421b63SDag-Erling Smørgrav extern int use_privsep;
364a421b63SDag-Erling Smørgrav extern ServerOptions options;
374a421b63SDag-Erling Smørgrav 
38761efaa7SDag-Erling Smørgrav void
39b15c8340SDag-Erling Smørgrav platform_pre_listen(void)
40b15c8340SDag-Erling Smørgrav {
41b15c8340SDag-Erling Smørgrav #ifdef LINUX_OOM_ADJUST
42b15c8340SDag-Erling Smørgrav 	/* Adjust out-of-memory killer so listening process is not killed */
43b15c8340SDag-Erling Smørgrav 	oom_adjust_setup();
44b15c8340SDag-Erling Smørgrav #endif
45b15c8340SDag-Erling Smørgrav }
46b15c8340SDag-Erling Smørgrav 
47b15c8340SDag-Erling Smørgrav void
48761efaa7SDag-Erling Smørgrav platform_pre_fork(void)
49761efaa7SDag-Erling Smørgrav {
50761efaa7SDag-Erling Smørgrav #ifdef USE_SOLARIS_PROCESS_CONTRACTS
51761efaa7SDag-Erling Smørgrav 	solaris_contract_pre_fork();
52761efaa7SDag-Erling Smørgrav #endif
53761efaa7SDag-Erling Smørgrav }
54761efaa7SDag-Erling Smørgrav 
55761efaa7SDag-Erling Smørgrav void
56f7167e0eSDag-Erling Smørgrav platform_pre_restart(void)
57f7167e0eSDag-Erling Smørgrav {
58f7167e0eSDag-Erling Smørgrav #ifdef LINUX_OOM_ADJUST
59f7167e0eSDag-Erling Smørgrav 	oom_adjust_restore();
60f7167e0eSDag-Erling Smørgrav #endif
61f7167e0eSDag-Erling Smørgrav }
62f7167e0eSDag-Erling Smørgrav 
63f7167e0eSDag-Erling Smørgrav void
64761efaa7SDag-Erling Smørgrav platform_post_fork_parent(pid_t child_pid)
65761efaa7SDag-Erling Smørgrav {
66761efaa7SDag-Erling Smørgrav #ifdef USE_SOLARIS_PROCESS_CONTRACTS
67761efaa7SDag-Erling Smørgrav 	solaris_contract_post_fork_parent(child_pid);
68761efaa7SDag-Erling Smørgrav #endif
69761efaa7SDag-Erling Smørgrav }
70761efaa7SDag-Erling Smørgrav 
71761efaa7SDag-Erling Smørgrav void
72761efaa7SDag-Erling Smørgrav platform_post_fork_child(void)
73761efaa7SDag-Erling Smørgrav {
74761efaa7SDag-Erling Smørgrav #ifdef USE_SOLARIS_PROCESS_CONTRACTS
75761efaa7SDag-Erling Smørgrav 	solaris_contract_post_fork_child();
76761efaa7SDag-Erling Smørgrav #endif
77b15c8340SDag-Erling Smørgrav #ifdef LINUX_OOM_ADJUST
78b15c8340SDag-Erling Smørgrav 	oom_adjust_restore();
79b15c8340SDag-Erling Smørgrav #endif
80b15c8340SDag-Erling Smørgrav }
81b15c8340SDag-Erling Smørgrav 
824a421b63SDag-Erling Smørgrav /* return 1 if we are running with privilege to swap UIDs, 0 otherwise */
834a421b63SDag-Erling Smørgrav int
844a421b63SDag-Erling Smørgrav platform_privileged_uidswap(void)
854a421b63SDag-Erling Smørgrav {
864a421b63SDag-Erling Smørgrav #ifdef HAVE_CYGWIN
874a421b63SDag-Erling Smørgrav 	/* uid 0 is not special on Cygwin so always try */
884a421b63SDag-Erling Smørgrav 	return 1;
894a421b63SDag-Erling Smørgrav #else
904a421b63SDag-Erling Smørgrav 	return (getuid() == 0 || geteuid() == 0);
914a421b63SDag-Erling Smørgrav #endif
924a421b63SDag-Erling Smørgrav }
934a421b63SDag-Erling Smørgrav 
944a421b63SDag-Erling Smørgrav /*
954a421b63SDag-Erling Smørgrav  * This gets called before switching UIDs, and is called even when sshd is
964a421b63SDag-Erling Smørgrav  * not running as root.
974a421b63SDag-Erling Smørgrav  */
984a421b63SDag-Erling Smørgrav void
994a421b63SDag-Erling Smørgrav platform_setusercontext(struct passwd *pw)
1004a421b63SDag-Erling Smørgrav {
1014a421b63SDag-Erling Smørgrav #ifdef WITH_SELINUX
1024a421b63SDag-Erling Smørgrav 	/* Cache selinux status for later use */
1034a421b63SDag-Erling Smørgrav 	(void)ssh_selinux_enabled();
1044a421b63SDag-Erling Smørgrav #endif
1054a421b63SDag-Erling Smørgrav 
1064a421b63SDag-Erling Smørgrav #ifdef USE_SOLARIS_PROJECTS
107076ad2f8SDag-Erling Smørgrav 	/*
108076ad2f8SDag-Erling Smørgrav 	 * If solaris projects were detected, set the default now, unless
109076ad2f8SDag-Erling Smørgrav 	 * we are using PAM in which case it is the responsibility of the
110076ad2f8SDag-Erling Smørgrav 	 * PAM stack.
111076ad2f8SDag-Erling Smørgrav 	 */
112076ad2f8SDag-Erling Smørgrav 	if (!options.use_pam && (getuid() == 0 || geteuid() == 0))
1134a421b63SDag-Erling Smørgrav 		solaris_set_default_project(pw);
1144a421b63SDag-Erling Smørgrav #endif
1154a421b63SDag-Erling Smørgrav 
1164a421b63SDag-Erling Smørgrav #if defined(HAVE_LOGIN_CAP) && defined (__bsdi__)
1174a421b63SDag-Erling Smørgrav 	if (getuid() == 0 || geteuid() == 0)
1184a421b63SDag-Erling Smørgrav 		setpgid(0, 0);
1194a421b63SDag-Erling Smørgrav # endif
1204a421b63SDag-Erling Smørgrav 
1214a421b63SDag-Erling Smørgrav #if defined(HAVE_LOGIN_CAP) && defined(USE_PAM)
1224a421b63SDag-Erling Smørgrav 	/*
1234a421b63SDag-Erling Smørgrav 	 * If we have both LOGIN_CAP and PAM, we want to establish creds
1244a421b63SDag-Erling Smørgrav 	 * before calling setusercontext (in session.c:do_setusercontext).
1254a421b63SDag-Erling Smørgrav 	 */
1264a421b63SDag-Erling Smørgrav 	if (getuid() == 0 || geteuid() == 0) {
1274a421b63SDag-Erling Smørgrav 		if (options.use_pam) {
1284a421b63SDag-Erling Smørgrav 			do_pam_setcred(use_privsep);
1294a421b63SDag-Erling Smørgrav 		}
1304a421b63SDag-Erling Smørgrav 	}
1314a421b63SDag-Erling Smørgrav # endif /* USE_PAM */
1324a421b63SDag-Erling Smørgrav 
1334a421b63SDag-Erling Smørgrav #if !defined(HAVE_LOGIN_CAP) && defined(HAVE_GETLUID) && defined(HAVE_SETLUID)
1344a421b63SDag-Erling Smørgrav 	if (getuid() == 0 || geteuid() == 0) {
1354a421b63SDag-Erling Smørgrav 		/* Sets login uid for accounting */
1364a421b63SDag-Erling Smørgrav 		if (getluid() == -1 && setluid(pw->pw_uid) == -1)
1374a421b63SDag-Erling Smørgrav 			error("setluid: %s", strerror(errno));
1384a421b63SDag-Erling Smørgrav 	}
1394a421b63SDag-Erling Smørgrav #endif
1404a421b63SDag-Erling Smørgrav }
1414a421b63SDag-Erling Smørgrav 
1424a421b63SDag-Erling Smørgrav /*
1434a421b63SDag-Erling Smørgrav  * This gets called after we've established the user's groups, and is only
1444a421b63SDag-Erling Smørgrav  * called if sshd is running as root.
1454a421b63SDag-Erling Smørgrav  */
1464a421b63SDag-Erling Smørgrav void
1474a421b63SDag-Erling Smørgrav platform_setusercontext_post_groups(struct passwd *pw)
1484a421b63SDag-Erling Smørgrav {
1494a421b63SDag-Erling Smørgrav #if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM)
1504a421b63SDag-Erling Smørgrav 	/*
1514a421b63SDag-Erling Smørgrav 	 * PAM credentials may take the form of supplementary groups.
1524a421b63SDag-Erling Smørgrav 	 * These will have been wiped by the above initgroups() call.
1534a421b63SDag-Erling Smørgrav 	 * Reestablish them here.
1544a421b63SDag-Erling Smørgrav 	 */
1554a421b63SDag-Erling Smørgrav 	if (options.use_pam) {
1564a421b63SDag-Erling Smørgrav 		do_pam_setcred(use_privsep);
1574a421b63SDag-Erling Smørgrav 	}
1584a421b63SDag-Erling Smørgrav #endif /* USE_PAM */
1594a421b63SDag-Erling Smørgrav 
1604a421b63SDag-Erling Smørgrav #if !defined(HAVE_LOGIN_CAP) && (defined(WITH_IRIX_PROJECT) || \
1614a421b63SDag-Erling Smørgrav     defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY))
1624a421b63SDag-Erling Smørgrav 	irix_setusercontext(pw);
1634a421b63SDag-Erling Smørgrav #endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */
1644a421b63SDag-Erling Smørgrav 
1654a421b63SDag-Erling Smørgrav #ifdef _AIX
1664a421b63SDag-Erling Smørgrav 	aix_usrinfo(pw);
1674a421b63SDag-Erling Smørgrav #endif /* _AIX */
1684a421b63SDag-Erling Smørgrav 
1694a421b63SDag-Erling Smørgrav #ifdef HAVE_SETPCRED
1704a421b63SDag-Erling Smørgrav 	/*
1714a421b63SDag-Erling Smørgrav 	 * If we have a chroot directory, we set all creds except real
1724a421b63SDag-Erling Smørgrav 	 * uid which we will need for chroot.  If we don't have a
1734a421b63SDag-Erling Smørgrav 	 * chroot directory, we don't override anything.
1744a421b63SDag-Erling Smørgrav 	 */
1754a421b63SDag-Erling Smørgrav 	{
1764a421b63SDag-Erling Smørgrav 		char **creds = NULL, *chroot_creds[] =
1774a421b63SDag-Erling Smørgrav 		    { "REAL_USER=root", NULL };
1784a421b63SDag-Erling Smørgrav 
1794a421b63SDag-Erling Smørgrav 		if (options.chroot_directory != NULL &&
1804a421b63SDag-Erling Smørgrav 		    strcasecmp(options.chroot_directory, "none") != 0)
1814a421b63SDag-Erling Smørgrav 			creds = chroot_creds;
1824a421b63SDag-Erling Smørgrav 
1834a421b63SDag-Erling Smørgrav 		if (setpcred(pw->pw_name, creds) == -1)
1844a421b63SDag-Erling Smørgrav 			fatal("Failed to set process credentials");
1854a421b63SDag-Erling Smørgrav 	}
1864a421b63SDag-Erling Smørgrav #endif /* HAVE_SETPCRED */
1874a421b63SDag-Erling Smørgrav #ifdef WITH_SELINUX
1884a421b63SDag-Erling Smørgrav 	ssh_selinux_setup_exec_context(pw->pw_name);
1894a421b63SDag-Erling Smørgrav #endif
1904a421b63SDag-Erling Smørgrav }
1914a421b63SDag-Erling Smørgrav 
192b15c8340SDag-Erling Smørgrav char *
193b15c8340SDag-Erling Smørgrav platform_krb5_get_principal_name(const char *pw_name)
194b15c8340SDag-Erling Smørgrav {
195b15c8340SDag-Erling Smørgrav #ifdef USE_AIX_KRB_NAME
196b15c8340SDag-Erling Smørgrav 	return aix_krb5_get_principal_name(pw_name);
197b15c8340SDag-Erling Smørgrav #else
198b15c8340SDag-Erling Smørgrav 	return NULL;
199b15c8340SDag-Erling Smørgrav #endif
200761efaa7SDag-Erling Smørgrav }
201*87c1498dSEd Maste 
202*87c1498dSEd Maste /* returns 1 if account is locked */
203*87c1498dSEd Maste int
204*87c1498dSEd Maste platform_locked_account(struct passwd *pw)
205*87c1498dSEd Maste {
206*87c1498dSEd Maste 	int locked = 0;
207*87c1498dSEd Maste 	char *passwd = pw->pw_passwd;
208*87c1498dSEd Maste #ifdef USE_SHADOW
209*87c1498dSEd Maste 	struct spwd *spw = NULL;
210*87c1498dSEd Maste #ifdef USE_LIBIAF
211*87c1498dSEd Maste 	char *iaf_passwd = NULL;
212*87c1498dSEd Maste #endif
213*87c1498dSEd Maste 
214*87c1498dSEd Maste 	spw = getspnam(pw->pw_name);
215*87c1498dSEd Maste #ifdef HAS_SHADOW_EXPIRE
216*87c1498dSEd Maste 	if (spw != NULL && auth_shadow_acctexpired(spw))
217*87c1498dSEd Maste 		return 1;
218*87c1498dSEd Maste #endif /* HAS_SHADOW_EXPIRE */
219*87c1498dSEd Maste 
220*87c1498dSEd Maste 	if (spw != NULL)
221*87c1498dSEd Maste #ifdef USE_LIBIAF
222*87c1498dSEd Maste 		iaf_passwd = passwd = get_iaf_password(pw);
223*87c1498dSEd Maste #else
224*87c1498dSEd Maste 		passwd = spw->sp_pwdp;
225*87c1498dSEd Maste #endif /* USE_LIBIAF */
226*87c1498dSEd Maste #endif
227*87c1498dSEd Maste 
228*87c1498dSEd Maste 	/* check for locked account */
229*87c1498dSEd Maste 	if (passwd && *passwd) {
230*87c1498dSEd Maste #ifdef LOCKED_PASSWD_STRING
231*87c1498dSEd Maste 		if (strcmp(passwd, LOCKED_PASSWD_STRING) == 0)
232*87c1498dSEd Maste 			locked = 1;
233*87c1498dSEd Maste #endif
234*87c1498dSEd Maste #ifdef LOCKED_PASSWD_PREFIX
235*87c1498dSEd Maste 		if (strncmp(passwd, LOCKED_PASSWD_PREFIX,
236*87c1498dSEd Maste 		    strlen(LOCKED_PASSWD_PREFIX)) == 0)
237*87c1498dSEd Maste 			locked = 1;
238*87c1498dSEd Maste #endif
239*87c1498dSEd Maste #ifdef LOCKED_PASSWD_SUBSTR
240*87c1498dSEd Maste 		if (strstr(passwd, LOCKED_PASSWD_SUBSTR))
241*87c1498dSEd Maste 			locked = 1;
242*87c1498dSEd Maste #endif
243*87c1498dSEd Maste 	}
244*87c1498dSEd Maste #ifdef USE_LIBIAF
245*87c1498dSEd Maste 	if (iaf_passwd != NULL)
246*87c1498dSEd Maste 		freezero(iaf_passwd, strlen(iaf_passwd));
247*87c1498dSEd Maste #endif /* USE_LIBIAF */
248*87c1498dSEd Maste 
249*87c1498dSEd Maste 	return locked;
250*87c1498dSEd Maste }
251