Skip to content

Commit

Permalink
pam_tcb: Add support for user authentication with SELinux.
Browse files Browse the repository at this point in the history
NSA Security-Enhanced Linux (SELinux) is an implementation
of a flexible mandatory access control architecture in the
Linux operating system.  Background information and technical
documentation about SELinux can be found at
https://github.com/SELinuxProject.

With SELinux running in enforced mode even read-access to
the shadow files, which the hashed user passwords are stored
in, is restricted to processes that have at least been granted
"shadow_t:file read" capabilites by the SELinux policy.  For that
reason the login authentication of a user must always be performed
by the "tcb_chkpwd" helper binary.

Signed-off-by: Björn Esser <[email protected]>
  • Loading branch information
besser82 committed Oct 8, 2021
1 parent 070cf4a commit c8858c8
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 4 deletions.
23 changes: 23 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
2021-10-08 Björn Esser <besser82 at fedoraproject.org>

pam_tcb: Add support for user authentication with SELinux.
With SELinux running in enforced mode even read-access to
the shadow files, which the hashed user passwords are stored
in, is restricted to processes that have at least been granted
"shadow_t:file read" capabilites by the SELinux policy. For
that reason the login authentication of a user must always be
performed by the "tcb_chkpwd" helper binary.
* pam_tcb/support.c (unix_verify_password_plain): Use the chkpwd
helper binary to verify the user's password if SELinux is enabled,
and prevents read-access to the file storing the hashed password.
* pam_tcb/support.h (SELINUX_ENABLED): Include <selinux/selinux.h>
if support for SELinux is requested. Also define SELINUX_ENABLED.
* progs/tcb_chkpwd.c (SELINUX_ENABLED): Likewise.
* progs/tcb_chkpwd.c (unix_verify_password): Do not fail during
authentication when SELinux is enabled and the UID of the user to
be authenticated differs from the UID of the actual caller.
* Make.defs: Add flag to (optionally) enable support for SELinux.
* pam_tcb/Makefile: Apply the needed pre-processor define
and link against libselinux if support for SELinux is requested.
* progs/Makefile: Likewise.

2021-09-30 Björn Esser <besser82 at fedoraproject.org>

pam_tcb: Fix "-Wpedantic".
Expand Down
3 changes: 3 additions & 0 deletions Make.defs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ MKDIR = mkdir
# Flag to enable -Werror on build.
WERROR =

# Flag to enable support for SELinux in pam_tcb.
ENABLE_SELINUX =

DBGFLAG = #-ggdb
ifndef CFLAGS
CFLAGS = -O2
Expand Down
11 changes: 10 additions & 1 deletion pam_tcb/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ ifneq ($(PAM_SO_SUFFIX),)
PAM_TCB_SONAME = -Wl,-soname,$(PAM_TCB)
endif

PAM_TCB_LIBS = -lcrypt -lpam

ifneq ($(ENABLE_SELINUX),)
CFLAGS += -DWITH_SELINUX
PAM_TCB_LIBS += -lselinux
endif

PAM_TCB_LIBS += -ltcb

LIBSRC = \
pam_unix_auth.c pam_unix_acct.c pam_unix_sess.c pam_unix_passwd.c \
support.c compat.c
Expand All @@ -18,7 +27,7 @@ all: $(PAM_TCB)

$(PAM_TCB): $(LIBOBJ) $(PAM_MAP)
$(CC) $(LDFLAGS) -shared -o $@ $(PAM_TCB_SONAME) \
-Wl,--version-script=$(PAM_MAP) $(LIBOBJ) -lcrypt -lpam -ltcb
-Wl,--version-script=$(PAM_MAP) $(LIBOBJ) $(PAM_TCB_LIBS)

.c.o:
$(CC) $(CFLAGS) -fPIC -c $< -o $@
Expand Down
2 changes: 1 addition & 1 deletion pam_tcb/support.c
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ static int unix_verify_password_plain(pam_handle_t *pamh,
if (!salt) {
/* we're not faking, we have an existing user, so... */
uid_t uid = getuid();
if (uid == geteuid() && uid == pw->pw_uid && uid != 0) {
if (SELINUX_ENABLED || (uid == geteuid() && uid == pw->pw_uid && uid != 0)) {
/* We are not root perhaps this is the reason? */
D(("running helper binary"));
retval = unix_run_helper_binary(user, pass);
Expand Down
7 changes: 7 additions & 0 deletions pam_tcb/support.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@
# include "compat.h"
#endif

#ifdef WITH_SELINUX
#include <selinux/selinux.h>
#define SELINUX_ENABLED (is_selinux_enabled()>0)
#else
#define SELINUX_ENABLED 0
#endif /* WITH_SELINUX */

#if defined(ENABLE_NLS) && defined(NLS_PACKAGE)
#include <libintl.h>
#define _(msgid) dgettext(NLS_PACKAGE, msgid)
Expand Down
9 changes: 8 additions & 1 deletion progs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ CONVERT = tcb_convert
UNCONVERT = tcb_unconvert
CHKPWD = tcb_chkpwd

CHKPWD_LIBS += -lcrypt

ifneq ($(ENABLE_SELINUX),)
CFLAGS += -DWITH_SELINUX
CHKPWD_LIBS += -lselinux
endif

all: $(CONVERT) $(UNCONVERT) $(CHKPWD)

$(CONVERT): $(CONVERT).o
Expand All @@ -13,7 +20,7 @@ $(UNCONVERT): $(UNCONVERT).o
$(CC) $(LDFLAGS) -o $@ $< -ltcb

$(CHKPWD): $(CHKPWD).o
$(CC) $(LDFLAGS) -o $@ $< -lcrypt
$(CC) $(LDFLAGS) -o $@ $< $(CHKPWD_LIBS)

.c.o:
$(CC) $(CFLAGS) -c $< -o $@
Expand Down
9 changes: 8 additions & 1 deletion progs/tcb_chkpwd.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
#include <pwd.h>
#include <shadow.h>

#ifdef WITH_SELINUX
#include <selinux/selinux.h>
#define SELINUX_ENABLED (is_selinux_enabled()>0)
#else
#define SELINUX_ENABLED 0
#endif /* WITH_SELINUX */

#include "_tcb.h"

IO_LOOP(read_loop, read,)
Expand Down Expand Up @@ -43,7 +50,7 @@ static int unix_verify_password(const char *user, const char *pass, int nullok)

stored_hash = NULL;
if (pw) {
if (getuid() != pw->pw_uid)
if (!SELINUX_ENABLED && getuid() != pw->pw_uid)
return AUTH_FAILED;

if (!strcmp(pw->pw_passwd, "x")) {
Expand Down

0 comments on commit c8858c8

Please sign in to comment.