rpms/pam/devel pam-0.99.8.1-sepermit-kill-user.patch, NONE, 1.1 pam-0.99.8.1-setkeycreatecon.patch, NONE, 1.1 pam.spec, 1.168, 1.169

Tomas Mraz (tmraz) fedora-extras-commits at redhat.com
Mon Jan 28 18:00:10 UTC 2008


Author: tmraz

Update of /cvs/pkgs/rpms/pam/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv22552

Modified Files:
	pam.spec 
Added Files:
	pam-0.99.8.1-sepermit-kill-user.patch 
	pam-0.99.8.1-setkeycreatecon.patch 
Log Message:
* Mon Jan 28 2008 Tomas Mraz <tmraz at redhat.com> 0.99.8.1-17
- test for setkeycreatecon correctly
- add exclusive login mode of operation to pam_selinux_permit (original
  patch by Dan Walsh)


pam-0.99.8.1-sepermit-kill-user.patch:

--- NEW FILE pam-0.99.8.1-sepermit-kill-user.patch ---
diff -up Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.c.kill-user Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.c
--- Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.c.kill-user	2008-01-28 18:34:18.000000000 +0100
+++ Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.c	2008-01-28 18:34:18.000000000 +0100
@@ -1,7 +1,7 @@
 /******************************************************************************
  * A module for Linux-PAM that allows/denies acces based on SELinux state.
  *
- * Copyright (c) 2007 Red Hat, Inc.
+ * Copyright (c) 2007, 2008 Red Hat, Inc.
  * Written by Tomas Mraz <tmraz at redhat.com>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -46,6 +46,14 @@
 #include <string.h>
 #include <syslog.h>
 #include <ctype.h>
+#include <signal.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <dirent.h>
 
 #define PAM_SM_AUTH
 #define PAM_SM_ACCOUNT
@@ -57,6 +65,165 @@
 
 #include <selinux/selinux.h>
 
+#define MODULE "pam_selinux_permit"
+#define OPT_DELIM ":"
+
+struct lockfd {
+	uid_t uid;
+	int fd;
+        int debug;
+};
+
+#define PROC_BASE "/proc"
+#define MAX_NAMES (int)(sizeof(unsigned long)*8)
+
+static int
+match_process_uid(pid_t pid, uid_t uid)
+{
+	char buf[128];
+	uid_t puid;
+	FILE *f;
+	int re = 0;
+	
+	snprintf (buf, sizeof buf, PROC_BASE "/%d/status", pid);
+	if (!(f = fopen (buf, "r")))
+		return 0;
+	
+	while (fgets(buf, sizeof buf, f)) {
+		if (sscanf (buf, "Uid:\t%d", &puid)) {
+			re = uid == puid;
+			break;
+		}
+	}
+	fclose(f);
+	return re;
+}
+
+static int
+check_running (pam_handle_t *pamh, uid_t uid, int killall, int debug)
+{
+	DIR *dir;
+	struct dirent *de;
+	pid_t *pid_table, pid, self;
+	int i;
+	int pids, max_pids;
+	int running = 0;
+	self = getpid();
+	if (!(dir = opendir(PROC_BASE))) {
+		pam_syslog(pamh, LOG_ERR, "Failed to open proc directory file %s:", PROC_BASE);
+		return -1;
+	}
+	max_pids = 256;
+	pid_table = malloc(max_pids * sizeof (pid_t));
+	if (!pid_table) {
+		pam_syslog(pamh, LOG_CRIT, "Memory allocation error");
+		return -1;
+	}
+	pids = 0;
+	while ((de = readdir (dir)) != NULL) {
+		if (!(pid = (pid_t)atoi(de->d_name)) || pid == self)
+			continue;
+
+		if (pids == max_pids) {
+			if (!(pid_table = realloc(pid_table, 2*pids*sizeof(pid_t)))) {
+				pam_syslog(pamh, LOG_CRIT, "Memory allocation error");
+				return -1;
+			}
+			max_pids *= 2;
+		}
+		pid_table[pids++] = pid;
+	}
+
+	(void)closedir(dir);
+
+	for (i = 0; i < pids; i++) {
+		pid_t id;
+
+		if (match_process_uid(pid_table[i], uid) == 0)
+			continue;
+		id = pid_table[i];
+
+		if (killall) {
+			if (debug)
+				pam_syslog(pamh, LOG_NOTICE, "Attempting to kill %d", id);
+			kill(id, SIGKILL);
+		}
+		running++;
+	}
+
+	free(pid_table);
+	return running;
+}
+
+static void
+sepermit_unlock(pam_handle_t *pamh, void *plockfd, int error_status UNUSED)
+{
+	struct lockfd *lockfd = plockfd;
+	struct flock fl;
+
+	memset(&fl, 0, sizeof(fl));
+	fl.l_type = F_UNLCK;
+	fl.l_whence = SEEK_SET;
+
+	if (lockfd->debug)
+		pam_syslog(pamh, LOG_ERR, "Unlocking fd: %d uid: %d", lockfd->fd, lockfd->uid);
+
+	/* Don't kill uid==0 */
+	if (lockfd->uid)
+		/* This is a DOS but it prevents an app from forking to prevent killing */
+		while(check_running(pamh, lockfd->uid, 1, lockfd->debug) > 0)
+			continue;
+
+	fcntl(lockfd->fd, F_SETLK, &fl);
+	close(lockfd->fd);
+	free(lockfd);
+}
+
+static int
+sepermit_lock(pam_handle_t *pamh, const char *user, int debug)
+{
+	char buf[PATH_MAX];
+	struct flock fl;
+
+	memset(&fl, 0, sizeof(fl));
+	fl.l_type = F_WRLCK;
+	fl.l_whence = SEEK_SET;
+
+	struct passwd *pw = pam_modutil_getpwnam( pamh, user );
+	if (!pw) {
+		pam_syslog(pamh, LOG_ERR, "Unable to find uid for user %s", user);
+		return -1;
+	}
+	if (check_running(pamh, pw->pw_uid, 0, debug) > 0)  {
+		pam_syslog(pamh, LOG_ERR, "User %s processes are running. Exclusive login not allowed", user);
+		return -1;
+	}
+
+	snprintf(buf, sizeof(buf), "%s/%d.lock", SEPERMIT_LOCKDIR, pw->pw_uid);
+	int fd = open(buf, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+	if (fd < 0) {
+		pam_syslog(pamh, LOG_ERR, "Unable to open lock file %s/%d.lock", SEPERMIT_LOCKDIR, pw->pw_uid);
+		return -1;
+	}
+
+	if (fcntl(fd, F_SETLK, &fl) == -1) {
+		pam_syslog(pamh, LOG_ERR, "User %s with exclusive login already logged in", user);
+		close(fd);
+		return -1;
+	}
+	struct lockfd *lockfd=calloc(1, sizeof(struct lockfd));
+	if (!lockfd) {
+		close(fd);
+		pam_syslog(pamh, LOG_CRIT, "Memory allocation error");
+		return -1;
+	}
+	lockfd->uid = pw->pw_uid;
+	lockfd->debug = debug;
+	lockfd->fd=fd;
+        pam_set_data(pamh, "pam_selinux_permit", lockfd, sepermit_unlock);
+	return 0;
+}
+
 /* return 0 when matched, -1 when unmatched, pam error otherwise */
 static int
 sepermit_match(pam_handle_t *pamh, const char *cfgfile, const char *user,
@@ -67,6 +234,7 @@ sepermit_match(pam_handle_t *pamh, const
 	char *start;
 	size_t len = 0;
 	int matched = 0;
+	int exclusive = 0;
 	
 	f = fopen(cfgfile, "r");
 	
@@ -77,6 +245,8 @@ sepermit_match(pam_handle_t *pamh, const
 
 	while (!matched && getline(&line, &len, f) != -1) {
 		size_t n;
+		char *sptr;
+		char *opt;
 
 		if (line[0] == '#')
 			continue;
@@ -92,6 +262,7 @@ sepermit_match(pam_handle_t *pamh, const
 			continue;
 
 		start[n] = '\0';
+		start = strtok_r(start, OPT_DELIM, &sptr);
 
 		switch (start[0]) {
 			case '@': 
@@ -117,11 +288,22 @@ sepermit_match(pam_handle_t *pamh, const
 					matched = 1;
 				}
 		}
+		if (matched)
+			while ((opt=strtok_r(NULL, OPT_DELIM, &sptr)) != NULL) {
+				if (strcmp(opt, "exclusive") == 0)
+					exclusive = 1;
+				else if (debug) {
+					pam_syslog(pamh, LOG_NOTICE, "Unknown user option: %s", opt);
+				}
+			}
 	}
 
 	free(line);
 	fclose(f);
-	return matched ? 0 : -1;
+	if (matched) 
+		return exclusive ? sepermit_lock(pamh, user, debug) : 0;
+	else
+		return -1;
 }
 
 PAM_EXTERN int
diff -up Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.8.xml.kill-user Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.8.xml
--- Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.8.xml.kill-user	2008-01-28 18:34:18.000000000 +0100
+++ Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.8.xml	2008-01-28 18:34:18.000000000 +0100
@@ -30,8 +30,8 @@
   <refsect1 id="pam_selinux_permit-description">
     <title>DESCRIPTION</title>
     <para>
-      The pam_selinux module allows or denies login depending on SELinux enforcement
-      state.
+      The pam_selinux_permit module allows or denies login depending on SELinux
+      enforcement state.
     </para>
     <para>
       When the user which is logging in matches an entry in the config file
@@ -41,14 +41,21 @@
     </para>
     <para>
       The config file contains a simple list of user names one per line. If the
-      <replaceable>name</replaceable> is prefixed with @ character it means that all
+      <replaceable>name</replaceable> is prefixed with <emphasis>@</emphasis> character it means that all
       users in the group <replaceable>name</replaceable> match. If it is prefixed
-      with a % character the SELinux user is used to match against the <replaceable>name</replaceable>
+      with a <emphasis>%</emphasis> character the SELinux user is used to match against the <replaceable>name</replaceable>
       instead of the account name. Note that when SELinux is disabled the
       SELinux user assigned to the account cannot be determined. This means that
       such entries are never matched when SELinux is disabled and pam_selinux_permit
       will return PAM_IGNORE.
     </para>
+    <para>
+      Each user name in the configuration file can have optional arguments separated
+      by <emphasis>:</emphasis> character. The only currently recognized argument is <emphasis>exclusive</emphasis>.
+      The pam_selinux_permit module will allow only single concurrent user session for
+      the user with this argument specified and it will attempt to kill all processes
+      of the user after logout.
+    </para>
   </refsect1>
 
   <refsect1 id="pam_selinux_permit-options">
diff -up Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am.kill-user Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am
--- Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am.kill-user	2008-01-28 18:34:18.000000000 +0100
+++ Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am	2008-01-28 18:35:01.000000000 +0100
@@ -16,10 +16,13 @@ XMLS = README.xml pam_selinux.8.xml pam_
 
 securelibdir = $(SECUREDIR)
 secureconfdir = $(SCONFIGDIR)
+sepermitlockdir = /var/run/sepermit
 
 AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
 	-I$(top_srcdir)/libpam_misc/include \
-	-D SEPERMIT_CONF_FILE=\"$(SCONFIGDIR)/sepermit.conf\"
+	-D SEPERMIT_CONF_FILE=\"$(SCONFIGDIR)/sepermit.conf\" \
+	-D SEPERMIT_LOCKDIR=\"$(sepermitlockdir)\"
+
 AM_LDFLAGS = -no-undefined \
 	-L$(top_builddir)/libpam -lpam @LIBSELINUX@
 
@@ -34,6 +37,7 @@ endif
 pam_selinux_permit_la_LDFLAGS= $(pam_selinux_la_LDFLAGS)
 
 secureconf_DATA = sepermit.conf
+sepermitlock_DATA =
 
 if HAVE_LIBSELINUX
   securelib_LTLIBRARIES = pam_selinux.la pam_selinux_permit.la
diff -up Linux-PAM-0.99.8.1/modules/pam_selinux/sepermit.conf.kill-user Linux-PAM-0.99.8.1/modules/pam_selinux/sepermit.conf
--- Linux-PAM-0.99.8.1/modules/pam_selinux/sepermit.conf.kill-user	2008-01-28 18:34:18.000000000 +0100
+++ Linux-PAM-0.99.8.1/modules/pam_selinux/sepermit.conf	2008-01-28 18:34:18.000000000 +0100
@@ -4,3 +4,8 @@
 #        - an user name
 #        - a group name, with @group syntax
 #        - a SELinux user name, with %seuser syntax
+# Each line can contain optional arguments separated by :
+# The possible arguments are:
+#        - exclusive - only single login session will
+#          be allowed for the user and the user's processes
+#          will be killed on logout

pam-0.99.8.1-setkeycreatecon.patch:

--- NEW FILE pam-0.99.8.1-setkeycreatecon.patch ---
diff -up Linux-PAM-0.99.8.1/configure.in.setkeycreatecon Linux-PAM-0.99.8.1/configure.in
--- Linux-PAM-0.99.8.1/configure.in.setkeycreatecon	2008-01-28 17:22:40.000000000 +0100
+++ Linux-PAM-0.99.8.1/configure.in	2008-01-28 17:26:25.000000000 +0100
@@ -379,6 +379,7 @@ AC_SUBST(LIBDB)
 AM_CONDITIONAL([HAVE_LIBDB], [test ! -z "$LIBDB"])
 
 AC_CHECK_LIB([nsl],[yp_get_default_domain], LIBNSL="-lnsl", LIBNSL="")
+BACKUP_LIBS=$LIBS
 LIBS="$LIBS $LIBNSL"
 AC_CHECK_FUNCS(yp_get_default_domain)
 LIBS=$BACKUP_LIBS
@@ -396,6 +397,10 @@ AC_SUBST(LIBSELINUX)
 AM_CONDITIONAL([HAVE_LIBSELINUX], [test ! -z "$LIBSELINUX"])
 if test ! -z "$LIBSELINUX" ; then
     AC_DEFINE([WITH_SELINUX], 1, [Defined if SE Linux support is compiled in])
+    BACKUP_LIBS=$LIBS
+    LIBS="$LIBS $LIBSELINUX"
+    AC_CHECK_FUNCS(setkeycreatecon)
+    LIBS=$BACKUP_LIBS
 fi
 
 dnl Checks for header files.
@@ -428,7 +433,7 @@ AC_CHECK_FUNCS(fseeko gethostname gettim
 AC_CHECK_FUNCS(strcspn strdup strspn strstr strtol uname)
 AC_CHECK_FUNCS(getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r)
 AC_CHECK_FUNCS(getgrouplist getline getdelim)
-AC_CHECK_FUNCS(inet_ntop inet_pton ruserok_af setkeycreatecon)
+AC_CHECK_FUNCS(inet_ntop inet_pton ruserok_af)
 
 AC_CHECK_FUNCS(unshare, [UNSHARE=yes], [UNSHARE=no])
 AM_CONDITIONAL([HAVE_UNSHARE], [test "$UNSHARE" = yes])


Index: pam.spec
===================================================================
RCS file: /cvs/pkgs/rpms/pam/devel/pam.spec,v
retrieving revision 1.168
retrieving revision 1.169
diff -u -r1.168 -r1.169
--- pam.spec	23 Jan 2008 07:43:33 -0000	1.168
+++ pam.spec	28 Jan 2008 17:59:35 -0000	1.169
@@ -11,7 +11,7 @@
 Summary: A security tool which provides authentication for applications
 Name: pam
 Version: 0.99.8.1
-Release: 16%{?dist}
+Release: 17%{?dist}
 # The library is BSD licensed with option to relicense as GPLv2+ - this option is redundant
 # as the BSD license allows that anyway. pam_timestamp and pam_console modules are GPLv2+,
 # pam_rhosts_auth module is BSD with advertising
@@ -47,6 +47,8 @@
 Patch49: pam-0.99.8.1-tty-audit.patch
 Patch50: pam-0.99.8.1-tty-audit2.patch
 Patch51: pam-0.99.8.1-audit-failed.patch
+Patch52: pam-0.99.8.1-setkeycreatecon.patch
+Patch53: pam-0.99.8.1-sepermit-kill-user.patch
 
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 Requires: cracklib, cracklib-dicts >= 2.8
@@ -119,6 +121,8 @@
 %patch49 -p1 -b .tty-audit
 %patch50 -p1 -b .tty-audit2
 %patch51 -p1 -b .audit-failed
+%patch52 -p1 -b .setkeycreatecon
+%patch53 -p1 -b .kill-user
 
 autoreconf
 
@@ -352,6 +356,7 @@
 %dir %{_sysconfdir}/security/console.perms.d
 %config %{_sysconfdir}/security/console.perms.d/50-default.perms
 %dir /var/run/console
+%dir /var/run/sepermit
 %ghost %verify(not md5 size mtime) /var/log/faillog
 %ghost %verify(not md5 size mtime) /var/log/tallylog
 %{_mandir}/man5/*
@@ -368,6 +373,11 @@
 %doc doc/adg/*.txt doc/adg/html
 
 %changelog
+* Mon Jan 28 2008 Tomas Mraz <tmraz at redhat.com> 0.99.8.1-17
+- test for setkeycreatecon correctly
+- add exclusive login mode of operation to pam_selinux_permit (original
+  patch by Dan Walsh)
+
 * Tue Jan 22 2008 Tomas Mraz <tmraz at redhat.com> 0.99.8.1-16
 - add auditing to pam_access, pam_limits, and pam_time
 - moved sanity testing code to check script




More information about the fedora-extras-commits mailing list