1 diff -up openssh-5.9p0/misc.c.mls openssh-5.9p0/misc.c
2 --- openssh-5.9p0/misc.c.mls 2011-05-05 06:14:34.000000000 +0200
3 +++ openssh-5.9p0/misc.c 2011-08-30 12:29:29.157087474 +0200
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.9p0/openbsd-compat/port-linux.c.mls openssh-5.9p0/openbsd-compat/port-linux.c
27 --- openssh-5.9p0/openbsd-compat/port-linux.c.mls 2011-08-30 12:29:28.873086987 +0200
28 +++ openssh-5.9p0/openbsd-compat/port-linux.c 2011-08-30 13:28:12.584149668 +0200
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 #ifndef SSH_SELINUX_UNCONFINED_TYPE
44 # define SSH_SELINUX_UNCONFINED_TYPE ":unconfined_t:"
45 @@ -51,6 +59,149 @@ extern Authctxt *the_authctxt;
46 extern int inetd_flag;
47 extern int rexeced_flag;
49 +/* Send audit message */
51 +send_audit_message(int success, security_context_t default_context,
52 + security_context_t selected_context)
55 +#ifdef HAVE_LINUX_AUDIT
57 + int audit_fd = audit_open();
58 + security_context_t default_raw=NULL;
59 + security_context_t selected_raw=NULL;
62 + if (errno == EINVAL || errno == EPROTONOSUPPORT ||
63 + errno == EAFNOSUPPORT)
64 + return 0; /* No audit support in kernel */
65 + error("Error connecting to audit system.");
68 + if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) {
69 + error("Error translating default context.");
72 + if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) {
73 + error("Error translating selected context.");
74 + selected_raw = NULL;
76 + if (asprintf(&msg, "sshd: default-context=%s selected-context=%s",
77 + default_raw ? default_raw : (default_context ? default_context: "?"),
78 + selected_context ? selected_raw : (selected_context ? selected_context :"?")) < 0) {
79 + error("Error allocating memory.");
82 + if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE,
83 + msg, NULL, NULL, NULL, success) <= 0) {
84 + error("Error sending audit message.");
90 + freecon(default_raw);
91 + freecon(selected_raw);
98 +mls_range_allowed(security_context_t src, security_context_t dst)
100 + struct av_decision avd;
102 + unsigned int bit = CONTEXT__CONTAINS;
104 + debug("%s: src:%s dst:%s", __func__, src, dst);
105 + retval = security_compute_av(src, dst, SECCLASS_CONTEXT, bit, &avd);
106 + if (retval || ((bit & avd.allowed) != bit))
113 +get_user_context(const char *sename, const char *role, const char *lvl,
114 + security_context_t *sc) {
115 +#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
116 + if (lvl == NULL || lvl[0] == '\0' || get_default_context_with_level(sename, lvl, NULL, sc) != 0) {
117 + /* User may have requested a level completely outside of his
118 + allowed range. We get a context just for auditing as the
119 + range check below will certainly fail for default context. */
121 + if (get_default_context(sename, NULL, sc) != 0) {
125 +#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
128 + if (role != NULL && role[0]) {
131 + if (get_default_type(role, &type) != 0) {
132 + error("get_default_type: failed to get default type for '%s'",
136 + con = context_new(*sc);
140 + context_role_set(con, role);
141 + context_type_set(con, type);
143 + *sc = strdup(context_str(con));
148 +#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
149 + if (lvl != NULL && lvl[0]) {
150 + /* verify that the requested range is obtained */
152 + security_context_t obtained_raw;
153 + security_context_t requested_raw;
154 + con = context_new(*sc);
158 + context_range_set(con, lvl);
159 + if (selinux_trans_to_raw_context(*sc, &obtained_raw) < 0) {
163 + if (selinux_trans_to_raw_context(context_str(con), &requested_raw) < 0) {
164 + freecon(obtained_raw);
169 + debug("get_user_context: obtained context '%s' requested context '%s'",
170 + obtained_raw, requested_raw);
171 + if (strcmp(obtained_raw, requested_raw)) {
172 + /* set the context to the real requested one but fail */
173 + freecon(requested_raw);
174 + freecon(obtained_raw);
176 + *sc = strdup(context_str(con));
180 + freecon(requested_raw);
181 + freecon(obtained_raw);
193 ssh_selinux_get_role_level(char **role, const char **level)
195 @@ -69,14 +220,15 @@ ssh_selinux_get_role_level(char **role,
198 /* Return the default security context for the given username */
199 -static security_context_t
200 -ssh_selinux_getctxbyname(char *pwname)
202 +ssh_selinux_getctxbyname(char *pwname,
203 + security_context_t *default_sc, security_context_t *user_sc)
205 - security_context_t sc = NULL;
210 + context_t con = NULL;
212 ssh_selinux_get_role_level(&role, &reqlvl);
214 @@ -87,37 +239,62 @@ ssh_selinux_getctxbyname(char *pwname)
223 #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
224 - if (role != NULL && role[0])
225 - r = get_default_context_with_rolelevel(sename, role, lvl, NULL, &sc);
227 - r = get_default_context_with_level(sename, lvl, NULL, &sc);
228 + r = get_default_context_with_level(sename, lvl, NULL, default_sc);
230 - if (role != NULL && role[0])
231 - r = get_default_context_with_role(sename, role, NULL, &sc);
233 - r = get_default_context(sename, NULL, &sc);
234 + r = get_default_context(sename, NULL, default_sc);
239 - switch (security_getenforce()) {
241 - fatal("%s: ssh_selinux_getctxbyname: "
242 - "security_getenforce() failed", __func__);
244 - error("%s: Failed to get default SELinux security "
245 - "context for %s", __func__, pwname);
248 - fatal("%s: Failed to get default SELinux security "
249 - "context for %s (in enforcing mode)",
252 + /* If launched from xinetd, we must use current level */
253 + if (inetd_flag && !rexeced_flag) {
254 + security_context_t sshdsc=NULL;
256 + if (getcon_raw(&sshdsc) < 0)
257 + fatal("failed to allocate security context");
259 + if ((con=context_new(sshdsc)) == NULL)
260 + fatal("failed to allocate selinux context");
261 + reqlvl = context_range_get(con);
263 + if (reqlvl !=NULL && lvl != NULL && strcmp(reqlvl, lvl) == 0)
264 + /* we actually don't change level */
267 + debug("%s: current connection level '%s'", __func__, reqlvl);
270 + if ((reqlvl != NULL && reqlvl[0]) || (role != NULL && role[0])) {
271 + r = get_user_context(sename, role, reqlvl, user_sc);
273 + if (r == 0 && reqlvl != NULL && reqlvl[0]) {
274 + security_context_t default_level_sc = *default_sc;
275 + if (role != NULL && role[0]) {
276 + if (get_user_context(sename, role, lvl, &default_level_sc) < 0)
277 + default_level_sc = *default_sc;
279 + /* verify that the requested range is contained in the user range */
280 + if (mls_range_allowed(default_level_sc, *user_sc)) {
281 + logit("permit MLS level %s (user range %s)", reqlvl, lvl);
284 + error("deny MLS level %s (user range %s)", reqlvl, lvl);
286 + if (default_level_sc != *default_sc)
287 + freecon(default_level_sc);
290 + *user_sc = *default_sc;
294 + error("%s: Failed to get default SELinux security "
295 + "context for %s", __func__, pwname);
298 #ifdef HAVE_GETSEUSERBYNAME
299 @@ -126,8 +303,12 @@ ssh_selinux_getctxbyname(char *pwname)
313 /* Setup environment variables for pam_selinux */
314 @@ -165,6 +346,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 @@ -189,22 +372,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 @@ -222,7 +428,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.9p0/sshd.c.mls openssh-5.9p0/sshd.c
389 --- openssh-5.9p0/sshd.c.mls 2011-08-30 12:29:22.663149706 +0200
390 +++ openssh-5.9p0/sshd.c 2011-08-30 12:29:29.524024777 +0200
391 @@ -2082,6 +2082,9 @@ main(int ac, char **av)
396 + ssh_selinux_setup_exec_context(authctxt->pw->pw_name);
399 if (options.use_pam) {