rpms/openssh/FC-6 openssh-4.3p2-mls.patch, NONE, 1.1 openssh-4.3p2-selinux-rolechg.patch, NONE, 1.1

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Thu Mar 1 12:09:42 UTC 2007


Author: tmraz

Update of /cvs/dist/rpms/openssh/FC-6
In directory cvs.devel.redhat.com:/tmp/cvs-serv22979

Added Files:
	openssh-4.3p2-mls.patch openssh-4.3p2-selinux-rolechg.patch 
Log Message:
- sync with RHEL-5


openssh-4.3p2-mls.patch:
 selinux.c |  159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 session.c |    2 
 sshd.c    |    2 
 3 files changed, 149 insertions(+), 14 deletions(-)

--- NEW FILE openssh-4.3p2-mls.patch ---
--- openssh-4.3p2/selinux.c.mls	2007-01-11 14:22:40.000000000 +0100
+++ openssh-4.3p2/selinux.c	2007-01-11 20:25:27.000000000 +0100
@@ -1,6 +1,7 @@
 #include "includes.h"
 #include "auth.h"
 #include "log.h"
+#include "xmalloc.h"
 
 #ifdef WITH_SELINUX
 #include <selinux/selinux.h>
@@ -8,23 +9,147 @@
 #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
+#include <libaudit.h>
+#include <sys/select.h>
+#include <errno.h>
+#endif
+
 extern Authctxt *the_authctxt;
+extern int inetd_flag;
+extern int rexeced_flag;
+
+/* Send audit message */
+static int send_audit_message(int success, security_context_t default_context,
+		       security_context_t selected_context)
+{
+	int rc=0;
+#ifdef HAVE_LINUX_AUDIT
+	char *msg = NULL;
+	int audit_fd = audit_open();
+	security_context_t default_raw=NULL;
+	security_context_t selected_raw=NULL;
+	rc = -1;
+	if (audit_fd < 0) {
+		if (errno == EINVAL || errno == EPROTONOSUPPORT ||
+                                        errno == EAFNOSUPPORT)
+                        return 0; /* No audit support in kernel */
+		error("Error connecting to audit system.");
+		return rc;
+	}
+	if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) {
+		error("Error translating default context.");
+		goto out;
+	}
+	if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) {
+		error("Error translating selected context.");
+		goto out;
+	}
+	if (asprintf(&msg, "sshd: default-context=%s selected-context=%s",
+		     default_context ? default_raw : "?",
+		     selected_context ? selected_raw : "?") < 0) {
+		error("Error allocating memory.");
+		goto out;
+	}
+	if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE,
+				   msg, NULL, NULL, NULL, success) <= 0) {
+		error("Error sending audit message.");
+		goto out;
+	}
+	rc = 0;
+      out:
+	free(msg);
+	freecon(default_raw);
+	freecon(selected_raw);
+	close(audit_fd);
+#endif
+	return rc;
+}
+/* from Linux-PAM-0.99.6.2/modules/pam_selinux/pam_selinux.c */
+static int mls_range_allowed(security_context_t src, security_context_t dst)
+{
+	struct av_decision avd;
+	int retval;
+	unsigned int bit = CONTEXT__CONTAINS;
+
+	retval = security_compute_av(src, dst, SECCLASS_CONTEXT, bit, &avd);
+	if (retval || ((bit & avd.allowed) != bit))
+		return 0;
+
+	return 1;
+}
+
+static int get_user_context(const char *user, const char *role, const char *level,
+	security_context_t *context) {
+	if (role != NULL && role[0]) 
+		return get_default_context_with_rolelevel(user, role, level, NULL, context);
+	else
+		return get_default_context_with_level(user, level, NULL, context);
+}
 
 static const security_context_t selinux_get_user_context(const char *name) {
 	security_context_t user_context=NULL;
+	security_context_t default_context=NULL;
+	char *seuser=NULL;
 	char *role=NULL;
 	int ret=-1;
-	char *seuser=NULL;
-	char *level=NULL;
-
-	if (the_authctxt) 
-		role=the_authctxt->role;
+	char *dlevel=NULL;
+	const char *rlevel=NULL;
+	context_t con=NULL;
+
+	if (the_authctxt) {
+		if (the_authctxt->role != NULL) {
+			char *slash;
+			role = xstrdup(the_authctxt->role);
+			if ((slash = strchr(role, '/')) != NULL) {
+				*slash = '\0';
+				rlevel = slash + 1;
+			}
+		}
+	}
+	
+	ret = getseuserbyname(name, &seuser, &dlevel);
+	
+	if (ret >= 0) {
+		ret = get_user_context(seuser, role, dlevel, &default_context);
+	}
+	
+	if (ret >= 0) {
+		/* If launched from xinetd, we must use current level */
+		if (inetd_flag && !rexeced_flag) {
+			security_context_t sshd_context=NULL;
+
+			if (getcon(&sshd_context) < 0)
+				fatal("failed to allocate security context");
+
+			con = context_new(sshd_context);
+			rlevel = context_range_get(con);
+			freecon(sshd_context);
 
-	if (getseuserbyname(name, &seuser, &level)==0) {
-		if (role != NULL && role[0]) 
-			ret=get_default_context_with_rolelevel(seuser, role, level,NULL,&user_context);
-		else
-			ret=get_default_context_with_level(seuser, level, NULL,&user_context);
+			debug("selinux_get_user_context: current connection level '%s'", rlevel);
+		}
+		
+		if (rlevel != NULL && rlevel[0]) {
+			ret = get_user_context(seuser, role, rlevel, &user_context);
+		
+			if (ret >= 0) {
+				if (mls_range_allowed(default_context, user_context)) {
+					send_audit_message(1, default_context, user_context);
+					logit("permit MLS level %s (user range %s)", rlevel, dlevel);
+				} else {
+					send_audit_message(0, default_context, user_context);
+					if (security_getenforce() > 0) 
+						fatal("deny MLS level %s (user range %s)", rlevel, dlevel);
+					else 
+						error("deny MLS level %s (user range %s). Continuing in permissive mode", rlevel, dlevel);
+				}
+			}
+			freecon(default_context);
+		} else {
+			user_context = default_context;
+		}
 	}
 
 	if ( ret < 0 ) {
@@ -32,7 +157,13 @@
 			fatal("Failed to get default security context for %s.", name);
 		else 
 			error("Failed to get default security context for %s. Continuing in permissive mode", name);
-	} 
+	}
+	
+	if (con)
+		context_free(con);
+	free(role);
+	free(seuser);
+	free(dlevel);
 	return user_context;
 }
 
@@ -40,11 +171,15 @@
 	if (is_selinux_enabled() > 0) {
 		security_context_t new_tty_context=NULL, user_context=NULL, old_tty_context=NULL; 
 
-		user_context=selinux_get_user_context(name);
+		if (getexeccon(&user_context) < 0) {
+			error("getexeccon() failed: %.100s", strerror(errno));
+			return;
+		}
 
 		if (getfilecon(tty, &old_tty_context) < 0) {
 			error("getfilecon(%.100s) failed: %.100s", tty, strerror(errno));
 		} else {
+			debug("user_context: %s old_tty_context: %s", user_context, old_tty_context);
 			if (security_compute_relabel(user_context,old_tty_context,
 						     SECCLASS_CHR_FILE,
 						     &new_tty_context) != 0) {
--- openssh-4.3p2/sshd.c.mls	2007-01-11 14:22:40.000000000 +0100
+++ openssh-4.3p2/sshd.c	2007-01-11 14:22:40.000000000 +0100
@@ -85,6 +85,7 @@
 #include "monitor.h"
 #include "monitor_wrap.h"
 #include "monitor_fdpass.h"
+#include "selinux.h"
 
 #ifdef LIBWRAP
 #include <tcpd.h>
@@ -1752,6 +1753,7 @@
 		restore_uid();
 	}
 #endif
+	setup_selinux_exec_context(authctxt->pw->pw_name); 
 #ifdef USE_PAM
 	if (options.use_pam) {
 		do_pam_setcred(1);
--- openssh-4.3p2/session.c.mls	2007-01-11 14:22:40.000000000 +0100
+++ openssh-4.3p2/session.c	2007-01-11 14:22:40.000000000 +0100
@@ -1313,8 +1313,6 @@
 #endif
 	if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
 		fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
-
-	setup_selinux_exec_context(pw->pw_name);
 }
 
 static void

openssh-4.3p2-selinux-rolechg.patch:
 selinux.c |  151 +++++++++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 116 insertions(+), 35 deletions(-)

--- NEW FILE openssh-4.3p2-selinux-rolechg.patch ---
--- openssh-4.3p2/selinux.c.rolechg	2007-02-27 20:56:16.000000000 +0100
+++ openssh-4.3p2/selinux.c	2007-02-27 21:42:09.000000000 +0100
@@ -82,16 +82,80 @@
 }
 
 static int get_user_context(const char *user, const char *role, const char *level,
-	security_context_t *context) {
-	if (role != NULL && role[0]) 
-		return get_default_context_with_rolelevel(user, role, level, NULL, context);
-	else
-		return get_default_context_with_level(user, level, NULL, context);
+			    security_context_t *context) {
+	if (get_default_context_with_level(user, level, NULL, context) != 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. */
+		if (get_default_context(user, NULL, context) != 0) {
+			*context = NULL;
+			return -1;
+		}
+	}
+	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(*context);
+		if (!con) {
+			goto out;
+		}
+		context_role_set(con, role);
+		context_type_set(con, type);
+		freecon(*context);
+		*context = strdup(context_str(con));
+		context_free(con);
+		if (!*context) 
+			return -1;
+	}
+	if (level != NULL && level[0]) {
+		/* verify that the requested range is obtained */
+		context_t con;
+		security_context_t obtained_raw;
+		security_context_t requested_raw;
+		con = context_new(*context);
+		if (!con) {
+			goto out;
+		}
+		context_range_set(con, level);
+		if (selinux_trans_to_raw_context(*context, &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(*context);
+			*context = strdup(context_str(con));
+			context_free(con);
+			return -1;
+		}
+		freecon(requested_raw);
+		freecon(obtained_raw);
+		context_free(con);
+	}
+	return 0;
+      out:
+        freecon(*context);
+        *context = NULL;
+        return -1;
 }
 
-static const security_context_t selinux_get_user_context(const char *name) {
-	security_context_t user_context=NULL;
-	security_context_t default_context=NULL;
+static int selinux_get_user_context(const char *name,
+	security_context_t *default_context, security_context_t *user_context) {
 	char *seuser=NULL;
 	char *role=NULL;
 	int ret=-1;
@@ -99,6 +163,8 @@
 	const char *rlevel=NULL;
 	context_t con=NULL;
 
+	*default_context = NULL;
+	*user_context = NULL;
 	if (the_authctxt) {
 		if (the_authctxt->role != NULL) {
 			char *slash;
@@ -113,7 +179,7 @@
 	ret = getseuserbyname(name, &seuser, &dlevel);
 	
 	if (ret >= 0) {
-		ret = get_user_context(seuser, role, dlevel, &default_context);
+		ret = get_default_context_with_level(seuser, dlevel, NULL, default_context);
 	}
 	
 	if (ret >= 0) {
@@ -121,42 +187,38 @@
 		if (inetd_flag && !rexeced_flag) {
 			security_context_t sshd_context=NULL;
 
-			if (getcon(&sshd_context) < 0)
+			if (getcon_raw(&sshd_context) < 0)
 				fatal("failed to allocate security context");
 
 			con = context_new(sshd_context);
 			rlevel = context_range_get(con);
 			freecon(sshd_context);
-
+			if (rlevel !=NULL && dlevel != NULL && strcmp(rlevel, dlevel) == 0)
+			    /* we actually don't change level */
+			    rlevel = NULL;
+			
 			debug("selinux_get_user_context: current connection level '%s'", rlevel);
 		}
 		
-		if (rlevel != NULL && rlevel[0]) {
-			ret = get_user_context(seuser, role, rlevel, &user_context);
+		if ((rlevel != NULL && rlevel[0]) || (role != NULL && role[0])) {
+			ret = get_user_context(seuser, role, rlevel, user_context);
 		
-			if (ret >= 0) {
-				if (mls_range_allowed(default_context, user_context)) {
-					send_audit_message(1, default_context, user_context);
+			if (ret >= 0 && rlevel != NULL && rlevel[0]) {
+				/* verify that the requested range is contained in the user range */
+				if (mls_range_allowed(*default_context, *user_context)) {
 					logit("permit MLS level %s (user range %s)", rlevel, dlevel);
 				} else {
-					send_audit_message(0, default_context, user_context);
-					if (security_getenforce() > 0) 
-						fatal("deny MLS level %s (user range %s)", rlevel, dlevel);
-					else 
-						error("deny MLS level %s (user range %s). Continuing in permissive mode", rlevel, dlevel);
+					ret = -1;
+					error("deny MLS level %s (user range %s)", rlevel, dlevel);
 				}
 			}
-			freecon(default_context);
 		} else {
-			user_context = default_context;
+			*user_context = *default_context;
 		}
 	}
 
 	if ( ret < 0 ) {
-		if (security_getenforce() > 0) 
-			fatal("Failed to get default security context for %s.", name);
-		else 
-			error("Failed to get default security context for %s. Continuing in permissive mode", name);
+		error("Failed to get default security context for %s.", name);
 	}
 	
 	if (con)
@@ -164,7 +226,7 @@
 	free(role);
 	free(seuser);
 	free(dlevel);
-	return user_context;
+	return ret;
 }
 
 void setup_selinux_pty(const char *name, const char *tty) {
@@ -201,18 +263,37 @@
 }
 
 void setup_selinux_exec_context(char *name) {
-
 	if (is_selinux_enabled() > 0) {
-		security_context_t user_context=selinux_get_user_context(name);
-		if (setexeccon(user_context)) {
-			if (security_getenforce() > 0) 
-				fatal("Failed to set exec security context %s for %s.", user_context, name);
+		int ret = 0;
+		security_context_t default_context = NULL;
+		security_context_t user_context = NULL;
+		ret = selinux_get_user_context(name, &default_context, &user_context);
+		if (ret >= 0) {
+			ret = setexeccon(user_context);
+			if (ret < 0) {
+				error("Failed to set exec security context %s for %s.", user_context, name);
+			}
+		}
+		if (user_context == NULL) {
+			user_context = default_context;
+		}
+		if (ret < 0 || user_context != default_context) {
+			/* audit just the case when user changed a role or there was
+			   a failure */
+			send_audit_message(ret >= 0, default_context, user_context);
+		}
+		if (ret < 0) {
+			if (security_getenforce() > 0)
+				fatal("SELinux failure. Aborting connection.");
 			else 
-				error("Failed to set exec security context %s for %s. Continuing in permissive mode", user_context, name);
+				error("SELinux failure. Continuing in permissive mode.");
 		}
-		if (user_context) {
+		if (user_context && user_context != default_context) {
 			freecon(user_context);
 		}
+		if (default_context) {
+			freecon(default_context);
+		}
 	}
 }
 




More information about the fedora-cvs-commits mailing list