Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added selinux support #70

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ CFLAGS+=-I$(srcdir)/libtomcrypt/src/headers/
LIBTOM_LIBS=$(STATIC_LTC) $(STATIC_LTM)
endif

LIBSELINUX_LIBS=@LIBSELINUX_LIBS@

OPTION_HEADERS = default_options_guard.h sysoptions.h
ifneq ($(wildcard localoptions.h),)
CFLAGS+=-DLOCALOPTIONS_H_EXISTS
Expand Down Expand Up @@ -189,7 +191,7 @@ dropbearkey: $(dropbearkeyobjs)
dropbearconvert: $(dropbearconvertobjs)

dropbear: $(HEADERS) $(LIBTOM_DEPS) Makefile
$(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS) $(LIBS) @CRYPTLIB@
$(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS) $(LIBSELINUX_LIBS) $(LIBS) @CRYPTLIB@

dbclient: $(HEADERS) $(LIBTOM_DEPS) Makefile
$(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS) $(LIBS)
Expand All @@ -210,7 +212,7 @@ ifeq ($(MULTI),1)
endif

dropbearmulti$(EXEEXT): $(HEADERS) $(MULTIOBJS) $(LIBTOM_DEPS) Makefile
$(CC) $(LDFLAGS) -o $@ $(MULTIOBJS) $(LIBTOM_LIBS) $(LIBS) @CRYPTLIB@
$(CC) $(LDFLAGS) -o $@ $(MULTIOBJS) $(LIBTOM_LIBS) $(LIBSELINUX_LIBS) $(LIBS) @CRYPTLIB@

multibinary: dropbearmulti$(EXEEXT)

Expand Down
4 changes: 4 additions & 0 deletions auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ struct AuthState {
#if DROPBEAR_SVR_PUBKEY_OPTIONS_BUILT
struct PubKeyOptions* pubkey_options;
#endif

#ifdef DROPBEAR_ENABLE_SELINUX
char *user_sid;
#endif
};

#if DROPBEAR_SVR_PUBKEY_OPTIONS_BUILT
Expand Down
4 changes: 4 additions & 0 deletions common-session.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ void common_session_init(int sock_in, int sock_out) {
ses.keys->trans.zstream = NULL;
#endif

#ifdef DROPBEAR_ENABLE_SELINUX
ses.authstate.user_sid = NULL;
#endif

/* key exchange buffers */
ses.session_id = NULL;
ses.kexhashbuf = NULL;
Expand Down
12 changes: 12 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,18 @@ AC_ARG_WITH(lastlog,
]
)

AC_MSG_CHECKING([whether to enable SELinux])
AC_ARG_ENABLE([selinux],
[ --enable-selinux Enable SELinux support]
)
AC_MSG_RESULT([$enable_selinux])

AC_ARG_VAR([LIBSELINUX_LIBS],[SELinux libraries])
if test x"$enable_selinux" = xyes; then
AC_DEFINE([DROPBEAR_ENABLE_SELINUX],[1],[Enable SELinux support])
AC_SUBST([LIBSELINUX_LIBS],[${LIBSELINUX_LIBS:--lselinux}])
fi

if test -z "$no_loginfunc_check"; then
dnl Checks for libutil functions (login(), logout() etc, not openpty() )
AC_SEARCH_LIBS(login, util bsd, [AC_DEFINE(HAVE_LOGIN,1,[Have login() function])])
Expand Down
46 changes: 46 additions & 0 deletions svr-auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,13 @@
#include "runopts.h"
#include "dbrandom.h"

#ifdef DROPBEAR_ENABLE_SELINUX
# include <selinux/selinux.h>
# include <selinux/get_context_list.h>
#endif

static int checkusername(const char *username, unsigned int userlen);
static void initselinux(const char *username);

/* initialise the first time for a session, resetting all parameters */
void svr_authinitialise() {
Expand Down Expand Up @@ -119,6 +125,8 @@ void recv_msg_userauth_request() {
valid_user = 1;
}

initselinux(ses.authstate.pw_name);

/* user wants to know what methods are supported */
if (methodlen == AUTH_METHOD_NONE_LEN &&
strncmp(methodname, AUTH_METHOD_NONE,
Expand Down Expand Up @@ -227,6 +235,44 @@ static int check_group_membership(gid_t check_gid, const char* username, gid_t u
}
#endif

static void initselinux(const char *username)
{
#ifdef DROPBEAR_ENABLE_SELINUX
char *seuser;
char *level;
int rc;

if (!is_selinux_enabled())
return;

freecon(ses.authstate.user_sid);
ses.authstate.user_sid = NULL;

rc = getseuserbyname(username, &seuser, &level);
if (rc < 0) {
dropbear_log(LOG_ERR, "getseuserbyname(%s) failed", username);
goto out;
}

rc = get_default_context_with_level(seuser, level, NULL,
&ses.authstate.user_sid);
free(seuser);
free(level);

if (rc < 0) {
dropbear_log(LOG_ERR, "get_default_context(%s) failed", username);
ses.authstate.user_sid = NULL;
goto out;
}

rc = 0;

out:
if (rc < 0 && security_getenforce() > 0)
dropbear_exit("SELinux: failed to initialie");
#endif
}

/* Check that the username exists and isn't disallowed (root), and has a valid shell.
* returns DROPBEAR_SUCCESS on valid username, DROPBEAR_FAILURE on failure */
static int checkusername(const char *username, unsigned int userlen) {
Expand Down
78 changes: 78 additions & 0 deletions svr-chansession.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
#include "runopts.h"
#include "auth.h"

#ifdef DROPBEAR_ENABLE_SELINUX
# include <selinux/selinux.h>
#endif

/* Handles sessions (either shells or programs) requested by the client */

static int sessioncommand(struct Channel *channel, struct ChanSess *chansess,
Expand Down Expand Up @@ -573,6 +577,53 @@ static void get_termmodes(const struct ChanSess *chansess) {
TRACE(("leave get_termmodes"))
}

static void relabelpty(const char *tty)
{
#ifdef DROPBEAR_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");
ensc marked this conversation as resolved.
Show resolved Hide resolved
if (!class) {
rc = -1;
dropbear_log(LOG_ERR, "SELinux: failed to map 'chr_file'");
goto out;
}

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 */
Expand Down Expand Up @@ -621,6 +672,8 @@ static int sessionpty(struct ChanSess * chansess) {
/* Read the terminal modes */
get_termmodes(chansess);

relabelpty(chansess->tty);

TRACE(("leave sessionpty"))
return DROPBEAR_SUCCESS;
}
Expand Down Expand Up @@ -743,6 +796,29 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess,
return ret;
}

static void init_selinux_session(void)
{
#ifdef DROPBEAR_ENABLE_SELINUX
char *ctx = ses.authstate.user_sid;
int rc;

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 */
Expand Down Expand Up @@ -949,6 +1025,8 @@ static void execchild(const void *user_data) {
#endif /* HAVE_CLEARENV */
#endif /* DEBUG_VALGRIND */

init_selinux_session();

#if DROPBEAR_SVR_MULTIUSER
/* We can only change uid/gid as root ... */
if (getuid() == 0) {
Expand Down
8 changes: 8 additions & 0 deletions svr-session.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@
#include "crypto_desc.h"
#include "fuzz.h"

#ifdef DROPBEAR_ENABLE_SELINUX
# include <selinux/selinux.h>
#endif

static void svr_remoteclosed(void);
static void svr_algos_initialise(void);

Expand Down Expand Up @@ -84,6 +88,10 @@ svr_session_cleanup(void) {
/* free potential public key options */
svr_pubkey_options_cleanup();

#ifdef DROPBEAR_ENABLE_SELINUX
freecon(ses.authstate.user_sid);
#endif

m_free(svr_ses.addrstring);
m_free(svr_ses.remotehost);
m_free(svr_ses.childpids);
Expand Down