xref: /freebsd/crypto/openssh/openbsd-compat/port-linux.c (revision d4af9e693f15f5155095f38c7650b24fe74ae351)
1d4af9e69SDag-Erling Smørgrav /* $Id: port-linux.c,v 1.5 2008/03/26 20:27:21 dtucker Exp $ */
2761efaa7SDag-Erling Smørgrav 
3761efaa7SDag-Erling Smørgrav /*
4761efaa7SDag-Erling Smørgrav  * Copyright (c) 2005 Daniel Walsh <dwalsh@redhat.com>
5761efaa7SDag-Erling Smørgrav  * Copyright (c) 2006 Damien Miller <djm@openbsd.org>
6761efaa7SDag-Erling Smørgrav  *
7761efaa7SDag-Erling Smørgrav  * Permission to use, copy, modify, and distribute this software for any
8761efaa7SDag-Erling Smørgrav  * purpose with or without fee is hereby granted, provided that the above
9761efaa7SDag-Erling Smørgrav  * copyright notice and this permission notice appear in all copies.
10761efaa7SDag-Erling Smørgrav  *
11761efaa7SDag-Erling Smørgrav  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12761efaa7SDag-Erling Smørgrav  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13761efaa7SDag-Erling Smørgrav  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14761efaa7SDag-Erling Smørgrav  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15761efaa7SDag-Erling Smørgrav  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16761efaa7SDag-Erling Smørgrav  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17761efaa7SDag-Erling Smørgrav  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18761efaa7SDag-Erling Smørgrav  */
19761efaa7SDag-Erling Smørgrav 
20761efaa7SDag-Erling Smørgrav /*
21761efaa7SDag-Erling Smørgrav  * Linux-specific portability code - just SELinux support at present
22761efaa7SDag-Erling Smørgrav  */
23761efaa7SDag-Erling Smørgrav 
24761efaa7SDag-Erling Smørgrav #include "includes.h"
25761efaa7SDag-Erling Smørgrav 
26761efaa7SDag-Erling Smørgrav #include <errno.h>
27761efaa7SDag-Erling Smørgrav #include <stdarg.h>
28761efaa7SDag-Erling Smørgrav #include <string.h>
29761efaa7SDag-Erling Smørgrav 
30761efaa7SDag-Erling Smørgrav #ifdef WITH_SELINUX
31761efaa7SDag-Erling Smørgrav #include "log.h"
32761efaa7SDag-Erling Smørgrav #include "port-linux.h"
33761efaa7SDag-Erling Smørgrav 
34761efaa7SDag-Erling Smørgrav #include <selinux/selinux.h>
35761efaa7SDag-Erling Smørgrav #include <selinux/flask.h>
36761efaa7SDag-Erling Smørgrav #include <selinux/get_context_list.h>
37761efaa7SDag-Erling Smørgrav 
38761efaa7SDag-Erling Smørgrav /* Wrapper around is_selinux_enabled() to log its return value once only */
39d4af9e69SDag-Erling Smørgrav int
40761efaa7SDag-Erling Smørgrav ssh_selinux_enabled(void)
41761efaa7SDag-Erling Smørgrav {
42761efaa7SDag-Erling Smørgrav 	static int enabled = -1;
43761efaa7SDag-Erling Smørgrav 
44761efaa7SDag-Erling Smørgrav 	if (enabled == -1) {
45761efaa7SDag-Erling Smørgrav 		enabled = is_selinux_enabled();
46761efaa7SDag-Erling Smørgrav 		debug("SELinux support %s", enabled ? "enabled" : "disabled");
47761efaa7SDag-Erling Smørgrav 	}
48761efaa7SDag-Erling Smørgrav 
49761efaa7SDag-Erling Smørgrav 	return (enabled);
50761efaa7SDag-Erling Smørgrav }
51761efaa7SDag-Erling Smørgrav 
52761efaa7SDag-Erling Smørgrav /* Return the default security context for the given username */
53761efaa7SDag-Erling Smørgrav static security_context_t
54761efaa7SDag-Erling Smørgrav ssh_selinux_getctxbyname(char *pwname)
55761efaa7SDag-Erling Smørgrav {
56761efaa7SDag-Erling Smørgrav 	security_context_t sc;
57761efaa7SDag-Erling Smørgrav 	char *sename = NULL, *lvl = NULL;
58761efaa7SDag-Erling Smørgrav 	int r;
59761efaa7SDag-Erling Smørgrav 
60761efaa7SDag-Erling Smørgrav #ifdef HAVE_GETSEUSERBYNAME
61761efaa7SDag-Erling Smørgrav 	if (getseuserbyname(pwname, &sename, &lvl) != 0)
62761efaa7SDag-Erling Smørgrav 		return NULL;
63761efaa7SDag-Erling Smørgrav #else
64761efaa7SDag-Erling Smørgrav 	sename = pwname;
65761efaa7SDag-Erling Smørgrav 	lvl = NULL;
66761efaa7SDag-Erling Smørgrav #endif
67761efaa7SDag-Erling Smørgrav 
68761efaa7SDag-Erling Smørgrav #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
69761efaa7SDag-Erling Smørgrav 	r = get_default_context_with_level(sename, lvl, NULL, &sc);
70761efaa7SDag-Erling Smørgrav #else
71761efaa7SDag-Erling Smørgrav 	r = get_default_context(sename, NULL, &sc);
72761efaa7SDag-Erling Smørgrav #endif
73761efaa7SDag-Erling Smørgrav 
74761efaa7SDag-Erling Smørgrav 	if (r != 0) {
75761efaa7SDag-Erling Smørgrav 		switch (security_getenforce()) {
76761efaa7SDag-Erling Smørgrav 		case -1:
77761efaa7SDag-Erling Smørgrav 			fatal("%s: ssh_selinux_getctxbyname: "
78761efaa7SDag-Erling Smørgrav 			    "security_getenforce() failed", __func__);
79761efaa7SDag-Erling Smørgrav 		case 0:
80761efaa7SDag-Erling Smørgrav 			error("%s: Failed to get default SELinux security "
81761efaa7SDag-Erling Smørgrav 			    "context for %s", __func__, pwname);
82d4af9e69SDag-Erling Smørgrav 			break;
83761efaa7SDag-Erling Smørgrav 		default:
84761efaa7SDag-Erling Smørgrav 			fatal("%s: Failed to get default SELinux security "
85761efaa7SDag-Erling Smørgrav 			    "context for %s (in enforcing mode)",
86761efaa7SDag-Erling Smørgrav 			    __func__, pwname);
87761efaa7SDag-Erling Smørgrav 		}
88761efaa7SDag-Erling Smørgrav 	}
89761efaa7SDag-Erling Smørgrav 
90761efaa7SDag-Erling Smørgrav #ifdef HAVE_GETSEUSERBYNAME
91761efaa7SDag-Erling Smørgrav 	if (sename != NULL)
92761efaa7SDag-Erling Smørgrav 		xfree(sename);
93761efaa7SDag-Erling Smørgrav 	if (lvl != NULL)
94761efaa7SDag-Erling Smørgrav 		xfree(lvl);
95761efaa7SDag-Erling Smørgrav #endif
96761efaa7SDag-Erling Smørgrav 
97761efaa7SDag-Erling Smørgrav 	return (sc);
98761efaa7SDag-Erling Smørgrav }
99761efaa7SDag-Erling Smørgrav 
100761efaa7SDag-Erling Smørgrav /* Set the execution context to the default for the specified user */
101761efaa7SDag-Erling Smørgrav void
102761efaa7SDag-Erling Smørgrav ssh_selinux_setup_exec_context(char *pwname)
103761efaa7SDag-Erling Smørgrav {
104761efaa7SDag-Erling Smørgrav 	security_context_t user_ctx = NULL;
105761efaa7SDag-Erling Smørgrav 
106761efaa7SDag-Erling Smørgrav 	if (!ssh_selinux_enabled())
107761efaa7SDag-Erling Smørgrav 		return;
108761efaa7SDag-Erling Smørgrav 
109761efaa7SDag-Erling Smørgrav 	debug3("%s: setting execution context", __func__);
110761efaa7SDag-Erling Smørgrav 
111761efaa7SDag-Erling Smørgrav 	user_ctx = ssh_selinux_getctxbyname(pwname);
112761efaa7SDag-Erling Smørgrav 	if (setexeccon(user_ctx) != 0) {
113761efaa7SDag-Erling Smørgrav 		switch (security_getenforce()) {
114761efaa7SDag-Erling Smørgrav 		case -1:
115761efaa7SDag-Erling Smørgrav 			fatal("%s: security_getenforce() failed", __func__);
116761efaa7SDag-Erling Smørgrav 		case 0:
117761efaa7SDag-Erling Smørgrav 			error("%s: Failed to set SELinux execution "
118761efaa7SDag-Erling Smørgrav 			    "context for %s", __func__, pwname);
119d4af9e69SDag-Erling Smørgrav 			break;
120761efaa7SDag-Erling Smørgrav 		default:
121761efaa7SDag-Erling Smørgrav 			fatal("%s: Failed to set SELinux execution context "
122761efaa7SDag-Erling Smørgrav 			    "for %s (in enforcing mode)", __func__, pwname);
123761efaa7SDag-Erling Smørgrav 		}
124761efaa7SDag-Erling Smørgrav 	}
125761efaa7SDag-Erling Smørgrav 	if (user_ctx != NULL)
126761efaa7SDag-Erling Smørgrav 		freecon(user_ctx);
127761efaa7SDag-Erling Smørgrav 
128761efaa7SDag-Erling Smørgrav 	debug3("%s: done", __func__);
129761efaa7SDag-Erling Smørgrav }
130761efaa7SDag-Erling Smørgrav 
131761efaa7SDag-Erling Smørgrav /* Set the TTY context for the specified user */
132761efaa7SDag-Erling Smørgrav void
133761efaa7SDag-Erling Smørgrav ssh_selinux_setup_pty(char *pwname, const char *tty)
134761efaa7SDag-Erling Smørgrav {
135761efaa7SDag-Erling Smørgrav 	security_context_t new_tty_ctx = NULL;
136761efaa7SDag-Erling Smørgrav 	security_context_t user_ctx = NULL;
137761efaa7SDag-Erling Smørgrav 	security_context_t old_tty_ctx = NULL;
138761efaa7SDag-Erling Smørgrav 
139761efaa7SDag-Erling Smørgrav 	if (!ssh_selinux_enabled())
140761efaa7SDag-Erling Smørgrav 		return;
141761efaa7SDag-Erling Smørgrav 
142761efaa7SDag-Erling Smørgrav 	debug3("%s: setting TTY context on %s", __func__, tty);
143761efaa7SDag-Erling Smørgrav 
144761efaa7SDag-Erling Smørgrav 	user_ctx = ssh_selinux_getctxbyname(pwname);
145761efaa7SDag-Erling Smørgrav 
146761efaa7SDag-Erling Smørgrav 	/* XXX: should these calls fatal() upon failure in enforcing mode? */
147761efaa7SDag-Erling Smørgrav 
148761efaa7SDag-Erling Smørgrav 	if (getfilecon(tty, &old_tty_ctx) == -1) {
149761efaa7SDag-Erling Smørgrav 		error("%s: getfilecon: %s", __func__, strerror(errno));
150761efaa7SDag-Erling Smørgrav 		goto out;
151761efaa7SDag-Erling Smørgrav 	}
152761efaa7SDag-Erling Smørgrav 
153761efaa7SDag-Erling Smørgrav 	if (security_compute_relabel(user_ctx, old_tty_ctx,
154761efaa7SDag-Erling Smørgrav 	    SECCLASS_CHR_FILE, &new_tty_ctx) != 0) {
155761efaa7SDag-Erling Smørgrav 		error("%s: security_compute_relabel: %s",
156761efaa7SDag-Erling Smørgrav 		    __func__, strerror(errno));
157761efaa7SDag-Erling Smørgrav 		goto out;
158761efaa7SDag-Erling Smørgrav 	}
159761efaa7SDag-Erling Smørgrav 
160761efaa7SDag-Erling Smørgrav 	if (setfilecon(tty, new_tty_ctx) != 0)
161761efaa7SDag-Erling Smørgrav 		error("%s: setfilecon: %s", __func__, strerror(errno));
162761efaa7SDag-Erling Smørgrav  out:
163761efaa7SDag-Erling Smørgrav 	if (new_tty_ctx != NULL)
164761efaa7SDag-Erling Smørgrav 		freecon(new_tty_ctx);
165761efaa7SDag-Erling Smørgrav 	if (old_tty_ctx != NULL)
166761efaa7SDag-Erling Smørgrav 		freecon(old_tty_ctx);
167761efaa7SDag-Erling Smørgrav 	if (user_ctx != NULL)
168761efaa7SDag-Erling Smørgrav 		freecon(user_ctx);
169761efaa7SDag-Erling Smørgrav 	debug3("%s: done", __func__);
170761efaa7SDag-Erling Smørgrav }
171761efaa7SDag-Erling Smørgrav #endif /* WITH_SELINUX */
172