From 24e456a510a2c7f7021e3d6e1c2341d83b9d5401 Mon Sep 17 00:00:00 2001 From: Enrico Scholz Date: Wed, 7 Nov 2018 13:53:10 +0100 Subject: [PATCH] added selinu support Commit adds SELinux support to dropbear by: - adding a new '--enable-selinux' option to configure; by default, it is disabled. This option defines an ENABLE_SELINUX preprocessor macro. - mapping the unix username to the SELinux user which is stored in a new 'user_sid' attribute in the AuthState object - relabeling the controlling pty - setting the context for the next execve() call to the user_sid Operations above will not be done when SELinux is disabled. Failures will generate LOG_ERR messages and in enforcing SELinux mode, dropbear_exit() will be called. Signed-off-by: Enrico Scholz --- svr-chansession.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/svr-chansession.c b/svr-chansession.c index faf62e5c4..390260b61 100644 --- a/svr-chansession.c +++ b/svr-chansession.c @@ -38,6 +38,10 @@ #include "runopts.h" #include "auth.h" +#ifdef ENABLE_SELINUX +# include +#endif + /* Handles sessions (either shells or programs) requested by the client */ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess, @@ -556,6 +560,48 @@ static void get_termmodes(const struct ChanSess *chansess) { TRACE(("leave get_termmodes")) } +static void relabelpty(const char *tty) +{ +#ifdef ENABLE_SELINUX + char *old_sid = NULL; + char *new_sid = NULL; + security_class_t class; + int rc; + + if (!is_selinux_enabled()) + return; + + rc = getfilecon(tty, &old_sid); + if (rc < 0) { + dropbear_log(LOG_ERR, "failed to get context of tty '%s'", tty); + goto out; + } + + class = string_to_security_class("chr_file"); + + rc = security_compute_relabel(ses.authstate.user_sid, old_sid, class, &new_sid); + if (rc < 0) { + dropbear_log(LOG_ERR, "failed to compute tty relabel"); + goto out; + } + + rc = setfilecon(tty, new_sid); + if (rc < 0) { + dropbear_log(LOG_ERR, "failed to set file context for '%s'", tty); + goto out; + } + + rc = 0; + +out: + freecon(new_sid); + freecon(old_sid); + + if (rc < 0 && security_getenforce() > 0) + dropbear_exit("SELinux: failed to relabel PTY"); +#endif +} + /* Set up a session pty which will be used to execute the shell or program. * The pty is allocated now, and kept for when the shell/program executes. * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ @@ -604,6 +650,8 @@ static int sessionpty(struct ChanSess * chansess) { /* Read the terminal modes */ get_termmodes(chansess); + relabelpty(chansess->tty); + TRACE(("leave sessionpty")) return DROPBEAR_SUCCESS; } @@ -726,6 +774,31 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess, return ret; } +static void init_selinux_session(void) +{ +#ifdef ENABLE_SELINUX + char *ctx = ses.authstate.user_sid; + int rc; + unsigned int i; + security_class_t class; + + if (!is_selinux_enabled()) + return; + + rc = setexeccon(ctx); + if (rc < 0) { + dropbear_log(LOG_ERR, "setexeccon() failed"); + goto out; + } + + rc = 0; + +out: + if (rc < 0 && security_getenforce() > 0) + dropbear_exit("SELinux: failed to initialize session"); +#endif +} + /* Execute a command and set up redirection of stdin/stdout/stderr without a * pty. * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ @@ -932,6 +1005,8 @@ static void execchild(const void *user_data) { #endif /* HAVE_CLEARENV */ #endif /* DEBUG_VALGRIND */ + init_selinux_session(); + /* We can only change uid/gid as root ... */ if (getuid() == 0) {