1 diff -up openssh-5.8p1/misc.c.mls openssh-5.8p1/misc.c
2 --- openssh-5.8p1/misc.c.mls 2011-01-13 02:21:36.000000000 +0100
3 +++ openssh-5.8p1/misc.c 2011-02-12 15:05:06.000000000 +0100
4 @@ -427,6 +427,7 @@ char *
10 if (*cp == ':') /* Leading colon is part of file name. */
12 @@ -442,6 +443,13 @@ colon(char *cp)
17 + /* Slash on beginning or after dots only denotes file name. */
26 diff -up openssh-5.8p1/openbsd-compat/port-linux.c.mls openssh-5.8p1/openbsd-compat/port-linux.c
27 --- openssh-5.8p1/openbsd-compat/port-linux.c.mls 2011-02-12 15:05:06.000000000 +0100
28 +++ openssh-5.8p1/openbsd-compat/port-linux.c 2011-02-12 15:09:23.000000000 +0100
31 #include <selinux/selinux.h>
32 #include <selinux/flask.h>
33 +#include <selinux/context.h>
34 #include <selinux/get_context_list.h>
35 +#include <selinux/get_default_type.h>
36 +#include <selinux/av_permissions.h>
38 +#ifdef HAVE_LINUX_AUDIT
39 +#include <libaudit.h>
43 extern ServerOptions options;
44 extern Authctxt *the_authctxt;
45 extern int inetd_flag;
46 extern int rexeced_flag;
48 +/* Send audit message */
50 +send_audit_message(int success, security_context_t default_context,
51 + security_context_t selected_context)
54 +#ifdef HAVE_LINUX_AUDIT
56 + int audit_fd = audit_open();
57 + security_context_t default_raw=NULL;
58 + security_context_t selected_raw=NULL;
61 + if (errno == EINVAL || errno == EPROTONOSUPPORT ||
62 + errno == EAFNOSUPPORT)
63 + return 0; /* No audit support in kernel */
64 + error("Error connecting to audit system.");
67 + if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) {
68 + error("Error translating default context.");
71 + if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) {
72 + error("Error translating selected context.");
73 + selected_raw = NULL;
75 + if (asprintf(&msg, "sshd: default-context=%s selected-context=%s",
76 + default_raw ? default_raw : (default_context ? default_context: "?"),
77 + selected_context ? selected_raw : (selected_context ? selected_context :"?")) < 0) {
78 + error("Error allocating memory.");
81 + if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE,
82 + msg, NULL, NULL, NULL, success) <= 0) {
83 + error("Error sending audit message.");
89 + freecon(default_raw);
90 + freecon(selected_raw);
97 +mls_range_allowed(security_context_t src, security_context_t dst)
99 + struct av_decision avd;
101 + unsigned int bit = CONTEXT__CONTAINS;
103 + debug("%s: src:%s dst:%s", __func__, src, dst);
104 + retval = security_compute_av(src, dst, SECCLASS_CONTEXT, bit, &avd);
105 + if (retval || ((bit & avd.allowed) != bit))
112 +get_user_context(const char *sename, const char *role, const char *lvl,
113 + security_context_t *sc) {
114 +#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
115 + if (lvl == NULL || lvl[0] == '\0' || get_default_context_with_level(sename, lvl, NULL, sc) != 0) {
116 + /* User may have requested a level completely outside of his
117 + allowed range. We get a context just for auditing as the
118 + range check below will certainly fail for default context. */
120 + if (get_default_context(sename, NULL, sc) != 0) {
124 +#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
127 + if (role != NULL && role[0]) {
130 + if (get_default_type(role, &type) != 0) {
131 + error("get_default_type: failed to get default type for '%s'",
135 + con = context_new(*sc);
139 + context_role_set(con, role);
140 + context_type_set(con, type);
142 + *sc = strdup(context_str(con));
147 +#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
148 + if (lvl != NULL && lvl[0]) {
149 + /* verify that the requested range is obtained */
151 + security_context_t obtained_raw;
152 + security_context_t requested_raw;
153 + con = context_new(*sc);
157 + context_range_set(con, lvl);
158 + if (selinux_trans_to_raw_context(*sc, &obtained_raw) < 0) {
162 + if (selinux_trans_to_raw_context(context_str(con), &requested_raw) < 0) {
163 + freecon(obtained_raw);
168 + debug("get_user_context: obtained context '%s' requested context '%s'",
169 + obtained_raw, requested_raw);
170 + if (strcmp(obtained_raw, requested_raw)) {
171 + /* set the context to the real requested one but fail */
172 + freecon(requested_raw);
173 + freecon(obtained_raw);
175 + *sc = strdup(context_str(con));
179 + freecon(requested_raw);
180 + freecon(obtained_raw);
192 ssh_selinux_get_role_level(char **role, const char **level)
194 @@ -65,14 +216,16 @@ ssh_selinux_get_role_level(char **role,
197 /* Return the default security context for the given username */
198 -static security_context_t
199 -ssh_selinux_getctxbyname(char *pwname)
201 +ssh_selinux_getctxbyname(char *pwname,
202 + security_context_t *default_sc, security_context_t *user_sc)
204 security_context_t sc = NULL;
211 ssh_selinux_get_role_level(&role, &reqlvl);
212 #ifdef HAVE_GETSEUSERBYNAME
213 @@ -82,38 +235,63 @@ ssh_selinux_getctxbyname(char *pwname)
222 #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
223 - if (role != NULL && role[0])
224 - r = get_default_context_with_rolelevel(sename, role, lvl, NULL, &sc);
226 - r = get_default_context_with_level(sename, lvl, NULL, &sc);
227 + r = get_default_context_with_level(sename, lvl, NULL, default_sc);
229 - if (role != NULL && role[0])
230 - r = get_default_context_with_role(sename, role, NULL, &sc);
232 - r = get_default_context(sename, NULL, &sc);
233 + r = get_default_context(sename, NULL, default_sc);
238 - switch (security_getenforce()) {
240 - fatal("%s: ssh_selinux_getctxbyname: "
241 - "security_getenforce() failed", __func__);
243 - error("%s: Failed to get default SELinux security "
244 - "context for %s", __func__, pwname);
247 - fatal("%s: Failed to get default SELinux security "
248 - "context for %s (in enforcing mode)",
251 + /* If launched from xinetd, we must use current level */
252 + if (inetd_flag && !rexeced_flag) {
253 + security_context_t sshdsc=NULL;
255 + if (getcon_raw(&sshdsc) < 0)
256 + fatal("failed to allocate security context");
258 + if ((con=context_new(sshdsc)) == NULL)
259 + fatal("failed to allocate selinux context");
260 + reqlvl = context_range_get(con);
262 + if (reqlvl !=NULL && lvl != NULL && strcmp(reqlvl, lvl) == 0)
263 + /* we actually don't change level */
266 + debug("%s: current connection level '%s'", __func__, reqlvl);
269 + if ((reqlvl != NULL && reqlvl[0]) || (role != NULL && role[0])) {
270 + r = get_user_context(sename, role, reqlvl, user_sc);
272 + if (r == 0 && reqlvl != NULL && reqlvl[0]) {
273 + security_context_t default_level_sc = *default_sc;
274 + if (role != NULL && role[0]) {
275 + if (get_user_context(sename, role, lvl, &default_level_sc) < 0)
276 + default_level_sc = *default_sc;
278 + /* verify that the requested range is contained in the user range */
279 + if (mls_range_allowed(default_level_sc, *user_sc)) {
280 + logit("permit MLS level %s (user range %s)", reqlvl, lvl);
283 + error("deny MLS level %s (user range %s)", reqlvl, lvl);
285 + if (default_level_sc != *default_sc)
286 + freecon(default_level_sc);
289 + *user_sc = *default_sc;
293 + error("%s: Failed to get default SELinux security "
294 + "context for %s", __func__, pwname);
297 #ifdef HAVE_GETSEUSERBYNAME
299 @@ -121,8 +299,12 @@ ssh_selinux_getctxbyname(char *pwname)
313 /* Setup environment variables for pam_selinux */
314 @@ -160,6 +342,8 @@ void
315 ssh_selinux_setup_exec_context(char *pwname)
317 security_context_t user_ctx = NULL;
319 + security_context_t default_ctx = NULL;
321 if (!ssh_selinux_enabled())
323 @@ -184,22 +368,45 @@ ssh_selinux_setup_exec_context(char *pwn
325 debug3("%s: setting execution context", __func__);
327 - user_ctx = ssh_selinux_getctxbyname(pwname);
328 - if (setexeccon(user_ctx) != 0) {
329 + r = ssh_selinux_getctxbyname(pwname, &default_ctx, &user_ctx);
331 + r = setexeccon(user_ctx);
333 + error("%s: Failed to set SELinux execution context %s for %s",
334 + __func__, user_ctx, pwname);
336 +#ifdef HAVE_SETKEYCREATECON
337 + else if (setkeycreatecon(user_ctx) < 0) {
338 + error("%s: Failed to set SELinux keyring creation context %s for %s",
339 + __func__, user_ctx, pwname);
343 + if (user_ctx == NULL) {
344 + user_ctx = default_ctx;
346 + if (r < 0 || user_ctx != default_ctx) {
347 + /* audit just the case when user changed a role or there was
349 + send_audit_message(r >= 0, default_ctx, user_ctx);
352 switch (security_getenforce()) {
354 fatal("%s: security_getenforce() failed", __func__);
356 - error("%s: Failed to set SELinux execution "
357 - "context for %s", __func__, pwname);
358 + error("%s: SELinux failure. Continuing in permissive mode.",
362 - fatal("%s: Failed to set SELinux execution context "
363 - "for %s (in enforcing mode)", __func__, pwname);
364 + fatal("%s: SELinux failure. Aborting connection.",
368 - if (user_ctx != NULL)
369 + if (user_ctx != NULL && user_ctx != default_ctx)
371 + if (default_ctx != NULL)
372 + freecon(default_ctx);
374 debug3("%s: done", __func__);
376 @@ -217,7 +424,10 @@ ssh_selinux_setup_pty(char *pwname, cons
378 debug3("%s: setting TTY context on %s", __func__, tty);
380 - user_ctx = ssh_selinux_getctxbyname(pwname);
381 + if (getexeccon(&user_ctx) < 0) {
382 + error("%s: getexeccon: %s", __func__, strerror(errno));
386 /* XXX: should these calls fatal() upon failure in enforcing mode? */
388 diff -up openssh-5.8p1/sshd.c.mls openssh-5.8p1/sshd.c
389 --- openssh-5.8p1/sshd.c.mls 2011-02-12 15:05:05.000000000 +0100
390 +++ openssh-5.8p1/sshd.c 2011-02-12 15:05:06.000000000 +0100
391 @@ -2011,6 +2011,9 @@ main(int ac, char **av)
396 + ssh_selinux_setup_exec_context(authctxt->pw->pw_name);
399 if (options.use_pam) {