- reject connection if requested mls range is not obtained (#229278)

This commit is contained in:
Tomáš Mráz 2007-03-01 08:28:22 +00:00
parent 9d725bd1ab
commit 546fdd9f47
2 changed files with 196 additions and 49 deletions

View File

@ -1,6 +1,6 @@
--- openssh-4.5p1/openbsd-compat/port-linux.c.mls 2007-01-16 22:08:06.000000000 +0100
+++ openssh-4.5p1/openbsd-compat/port-linux.c 2007-01-16 22:11:05.000000000 +0100
@@ -33,12 +33,22 @@
--- openssh-4.5p1/openbsd-compat/port-linux.c.mls 2007-01-16 22:13:32.000000000 +0100
+++ openssh-4.5p1/openbsd-compat/port-linux.c 2007-03-01 09:04:17.000000000 +0100
@@ -33,12 +33,23 @@
#include "key.h"
#include "hostfile.h"
#include "auth.h"
@ -10,6 +10,7 @@
#include <selinux/flask.h>
+#include <selinux/context.h>
#include <selinux/get_context_list.h>
+#include <selinux/get_default_type.h>
+#include <selinux/av_permissions.h>
+
+#ifdef HAVE_LINUX_AUDIT
@ -23,7 +24,7 @@
/* Wrapper around is_selinux_enabled() to log its return value once only */
static int
@@ -54,17 +64,107 @@
@@ -54,17 +65,172 @@
return (enabled);
}
@ -93,30 +94,99 @@
+get_user_context(const char *sename, const char *role, const char *lvl,
+ security_context_t *sc) {
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
+ if (role != NULL && role[0])
+ return get_default_context_with_rolelevel(sename, role, lvl, NULL, sc);
+ else
+ return get_default_context_with_level(sename, lvl, NULL, sc);
+#else
+ if (role != NULL && role[0])
+ return get_default_context_with_role(sename, role, NULL, sc);
+ else
+ return get_default_context(sename, NULL, sc);
+ if (get_default_context_with_level(sename, lvl, NULL, sc) != 0) {
+ /* User may have requested a level completely outside of his
+ allowed range. We get a context just for auditing as the
+ range check below will certainly fail for default context. */
+#endif
+ if (get_default_context(sename, NULL, sc) != 0) {
+ *sc = NULL;
+ return -1;
+ }
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
+ }
+#endif
+ if (role != NULL && role[0]) {
+ context_t con;
+ char *type=NULL;
+ if (get_default_type(role, &type) != 0) {
+ error("get_default_type: failed to get default type for '%s'",
+ role);
+ goto out;
+ }
+ con = context_new(*sc);
+ if (!con) {
+ goto out;
+ }
+ context_role_set(con, role);
+ context_type_set(con, type);
+ freecon(*sc);
+ *sc = strdup(context_str(con));
+ context_free(con);
+ if (!*sc)
+ return -1;
+ }
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
+ if (lvl != NULL && lvl[0]) {
+ /* verify that the requested range is obtained */
+ context_t con;
+ security_context_t obtained_raw;
+ security_context_t requested_raw;
+ con = context_new(*sc);
+ if (!con) {
+ goto out;
+ }
+ context_range_set(con, lvl);
+ if (selinux_trans_to_raw_context(*sc, &obtained_raw) < 0) {
+ context_free(con);
+ goto out;
+ }
+ if (selinux_trans_to_raw_context(context_str(con), &requested_raw) < 0) {
+ freecon(obtained_raw);
+ context_free(con);
+ goto out;
+ }
+
+ debug("get_user_context: obtained context '%s' requested context '%s'",
+ obtained_raw, requested_raw);
+ if (strcmp(obtained_raw, requested_raw)) {
+ /* set the context to the real requested one but fail */
+ freecon(requested_raw);
+ freecon(obtained_raw);
+ freecon(*sc);
+ *sc = strdup(context_str(con));
+ context_free(con);
+ return -1;
+ }
+ freecon(requested_raw);
+ freecon(obtained_raw);
+ context_free(con);
+ }
+#endif
+ return 0;
+ out:
+ freecon(*sc);
+ *sc = NULL;
+ return -1;
+}
+
/* Return the default security context for the given username */
static security_context_t
ssh_selinux_getctxbyname(char *pwname)
-static security_context_t
-ssh_selinux_getctxbyname(char *pwname)
+static int
+ssh_selinux_getctxbyname(char *pwname,
+ security_context_t *default_sc, security_context_t *user_sc)
{
security_context_t sc = NULL;
+ security_context_t defsc = NULL;
- security_context_t sc = NULL;
char *sename, *lvl;
+ const char *reqlvl = NULL;
char *role = NULL;
int r = 0;
- int r = 0;
+ int r = -1;
+ context_t con = NULL;
+
+ *default_sc = NULL;
+ *user_sc = NULL;
+ if (the_authctxt) {
+ if (the_authctxt->role != NULL) {
+ char *slash;
@ -133,7 +203,7 @@
#ifdef HAVE_GETSEUSERBYNAME
if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) {
sename = NULL;
@@ -72,23 +172,49 @@
@@ -72,37 +238,56 @@
}
#else
sename = pwname;
@ -142,60 +212,76 @@
#endif
if (r == 0) {
-#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
- if (role != NULL && role[0])
- r = get_default_context_with_rolelevel(sename, role, lvl, NULL, &sc);
- else
- r = get_default_context_with_level(sename, lvl, NULL, &sc);
-#else
+ r = get_default_context_with_level(sename, lvl, NULL, default_sc);
#else
- if (role != NULL && role[0])
- r = get_default_context_with_role(sename, role, NULL, &sc);
- else
- r = get_default_context(sename, NULL, &sc);
-#endif
+ r = get_user_context(sename, role, lvl, &defsc);
+ r = get_default_context(sename, NULL, default_sc);
#endif
}
- if (r != 0) {
- switch (security_getenforce()) {
- case -1:
- fatal("%s: ssh_selinux_getctxbyname: "
- "security_getenforce() failed", __func__);
- case 0:
- error("%s: Failed to get default SELinux security "
- "context for %s", __func__, pwname);
- default:
- fatal("%s: Failed to get default SELinux security "
- "context for %s (in enforcing mode)",
- __func__, pwname);
+ if (r == 0) {
+ /* If launched from xinetd, we must use current level */
+ if (inetd_flag && !rexeced_flag) {
+ security_context_t sshdsc=NULL;
+
+ if (getcon(&sshdsc) < 0)
+ if (getcon_raw(&sshdsc) < 0)
+ fatal("failed to allocate security context");
+
+ if ((con=context_new(sshdsc)) == NULL)
+ fatal("failed to allocate selinux context");
+ reqlvl = context_range_get(con);
+ freecon(sshdsc);
+ if (reqlvl !=NULL && lvl != NULL && strcmp(reqlvl, lvl) == 0)
+ /* we actually don't change level */
+ reqlvl = "";
+
+ debug("%s: current connection level '%s'", __func__, reqlvl);
+ }
+
+ if (reqlvl != NULL && reqlvl[0]) {
+ r = get_user_context(sename, role, reqlvl, &sc);
+ if ((reqlvl != NULL && reqlvl[0]) || (role != NULL && role[0])) {
+ r = get_user_context(sename, role, reqlvl, user_sc);
+
+ if (r == 0) {
+ if (mls_range_allowed(defsc, sc)) {
+ send_audit_message(1, defsc, sc);
+ if (r == 0 && reqlvl != NULL && reqlvl[0]) {
+ /* verify that the requested range is contained in the user range */
+ if (mls_range_allowed(*default_sc, *user_sc)) {
+ logit("permit MLS level %s (user range %s)", reqlvl, lvl);
+ } else {
+ send_audit_message(0, defsc, sc);
+ if (security_getenforce() > 0)
+ fatal("deny MLS level %s (user range %s)", reqlvl, lvl);
+ else
+ error("deny MLS level %s (user range %s). Continuing in permissive mode", reqlvl, lvl);
+ r = -1;
+ error("deny MLS level %s (user range %s)", reqlvl, lvl);
+ }
+ }
+ freecon(defsc);
+ } else {
+ sc = defsc;
+ *user_sc = *default_sc;
}
}
+ if (r != 0) {
+ error("%s: Failed to get default SELinux security "
+ "context for %s", __func__, pwname);
+ }
+ }
if (r != 0) {
switch (security_getenforce()) {
case -1:
@@ -110,6 +236,10 @@
#ifdef HAVE_GETSEUSERBYNAME
if (sename != NULL)
@@ -110,14 +295,20 @@
if (lvl != NULL)
xfree(lvl);
#endif
@ -204,9 +290,67 @@
+ if (con)
+ context_free(con);
return (sc);
- return (sc);
+ return (r);
}
@@ -157,7 +287,10 @@
/* Set the execution context to the default for the specified user */
void
ssh_selinux_setup_exec_context(char *pwname)
{
+ int r = 0;
+ security_context_t default_ctx = NULL;
security_context_t user_ctx = NULL;
if (!ssh_selinux_enabled())
@@ -125,21 +316,39 @@
debug3("%s: setting execution context", __func__);
- user_ctx = ssh_selinux_getctxbyname(pwname);
- if (setexeccon(user_ctx) != 0) {
+ r = ssh_selinux_getctxbyname(pwname, &default_ctx, &user_ctx);
+ if (r >= 0) {
+ r = setexeccon(user_ctx);
+ if (r < 0) {
+ error("%s: Failed to set SELinux execution context %s for %s",
+ __func__, user_ctx, pwname);
+ }
+ }
+ if (user_ctx == NULL) {
+ user_ctx = default_ctx;
+ }
+ if (r < 0 || user_ctx != default_ctx) {
+ /* audit just the case when user changed a role or there was
+ a failure */
+ send_audit_message(r >= 0, default_ctx, user_ctx);
+ }
+ if (r < 0) {
switch (security_getenforce()) {
case -1:
fatal("%s: security_getenforce() failed", __func__);
case 0:
- error("%s: Failed to set SELinux execution "
- "context for %s", __func__, pwname);
+ error("%s: SELinux failure. Continuing in permissive mode.",
+ __func__);
+ break;
default:
- fatal("%s: Failed to set SELinux execution context "
- "for %s (in enforcing mode)", __func__, pwname);
+ fatal("%s: SELinux failure. Aborting connection.",
+ __func__);
}
}
- if (user_ctx != NULL)
+ if (user_ctx != NULL && user_ctx != default_ctx)
freecon(user_ctx);
+ if (default_ctx != NULL)
+ freecon(default_ctx);
debug3("%s: done", __func__);
}
@@ -157,7 +366,10 @@
debug3("%s: setting TTY context on %s", __func__, tty);
@ -218,8 +362,8 @@
/* XXX: should these calls fatal() upon failure in enforcing mode? */
--- openssh-4.5p1/sshd.c.mls 2007-01-16 21:43:11.000000000 +0100
+++ openssh-4.5p1/sshd.c 2007-01-16 21:48:37.000000000 +0100
--- openssh-4.5p1/sshd.c.mls 2007-01-16 22:13:32.000000000 +0100
+++ openssh-4.5p1/sshd.c 2007-01-16 22:13:32.000000000 +0100
@@ -1833,6 +1833,9 @@
restore_uid();
}
@ -231,7 +375,7 @@
if (options.use_pam) {
do_pam_setcred(1);
--- openssh-4.5p1/misc.c.mls 2006-08-05 04:39:40.000000000 +0200
+++ openssh-4.5p1/misc.c 2007-01-16 21:56:40.000000000 +0100
+++ openssh-4.5p1/misc.c 2007-01-16 22:13:32.000000000 +0100
@@ -418,6 +418,7 @@
colon(char *cp)
{
@ -256,8 +400,8 @@
}
return (0);
}
--- openssh-4.5p1/session.c.mls 2007-01-16 21:43:11.000000000 +0100
+++ openssh-4.5p1/session.c 2007-01-16 21:46:35.000000000 +0100
--- openssh-4.5p1/session.c.mls 2007-01-16 22:13:32.000000000 +0100
+++ openssh-4.5p1/session.c 2007-01-16 22:13:32.000000000 +0100
@@ -1347,10 +1347,6 @@
#endif
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)

View File

@ -61,7 +61,7 @@
Summary: The OpenSSH implementation of SSH protocol versions 1 and 2
Name: openssh
Version: 4.5p1
Release: 3%{?dist}%{?rescue_rel}
Release: 4%{?dist}%{?rescue_rel}
URL: http://www.openssh.com/portable.html
#Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz
#Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.sig
@ -459,6 +459,9 @@ fi
%endif
%changelog
* Thu Feb 27 2007 Tomas Mraz <tmraz@redhat.com> - 4.5p1-4
- reject connection if requested mls range is not obtained (#229278)
* Wed Feb 22 2007 Tomas Mraz <tmraz@redhat.com> - 4.5p1-3
- improve Buildroot
- remove duplicate /etc/ssh from files