- new upstream release
- add default soft limit for nproc of 1024 to prevent accidental fork bombs (#432903)
This commit is contained in:
parent
717cfde74b
commit
0533865ad8
@ -1,5 +1,5 @@
|
||||
*.src.rpm
|
||||
*.tar.bz2
|
||||
pam-redhat-0.99.8-1.tar.bz2
|
||||
Linux-PAM-0.99.8.1.tar.bz2
|
||||
db-4.6.19.tar.gz
|
||||
Linux-PAM-0.99.10.0.tar.bz2
|
||||
|
5
90-nproc.conf
Normal file
5
90-nproc.conf
Normal file
@ -0,0 +1,5 @@
|
||||
# Default limit for number of user's processes to prevent
|
||||
# accidental fork bombs.
|
||||
# See rhbz #432903 for reasoning.
|
||||
|
||||
* soft nproc 1024
|
@ -2,7 +2,7 @@
|
||||
Version: GnuPG v1.4.7 (GNU/Linux)
|
||||
Comment: See http://www.kernel.org/signature.html for info
|
||||
|
||||
iD8DBQBGneVeyGugalF9Dw4RAkclAJ4lTnGnONrVg01e1Zk5K2tfFZxhQACeITvP
|
||||
P+lEUXjXsjLVoZ1EOJn7Lts=
|
||||
=Q5X1
|
||||
iD8DBQBHtBCvyGugalF9Dw4RAkscAKCAir9EhJ5VxjIog6Vs+N6Sr27n6ACcD0Iy
|
||||
ycgdOs9Ea8z8pqgPZMmocyY=
|
||||
=djTw
|
||||
-----END PGP SIGNATURE-----
|
@ -1,8 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (GNU/Linux)
|
||||
Comment: See http://www.kernel.org/signature.html for info
|
||||
|
||||
iD8DBQBFtgDAyGugalF9Dw4RArOyAJ0duc7/WqnlX1+LfjYsUOQsJhICOgCfdWDb
|
||||
aMzAtzhCqvu+IxJTFwXx/kk=
|
||||
=I+NT
|
||||
-----END PGP SIGNATURE-----
|
@ -1,47 +0,0 @@
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.init.homedir Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.init
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.init.homedir 2007-09-19 19:37:26.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.init 2007-09-21 14:13:52.000000000 +0200
|
||||
@@ -1,26 +1,24 @@
|
||||
#!/bin/sh -p
|
||||
-# This is only a boilerplate for the instance initialization script.
|
||||
# It receives polydir path as $1, the instance path as $2,
|
||||
# a flag whether the instance dir was newly created (0 - no, 1 - yes) in $3,
|
||||
# and user name in $4.
|
||||
#
|
||||
-# If you intend to polyinstantiate /tmp and you also want to use the X windows
|
||||
-# environment, you will have to use this script to bind mount the socket that
|
||||
-# is used by the X server to communicate with its clients. X server places
|
||||
-# this socket in /tmp/.X11-unix directory, which will get obscured by
|
||||
-# polyinstantiation. Uncommenting the following lines will bind mount
|
||||
-# the relevant directory at an alternative location (/.tmp/.X11-unix) such
|
||||
-# that the X server, window manager and X clients, can still find the
|
||||
-# socket X0 at the polyinstanted /tmp/.X11-unix.
|
||||
-#
|
||||
-#if [ $1 = /tmp ]; then
|
||||
-# if [ ! -f /.tmp/.X11-unix ]; then
|
||||
-# mkdir -p /.tmp/.X11-unix
|
||||
-# fi
|
||||
-# mount --bind /tmp/.X11-unix /.tmp/.X11-unix
|
||||
-# cp -fp -- /tmp/.X0-lock "$2/.X0-lock"
|
||||
-# mkdir -- "$2/.X11-unix"
|
||||
-# ln -fs -- /.tmp/.X11-unix/X0 "$2/.X11-unix/X0"
|
||||
-#fi
|
||||
+# The following section will copy the contents of /etc/skel if this is a
|
||||
+# newly created home directory.
|
||||
+if [ "$3" = 1 ]; then
|
||||
+ # This line will fix the labeling on all newly created directories
|
||||
+ [ -x /sbin/restorecon ] && /sbin/restorecon "$1"
|
||||
+ user="$4"
|
||||
+ passwd=$(getent passwd "$user")
|
||||
+ homedir=$(echo "$passwd" | cut -f6 -d":")
|
||||
+ if [ "$1" = "$homedir" ]; then
|
||||
+ gid=$(echo "$passwd" | cut -f4 -d":")
|
||||
+ cp -rT /etc/skel "$homedir"
|
||||
+ chown -R "$user":"$gid" "$homedir"
|
||||
+ mode=$(awk '/^UMASK/{gsub("#.*$", "", $2); printf "%o", and(0777,compl(strtonum("0" $2))); exit}' /etc/login.defs)
|
||||
+ chmod ${mode:-700} "$homedir"
|
||||
+ [ -x /sbin/restorecon ] && /sbin/restorecon -R "$homedir"
|
||||
+ fi
|
||||
+fi
|
||||
|
||||
exit 0
|
@ -1,465 +0,0 @@
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.conf.5.xml.temp-logon Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.conf.5.xml
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.conf.5.xml.temp-logon 2007-06-18 12:46:47.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.conf.5.xml 2007-08-06 13:16:56.000000000 +0200
|
||||
@@ -72,10 +72,13 @@
|
||||
|
||||
<para>
|
||||
The third field, <replaceable>method</replaceable>, is the method
|
||||
- used for polyinstantiation. It can take 3 different values; "user"
|
||||
+ used for polyinstantiation. It can take these values; "user"
|
||||
for polyinstantiation based on user name, "level" for
|
||||
- polyinstantiation based on process MLS level and user name, and "context" for
|
||||
- polyinstantiation based on process security context and user name
|
||||
+ polyinstantiation based on process MLS level and user name, "context" for
|
||||
+ polyinstantiation based on process security context and user name,
|
||||
+ "tmpfs" for mounting tmpfs filesystem as an instance dir, and
|
||||
+ "tmpdir" for creating temporary directory as an instance dir which is
|
||||
+ removed when the user's session is closed.
|
||||
Methods "context" and "level" are only available with SELinux. This
|
||||
field cannot be blank.
|
||||
</para>
|
||||
@@ -84,7 +87,8 @@
|
||||
The fourth field, <replaceable>list_of_uids</replaceable>, is
|
||||
a comma separated list of user names for whom the polyinstantiation
|
||||
is not performed. If left blank, polyinstantiation will be performed
|
||||
- for all users.
|
||||
+ for all users. If the list is preceded with a single "~" character,
|
||||
+ polyinstantiation is performed only for users in the list.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.h.temp-logon Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.h
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.h.temp-logon 2007-06-18 12:46:47.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.h 2007-08-06 11:41:46.000000000 +0200
|
||||
@@ -90,6 +90,7 @@
|
||||
#define PAMNS_NO_UNMOUNT_ON_CLOSE 0x00010000 /* no unmount at session close */
|
||||
|
||||
#define NAMESPACE_MAX_DIR_LEN 80
|
||||
+#define NAMESPACE_POLYDIR_DATA "pam_namespace:polydir_data"
|
||||
|
||||
/*
|
||||
* Polyinstantiation method options, based on user, security context
|
||||
@@ -100,6 +101,8 @@ enum polymethod {
|
||||
USER,
|
||||
CONTEXT,
|
||||
LEVEL,
|
||||
+ TMPDIR,
|
||||
+ TMPFS
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -128,6 +131,7 @@ struct polydir_s {
|
||||
enum polymethod method; /* method used to polyinstantiate */
|
||||
unsigned int num_uids; /* number of override uids */
|
||||
uid_t *uid; /* list of override uids */
|
||||
+ int exclusive; /* polyinstatiate exclusively for override uids */
|
||||
struct polydir_s *next; /* pointer to the next polydir entry */
|
||||
};
|
||||
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c.temp-logon Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c.temp-logon 2007-06-18 12:46:47.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c 2007-08-06 11:41:46.000000000 +0200
|
||||
@@ -43,6 +43,7 @@ static int copy_ent(const struct polydir
|
||||
strcpy(pent->instance_prefix, ent->instance_prefix);
|
||||
pent->method = ent->method;
|
||||
pent->num_uids = ent->num_uids;
|
||||
+ pent->exclusive = ent->exclusive;
|
||||
if (ent->num_uids) {
|
||||
uid_t *pptr, *eptr;
|
||||
|
||||
@@ -120,6 +121,10 @@ static void del_polydir_list(struct poly
|
||||
}
|
||||
}
|
||||
|
||||
+static void cleanup_data(pam_handle_t *pamh, void *data, int err)
|
||||
+{
|
||||
+ del_polydir_list(data);
|
||||
+}
|
||||
|
||||
/*
|
||||
* Called from parse_config_file, this function processes a single line
|
||||
@@ -140,6 +145,7 @@ static int process_line(char *line, cons
|
||||
|
||||
poly.uid = NULL;
|
||||
poly.num_uids = 0;
|
||||
+ poly.exclusive = 0;
|
||||
|
||||
/*
|
||||
* skip the leading white space
|
||||
@@ -223,24 +229,13 @@ static int process_line(char *line, cons
|
||||
}
|
||||
|
||||
/*
|
||||
- * Ensure that all pathnames are absolute path names.
|
||||
- */
|
||||
- if ((dir[0] != '/') || (instance_prefix[0] != '/')) {
|
||||
- pam_syslog(idata->pamh, LOG_NOTICE,"Pathnames must start with '/'");
|
||||
- goto skipping;
|
||||
- }
|
||||
- if (strstr(dir, "..") || strstr(instance_prefix, "..")) {
|
||||
- pam_syslog(idata->pamh, LOG_NOTICE,"Pathnames must not contain '..'");
|
||||
- goto skipping;
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
* Populate polyinstantiated directory structure with appropriate
|
||||
* pathnames and the method with which to polyinstantiate.
|
||||
*/
|
||||
if (strlen(dir) >= sizeof(poly.dir)
|
||||
|| strlen(instance_prefix) >= sizeof(poly.instance_prefix)) {
|
||||
pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames too long");
|
||||
+ goto skipping;
|
||||
}
|
||||
strcpy(poly.dir, dir);
|
||||
strcpy(poly.instance_prefix, instance_prefix);
|
||||
@@ -248,6 +243,18 @@ static int process_line(char *line, cons
|
||||
poly.method = NONE;
|
||||
if (strcmp(method, "user") == 0)
|
||||
poly.method = USER;
|
||||
+
|
||||
+ if (strcmp(method, "tmpdir") == 0) {
|
||||
+ poly.method = TMPDIR;
|
||||
+ if (sizeof(poly.instance_prefix) - strlen(poly.instance_prefix) < 7) {
|
||||
+ pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames too long");
|
||||
+ goto skipping;
|
||||
+ }
|
||||
+ strcat(poly.instance_prefix, "XXXXXX");
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(method, "tmpfs") == 0)
|
||||
+ poly.method = TMPFS;
|
||||
|
||||
#ifdef WITH_SELINUX
|
||||
if (strcmp(method, "level") == 0) {
|
||||
@@ -266,12 +273,24 @@ static int process_line(char *line, cons
|
||||
|
||||
#endif
|
||||
|
||||
- if ( poly.method == NONE) {
|
||||
+ if (poly.method == NONE) {
|
||||
pam_syslog(idata->pamh, LOG_NOTICE, "Illegal method");
|
||||
goto skipping;
|
||||
}
|
||||
|
||||
/*
|
||||
+ * Ensure that all pathnames are absolute path names.
|
||||
+ */
|
||||
+ if ((dir[0] != '/') || (poly.method != TMPFS && instance_prefix[0] != '/')) {
|
||||
+ pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames must start with '/'");
|
||||
+ goto skipping;
|
||||
+ }
|
||||
+ if (strstr(dir, "..") || strstr(instance_prefix, "..")) {
|
||||
+ pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames must not contain '..'");
|
||||
+ goto skipping;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
* If the line in namespace.conf for a directory to polyinstantiate
|
||||
* contains a list of override users (users for whom polyinstantiation
|
||||
* is not performed), read the user ids, convert names into uids, and
|
||||
@@ -281,7 +300,11 @@ static int process_line(char *line, cons
|
||||
uid_t *uidptr;
|
||||
const char *ustr, *sstr;
|
||||
int count, i;
|
||||
-
|
||||
+
|
||||
+ if (*uids == '~') {
|
||||
+ poly.exclusive = 1;
|
||||
+ uids++;
|
||||
+ }
|
||||
for (count = 0, ustr = sstr = uids; sstr; ustr = sstr + 1, count++)
|
||||
sstr = strchr(ustr, ',');
|
||||
|
||||
@@ -419,6 +442,7 @@ static int parse_config_file(struct inst
|
||||
* directory's list of override uids. If the uid is one of the override
|
||||
* uids for the polyinstantiated directory, polyinstantiation is not
|
||||
* performed for that user for that directory.
|
||||
+ * If exclusive is set the returned values are opposite.
|
||||
*/
|
||||
static int ns_override(struct polydir_s *polyptr, struct instance_data *idata,
|
||||
uid_t uid)
|
||||
@@ -432,11 +456,11 @@ static int ns_override(struct polydir_s
|
||||
|
||||
for (i = 0; i < polyptr->num_uids; i++) {
|
||||
if (uid == polyptr->uid[i]) {
|
||||
- return 1;
|
||||
+ return !polyptr->exclusive;
|
||||
}
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ return polyptr->exclusive;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -622,6 +646,12 @@ static int poly_name(const struct polydi
|
||||
|
||||
#endif /* WITH_SELINUX */
|
||||
|
||||
+ case TMPDIR:
|
||||
+ case TMPFS:
|
||||
+ if ((*i_name=strdup("")) == NULL)
|
||||
+ goto fail;
|
||||
+ return PAM_SUCCESS;
|
||||
+
|
||||
default:
|
||||
if (idata->flags & PAMNS_DEBUG)
|
||||
pam_syslog(idata->pamh, LOG_ERR, "Unknown method");
|
||||
@@ -725,7 +755,7 @@ static int check_inst_parent(char *ipath
|
||||
* execute it and pass directory to polyinstantiate and instance
|
||||
* directory as arguments.
|
||||
*/
|
||||
-static int inst_init(const struct polydir_s *polyptr, char *ipath,
|
||||
+static int inst_init(const struct polydir_s *polyptr, const char *ipath,
|
||||
struct instance_data *idata)
|
||||
{
|
||||
pid_t rc, pid;
|
||||
@@ -791,11 +821,11 @@ out:
|
||||
* Create polyinstantiated instance directory (ipath).
|
||||
*/
|
||||
#ifdef WITH_SELINUX
|
||||
-static int create_dirs(const struct polydir_s *polyptr, char *ipath,
|
||||
+static int create_dirs(struct polydir_s *polyptr, char *ipath,
|
||||
security_context_t icontext, security_context_t ocontext,
|
||||
struct instance_data *idata)
|
||||
#else
|
||||
-static int create_dirs(const struct polydir_s *polyptr, char *ipath,
|
||||
+static int create_dirs(struct polydir_s *polyptr, char *ipath,
|
||||
struct instance_data *idata)
|
||||
#endif
|
||||
{
|
||||
@@ -834,7 +864,17 @@ static int create_dirs(const struct poly
|
||||
* attributes to match that of the original directory that is being
|
||||
* polyinstantiated.
|
||||
*/
|
||||
- if (mkdir(ipath, S_IRUSR) < 0) {
|
||||
+
|
||||
+ if (polyptr->method == TMPDIR) {
|
||||
+ if (mkdtemp(polyptr->instance_prefix) == NULL) {
|
||||
+ pam_syslog(idata->pamh, LOG_ERR, "Error creating temporary instance %s, %m",
|
||||
+ polyptr->instance_prefix);
|
||||
+ polyptr->method = NONE; /* do not clean up! */
|
||||
+ return PAM_SESSION_ERR;
|
||||
+ }
|
||||
+ /* copy the actual directory name to ipath */
|
||||
+ strcpy(ipath, polyptr->instance_prefix);
|
||||
+ } else if (mkdir(ipath, S_IRUSR) < 0) {
|
||||
if (errno == EEXIST)
|
||||
goto inst_init;
|
||||
else {
|
||||
@@ -920,13 +960,12 @@ inst_init:
|
||||
* security attributes, and performs bind mount to setup the process
|
||||
* namespace.
|
||||
*/
|
||||
-static int ns_setup(const struct polydir_s *polyptr,
|
||||
+static int ns_setup(struct polydir_s *polyptr,
|
||||
struct instance_data *idata)
|
||||
{
|
||||
int retval = 0;
|
||||
char *inst_dir = NULL;
|
||||
char *instname = NULL;
|
||||
- char *dir;
|
||||
#ifdef WITH_SELINUX
|
||||
security_context_t instcontext = NULL, origcontext = NULL;
|
||||
#endif
|
||||
@@ -935,9 +974,15 @@ static int ns_setup(const struct polydir
|
||||
pam_syslog(idata->pamh, LOG_DEBUG,
|
||||
"Set namespace for directory %s", polyptr->dir);
|
||||
|
||||
- dir = strrchr(polyptr->dir, '/');
|
||||
- if (dir && strlen(dir) > 1)
|
||||
- dir++;
|
||||
+ if (polyptr->method == TMPFS) {
|
||||
+ if (mount("tmpfs", polyptr->dir, "tmpfs", 0, NULL) < 0) {
|
||||
+ pam_syslog(idata->pamh, LOG_ERR, "Error mounting tmpfs on %s, %m",
|
||||
+ polyptr->dir);
|
||||
+ return PAM_SESSION_ERR;
|
||||
+ }
|
||||
+ /* we must call inst_init after the mount in this case */
|
||||
+ return inst_init(polyptr, "tmpfs", idata);
|
||||
+ }
|
||||
|
||||
/*
|
||||
* Obtain the name of instance pathname based on the
|
||||
@@ -1043,6 +1088,58 @@ static int cwd_in(char *dir, struct inst
|
||||
return retval;
|
||||
}
|
||||
|
||||
+static int cleanup_tmpdirs(struct instance_data *idata)
|
||||
+{
|
||||
+ struct polydir_s *pptr;
|
||||
+ pid_t rc, pid;
|
||||
+ sighandler_t osighand = NULL;
|
||||
+ int status;
|
||||
+
|
||||
+ osighand = signal(SIGCHLD, SIG_DFL);
|
||||
+ if (osighand == SIG_ERR) {
|
||||
+ pam_syslog(idata->pamh, LOG_ERR, "Cannot set signal value");
|
||||
+ rc = PAM_SESSION_ERR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ for (pptr = idata->polydirs_ptr; pptr; pptr = pptr->next) {
|
||||
+ if (pptr->method == TMPDIR && access(pptr->instance_prefix, F_OK) == 0) {
|
||||
+ pid = fork();
|
||||
+ if (pid == 0) {
|
||||
+#ifdef WITH_SELINUX
|
||||
+ if (idata->flags & PAMNS_SELINUX_ENABLED) {
|
||||
+ if (setexeccon(NULL) < 0)
|
||||
+ exit(1);
|
||||
+ }
|
||||
+#endif
|
||||
+ if (execl("/bin/rm", "/bin/rm", "-rf", pptr->instance_prefix, (char *)NULL) < 0)
|
||||
+ exit(1);
|
||||
+ } else if (pid > 0) {
|
||||
+ while (((rc = waitpid(pid, &status, 0)) == (pid_t)-1) &&
|
||||
+ (errno == EINTR));
|
||||
+ if (rc == (pid_t)-1) {
|
||||
+ pam_syslog(idata->pamh, LOG_ERR, "waitpid failed- %m");
|
||||
+ rc = PAM_SESSION_ERR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (!WIFEXITED(status) || WIFSIGNALED(status) > 0) {
|
||||
+ pam_syslog(idata->pamh, LOG_ERR,
|
||||
+ "Error removing %s", pptr->instance_prefix);
|
||||
+ }
|
||||
+ } else if (pid < 0) {
|
||||
+ pam_syslog(idata->pamh, LOG_ERR,
|
||||
+ "Cannot fork to run namespace init script, %m");
|
||||
+ rc = PAM_SESSION_ERR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ rc = PAM_SUCCESS;
|
||||
+out:
|
||||
+ signal(SIGCHLD, osighand);
|
||||
+ return rc;
|
||||
+}
|
||||
|
||||
/*
|
||||
* This function checks to see if polyinstantiation is needed for any
|
||||
@@ -1111,13 +1208,22 @@ static int setup_namespace(struct instan
|
||||
* disassociate from the parent namespace.
|
||||
*/
|
||||
if (need_poly) {
|
||||
+ if (pam_set_data(idata->pamh, NAMESPACE_POLYDIR_DATA, idata->polydirs_ptr,
|
||||
+ cleanup_data) != PAM_SUCCESS) {
|
||||
+ pam_syslog(idata->pamh, LOG_ERR,
|
||||
+ "Unable to set namespace data");
|
||||
+ return PAM_SYSTEM_ERR;
|
||||
+ }
|
||||
if (unshare(CLONE_NEWNS) < 0) {
|
||||
- pam_syslog(idata->pamh, LOG_ERR,
|
||||
+ pam_set_data(idata->pamh, NAMESPACE_POLYDIR_DATA, NULL, NULL);
|
||||
+ pam_syslog(idata->pamh, LOG_ERR,
|
||||
"Unable to unshare from parent namespace, %m");
|
||||
return PAM_SESSION_ERR;
|
||||
}
|
||||
- } else
|
||||
+ } else {
|
||||
+ del_polydir_list(idata->polydirs_ptr);
|
||||
return PAM_SUCCESS;
|
||||
+ }
|
||||
|
||||
/*
|
||||
* Again cycle through all polyinstantiated directories, this time,
|
||||
@@ -1144,7 +1250,8 @@ static int setup_namespace(struct instan
|
||||
* umount
|
||||
*/
|
||||
if ((changing_dir = cwd_in(pptr->dir, idata)) < 0) {
|
||||
- return PAM_SESSION_ERR;
|
||||
+ retval = PAM_SESSION_ERR;
|
||||
+ goto out;
|
||||
} else if (changing_dir) {
|
||||
if (idata->flags & PAMNS_DEBUG)
|
||||
pam_syslog(idata->pamh, LOG_DEBUG, "changing cwd");
|
||||
@@ -1172,8 +1279,10 @@ static int setup_namespace(struct instan
|
||||
int saved_errno = errno;
|
||||
pam_syslog(idata->pamh, LOG_ERR, "Unmount of %s failed, %m",
|
||||
pptr->dir);
|
||||
- if (saved_errno != EINVAL)
|
||||
- return PAM_SESSION_ERR;
|
||||
+ if (saved_errno != EINVAL) {
|
||||
+ retval = PAM_SESSION_ERR;
|
||||
+ goto out;
|
||||
+ }
|
||||
} else if (idata->flags & PAMNS_DEBUG)
|
||||
pam_syslog(idata->pamh, LOG_DEBUG, "Umount succeeded %s",
|
||||
pptr->dir);
|
||||
@@ -1185,7 +1294,9 @@ static int setup_namespace(struct instan
|
||||
break;
|
||||
}
|
||||
}
|
||||
-
|
||||
+out:
|
||||
+ if (retval != PAM_SUCCESS)
|
||||
+ cleanup_tmpdirs(idata);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -1224,8 +1335,10 @@ static int orig_namespace(struct instanc
|
||||
} else if (idata->flags & PAMNS_DEBUG)
|
||||
pam_syslog(idata->pamh, LOG_DEBUG, "Unmount of %s succeeded",
|
||||
pptr->dir);
|
||||
- }
|
||||
+ }
|
||||
}
|
||||
+
|
||||
+ cleanup_tmpdirs(idata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1350,7 +1463,8 @@ PAM_EXTERN int pam_sm_open_session(pam_h
|
||||
} else if (idata.flags & PAMNS_DEBUG)
|
||||
pam_syslog(idata.pamh, LOG_DEBUG, "Nothing to polyinstantiate");
|
||||
|
||||
- del_polydir_list(idata.polydirs_ptr);
|
||||
+ if (retval != PAM_SUCCESS)
|
||||
+ del_polydir_list(idata.polydirs_ptr);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -1365,6 +1479,7 @@ PAM_EXTERN int pam_sm_close_session(pam_
|
||||
struct instance_data idata;
|
||||
char *user_name;
|
||||
struct passwd *pwd;
|
||||
+ const void *polyptr;
|
||||
|
||||
/* init instance data */
|
||||
idata.flags = 0;
|
||||
@@ -1428,16 +1543,12 @@ PAM_EXTERN int pam_sm_close_session(pam_
|
||||
strncat(idata.user, user_name, sizeof(idata.user) - 1);
|
||||
idata.uid = pwd->pw_uid;
|
||||
|
||||
- /*
|
||||
- * Parse namespace configuration file which lists directories that
|
||||
- * are polyinstantiated, directories where instance directories are
|
||||
- * created and the method used for polyinstantiation.
|
||||
- */
|
||||
- retval = parse_config_file(&idata);
|
||||
- if ((retval != PAM_SUCCESS) || !idata.polydirs_ptr) {
|
||||
- del_polydir_list(idata.polydirs_ptr);
|
||||
- return PAM_SESSION_ERR;
|
||||
- }
|
||||
+ retval = pam_get_data(idata.pamh, NAMESPACE_POLYDIR_DATA, &polyptr);
|
||||
+ if (retval != PAM_SUCCESS || polyptr == NULL)
|
||||
+ /* nothing to reset */
|
||||
+ return PAM_SUCCESS;
|
||||
+
|
||||
+ idata.polydirs_ptr = polyptr;
|
||||
|
||||
if (idata.flags & PAMNS_DEBUG)
|
||||
pam_syslog(idata.pamh, LOG_DEBUG, "Resetting namespace for pid %d",
|
||||
@@ -1452,7 +1563,9 @@ PAM_EXTERN int pam_sm_close_session(pam_
|
||||
pam_syslog(idata.pamh, LOG_DEBUG,
|
||||
"resetting namespace ok for pid %d", getpid());
|
||||
}
|
||||
- del_polydir_list(idata.polydirs_ptr);
|
||||
+
|
||||
+ pam_set_data(idata.pamh, NAMESPACE_POLYDIR_DATA, NULL, NULL);
|
||||
+
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
@ -1,838 +0,0 @@
|
||||
diff -up Linux-PAM-0.99.8.1/libpam/libpam.map.audit-failed Linux-PAM-0.99.8.1/libpam/libpam.map
|
||||
--- Linux-PAM-0.99.8.1/libpam/libpam.map.audit-failed 2006-06-14 17:28:44.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/libpam/libpam.map 2008-01-22 22:24:05.000000000 +0100
|
||||
@@ -45,3 +45,7 @@ LIBPAM_MODUTIL_1.0 {
|
||||
pam_modutil_read;
|
||||
pam_modutil_write;
|
||||
};
|
||||
+LIBPAM_MODUTIL_1.1 {
|
||||
+ global:
|
||||
+ pam_modutil_audit_write;
|
||||
+} LIBPAM_MODUTIL_1.0;
|
||||
diff -up Linux-PAM-0.99.8.1/libpam/pam_audit.c.audit-failed Linux-PAM-0.99.8.1/libpam/pam_audit.c
|
||||
--- Linux-PAM-0.99.8.1/libpam/pam_audit.c.audit-failed 2008-01-22 22:24:05.000000000 +0100
|
||||
+++ Linux-PAM-0.99.8.1/libpam/pam_audit.c 2008-01-22 22:24:05.000000000 +0100
|
||||
@@ -42,39 +42,53 @@ _pam_audit_writelog(pam_handle_t *pamh,
|
||||
best to fix it. */
|
||||
errno = -rc;
|
||||
|
||||
+ if (rc < 0 && errno != old_errno)
|
||||
+ {
|
||||
+ old_errno = errno;
|
||||
+ pam_syslog (pamh, LOG_CRIT, "audit_log_acct_message() failed: %m");
|
||||
+ }
|
||||
+
|
||||
pamh->audit_state |= PAMAUDIT_LOGGED;
|
||||
|
||||
- if (rc < 0) {
|
||||
- if (rc == -EPERM && getuid() != 0)
|
||||
- return 0;
|
||||
- if (errno != old_errno) {
|
||||
- old_errno = errno;
|
||||
- pam_syslog (pamh, LOG_CRIT, "audit_log_acct_message() failed: %m");
|
||||
- }
|
||||
- }
|
||||
- return rc;
|
||||
+ if (rc == -EPERM && getuid () != 0)
|
||||
+ return 0;
|
||||
+ else
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
-int
|
||||
-_pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags)
|
||||
+static int
|
||||
+_pam_audit_open(pam_handle_t *pamh)
|
||||
{
|
||||
- const char *message;
|
||||
- int type;
|
||||
int audit_fd;
|
||||
-
|
||||
audit_fd = audit_open();
|
||||
if (audit_fd < 0) {
|
||||
/* You get these error codes only when the kernel doesn't have
|
||||
* audit compiled in. */
|
||||
if (errno == EINVAL || errno == EPROTONOSUPPORT ||
|
||||
errno == EAFNOSUPPORT)
|
||||
- return retval;
|
||||
+ return -2;
|
||||
|
||||
/* this should only fail in case of extreme resource shortage,
|
||||
* need to prevent login in that case for CAPP compliance.
|
||||
*/
|
||||
pam_syslog(pamh, LOG_CRIT, "audit_open() failed: %m");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return audit_fd;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+_pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags)
|
||||
+{
|
||||
+ const char *message;
|
||||
+ int type;
|
||||
+ int audit_fd;
|
||||
+
|
||||
+ if ((audit_fd=_pam_audit_open(pamh)) == -1) {
|
||||
return PAM_SYSTEM_ERR;
|
||||
+ } else if (audit_fd == -2) {
|
||||
+ return retval;
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
@@ -141,4 +155,30 @@ _pam_audit_end(pam_handle_t *pamh, int s
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int
|
||||
+pam_modutil_audit_write(pam_handle_t *pamh, int type,
|
||||
+ const char *message, int retval)
|
||||
+{
|
||||
+ int audit_fd;
|
||||
+ int rc;
|
||||
+
|
||||
+ if ((audit_fd=_pam_audit_open(pamh)) == -1) {
|
||||
+ return PAM_SYSTEM_ERR;
|
||||
+ } else if (audit_fd == -2) {
|
||||
+ return retval;
|
||||
+ }
|
||||
+
|
||||
+ rc = _pam_audit_writelog(pamh, audit_fd, type, message, retval);
|
||||
+
|
||||
+ audit_close(audit_fd);
|
||||
+
|
||||
+ return rc < 0 ? PAM_SYSTEM_ERR : PAM_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+#else
|
||||
+int pam_modutil_audit_write(pam_handle_t *pamh UNUSED, int type UNUSED,
|
||||
+ const char *message UNUSED, int retval UNUSED)
|
||||
+{
|
||||
+ return PAM_SUCCESS;
|
||||
+}
|
||||
#endif /* HAVE_LIBAUDIT */
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_access/pam_access.8.xml.audit-failed Linux-PAM-0.99.8.1/modules/pam_access/pam_access.8.xml
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_access/pam_access.8.xml.audit-failed 2007-06-22 10:03:29.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_access/pam_access.8.xml 2008-01-22 22:24:05.000000000 +0100
|
||||
@@ -29,6 +29,9 @@
|
||||
nodefgroup
|
||||
</arg>
|
||||
<arg choice="opt">
|
||||
+ noaudit
|
||||
+ </arg>
|
||||
+ <arg choice="opt">
|
||||
accessfile=<replaceable>file</replaceable>
|
||||
</arg>
|
||||
<arg choice="opt">
|
||||
@@ -54,6 +57,10 @@
|
||||
<filename>/etc/security/access.conf</filename> if you don't specify
|
||||
another file.
|
||||
</para>
|
||||
+ <para>
|
||||
+ If Linux PAM is compiled with audit support the module will report
|
||||
+ when it denies access based on origin (host or tty).
|
||||
+ </para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="pam_access-options">
|
||||
@@ -87,6 +94,17 @@
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
+ <option>noaudit</option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Do not report logins from disallowed hosts and ttys to the audit subsystem.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
<option>fieldsep=<replaceable>separators</replaceable></option>
|
||||
</term>
|
||||
<listitem>
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_access/pam_access.c.audit-failed Linux-PAM-0.99.8.1/modules/pam_access/pam_access.c
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_access/pam_access.c.audit-failed 2007-06-25 11:59:11.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_access/pam_access.c 2008-01-22 22:24:05.000000000 +0100
|
||||
@@ -46,6 +46,10 @@
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
+#ifdef HAVE_LIBAUDIT
|
||||
+#include <libaudit.h>
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* here, we make definitions for the externally accessible functions
|
||||
* in this file (these definitions are required for static modules
|
||||
@@ -81,17 +85,11 @@
|
||||
|
||||
/* Delimiters for fields and for lists of users, ttys or hosts. */
|
||||
|
||||
-static const char *fs = ":"; /* field separator */
|
||||
-static const char *sep = ", \t"; /* list-element separator */
|
||||
-
|
||||
- /* Constants to be used in assignments only, not in comparisons... */
|
||||
|
||||
+#define ALL 2
|
||||
#define YES 1
|
||||
#define NO 0
|
||||
|
||||
-/* Only allow group entries of the form "(xyz)" */
|
||||
-static int only_new_group_syntax = NO;
|
||||
-
|
||||
/*
|
||||
* A structure to bundle up all login-related information to keep the
|
||||
* functional interfaces as generic as possible.
|
||||
@@ -100,12 +98,13 @@ struct login_info {
|
||||
const struct passwd *user;
|
||||
const char *from;
|
||||
const char *config_file;
|
||||
+ int debug; /* Print debugging messages. */
|
||||
+ int only_new_group_syntax; /* Only allow group entries of the form "(xyz)" */
|
||||
+ int noaudit; /* Do not audit denials */
|
||||
+ const char *fs; /* field separator */
|
||||
+ const char *sep; /* list-element separator */
|
||||
};
|
||||
|
||||
-/* Print debugging messages.
|
||||
- Default is NO which means don't print debugging messages. */
|
||||
-static char pam_access_debug = NO;
|
||||
-
|
||||
/* Parse module config arguments */
|
||||
|
||||
static int
|
||||
@@ -113,17 +112,22 @@ parse_args(pam_handle_t *pamh, struct lo
|
||||
int argc, const char **argv)
|
||||
{
|
||||
int i;
|
||||
-
|
||||
+
|
||||
+ loginfo->noaudit = NO;
|
||||
+ loginfo->debug = NO;
|
||||
+ loginfo->only_new_group_syntax = NO;
|
||||
+ loginfo->fs = ":";
|
||||
+ loginfo->sep = ", \t";
|
||||
for (i=0; i<argc; ++i) {
|
||||
if (!strncmp("fieldsep=", argv[i], 9)) {
|
||||
|
||||
/* the admin wants to override the default field separators */
|
||||
- fs = argv[i]+9;
|
||||
+ loginfo->fs = argv[i]+9;
|
||||
|
||||
} else if (!strncmp("listsep=", argv[i], 8)) {
|
||||
|
||||
/* the admin wants to override the default list separators */
|
||||
- sep = argv[i]+8;
|
||||
+ loginfo->sep = argv[i]+8;
|
||||
|
||||
} else if (!strncmp("accessfile=", argv[i], 11)) {
|
||||
FILE *fp = fopen(11 + argv[i], "r");
|
||||
@@ -138,9 +142,11 @@ parse_args(pam_handle_t *pamh, struct lo
|
||||
}
|
||||
|
||||
} else if (strcmp (argv[i], "debug") == 0) {
|
||||
- pam_access_debug = YES;
|
||||
+ loginfo->debug = YES;
|
||||
} else if (strcmp (argv[i], "nodefgroup") == 0) {
|
||||
- only_new_group_syntax = YES;
|
||||
+ loginfo->only_new_group_syntax = YES;
|
||||
+ } else if (strcmp (argv[i], "noaudit") == 0) {
|
||||
+ loginfo->noaudit = YES;
|
||||
} else {
|
||||
pam_syslog(pamh, LOG_ERR, "unrecognized option [%s]", argv[i]);
|
||||
}
|
||||
@@ -153,13 +159,13 @@ parse_args(pam_handle_t *pamh, struct lo
|
||||
|
||||
typedef int match_func (pam_handle_t *, char *, struct login_info *);
|
||||
|
||||
-static int list_match (pam_handle_t *, char *, struct login_info *,
|
||||
+static int list_match (pam_handle_t *, char *, char *, struct login_info *,
|
||||
match_func *);
|
||||
static int user_match (pam_handle_t *, char *, struct login_info *);
|
||||
-static int group_match (pam_handle_t *, const char *, const char *);
|
||||
+static int group_match (pam_handle_t *, const char *, const char *, int);
|
||||
static int from_match (pam_handle_t *, char *, struct login_info *);
|
||||
-static int string_match (pam_handle_t *, const char *, const char *);
|
||||
-static int network_netmask_match (pam_handle_t *, const char *, const char *);
|
||||
+static int string_match (pam_handle_t *, const char *, const char *, int);
|
||||
+static int network_netmask_match (pam_handle_t *, const char *, const char *, int);
|
||||
|
||||
|
||||
/* isipaddr - find out if string provided is an IP address or not */
|
||||
@@ -325,11 +331,12 @@ login_access (pam_handle_t *pamh, struct
|
||||
char *users; /* becomes list of login names */
|
||||
char *froms; /* becomes list of terminals or hosts */
|
||||
int match = NO;
|
||||
+ int nonall_match = NO;
|
||||
int end;
|
||||
int lineno = 0; /* for diagnostics */
|
||||
char *sptr;
|
||||
|
||||
- if (pam_access_debug)
|
||||
+ if (item->debug)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"login_access: user=%s, from=%s, file=%s",
|
||||
item->user->pw_name,
|
||||
@@ -361,8 +368,8 @@ login_access (pam_handle_t *pamh, struct
|
||||
continue;
|
||||
|
||||
/* Allow field seperator in last field of froms */
|
||||
- if (!(perm = strtok_r(line, fs, &sptr))
|
||||
- || !(users = strtok_r(NULL, fs, &sptr))
|
||||
+ if (!(perm = strtok_r(line, item->fs, &sptr))
|
||||
+ || !(users = strtok_r(NULL, item->fs, &sptr))
|
||||
|| !(froms = strtok_r(NULL, "\n", &sptr))) {
|
||||
pam_syslog(pamh, LOG_ERR, "%s: line %d: bad field count",
|
||||
item->config_file, lineno);
|
||||
@@ -373,17 +380,22 @@ login_access (pam_handle_t *pamh, struct
|
||||
item->config_file, lineno);
|
||||
continue;
|
||||
}
|
||||
- if (pam_access_debug)
|
||||
+ if (item->debug)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"line %d: %s : %s : %s", lineno, perm, users, froms);
|
||||
- match = list_match(pamh, froms, item, from_match);
|
||||
- if (pam_access_debug)
|
||||
- pam_syslog (pamh, LOG_DEBUG,
|
||||
- "from_match=%d, \"%s\"", match, item->from);
|
||||
- match = match && list_match (pamh, users, item, user_match);
|
||||
- if (pam_access_debug)
|
||||
+ match = list_match(pamh, users, NULL, item, user_match);
|
||||
+ if (item->debug)
|
||||
pam_syslog (pamh, LOG_DEBUG, "user_match=%d, \"%s\"",
|
||||
match, item->user->pw_name);
|
||||
+ if (match) {
|
||||
+ match = list_match(pamh, froms, NULL, item, from_match);
|
||||
+ if (!match && perm[0] == '+') {
|
||||
+ nonall_match = YES;
|
||||
+ }
|
||||
+ if (item->debug)
|
||||
+ pam_syslog (pamh, LOG_DEBUG,
|
||||
+ "from_match=%d, \"%s\"", match, item->from);
|
||||
+ }
|
||||
}
|
||||
(void) fclose(fp);
|
||||
} else if (errno == ENOENT) {
|
||||
@@ -394,20 +406,27 @@ login_access (pam_handle_t *pamh, struct
|
||||
pam_syslog(pamh, LOG_ERR, "cannot open %s: %m", item->config_file);
|
||||
return NO;
|
||||
}
|
||||
+#ifdef HAVE_LIBAUDIT
|
||||
+ if (!item->noaudit && line[0] == '-' && (match == YES || (match == ALL &&
|
||||
+ nonall_match == YES))) {
|
||||
+ pam_modutil_audit_write(pamh, AUDIT_ANOM_LOGIN_LOCATION,
|
||||
+ "pam_access", 0);
|
||||
+ }
|
||||
+#endif
|
||||
return (match == NO || (line[0] == '+'));
|
||||
}
|
||||
|
||||
|
||||
/* list_match - match an item against a list of tokens with exceptions */
|
||||
|
||||
-static int list_match(pam_handle_t *pamh,
|
||||
- char *list, struct login_info *item, match_func *match_fn)
|
||||
+static int
|
||||
+list_match(pam_handle_t *pamh, char *list, char *sptr,
|
||||
+ struct login_info *item, match_func *match_fn)
|
||||
{
|
||||
char *tok;
|
||||
int match = NO;
|
||||
- char *sptr;
|
||||
|
||||
- if (pam_access_debug)
|
||||
+ if (item->debug && list != NULL)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"list_match: list=%s, item=%s", list, item->user->pw_name);
|
||||
|
||||
@@ -418,8 +437,8 @@ static int list_match(pam_handle_t *pamh
|
||||
* the match is affected by any exceptions.
|
||||
*/
|
||||
|
||||
- for (tok = strtok_r(list, sep, &sptr); tok != 0;
|
||||
- tok = strtok_r(NULL, sep, &sptr)) {
|
||||
+ for (tok = strtok_r(list, item->sep, &sptr); tok != 0;
|
||||
+ tok = strtok_r(NULL, item->sep, &sptr)) {
|
||||
if (strcasecmp(tok, "EXCEPT") == 0) /* EXCEPT: give up */
|
||||
break;
|
||||
if ((match = (*match_fn) (pamh, tok, item))) /* YES */
|
||||
@@ -428,10 +447,12 @@ static int list_match(pam_handle_t *pamh
|
||||
/* Process exceptions to matches. */
|
||||
|
||||
if (match != NO) {
|
||||
- while ((tok = strtok_r(NULL, sep, &sptr)) && strcasecmp(tok, "EXCEPT"))
|
||||
+ while ((tok = strtok_r(NULL, item->sep, &sptr)) && strcasecmp(tok, "EXCEPT"))
|
||||
/* VOID */ ;
|
||||
- if (tok == 0 || list_match(pamh, sptr, item, match_fn) == NO)
|
||||
- return (match);
|
||||
+ if (tok == 0)
|
||||
+ return match;
|
||||
+ if (list_match(pamh, NULL, sptr, item, match_fn) == NO)
|
||||
+ return YES; /* drop special meaning of ALL */
|
||||
}
|
||||
return (NO);
|
||||
}
|
||||
@@ -453,7 +474,7 @@ static char *myhostname(void)
|
||||
|
||||
static int
|
||||
netgroup_match (pam_handle_t *pamh, const char *netgroup,
|
||||
- const char *machine, const char *user)
|
||||
+ const char *machine, const char *user, int debug)
|
||||
{
|
||||
char *mydomain = NULL;
|
||||
int retval;
|
||||
@@ -462,7 +483,7 @@ netgroup_match (pam_handle_t *pamh, cons
|
||||
|
||||
|
||||
retval = innetgr (netgroup, machine, user, mydomain);
|
||||
- if (pam_access_debug == YES)
|
||||
+ if (debug == YES)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"netgroup_match: %d (netgroup=%s, machine=%s, user=%s, domain=%s)",
|
||||
retval, netgroup ? netgroup : "NULL",
|
||||
@@ -480,8 +501,9 @@ user_match (pam_handle_t *pamh, char *to
|
||||
char *string = item->user->pw_name;
|
||||
struct login_info fake_item;
|
||||
char *at;
|
||||
+ int rv;
|
||||
|
||||
- if (pam_access_debug)
|
||||
+ if (item->debug)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"user_match: tok=%s, item=%s", tok, string);
|
||||
|
||||
@@ -500,12 +522,12 @@ user_match (pam_handle_t *pamh, char *to
|
||||
return (user_match (pamh, tok, item) &&
|
||||
from_match (pamh, at + 1, &fake_item));
|
||||
} else if (tok[0] == '@') /* netgroup */
|
||||
- return (netgroup_match (pamh, tok + 1, (char *) 0, string));
|
||||
+ return (netgroup_match (pamh, tok + 1, (char *) 0, string, item->debug));
|
||||
else if (tok[0] == '(' && tok[strlen(tok) - 1] == ')')
|
||||
- return (group_match (pamh, tok, string));
|
||||
- else if (string_match (pamh, tok, string)) /* ALL or exact match */
|
||||
- return YES;
|
||||
- else if (only_new_group_syntax == NO &&
|
||||
+ return (group_match (pamh, tok, string, item->debug));
|
||||
+ else if ((rv=string_match (pamh, tok, string, item->debug)) != NO) /* ALL or exact match */
|
||||
+ return rv;
|
||||
+ else if (item->only_new_group_syntax == NO &&
|
||||
pam_modutil_user_in_group_nam_nam (pamh,
|
||||
item->user->pw_name, tok))
|
||||
/* try group membership */
|
||||
@@ -518,11 +540,12 @@ user_match (pam_handle_t *pamh, char *to
|
||||
/* group_match - match a username against token named group */
|
||||
|
||||
static int
|
||||
-group_match (pam_handle_t *pamh, const char *tok, const char* usr)
|
||||
+group_match (pam_handle_t *pamh, const char *tok, const char* usr,
|
||||
+ int debug)
|
||||
{
|
||||
char grptok[BUFSIZ];
|
||||
|
||||
- if (pam_access_debug)
|
||||
+ if (debug)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"group_match: grp=%s, user=%s", grptok, usr);
|
||||
|
||||
@@ -548,8 +571,9 @@ from_match (pam_handle_t *pamh UNUSED, c
|
||||
const char *string = item->from;
|
||||
int tok_len;
|
||||
int str_len;
|
||||
+ int rv;
|
||||
|
||||
- if (pam_access_debug)
|
||||
+ if (item->debug)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"from_match: tok=%s, item=%s", tok, string);
|
||||
|
||||
@@ -565,10 +589,10 @@ from_match (pam_handle_t *pamh UNUSED, c
|
||||
if (string == NULL) {
|
||||
return NO;
|
||||
} else if (tok[0] == '@') { /* netgroup */
|
||||
- return (netgroup_match (pamh, tok + 1, string, (char *) 0));
|
||||
- } else if (string_match(pamh, tok, string)) {
|
||||
+ return (netgroup_match (pamh, tok + 1, string, (char *) 0, item->debug));
|
||||
+ } else if ((rv = string_match(pamh, tok, string, item->debug)) != NO) {
|
||||
/* ALL or exact match */
|
||||
- return (YES);
|
||||
+ return rv;
|
||||
} else if (tok[0] == '.') { /* domain: match last fields */
|
||||
if ((str_len = strlen(string)) > (tok_len = strlen(tok))
|
||||
&& strcasecmp(tok, string + str_len - tok_len) == 0)
|
||||
@@ -614,7 +638,7 @@ from_match (pam_handle_t *pamh UNUSED, c
|
||||
}
|
||||
} else if (isipaddr(string, NULL, NULL) == YES) {
|
||||
/* Assume network/netmask with a IP of a host. */
|
||||
- if (network_netmask_match(pamh, tok, string))
|
||||
+ if (network_netmask_match(pamh, tok, string, item->debug))
|
||||
return YES;
|
||||
} else {
|
||||
/* Assume network/netmask with a name of a host. */
|
||||
@@ -641,7 +665,7 @@ from_match (pam_handle_t *pamh UNUSED, c
|
||||
: (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr,
|
||||
buf, sizeof (buf));
|
||||
|
||||
- if (network_netmask_match(pamh, tok, buf))
|
||||
+ if (network_netmask_match(pamh, tok, buf, item->debug))
|
||||
{
|
||||
freeaddrinfo (res);
|
||||
return YES;
|
||||
@@ -658,10 +682,11 @@ from_match (pam_handle_t *pamh UNUSED, c
|
||||
/* string_match - match a string against one token */
|
||||
|
||||
static int
|
||||
-string_match (pam_handle_t *pamh, const char *tok, const char *string)
|
||||
+string_match (pam_handle_t *pamh, const char *tok, const char *string,
|
||||
+ int debug)
|
||||
{
|
||||
|
||||
- if (pam_access_debug)
|
||||
+ if (debug)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"string_match: tok=%s, item=%s", tok, string);
|
||||
|
||||
@@ -672,7 +697,7 @@ string_match (pam_handle_t *pamh, const
|
||||
*/
|
||||
|
||||
if (strcasecmp(tok, "ALL") == 0) { /* all: always matches */
|
||||
- return (YES);
|
||||
+ return (ALL);
|
||||
} else if (string != NULL) {
|
||||
if (strcasecmp(tok, string) == 0) { /* try exact match */
|
||||
return (YES);
|
||||
@@ -690,9 +715,9 @@ string_match (pam_handle_t *pamh, const
|
||||
*/
|
||||
static int
|
||||
network_netmask_match (pam_handle_t *pamh,
|
||||
- const char *tok, const char *string)
|
||||
+ const char *tok, const char *string, int debug)
|
||||
{
|
||||
- if (pam_access_debug)
|
||||
+ if (debug)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"network_netmask_match: tok=%s, item=%s", tok, string);
|
||||
|
||||
@@ -771,6 +796,22 @@ pam_sm_authenticate (pam_handle_t *pamh,
|
||||
return PAM_USER_UNKNOWN;
|
||||
}
|
||||
|
||||
+ if ((user_pw=pam_modutil_getpwnam(pamh, user))==NULL)
|
||||
+ return (PAM_USER_UNKNOWN);
|
||||
+
|
||||
+ /*
|
||||
+ * Bundle up the arguments to avoid unnecessary clumsiness later on.
|
||||
+ */
|
||||
+ loginfo.user = user_pw;
|
||||
+ loginfo.config_file = PAM_ACCESS_CONFIG;
|
||||
+
|
||||
+ /* parse the argument list */
|
||||
+
|
||||
+ if (!parse_args(pamh, &loginfo, argc, argv)) {
|
||||
+ pam_syslog(pamh, LOG_ERR, "failed to parse the module arguments");
|
||||
+ return PAM_ABORT;
|
||||
+ }
|
||||
+
|
||||
/* remote host name */
|
||||
|
||||
if (pam_get_item(pamh, PAM_RHOST, &void_from)
|
||||
@@ -799,7 +840,7 @@ pam_sm_authenticate (pam_handle_t *pamh,
|
||||
return PAM_ABORT;
|
||||
}
|
||||
from = void_from;
|
||||
- if (pam_access_debug)
|
||||
+ if (loginfo.debug)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"cannot determine tty or remote hostname, using service %s",
|
||||
from);
|
||||
@@ -817,22 +858,7 @@ pam_sm_authenticate (pam_handle_t *pamh,
|
||||
}
|
||||
}
|
||||
|
||||
- if ((user_pw=pam_modutil_getpwnam(pamh, user))==NULL)
|
||||
- return (PAM_USER_UNKNOWN);
|
||||
-
|
||||
- /*
|
||||
- * Bundle up the arguments to avoid unnecessary clumsiness later on.
|
||||
- */
|
||||
- loginfo.user = user_pw;
|
||||
loginfo.from = from;
|
||||
- loginfo.config_file = PAM_ACCESS_CONFIG;
|
||||
-
|
||||
- /* parse the argument list */
|
||||
-
|
||||
- if (!parse_args(pamh, &loginfo, argc, argv)) {
|
||||
- pam_syslog(pamh, LOG_ERR, "failed to parse the module arguments");
|
||||
- return PAM_ABORT;
|
||||
- }
|
||||
|
||||
if (login_access(pamh, &loginfo)) {
|
||||
return (PAM_SUCCESS);
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_time/pam_time.c.audit-failed Linux-PAM-0.99.8.1/modules/pam_time/pam_time.c
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_time/pam_time.c.audit-failed 2006-06-16 08:35:16.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_time/pam_time.c 2008-01-22 22:24:05.000000000 +0100
|
||||
@@ -22,9 +22,16 @@
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
|
||||
+#ifdef HAVE_LIBAUDIT
|
||||
+#include <libaudit.h>
|
||||
+#endif
|
||||
+
|
||||
#define PAM_TIME_BUFLEN 1000
|
||||
#define FIELD_SEPARATOR ';' /* this is new as of .02 */
|
||||
|
||||
+#define PAM_DEBUG_ARG 0x0001
|
||||
+#define PAM_NO_AUDIT 0x0002
|
||||
+
|
||||
#ifndef TRUE
|
||||
# define TRUE 1
|
||||
#endif
|
||||
@@ -46,6 +53,29 @@ typedef enum { AND, OR } operator;
|
||||
#include <security/_pam_macros.h>
|
||||
#include <security/pam_modules.h>
|
||||
#include <security/pam_ext.h>
|
||||
+#include <security/pam_modutil.h>
|
||||
+
|
||||
+static int
|
||||
+_pam_parse (const pam_handle_t *pamh, int argc, const char **argv)
|
||||
+{
|
||||
+ int ctrl = 0;
|
||||
+
|
||||
+ /* step through arguments */
|
||||
+ for (; argc-- > 0; ++argv) {
|
||||
+
|
||||
+ /* generic options */
|
||||
+
|
||||
+ if (!strcmp(*argv, "debug")) {
|
||||
+ ctrl |= PAM_DEBUG_ARG;
|
||||
+ } else if (!strcmp(*argv, "noaudit")) {
|
||||
+ ctrl |= PAM_NO_AUDIT;
|
||||
+ } else {
|
||||
+ pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return ctrl;
|
||||
+}
|
||||
|
||||
/* --- static functions for checking whether the user should be let in --- */
|
||||
|
||||
@@ -59,7 +89,7 @@ shift_bytes(char *mem, int from, int by)
|
||||
}
|
||||
|
||||
static int
|
||||
-read_field(pam_handle_t *pamh, int fd, char **buf, int *from, int *to)
|
||||
+read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *to)
|
||||
{
|
||||
/* is buf set ? */
|
||||
|
||||
@@ -137,6 +167,7 @@ read_field(pam_handle_t *pamh, int fd, c
|
||||
switch ((*buf)[i]) {
|
||||
int j,c;
|
||||
case '#':
|
||||
+ c = 0;
|
||||
for (j=i; j < *to && (c = (*buf)[j]) != '\n'; ++j);
|
||||
if (j >= *to) {
|
||||
(*buf)[*to = ++i] = '\0';
|
||||
@@ -324,6 +355,13 @@ is_same(pam_handle_t *pamh UNUSED, const
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ /* Ok, we know that b is a substring from A and does not contain
|
||||
+ wildcards, but now the length of both strings must be the same,
|
||||
+ too. */
|
||||
+ if (strlen (a) != strlen(b))
|
||||
+ return FALSE;
|
||||
+
|
||||
return ( !len );
|
||||
}
|
||||
|
||||
@@ -559,11 +597,15 @@ check_account(pam_handle_t *pamh, const
|
||||
|
||||
PAM_EXTERN int
|
||||
pam_sm_acct_mgmt(pam_handle_t *pamh, int flags UNUSED,
|
||||
- int argc UNUSED, const char **argv UNUSED)
|
||||
+ int argc, const char **argv)
|
||||
{
|
||||
const void *service=NULL, *void_tty=NULL;
|
||||
const char *tty;
|
||||
const char *user=NULL;
|
||||
+ int ctrl;
|
||||
+ int rv;
|
||||
+
|
||||
+ ctrl = _pam_parse(pamh, argc, argv);
|
||||
|
||||
/* set service name */
|
||||
|
||||
@@ -612,7 +654,19 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int
|
||||
D(("user=%s", user));
|
||||
D(("tty=%s", tty));
|
||||
|
||||
- return check_account(pamh, service, tty, user);
|
||||
+ rv = check_account(pamh, service, tty, user);
|
||||
+ if (rv != PAM_SUCCESS) {
|
||||
+#ifdef HAVE_LIBAUDIT
|
||||
+ if (!(ctrl & PAM_NO_AUDIT)) {
|
||||
+ pam_modutil_audit_write(pamh, AUDIT_ANOM_LOGIN_TIME,
|
||||
+ "pam_time", rv); /* ignore return value as we fail anyway */
|
||||
+ }
|
||||
+#endif
|
||||
+ if (ctrl & PAM_DEBUG_ARG) {
|
||||
+ pam_syslog(pamh, LOG_DEBUG, "user %s rejected", user);
|
||||
+ }
|
||||
+ }
|
||||
+ return rv;
|
||||
}
|
||||
|
||||
/* end of module definition */
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_time/pam_time.8.xml.audit-failed Linux-PAM-0.99.8.1/modules/pam_time/pam_time.8.xml
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_time/pam_time.8.xml.audit-failed 2006-06-22 21:44:30.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_time/pam_time.8.xml 2008-01-22 22:24:05.000000000 +0100
|
||||
@@ -22,6 +22,12 @@
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis id="pam_time-cmdsynopsis">
|
||||
<command>pam_time.so</command>
|
||||
+ <arg choice="opt">
|
||||
+ debug
|
||||
+ </arg>
|
||||
+ <arg choice="opt">
|
||||
+ noaudit
|
||||
+ </arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
@@ -41,11 +47,40 @@
|
||||
By default rules for time/port access are taken from config file
|
||||
<filename>/etc/security/time.conf</filename>.
|
||||
</para>
|
||||
+ <para>
|
||||
+ If Linux PAM is compiled with audit support the module will report
|
||||
+ when it denies access.
|
||||
+ </para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="pam_time-options">
|
||||
<title>OPTIONS</title>
|
||||
- <para>This module does not recognice any options.</para>
|
||||
+ <variablelist>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>debug</option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Some debug informations are printed with
|
||||
+ <citerefentry><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>noaudit</option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Do not report logins at disallowed time to the audit subsystem.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ </variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="pam_time-services">
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.c.audit-failed Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.c
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.c.audit-failed 2007-07-10 12:10:56.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.c 2008-01-22 22:41:40.000000000 +0100
|
||||
@@ -41,6 +41,10 @@
|
||||
#include <pwd.h>
|
||||
#include <locale.h>
|
||||
|
||||
+#ifdef HAVE_LIBAUDIT
|
||||
+#include <libaudit.h>
|
||||
+#endif
|
||||
+
|
||||
/* Module defines */
|
||||
#define LINE_LENGTH 1024
|
||||
|
||||
@@ -101,6 +105,7 @@ struct pam_limit_s {
|
||||
#define PAM_DEBUG_ARG 0x0001
|
||||
#define PAM_DO_SETREUID 0x0002
|
||||
#define PAM_UTMP_EARLY 0x0004
|
||||
+#define PAM_NO_AUDIT 0x0008
|
||||
|
||||
/* Limits from globbed files. */
|
||||
#define LIMITS_CONF_GLOB LIMITS_FILE_DIR
|
||||
@@ -126,6 +131,8 @@ _pam_parse (const pam_handle_t *pamh, in
|
||||
ctrl |= PAM_DO_SETREUID;
|
||||
} else if (!strcmp(*argv,"utmp_early")) {
|
||||
ctrl |= PAM_UTMP_EARLY;
|
||||
+ } else if (!strcmp(*argv,"noaudit")) {
|
||||
+ ctrl |= PAM_NO_AUDIT;
|
||||
} else {
|
||||
pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
|
||||
}
|
||||
@@ -599,6 +606,13 @@ static int setup_limits(pam_handle_t *pa
|
||||
D(("skip login limit check for uid=0"));
|
||||
} else if (pl->login_limit > 0) {
|
||||
if (check_logins(pamh, uname, pl->login_limit, ctrl, pl) == LOGIN_ERR) {
|
||||
+#ifdef HAVE_LIBAUDIT
|
||||
+ if (!(ctrl & PAM_NO_AUDIT)) {
|
||||
+ pam_modutil_audit_write(pamh, AUDIT_ANOM_LOGIN_SESSIONS,
|
||||
+ "pam_limits", PAM_PERM_DENIED);
|
||||
+ /* ignore return value as we fail anyway */
|
||||
+ }
|
||||
+#endif
|
||||
retval |= LOGIN_ERR;
|
||||
}
|
||||
} else if (pl->login_limit == 0) {
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.8.xml.audit-failed Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.8.xml
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.8.xml.audit-failed 2007-04-30 12:47:26.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.8.xml 2008-01-22 22:24:05.000000000 +0100
|
||||
@@ -34,6 +34,9 @@
|
||||
<arg choice="opt">
|
||||
utmp_early
|
||||
</arg>
|
||||
+ <arg choice="opt">
|
||||
+ noaudit
|
||||
+ </arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
@@ -57,6 +60,11 @@
|
||||
<para>
|
||||
The module must not be called by a multithreaded application.
|
||||
</para>
|
||||
+ <para>
|
||||
+ If Linux PAM is compiled with audit support the module will report
|
||||
+ when it denies access based on limit of maximum number of concurrent
|
||||
+ login sessions.
|
||||
+ </para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="pam_limits-options">
|
||||
@@ -111,6 +119,16 @@
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>noaudit</option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Do not report exceeded maximum logins count to the audit subsystem.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
@ -1,91 +0,0 @@
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c.ns-init Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c.ns-init 2007-08-06 13:57:56.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c 2007-08-06 14:06:52.000000000 +0200
|
||||
@@ -672,7 +672,7 @@ static int poly_name(const struct polydi
|
||||
hash = NULL;
|
||||
} else {
|
||||
char *newname;
|
||||
- if (asprintf(&newname, "%.*s_%s", NAMESPACE_MAX_DIR_LEN-1-strlen(hash),
|
||||
+ if (asprintf(&newname, "%.*s_%s", NAMESPACE_MAX_DIR_LEN-1-(int)strlen(hash),
|
||||
*i_name, hash) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -756,7 +756,7 @@ static int check_inst_parent(char *ipath
|
||||
* directory as arguments.
|
||||
*/
|
||||
static int inst_init(const struct polydir_s *polyptr, const char *ipath,
|
||||
- struct instance_data *idata)
|
||||
+ struct instance_data *idata, int newdir)
|
||||
{
|
||||
pid_t rc, pid;
|
||||
sighandler_t osighand = NULL;
|
||||
@@ -786,7 +786,7 @@ static int inst_init(const struct polydi
|
||||
}
|
||||
#endif
|
||||
if (execl(NAMESPACE_INIT_SCRIPT, NAMESPACE_INIT_SCRIPT,
|
||||
- polyptr->dir, ipath, (char *)NULL) < 0)
|
||||
+ polyptr->dir, ipath, newdir?"1":"0", idata->user, (char *)NULL) < 0)
|
||||
exit(1);
|
||||
} else if (pid > 0) {
|
||||
while (((rc = waitpid(pid, &status, 0)) == (pid_t)-1) &&
|
||||
@@ -831,6 +831,7 @@ static int create_dirs(struct polydir_s
|
||||
{
|
||||
struct stat statbuf, newstatbuf;
|
||||
int rc, fd;
|
||||
+ int newdir = 0;
|
||||
|
||||
/*
|
||||
* stat the directory to polyinstantiate, so its owner-group-mode
|
||||
@@ -884,6 +885,7 @@ static int create_dirs(struct polydir_s
|
||||
}
|
||||
}
|
||||
|
||||
+ newdir = 1;
|
||||
/* Open a descriptor to it to prevent races */
|
||||
fd = open(ipath, O_DIRECTORY | O_RDONLY);
|
||||
if (fd < 0) {
|
||||
@@ -948,7 +950,7 @@ static int create_dirs(struct polydir_s
|
||||
*/
|
||||
|
||||
inst_init:
|
||||
- rc = inst_init(polyptr, ipath, idata);
|
||||
+ rc = inst_init(polyptr, ipath, idata, newdir);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -981,7 +983,7 @@ static int ns_setup(struct polydir_s *po
|
||||
return PAM_SESSION_ERR;
|
||||
}
|
||||
/* we must call inst_init after the mount in this case */
|
||||
- return inst_init(polyptr, "tmpfs", idata);
|
||||
+ return inst_init(polyptr, "tmpfs", idata, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.8.xml.ns-init Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.8.xml
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.8.xml.ns-init 2007-06-18 12:46:47.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.8.xml 2007-08-06 13:57:56.000000000 +0200
|
||||
@@ -60,7 +60,9 @@
|
||||
script <filename>/etc/security/namespace.init</filename> exists, it
|
||||
is used to initialize the namespace every time a new instance
|
||||
directory is setup. The script receives the polyinstantiated
|
||||
- directory path and the instance directory path as its arguments.
|
||||
+ directory path, the instance directory path, flag whether the instance
|
||||
+ directory was newly created (0 for no, 1 for yes), and the user name
|
||||
+ as its arguments.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.init.ns-init Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.init
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.init.ns-init 2007-06-18 12:46:47.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.init 2007-08-06 13:57:56.000000000 +0200
|
||||
@@ -1,6 +1,8 @@
|
||||
#!/bin/sh -p
|
||||
# This is only a boilerplate for the instance initialization script.
|
||||
-# It receives polydir path as $1 and the instance path as $2.
|
||||
+# It receives polydir path as $1, the instance path as $2,
|
||||
+# a flag whether the instance dir was newly created (0 - no, 1 - yes) in $3,
|
||||
+# and user name in $4.
|
||||
#
|
||||
# If you intend to polyinstantiate /tmp and you also want to use the X windows
|
||||
# environment, you will have to use this script to bind mount the socket that
|
@ -1,473 +0,0 @@
|
||||
Written-by: Tomas Mraz <tmraz@redhat.com>
|
||||
Reviewed-by: Karel Zak <kzak@redhat.com>
|
||||
|
||||
diff -up /dev/null Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.8.xml
|
||||
--- /dev/null 2007-09-17 08:57:19.474470099 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.8.xml 2007-09-19 19:37:26.000000000 +0200
|
||||
@@ -0,0 +1,182 @@
|
||||
+<?xml version="1.0" encoding='UTF-8'?>
|
||||
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
|
||||
+
|
||||
+<refentry id="pam_selinux_permit">
|
||||
+
|
||||
+ <refmeta>
|
||||
+ <refentrytitle>pam_selinux_permit</refentrytitle>
|
||||
+ <manvolnum>8</manvolnum>
|
||||
+ <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo>
|
||||
+ </refmeta>
|
||||
+
|
||||
+ <refnamediv id="pam_selinux_permit-name">
|
||||
+ <refname>pam_selinux_permit</refname>
|
||||
+ <refpurpose>PAM module to allow/deny login depending on SELinux enforcement state</refpurpose>
|
||||
+ </refnamediv>
|
||||
+
|
||||
+ <refsynopsisdiv>
|
||||
+ <cmdsynopsis id="pam_selinux_permit-cmdsynopsis">
|
||||
+ <command>pam_selinux_permit.so</command>
|
||||
+ <arg choice="opt">
|
||||
+ debug
|
||||
+ </arg>
|
||||
+ <arg choice="opt">
|
||||
+ conf=<replaceable>/path/to/config/file</replaceable>
|
||||
+ </arg>
|
||||
+ </cmdsynopsis>
|
||||
+ </refsynopsisdiv>
|
||||
+
|
||||
+ <refsect1 id="pam_selinux_permit-description">
|
||||
+ <title>DESCRIPTION</title>
|
||||
+ <para>
|
||||
+ The pam_selinux 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
|
||||
+ he is allowed access only when the SELinux is in enforcing mode. Otherwise
|
||||
+ he is denied access. For users not matching any entry in the config file
|
||||
+ the pam_selinux_permit module returns PAM_IGNORE return value.
|
||||
+ </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
|
||||
+ 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>
|
||||
+ 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>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id="pam_selinux_permit-options">
|
||||
+ <title>OPTIONS</title>
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>debug</option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Turns on debugging via
|
||||
+ <citerefentry>
|
||||
+ <refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum>
|
||||
+ </citerefentry>.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>conf=<replaceable>/path/to/config/file</replaceable></option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Path to alternative config file overriding the default.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id="pam_selinux_permit-services">
|
||||
+ <title>MODULE SERVICES PROVIDED</title>
|
||||
+ <para>
|
||||
+ Only the <option>auth</option> and <option>account</option>
|
||||
+ services are supported.
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id='pam_selinux_permit-return_values'>
|
||||
+ <title>RETURN VALUES</title>
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term>PAM_AUTH_ERR</term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ SELinux is disabled or in the permissive mode and the user
|
||||
+ matches.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term>PAM_SUCCESS</term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ SELinux is in the enforcing mode and the user matches.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term>PAM_IGNORE</term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ The user does not match any entry in the config file.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term>PAM_USER_UNKNOWN</term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ The module was unable to determine the user's name.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term>PAM_SERVICE_ERR</term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Error during reading or parsing the config file.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id="pam_selinux_permit-files">
|
||||
+ <title>FILES</title>
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term><filename>/etc/security/sepermit.conf</filename></term>
|
||||
+ <listitem>
|
||||
+ <para>Default configuration file</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id='pam_selinux_permit-examples'>
|
||||
+ <title>EXAMPLES</title>
|
||||
+ <programlisting>
|
||||
+auth [success=done ignore=ignore default=bad] pam_selinux_permit.so
|
||||
+auth required pam_unix.so
|
||||
+account required pam_unix.so
|
||||
+session required pam_permit.so
|
||||
+ </programlisting>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id='pam_selinux_permit-see_also'>
|
||||
+ <title>SEE ALSO</title>
|
||||
+ <para>
|
||||
+ <citerefentry>
|
||||
+ <refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum>
|
||||
+ </citerefentry>,
|
||||
+ <citerefentry>
|
||||
+ <refentrytitle>pam.d</refentrytitle><manvolnum>8</manvolnum>
|
||||
+ </citerefentry>,
|
||||
+ <citerefentry>
|
||||
+ <refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum>
|
||||
+ </citerefentry>
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id='pam_selinux_permit-author'>
|
||||
+ <title>AUTHOR</title>
|
||||
+ <para>
|
||||
+ pam_selinux_permit was written by Tomas Mraz <tmraz@redhat.com>.
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+</refentry>
|
||||
diff -up /dev/null Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.c
|
||||
--- /dev/null 2007-09-17 08:57:19.474470099 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.c 2007-09-19 20:29:47.000000000 +0200
|
||||
@@ -0,0 +1,222 @@
|
||||
+/******************************************************************************
|
||||
+ * A module for Linux-PAM that allows/denies acces based on SELinux state.
|
||||
+ *
|
||||
+ * Copyright (c) 2007 Red Hat, Inc.
|
||||
+ * Written by Tomas Mraz <tmraz@redhat.com>
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions
|
||||
+ * are met:
|
||||
+ * 1. Redistributions of source code must retain the above copyright
|
||||
+ * notice, and the entire permission notice in its entirety,
|
||||
+ * including the disclaimer of warranties.
|
||||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ * 3. The name of the author may not be used to endorse or promote
|
||||
+ * products derived from this software without specific prior
|
||||
+ * written permission.
|
||||
+ *
|
||||
+ * ALTERNATIVELY, this product may be distributed under the terms of
|
||||
+ * the GNU Public License, in which case the provisions of the GPL are
|
||||
+ * required INSTEAD OF the above restrictions. (This clause is
|
||||
+ * necessary due to a potential bad interaction between the GPL and
|
||||
+ * the restrictions contained in a BSD-style copyright.)
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#include "config.h"
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <pwd.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <syslog.h>
|
||||
+#include <ctype.h>
|
||||
+
|
||||
+#define PAM_SM_AUTH
|
||||
+#define PAM_SM_ACCOUNT
|
||||
+
|
||||
+#include <security/pam_modules.h>
|
||||
+#include <security/_pam_macros.h>
|
||||
+#include <security/pam_modutil.h>
|
||||
+#include <security/pam_ext.h>
|
||||
+
|
||||
+#include <selinux/selinux.h>
|
||||
+
|
||||
+/* return 0 when matched, -1 when unmatched, pam error otherwise */
|
||||
+static int
|
||||
+sepermit_match(pam_handle_t *pamh, const char *cfgfile, const char *user,
|
||||
+ const char *seuser, int debug)
|
||||
+{
|
||||
+ FILE *f;
|
||||
+ char *line = NULL;
|
||||
+ char *start;
|
||||
+ size_t len = 0;
|
||||
+ int matched = 0;
|
||||
+
|
||||
+ f = fopen(cfgfile, "r");
|
||||
+
|
||||
+ if (!f) {
|
||||
+ pam_syslog(pamh, LOG_ERR, "Failed to open config file %s: %m", cfgfile);
|
||||
+ return PAM_SERVICE_ERR;
|
||||
+ }
|
||||
+
|
||||
+ while (!matched && getline(&line, &len, f) != -1) {
|
||||
+ size_t n;
|
||||
+
|
||||
+ if (line[0] == '#')
|
||||
+ continue;
|
||||
+
|
||||
+ start = line;
|
||||
+ while (isspace(*start))
|
||||
+ ++start;
|
||||
+ n = strlen(start);
|
||||
+ while (n > 0 && isspace(start[n-1])) {
|
||||
+ --n;
|
||||
+ }
|
||||
+ if (n == 0)
|
||||
+ continue;
|
||||
+
|
||||
+ start[n] = '\0';
|
||||
+
|
||||
+ switch (start[0]) {
|
||||
+ case '@':
|
||||
+ ++start;
|
||||
+ if (debug)
|
||||
+ pam_syslog(pamh, LOG_NOTICE, "Matching user %s against group %s", user, start);
|
||||
+ if (pam_modutil_user_in_group_nam_nam(pamh, user, start)) {
|
||||
+ matched = 1;
|
||||
+ }
|
||||
+ break;
|
||||
+ case '%':
|
||||
+ ++start;
|
||||
+ if (debug)
|
||||
+ pam_syslog(pamh, LOG_NOTICE, "Matching seuser %s against seuser %s", seuser, start);
|
||||
+ if (strcmp(seuser, start) == 0) {
|
||||
+ matched = 1;
|
||||
+ }
|
||||
+ break;
|
||||
+ default:
|
||||
+ if (debug)
|
||||
+ pam_syslog(pamh, LOG_NOTICE, "Matching user %s against user %s", user, start);
|
||||
+ if (strcmp(user, start) == 0) {
|
||||
+ matched = 1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ free(line);
|
||||
+ fclose(f);
|
||||
+ return matched ? 0 : -1;
|
||||
+}
|
||||
+
|
||||
+PAM_EXTERN int
|
||||
+pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED,
|
||||
+ int argc, const char **argv)
|
||||
+{
|
||||
+ int i;
|
||||
+ int rv;
|
||||
+ int debug = 0;
|
||||
+ int sense = PAM_AUTH_ERR;
|
||||
+ const char *user = NULL;
|
||||
+ char *seuser = NULL;
|
||||
+ char *level = NULL;
|
||||
+ const char *cfgfile = SEPERMIT_CONF_FILE;
|
||||
+
|
||||
+ /* Parse arguments. */
|
||||
+ for (i = 0; i < argc; i++) {
|
||||
+ if (strcmp(argv[i], "debug") == 0) {
|
||||
+ debug = 1;
|
||||
+ }
|
||||
+ if (strcmp(argv[i], "conf=") == 0) {
|
||||
+ cfgfile = argv[i] + 5;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (debug)
|
||||
+ pam_syslog(pamh, LOG_NOTICE, "Parsing config file: %s", cfgfile);
|
||||
+
|
||||
+ if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS || user == NULL
|
||||
+ || *user == '\0') {
|
||||
+ pam_syslog(pamh, LOG_ERR, "Cannot determine the user's name");
|
||||
+ return PAM_USER_UNKNOWN;
|
||||
+ }
|
||||
+
|
||||
+ if (is_selinux_enabled() > 0) {
|
||||
+ if (security_getenforce() == 1) {
|
||||
+ if (debug)
|
||||
+ pam_syslog(pamh, LOG_NOTICE, "Enforcing mode, access will be allowed on match");
|
||||
+ sense = PAM_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
+ if (getseuserbyname(user, &seuser, &level) != 0) {
|
||||
+ seuser = NULL;
|
||||
+ level = NULL;
|
||||
+ pam_syslog(pamh, LOG_ERR, "getseuserbyname failed: %m");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (debug && sense != PAM_SUCCESS)
|
||||
+ pam_syslog(pamh, LOG_NOTICE, "Access will not be allowed on match");
|
||||
+
|
||||
+ rv = sepermit_match(pamh, cfgfile, user, seuser, debug);
|
||||
+
|
||||
+ if (debug)
|
||||
+ pam_syslog(pamh, LOG_NOTICE, "sepermit_match returned: %d", rv);
|
||||
+
|
||||
+ free(seuser);
|
||||
+ free(level);
|
||||
+
|
||||
+ switch (rv) {
|
||||
+ case -1:
|
||||
+ return PAM_IGNORE;
|
||||
+ case 0:
|
||||
+ return sense;
|
||||
+ }
|
||||
+
|
||||
+ return rv;
|
||||
+}
|
||||
+
|
||||
+PAM_EXTERN int
|
||||
+pam_sm_setcred (pam_handle_t *pamh UNUSED, int flags UNUSED,
|
||||
+ int argc UNUSED, const char **argv UNUSED)
|
||||
+{
|
||||
+ return PAM_IGNORE;
|
||||
+}
|
||||
+
|
||||
+PAM_EXTERN int
|
||||
+pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
|
||||
+ int argc, const char **argv)
|
||||
+{
|
||||
+ return pam_sm_authenticate(pamh, flags, argc, argv);
|
||||
+}
|
||||
+
|
||||
+#ifdef PAM_STATIC
|
||||
+
|
||||
+/* static module data */
|
||||
+
|
||||
+struct pam_module _pam_access_modstruct = {
|
||||
+ "pam_access",
|
||||
+ pam_sm_authenticate,
|
||||
+ pam_sm_setcred,
|
||||
+ pam_sm_acct_mgmt,
|
||||
+ NULL,
|
||||
+ NULL,
|
||||
+ NULL
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
diff -up /dev/null Linux-PAM-0.99.8.1/modules/pam_selinux/sepermit.conf
|
||||
--- /dev/null 2007-09-17 08:57:19.474470099 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_selinux/sepermit.conf 2007-09-19 19:37:26.000000000 +0200
|
||||
@@ -0,0 +1,6 @@
|
||||
+# /etc/security/sepermit.conf
|
||||
+#
|
||||
+# Each line contains either:
|
||||
+# - an user name
|
||||
+# - a group name, with @group syntax
|
||||
+# - a SELinux user name, with %seuser syntax
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am.permit Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am.permit 2007-01-23 11:09:25.000000000 +0100
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am 2007-09-19 19:37:26.000000000 +0200
|
||||
@@ -5,20 +5,21 @@
|
||||
CLEANFILES = *~
|
||||
|
||||
EXTRA_DIST = README $(XMLS) pam_selinux.8 pam_selinux_check.8 \
|
||||
- tst-pam_selinux
|
||||
+ pam_seliux_permit.8 sepermit.conf tst-pam_selinux
|
||||
|
||||
if HAVE_LIBSELINUX
|
||||
TESTS = tst-pam_selinux
|
||||
- man_MANS = pam_selinux.8
|
||||
+ man_MANS = pam_selinux.8 pam_selinux_permit.8
|
||||
endif
|
||||
|
||||
-XMLS = README.xml pam_selinux.8.xml
|
||||
+XMLS = README.xml pam_selinux.8.xml pam_selinux_permit.8.xml
|
||||
|
||||
securelibdir = $(SECUREDIR)
|
||||
secureconfdir = $(SCONFIGDIR)
|
||||
|
||||
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
|
||||
- -I$(top_srcdir)/libpam_misc/include
|
||||
+ -I$(top_srcdir)/libpam_misc/include \
|
||||
+ -D SEPERMIT_CONF_FILE=\"$(SCONFIGDIR)/sepermit.conf\"
|
||||
AM_LDFLAGS = -no-undefined \
|
||||
-L$(top_builddir)/libpam -lpam @LIBSELINUX@
|
||||
|
||||
@@ -30,12 +31,16 @@ if HAVE_VERSIONING
|
||||
-Wl,--version-script=$(srcdir)/../modules.map
|
||||
endif
|
||||
|
||||
+pam_selinux_permit_la_LDFLAGS= $(pam_selinux_la_LDFLAGS)
|
||||
+
|
||||
+secureconf_DATA = sepermit.conf
|
||||
+
|
||||
if HAVE_LIBSELINUX
|
||||
- securelib_LTLIBRARIES = pam_selinux.la
|
||||
+ securelib_LTLIBRARIES = pam_selinux.la pam_selinux_permit.la
|
||||
noinst_PROGRAMS = pam_selinux_check
|
||||
endif
|
||||
if ENABLE_REGENERATE_MAN
|
||||
-noinst_DATA = README pam_selinux.8
|
||||
+noinst_DATA = README pam_selinux.8 pam_selinux_permit.8
|
||||
README: pam_selinux.8.xml
|
||||
-include $(top_srcdir)/Make.xml.rules
|
||||
endif
|
@ -1,318 +0,0 @@
|
||||
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@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
|
@ -1,31 +0,0 @@
|
||||
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])
|
@ -1,784 +0,0 @@
|
||||
Index: libpam/pam_dispatch.c
|
||||
===================================================================
|
||||
RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_dispatch.c,v
|
||||
retrieving revision 1.11
|
||||
diff -u -p -r1.11 pam_dispatch.c
|
||||
--- libpam/pam_dispatch.c 1 Aug 2006 08:54:57 -0000 1.11
|
||||
+++ libpam/pam_dispatch.c 12 Oct 2007 16:23:37 -0000
|
||||
@@ -34,7 +34,8 @@
|
||||
static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h,
|
||||
_pam_boolean resumed, int use_cached_chain)
|
||||
{
|
||||
- int depth, impression, status, skip_depth;
|
||||
+ int depth, impression, status, skip_depth, prev_level, stack_level;
|
||||
+ struct _pam_substack_state *substates = NULL;
|
||||
|
||||
IF_NO_PAMH("_pam_dispatch_aux", pamh, PAM_SYSTEM_ERR);
|
||||
|
||||
@@ -54,27 +55,51 @@ static int _pam_dispatch_aux(pam_handle_
|
||||
skip_depth = pamh->former.depth;
|
||||
status = pamh->former.status;
|
||||
impression = pamh->former.impression;
|
||||
+ substates = pamh->former.substates;
|
||||
/* forget all that */
|
||||
pamh->former.impression = _PAM_UNDEF;
|
||||
pamh->former.status = PAM_MUST_FAIL_CODE;
|
||||
pamh->former.depth = 0;
|
||||
+ pamh->former.substates = NULL;
|
||||
} else {
|
||||
skip_depth = 0;
|
||||
- impression = _PAM_UNDEF;
|
||||
- status = PAM_MUST_FAIL_CODE;
|
||||
+ substates = malloc(PAM_SUBSTACK_MAX_LEVEL * sizeof(*substates));
|
||||
+ if (substates == NULL) {
|
||||
+ pam_syslog(pamh, LOG_CRIT,
|
||||
+ "_pam_dispatch_aux: no memory for substack states");
|
||||
+ return PAM_BUF_ERR;
|
||||
+ }
|
||||
+ substates[0].impression = impression = _PAM_UNDEF;
|
||||
+ substates[0].status = status = PAM_MUST_FAIL_CODE;
|
||||
}
|
||||
|
||||
+ prev_level = 0;
|
||||
+
|
||||
/* Loop through module logic stack */
|
||||
- for (depth=0 ; h != NULL ; h = h->next, ++depth) {
|
||||
+ for (depth=0 ; h != NULL ; prev_level = stack_level, h = h->next, ++depth) {
|
||||
int retval, cached_retval, action;
|
||||
|
||||
+ stack_level = h->stack_level;
|
||||
+
|
||||
/* skip leading modules if they have already returned */
|
||||
if (depth < skip_depth) {
|
||||
continue;
|
||||
}
|
||||
|
||||
+ /* remember state if we are entering a substack */
|
||||
+ if (prev_level < stack_level) {
|
||||
+ substates[stack_level].impression = impression;
|
||||
+ substates[stack_level].status = status;
|
||||
+ }
|
||||
+
|
||||
/* attempt to call the module */
|
||||
- if (h->func == NULL) {
|
||||
+ if (h->handler_type == PAM_HT_MUST_FAIL) {
|
||||
+ D(("module poorly listed in PAM config; forcing failure"));
|
||||
+ retval = PAM_MUST_FAIL_CODE;
|
||||
+ } else if (h->handler_type == PAM_HT_SUBSTACK) {
|
||||
+ D(("skipping substack handler"));
|
||||
+ continue;
|
||||
+ } else if (h->func == NULL) {
|
||||
D(("module function is not defined, indicating failure"));
|
||||
retval = PAM_MODULE_UNKNOWN;
|
||||
} else {
|
||||
@@ -83,10 +108,6 @@ static int _pam_dispatch_aux(pam_handle_
|
||||
retval = h->func(pamh, flags, h->argc, h->argv);
|
||||
pamh->mod_name=NULL;
|
||||
D(("module returned: %s", pam_strerror(pamh, retval)));
|
||||
- if (h->must_fail) {
|
||||
- D(("module poorly listed in PAM config; forcing failure"));
|
||||
- retval = PAM_MUST_FAIL_CODE;
|
||||
- }
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -100,6 +121,7 @@ static int _pam_dispatch_aux(pam_handle_
|
||||
pamh->former.impression = impression;
|
||||
pamh->former.status = status;
|
||||
pamh->former.depth = depth;
|
||||
+ pamh->former.substates = substates;
|
||||
|
||||
D(("module %d returned PAM_INCOMPLETE", depth));
|
||||
return retval;
|
||||
@@ -176,8 +198,8 @@ static int _pam_dispatch_aux(pam_handle_
|
||||
switch (action) {
|
||||
case _PAM_ACTION_RESET:
|
||||
|
||||
- impression = _PAM_UNDEF;
|
||||
- status = PAM_MUST_FAIL_CODE;
|
||||
+ impression = substates[stack_level].impression;
|
||||
+ status = substates[stack_level].status;
|
||||
break;
|
||||
|
||||
case _PAM_ACTION_OK:
|
||||
@@ -244,9 +266,13 @@ static int _pam_dispatch_aux(pam_handle_
|
||||
}
|
||||
|
||||
/* this means that we need to skip #action stacked modules */
|
||||
- do {
|
||||
- h = h->next;
|
||||
- } while ( --action > 0 && h != NULL );
|
||||
+ while (h->next != NULL && h->next->stack_level >= stack_level && action > 0) {
|
||||
+ do {
|
||||
+ h = h->next;
|
||||
+ ++depth;
|
||||
+ } while (h->next != NULL && h->next->stack_level > stack_level);
|
||||
+ --action;
|
||||
+ }
|
||||
|
||||
/* note if we try to skip too many modules action is
|
||||
still non-zero and we snag the next if. */
|
||||
@@ -254,14 +280,19 @@ static int _pam_dispatch_aux(pam_handle_
|
||||
|
||||
/* this case is a syntax error: we can't succeed */
|
||||
if (action) {
|
||||
- D(("action syntax error"));
|
||||
+ pam_syslog(pamh, LOG_ERR, "bad jump in stack");
|
||||
impression = _PAM_NEGATIVE;
|
||||
status = PAM_MUST_FAIL_CODE;
|
||||
}
|
||||
}
|
||||
- }
|
||||
-
|
||||
+ continue;
|
||||
+
|
||||
decision_made: /* by getting here we have made a decision */
|
||||
+ while (h->next != NULL && h->next->stack_level >= stack_level) {
|
||||
+ h = h->next;
|
||||
+ ++depth;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
/* Sanity check */
|
||||
if ( status == PAM_SUCCESS && impression != _PAM_POSITIVE ) {
|
||||
@@ -269,6 +300,7 @@ decision_made: /* by getting here w
|
||||
status = PAM_MUST_FAIL_CODE;
|
||||
}
|
||||
|
||||
+ free(substates);
|
||||
/* We have made a decision about the modules executed */
|
||||
return status;
|
||||
}
|
||||
Index: libpam/pam_end.c
|
||||
===================================================================
|
||||
RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_end.c,v
|
||||
retrieving revision 1.4
|
||||
diff -u -p -r1.4 pam_end.c
|
||||
--- libpam/pam_end.c 12 Jan 2006 10:06:49 -0000 1.4
|
||||
+++ libpam/pam_end.c 12 Oct 2007 16:23:37 -0000
|
||||
@@ -71,6 +71,8 @@ int pam_end(pam_handle_t *pamh, int pam_
|
||||
_pam_drop(pamh->pam_conversation);
|
||||
pamh->fail_delay.delay_fn_ptr = NULL;
|
||||
|
||||
+ _pam_drop(pamh->former.substates);
|
||||
+
|
||||
/* and finally liberate the memory for the pam_handle structure */
|
||||
|
||||
_pam_drop(pamh);
|
||||
Index: libpam/pam_handlers.c
|
||||
===================================================================
|
||||
RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_handlers.c,v
|
||||
retrieving revision 1.24
|
||||
diff -u -p -r1.24 pam_handlers.c
|
||||
--- libpam/pam_handlers.c 14 Jun 2006 11:41:47 -0000 1.24
|
||||
+++ libpam/pam_handlers.c 12 Oct 2007 16:23:37 -0000
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#define BUF_SIZE 1024
|
||||
#define MODULE_CHUNK 4
|
||||
-#define UNKNOWN_MODULE_PATH "<*unknown module path*>"
|
||||
+#define UNKNOWN_MODULE "<*unknown module*>"
|
||||
#ifndef _PAM_ISA
|
||||
#define _PAM_ISA "."
|
||||
#endif
|
||||
@@ -28,7 +28,7 @@ static int _pam_assemble_line(FILE *f, c
|
||||
static void _pam_free_handlers_aux(struct handler **hp);
|
||||
|
||||
static int _pam_add_handler(pam_handle_t *pamh
|
||||
- , int must_fail, int other, int type
|
||||
+ , int must_fail, int other, int stack_level, int type
|
||||
, int *actions, const char *mod_path
|
||||
, int argc, char **argv, int argvlen);
|
||||
|
||||
@@ -43,6 +43,7 @@ static int _pam_add_handler(pam_handle_t
|
||||
static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name
|
||||
, const char *service /* specific file */
|
||||
, int module_type /* specific type */
|
||||
+ , int stack_level /* level of substack */
|
||||
#ifdef PAM_READ_BOTH_CONFS
|
||||
, int not_other
|
||||
#endif /* PAM_READ_BOTH_CONFS */
|
||||
@@ -51,6 +52,7 @@ static int _pam_load_conf_file(pam_handl
|
||||
static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
|
||||
, const char *known_service /* specific file */
|
||||
, int requested_module_type /* specific type */
|
||||
+ , int stack_level /* level of substack */
|
||||
#ifdef PAM_READ_BOTH_CONFS
|
||||
, int not_other
|
||||
#endif /* PAM_READ_BOTH_CONFS */
|
||||
@@ -68,7 +70,7 @@ static int _pam_parse_conf_file(pam_hand
|
||||
int module_type, actions[_PAM_RETURN_VALUES];
|
||||
int other; /* set if module is for PAM_DEFAULT_SERVICE */
|
||||
int res; /* module added successfully? */
|
||||
- int must_fail=0; /* a badly formatted line must fail when used */
|
||||
+ int handler_type = PAM_HT_MODULE; /* regular handler from a module */
|
||||
int argc;
|
||||
char **argv;
|
||||
int argvlen;
|
||||
@@ -92,6 +94,7 @@ static int _pam_parse_conf_file(pam_hand
|
||||
/* accept "service name" or PAM_DEFAULT_SERVICE modules */
|
||||
if (!strcasecmp(this_service, pamh->service_name) || other) {
|
||||
int pam_include = 0;
|
||||
+ int substack = 0;
|
||||
|
||||
/* This is a service we are looking for */
|
||||
D(("_pam_init_handlers: Found PAM config entry for: %s"
|
||||
@@ -105,7 +108,7 @@ static int _pam_parse_conf_file(pam_hand
|
||||
"(%s) empty module type", this_service);
|
||||
module_type = (requested_module_type != PAM_T_ANY) ?
|
||||
requested_module_type : PAM_T_AUTH; /* most sensitive */
|
||||
- must_fail = 1; /* install as normal but fail when dispatched */
|
||||
+ handler_type = PAM_HT_MUST_FAIL; /* install as normal but fail when dispatched */
|
||||
} else if (!strcasecmp("auth", tok)) {
|
||||
module_type = PAM_T_AUTH;
|
||||
} else if (!strcasecmp("session", tok)) {
|
||||
@@ -121,9 +124,9 @@ static int _pam_parse_conf_file(pam_hand
|
||||
this_service, tok);
|
||||
module_type = (requested_module_type != PAM_T_ANY) ?
|
||||
requested_module_type : PAM_T_AUTH; /* most sensitive */
|
||||
- must_fail = 1; /* install as normal but fail when dispatched */
|
||||
+ handler_type = PAM_HT_MUST_FAIL; /* install as normal but fail when dispatched */
|
||||
}
|
||||
- D(("Using %s config entry: %s", must_fail?"BAD ":"", tok));
|
||||
+ D(("Using %s config entry: %s", handler_type?"BAD ":"", tok));
|
||||
if (requested_module_type != PAM_T_ANY &&
|
||||
module_type != requested_module_type) {
|
||||
D(("Skipping config entry: %s (requested=%d, found=%d)",
|
||||
@@ -145,7 +148,7 @@ static int _pam_parse_conf_file(pam_hand
|
||||
pam_syslog(pamh, LOG_ERR,
|
||||
"(%s) no control flag supplied", this_service);
|
||||
_pam_set_default_control(actions, _PAM_ACTION_BAD);
|
||||
- must_fail = 1;
|
||||
+ handler_type = PAM_HT_MUST_FAIL;
|
||||
} else if (!strcasecmp("required", tok)) {
|
||||
D(("*PAM_F_REQUIRED*"));
|
||||
actions[PAM_SUCCESS] = _PAM_ACTION_OK;
|
||||
@@ -171,6 +174,11 @@ static int _pam_parse_conf_file(pam_hand
|
||||
} else if (!strcasecmp("include", tok)) {
|
||||
D(("*PAM_F_INCLUDE*"));
|
||||
pam_include = 1;
|
||||
+ substack = 0;
|
||||
+ } else if (!strcasecmp("substack", tok)) {
|
||||
+ D(("*PAM_F_SUBSTACK*"));
|
||||
+ pam_include = 1;
|
||||
+ substack = 1;
|
||||
} else {
|
||||
D(("will need to parse %s", tok));
|
||||
_pam_parse_control(actions, tok);
|
||||
@@ -180,7 +188,18 @@ static int _pam_parse_conf_file(pam_hand
|
||||
|
||||
tok = _pam_StrTok(NULL, " \n\t", &nexttok);
|
||||
if (pam_include) {
|
||||
- if (_pam_load_conf_file(pamh, tok, this_service, module_type
|
||||
+ if (substack) {
|
||||
+ res = _pam_add_handler(pamh, PAM_HT_SUBSTACK, other,
|
||||
+ stack_level, module_type, actions, tok,
|
||||
+ 0, NULL, 0);
|
||||
+ if (res != PAM_SUCCESS) {
|
||||
+ pam_syslog(pamh, LOG_ERR, "error adding substack %s", tok);
|
||||
+ D(("failed to load module - aborting"));
|
||||
+ return PAM_ABORT;
|
||||
+ }
|
||||
+ }
|
||||
+ if (_pam_load_conf_file(pamh, tok, this_service, module_type,
|
||||
+ stack_level + substack
|
||||
#ifdef PAM_READ_BOTH_CONFS
|
||||
, !other
|
||||
#endif /* PAM_READ_BOTH_CONFS */
|
||||
@@ -188,7 +207,7 @@ static int _pam_parse_conf_file(pam_hand
|
||||
continue;
|
||||
_pam_set_default_control(actions, _PAM_ACTION_BAD);
|
||||
mod_path = NULL;
|
||||
- must_fail = 1;
|
||||
+ handler_type = PAM_HT_MUST_FAIL;
|
||||
nexttok = NULL;
|
||||
} else if (tok != NULL) {
|
||||
mod_path = tok;
|
||||
@@ -199,7 +218,7 @@ static int _pam_parse_conf_file(pam_hand
|
||||
pam_syslog(pamh, LOG_ERR,
|
||||
"(%s) no module name supplied", this_service);
|
||||
mod_path = NULL;
|
||||
- must_fail = 1;
|
||||
+ handler_type = PAM_HT_MUST_FAIL;
|
||||
}
|
||||
|
||||
/* nexttok points to remaining arguments... */
|
||||
@@ -219,7 +238,7 @@ static int _pam_parse_conf_file(pam_hand
|
||||
int y;
|
||||
|
||||
D(("CONF%s: %s%s %d %s %d"
|
||||
- , must_fail?"<*will fail*>":""
|
||||
+ , handler_type==PAM_HT_MUST_FAIL?"<*will fail*>":""
|
||||
, this_service, other ? "(backup)":""
|
||||
, module_type
|
||||
, mod_path, argc));
|
||||
@@ -235,7 +254,7 @@ static int _pam_parse_conf_file(pam_hand
|
||||
}
|
||||
#endif
|
||||
|
||||
- res = _pam_add_handler(pamh, must_fail, other
|
||||
+ res = _pam_add_handler(pamh, handler_type, other, stack_level
|
||||
, module_type, actions, mod_path
|
||||
, argc, argv, argvlen);
|
||||
if (res != PAM_SUCCESS) {
|
||||
@@ -252,6 +271,7 @@ static int _pam_parse_conf_file(pam_hand
|
||||
static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name
|
||||
, const char *service /* specific file */
|
||||
, int module_type /* specific type */
|
||||
+ , int stack_level /* level of substack */
|
||||
#ifdef PAM_READ_BOTH_CONFS
|
||||
, int not_other
|
||||
#endif /* PAM_READ_BOTH_CONFS */
|
||||
@@ -263,6 +283,12 @@ static int _pam_load_conf_file(pam_handl
|
||||
|
||||
D(("_pam_load_conf_file called"));
|
||||
|
||||
+ if (stack_level >= PAM_SUBSTACK_MAX_LEVEL) {
|
||||
+ D(("maximum level of substacks reached"));
|
||||
+ pam_syslog(pamh, LOG_ERR, "maximum level of substacks reached");
|
||||
+ return PAM_ABORT;
|
||||
+ }
|
||||
+
|
||||
if (config_name == NULL) {
|
||||
D(("no config file supplied"));
|
||||
pam_syslog(pamh, LOG_ERR, "(%s) no config file supplied", service);
|
||||
@@ -280,7 +306,7 @@ static int _pam_load_conf_file(pam_handl
|
||||
D(("opening %s", config_name));
|
||||
f = fopen(config_name, "r");
|
||||
if (f != NULL) {
|
||||
- retval = _pam_parse_conf_file(pamh, f, service, module_type
|
||||
+ retval = _pam_parse_conf_file(pamh, f, service, module_type, stack_level
|
||||
#ifdef PAM_READ_BOTH_CONFS
|
||||
, not_other
|
||||
#endif /* PAM_READ_BOTH_CONFS */
|
||||
@@ -379,7 +405,8 @@ int _pam_init_handlers(pam_handle_t *pam
|
||||
f = fopen(filename, "r");
|
||||
if (f != NULL) {
|
||||
/* would test magic here? */
|
||||
- retval = _pam_parse_conf_file(pamh, f, pamh->service_name, PAM_T_ANY
|
||||
+ retval = _pam_parse_conf_file(pamh, f, pamh->service_name,
|
||||
+ PAM_T_ANY, 0
|
||||
#ifdef PAM_READ_BOTH_CONFS
|
||||
, 0
|
||||
#endif /* PAM_READ_BOTH_CONFS */
|
||||
@@ -400,7 +427,7 @@ int _pam_init_handlers(pam_handle_t *pam
|
||||
D(("checking %s", PAM_CONFIG));
|
||||
|
||||
if ((f = fopen(PAM_CONFIG,"r")) != NULL) {
|
||||
- retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 1);
|
||||
+ retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 0, 1);
|
||||
fclose(f);
|
||||
} else
|
||||
#endif /* PAM_READ_BOTH_CONFS */
|
||||
@@ -419,9 +446,8 @@ int _pam_init_handlers(pam_handle_t *pam
|
||||
f = fopen(PAM_DEFAULT_SERVICE_FILE, "r");
|
||||
if (f != NULL) {
|
||||
/* would test magic here? */
|
||||
- retval = _pam_parse_conf_file(pamh, f
|
||||
- , PAM_DEFAULT_SERVICE
|
||||
- , PAM_T_ANY
|
||||
+ retval = _pam_parse_conf_file(pamh, f, PAM_DEFAULT_SERVICE,
|
||||
+ PAM_T_ANY, 0
|
||||
#ifdef PAM_READ_BOTH_CONFS
|
||||
, 0
|
||||
#endif /* PAM_READ_BOTH_CONFS */
|
||||
@@ -454,7 +480,7 @@ int _pam_init_handlers(pam_handle_t *pam
|
||||
return PAM_ABORT;
|
||||
}
|
||||
|
||||
- retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY
|
||||
+ retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 0
|
||||
#ifdef PAM_READ_BOTH_CONFS
|
||||
, 0
|
||||
#endif /* PAM_READ_BOTH_CONFS */
|
||||
@@ -581,46 +607,19 @@ extract_modulename(const char *mod_path)
|
||||
return retval;
|
||||
}
|
||||
|
||||
-int _pam_add_handler(pam_handle_t *pamh
|
||||
- , int must_fail, int other, int type
|
||||
- , int *actions, const char *mod_path
|
||||
- , int argc, char **argv, int argvlen)
|
||||
+static struct loaded_module *
|
||||
+_pam_load_module(pam_handle_t *pamh, const char *mod_path)
|
||||
{
|
||||
- struct loaded_module *mod;
|
||||
int x = 0;
|
||||
- struct handler **handler_p;
|
||||
- struct handler **handler_p2;
|
||||
- struct handlers *the_handlers;
|
||||
- const char *sym, *sym2;
|
||||
- char *mod_full_path=NULL;
|
||||
+ int success;
|
||||
#ifndef PAM_STATIC
|
||||
char *mod_full_isa_path=NULL, *isa=NULL;
|
||||
#endif
|
||||
- servicefn func, func2;
|
||||
- int success;
|
||||
-
|
||||
- D(("called."));
|
||||
- IF_NO_PAMH("_pam_add_handler",pamh,PAM_SYSTEM_ERR);
|
||||
-
|
||||
- /* if NULL set to something that can be searched for */
|
||||
- switch (mod_path != NULL) {
|
||||
- default:
|
||||
- if (mod_path[0] == '/') {
|
||||
- break;
|
||||
- }
|
||||
- if (asprintf(&mod_full_path, "%s%s",
|
||||
- DEFAULT_MODULE_PATH, mod_path) >= 0) {
|
||||
- mod_path = mod_full_path;
|
||||
- break;
|
||||
- }
|
||||
- mod_full_path = NULL;
|
||||
- pam_syslog(pamh, LOG_CRIT, "cannot malloc full mod path");
|
||||
- case 0:
|
||||
- mod_path = UNKNOWN_MODULE_PATH;
|
||||
- }
|
||||
+ struct loaded_module *mod;
|
||||
|
||||
- D(("_pam_add_handler: adding type %d, module `%s'",type,mod_path));
|
||||
- mod = pamh->handlers.module;
|
||||
+ D(("_pam_load_module: loading module `%s'", mod_path));
|
||||
+
|
||||
+ mod = pamh->handlers.module;
|
||||
|
||||
/* First, ensure the module is loaded */
|
||||
while (x < pamh->handlers.modules_used) {
|
||||
@@ -639,9 +638,8 @@ int _pam_add_handler(pam_handle_t *pamh
|
||||
if (tmp == NULL) {
|
||||
D(("cannot enlarge module pointer memory"));
|
||||
pam_syslog(pamh, LOG_ERR,
|
||||
- "realloc returned NULL in _pam_add_handler");
|
||||
- _pam_drop(mod_full_path);
|
||||
- return PAM_ABORT;
|
||||
+ "realloc returned NULL in _pam_load_module");
|
||||
+ return NULL;
|
||||
}
|
||||
pamh->handlers.module = tmp;
|
||||
pamh->handlers.modules_allocated += MODULE_CHUNK;
|
||||
@@ -654,10 +652,10 @@ int _pam_add_handler(pam_handle_t *pamh
|
||||
/* Only load static function if function was not found dynamically.
|
||||
* This code should work even if no dynamic loading is available. */
|
||||
if (success != PAM_SUCCESS) {
|
||||
- D(("_pam_add_handler: open static handler %s", mod_path));
|
||||
+ D(("_pam_load_module: open static handler %s", mod_path));
|
||||
mod->dl_handle = _pam_open_static_handler(pamh, mod_path);
|
||||
if (mod->dl_handle == NULL) {
|
||||
- D(("_pam_add_handler: unable to find static handler %s",
|
||||
+ D(("_pam_load_module: unable to find static handler %s",
|
||||
mod_path));
|
||||
pam_syslog(pamh, LOG_ERR,
|
||||
"unable to open static handler %s", mod_path);
|
||||
@@ -670,15 +668,15 @@ int _pam_add_handler(pam_handle_t *pamh
|
||||
}
|
||||
}
|
||||
#else
|
||||
- D(("_pam_add_handler: _pam_dlopen(%s)", mod_path));
|
||||
+ D(("_pam_load_module: _pam_dlopen(%s)", mod_path));
|
||||
mod->dl_handle = _pam_dlopen(mod_path);
|
||||
- D(("_pam_add_handler: _pam_dlopen'ed"));
|
||||
- D(("_pam_add_handler: dlopen'ed"));
|
||||
+ D(("_pam_load_module: _pam_dlopen'ed"));
|
||||
+ D(("_pam_load_module: dlopen'ed"));
|
||||
if (mod->dl_handle == NULL) {
|
||||
if (strstr(mod_path, "$ISA")) {
|
||||
mod_full_isa_path = malloc(strlen(mod_path) + strlen(_PAM_ISA) + 1);
|
||||
if (mod_full_isa_path == NULL) {
|
||||
- D(("_pam_handler: couldn't get memory for mod_path"));
|
||||
+ D(("_pam_load_module: couldn't get memory for mod_path"));
|
||||
pam_syslog(pamh, LOG_ERR, "no memory for module path");
|
||||
success = PAM_ABORT;
|
||||
} else {
|
||||
@@ -694,9 +692,9 @@ int _pam_add_handler(pam_handle_t *pamh
|
||||
}
|
||||
}
|
||||
if (mod->dl_handle == NULL) {
|
||||
- D(("_pam_add_handler: _pam_dlopen(%s) failed", mod_path));
|
||||
- pam_syslog(pamh, LOG_ERR, "unable to dlopen(%s)", mod_path);
|
||||
- pam_syslog(pamh, LOG_ERR, "[error: %s]", _pam_dlerror());
|
||||
+ D(("_pam_load_module: _pam_dlopen(%s) failed", mod_path));
|
||||
+ pam_syslog(pamh, LOG_ERR, "unable to dlopen(%s): %s", mod_path,
|
||||
+ _pam_dlerror());
|
||||
/* Don't abort yet; static code may be able to find function.
|
||||
* But defaults to abort if nothing found below... */
|
||||
} else {
|
||||
@@ -717,7 +715,7 @@ int _pam_add_handler(pam_handle_t *pamh
|
||||
|
||||
/* indicate its name - later we will search for it by this */
|
||||
if ((mod->name = _pam_strdup(mod_path)) == NULL) {
|
||||
- D(("_pam_handler: couldn't get memory for mod_path"));
|
||||
+ D(("_pam_load_module: couldn't get memory for mod_path"));
|
||||
pam_syslog(pamh, LOG_ERR, "no memory for module path");
|
||||
success = PAM_ABORT;
|
||||
}
|
||||
@@ -726,18 +724,54 @@ int _pam_add_handler(pam_handle_t *pamh
|
||||
mod += x; /* the located module */
|
||||
success = PAM_SUCCESS;
|
||||
}
|
||||
+ return success == PAM_SUCCESS ? mod : NULL;
|
||||
+}
|
||||
+
|
||||
+int _pam_add_handler(pam_handle_t *pamh
|
||||
+ , int handler_type, int other, int stack_level, int type
|
||||
+ , int *actions, const char *mod_path
|
||||
+ , int argc, char **argv, int argvlen)
|
||||
+{
|
||||
+ struct loaded_module *mod = NULL;
|
||||
+ struct handler **handler_p;
|
||||
+ struct handler **handler_p2;
|
||||
+ struct handlers *the_handlers;
|
||||
+ const char *sym, *sym2;
|
||||
+ char *mod_full_path;
|
||||
+ servicefn func, func2;
|
||||
+ int mod_type = PAM_MT_FAULTY_MOD;
|
||||
+
|
||||
+ D(("called."));
|
||||
+ IF_NO_PAMH("_pam_add_handler",pamh,PAM_SYSTEM_ERR);
|
||||
|
||||
- _pam_drop(mod_full_path);
|
||||
- mod_path = NULL; /* no longer needed or trusted */
|
||||
+ D(("_pam_add_handler: adding type %d, handler_type %d, module `%s'",
|
||||
+ type, handler_type, mod_path));
|
||||
|
||||
- /* Now return error if necessary after trying all possible ways... */
|
||||
- if (success != PAM_SUCCESS)
|
||||
- return(success);
|
||||
+ if (handler_type == PAM_HT_MODULE && mod_path != NULL) {
|
||||
+ if (mod_path[0] == '/') {
|
||||
+ mod = _pam_load_module(pamh, mod_path);
|
||||
+ } else if (asprintf(&mod_full_path, "%s%s",
|
||||
+ DEFAULT_MODULE_PATH, mod_path) >= 0) {
|
||||
+ mod = _pam_load_module(pamh, mod_full_path);
|
||||
+ _pam_drop(mod_full_path);
|
||||
+ } else {
|
||||
+ pam_syslog(pamh, LOG_CRIT, "cannot malloc full mod path");
|
||||
+ return PAM_ABORT;
|
||||
+ }
|
||||
+
|
||||
+ if (mod == NULL) {
|
||||
+ /* if we get here with NULL it means allocation error */
|
||||
+ return PAM_ABORT;
|
||||
+ }
|
||||
+
|
||||
+ mod_type = mod->type;
|
||||
+ }
|
||||
+
|
||||
+ if (mod_path == NULL)
|
||||
+ mod_path = UNKNOWN_MODULE;
|
||||
|
||||
/*
|
||||
- * At this point 'mod' points to the stored/loaded module. If its
|
||||
- * dl_handle is unknown, then we must be able to indicate dispatch
|
||||
- * failure with 'must_fail'
|
||||
+ * At this point 'mod' points to the stored/loaded module.
|
||||
*/
|
||||
|
||||
/* Now define the handler(s) based on mod->dlhandle and type */
|
||||
@@ -780,43 +814,43 @@ int _pam_add_handler(pam_handle_t *pamh
|
||||
/* are the modules reliable? */
|
||||
if (
|
||||
#ifdef PAM_STATIC
|
||||
- mod->type != PAM_MT_STATIC_MOD
|
||||
+ mod_type != PAM_MT_STATIC_MOD
|
||||
&&
|
||||
#else
|
||||
- mod->type != PAM_MT_DYNAMIC_MOD
|
||||
+ mod_type != PAM_MT_DYNAMIC_MOD
|
||||
&&
|
||||
#endif
|
||||
- mod->type != PAM_MT_FAULTY_MOD
|
||||
+ mod_type != PAM_MT_FAULTY_MOD
|
||||
) {
|
||||
- D(("_pam_add_handlers: illegal module library type; %d", mod->type));
|
||||
+ D(("_pam_add_handlers: illegal module library type; %d", mod_type));
|
||||
pam_syslog(pamh, LOG_ERR,
|
||||
"internal error: module library type not known: %s;%d",
|
||||
- sym, mod->type);
|
||||
+ sym, mod_type);
|
||||
return PAM_ABORT;
|
||||
}
|
||||
|
||||
/* now identify this module's functions - for non-faulty modules */
|
||||
|
||||
#ifdef PAM_STATIC
|
||||
- if ((mod->type == PAM_MT_STATIC_MOD) &&
|
||||
+ if ((mod_type == PAM_MT_STATIC_MOD) &&
|
||||
(func = (servicefn)_pam_get_static_sym(mod->dl_handle, sym)) == NULL) {
|
||||
pam_syslog(pamh, LOG_ERR, "unable to resolve static symbol: %s", sym);
|
||||
}
|
||||
#else
|
||||
- if ((mod->type == PAM_MT_DYNAMIC_MOD) &&
|
||||
+ if ((mod_type == PAM_MT_DYNAMIC_MOD) &&
|
||||
!(func = _pam_dlsym(mod->dl_handle, sym)) ) {
|
||||
pam_syslog(pamh, LOG_ERR, "unable to resolve symbol: %s", sym);
|
||||
}
|
||||
#endif
|
||||
if (sym2) {
|
||||
#ifdef PAM_STATIC
|
||||
- if ((mod->type == PAM_MT_STATIC_MOD) &&
|
||||
+ if ((mod_type == PAM_MT_STATIC_MOD) &&
|
||||
(func2 = (servicefn)_pam_get_static_sym(mod->dl_handle, sym2))
|
||||
== NULL) {
|
||||
pam_syslog(pamh, LOG_ERR, "unable to resolve symbol: %s", sym2);
|
||||
}
|
||||
#else
|
||||
- if ((mod->type == PAM_MT_DYNAMIC_MOD) &&
|
||||
+ if ((mod_type == PAM_MT_DYNAMIC_MOD) &&
|
||||
!(func2 = _pam_dlsym(mod->dl_handle, sym2)) ) {
|
||||
pam_syslog(pamh, LOG_ERR, "unable to resolve symbol: %s", sym2);
|
||||
}
|
||||
@@ -835,14 +869,15 @@ int _pam_add_handler(pam_handle_t *pamh
|
||||
return (PAM_ABORT);
|
||||
}
|
||||
|
||||
- (*handler_p)->must_fail = must_fail; /* failure forced? */
|
||||
+ (*handler_p)->handler_type = handler_type;
|
||||
+ (*handler_p)->stack_level = stack_level;
|
||||
(*handler_p)->func = func;
|
||||
memcpy((*handler_p)->actions,actions,sizeof((*handler_p)->actions));
|
||||
(*handler_p)->cached_retval = _PAM_INVALID_RETVAL;
|
||||
(*handler_p)->cached_retval_p = &((*handler_p)->cached_retval);
|
||||
(*handler_p)->argc = argc;
|
||||
(*handler_p)->argv = argv; /* not a copy */
|
||||
- (*handler_p)->mod_name = extract_modulename(mod->name);
|
||||
+ (*handler_p)->mod_name = extract_modulename(mod_path);
|
||||
(*handler_p)->next = NULL;
|
||||
|
||||
/* some of the modules have a second calling function */
|
||||
@@ -857,7 +892,8 @@ int _pam_add_handler(pam_handle_t *pamh
|
||||
return (PAM_ABORT);
|
||||
}
|
||||
|
||||
- (*handler_p2)->must_fail = must_fail; /* failure forced? */
|
||||
+ (*handler_p2)->handler_type = handler_type;
|
||||
+ (*handler_p2)->stack_level = stack_level;
|
||||
(*handler_p2)->func = func2;
|
||||
memcpy((*handler_p2)->actions,actions,sizeof((*handler_p2)->actions));
|
||||
(*handler_p2)->cached_retval = _PAM_INVALID_RETVAL; /* ignored */
|
||||
@@ -873,7 +909,7 @@ int _pam_add_handler(pam_handle_t *pamh
|
||||
} else {
|
||||
(*handler_p2)->argv = NULL; /* no arguments */
|
||||
}
|
||||
- (*handler_p2)->mod_name = extract_modulename(mod->name);
|
||||
+ (*handler_p2)->mod_name = extract_modulename(mod_path);
|
||||
(*handler_p2)->next = NULL;
|
||||
}
|
||||
|
||||
Index: libpam/pam_private.h
|
||||
===================================================================
|
||||
RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_private.h,v
|
||||
retrieving revision 1.19
|
||||
diff -u -p -r1.19 pam_private.h
|
||||
--- libpam/pam_private.h 24 Jul 2006 15:47:40 -0000 1.19
|
||||
+++ libpam/pam_private.h 12 Oct 2007 16:23:37 -0000
|
||||
@@ -44,7 +44,7 @@
|
||||
#define _PAM_INVALID_RETVAL -1 /* default value for cached_retval */
|
||||
|
||||
struct handler {
|
||||
- int must_fail;
|
||||
+ int handler_type;
|
||||
int (*func)(pam_handle_t *pamh, int flags, int argc, char **argv);
|
||||
int actions[_PAM_RETURN_VALUES];
|
||||
/* set by authenticate, open_session, chauthtok(1st)
|
||||
@@ -54,8 +54,13 @@ struct handler {
|
||||
char **argv;
|
||||
struct handler *next;
|
||||
char *mod_name;
|
||||
+ int stack_level;
|
||||
};
|
||||
|
||||
+#define PAM_HT_MODULE 0
|
||||
+#define PAM_HT_MUST_FAIL 1
|
||||
+#define PAM_HT_SUBSTACK 2
|
||||
+
|
||||
struct loaded_module {
|
||||
char *name;
|
||||
int type; /* PAM_STATIC_MOD or PAM_DYNAMIC_MOD */
|
||||
@@ -76,7 +81,7 @@ struct handlers {
|
||||
};
|
||||
|
||||
struct service {
|
||||
- struct loaded_module *module; /* Only used for dynamic loading */
|
||||
+ struct loaded_module *module; /* Array of modules */
|
||||
int modules_allocated;
|
||||
int modules_used;
|
||||
int handlers_loaded;
|
||||
@@ -111,6 +116,12 @@ struct _pam_fail_delay {
|
||||
const void *delay_fn_ptr;
|
||||
};
|
||||
|
||||
+/* initial state in substack */
|
||||
+struct _pam_substack_state {
|
||||
+ int impression;
|
||||
+ int status;
|
||||
+};
|
||||
+
|
||||
struct _pam_former_state {
|
||||
/* this is known and set by _pam_dispatch() */
|
||||
int choice; /* which flavor of module function did we call? */
|
||||
@@ -119,6 +130,7 @@ struct _pam_former_state {
|
||||
int depth; /* how deep in the stack were we? */
|
||||
int impression; /* the impression at that time */
|
||||
int status; /* the status before returning incomplete */
|
||||
+ struct _pam_substack_state *substates; /* array of initial substack states */
|
||||
|
||||
/* state info used by pam_get_user() function */
|
||||
int fail_user;
|
||||
@@ -175,6 +187,8 @@ struct pam_handle {
|
||||
#define _PAM_ACTION_UNDEF -6 /* this is treated as an error
|
||||
( = _PAM_ACTION_BAD) */
|
||||
|
||||
+#define PAM_SUBSTACK_MAX_LEVEL 16 /* maximum level of substacks */
|
||||
+
|
||||
/* character tables for parsing config files */
|
||||
extern const char * const _pam_token_actions[-_PAM_ACTION_UNDEF];
|
||||
extern const char * const _pam_token_returns[_PAM_RETURN_VALUES+1];
|
||||
Index: libpam/pam_start.c
|
||||
===================================================================
|
||||
RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_start.c,v
|
||||
retrieving revision 1.9
|
||||
diff -u -p -r1.9 pam_start.c
|
||||
--- libpam/pam_start.c 24 Jul 2006 15:47:40 -0000 1.9
|
||||
+++ libpam/pam_start.c 12 Oct 2007 16:23:37 -0000
|
||||
@@ -88,6 +88,7 @@ int pam_start (
|
||||
(*pamh)->oldauthtok = NULL;
|
||||
(*pamh)->fail_delay.delay_fn_ptr = NULL;
|
||||
(*pamh)->former.choice = PAM_NOT_STACKED;
|
||||
+ (*pamh)->former.substates = NULL;
|
||||
#ifdef HAVE_LIBAUDIT
|
||||
(*pamh)->audit_state = 0;
|
||||
#endif
|
||||
Index: doc/man/pam.conf-syntax.xml
|
||||
===================================================================
|
||||
RCS file: /cvsroot/pam/Linux-PAM/doc/man/pam.conf-syntax.xml,v
|
||||
retrieving revision 1.4
|
||||
retrieving revision 1.5
|
||||
diff -u -r1.4 -r1.5
|
||||
--- doc/man/pam.conf-syntax.xml 26 Aug 2007 22:44:51 -0000 1.4
|
||||
+++ doc/man/pam.conf-syntax.xml 19 Oct 2007 17:06:30 -0000 1.5
|
||||
@@ -180,6 +180,24 @@
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term>substack</term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ include all lines of given type from the configuration
|
||||
+ file specified as an argument to this control. This differs from
|
||||
+ <emphasis>include</emphasis> in that evaluation of the
|
||||
+ <emphasis>done</emphasis> and <emphasis>die</emphasis> actions
|
||||
+ in a substack does not cause skipping the rest of the complete
|
||||
+ module stack, but only of the substack. Jumps in a substack
|
||||
+ also can not make evaluation jump out of it, and the whole substack
|
||||
+ is counted as one module when the jump is done in a parent stack.
|
||||
+ The <emphasis>reset</emphasis> action will reset the state of a
|
||||
+ module stack to the state it was in as of beginning of the substack
|
||||
+ evaluation.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>
|
@ -1,32 +0,0 @@
|
||||
Written-by: Tomas Mraz <tmraz@redhat.com>
|
||||
Reviewed-by: Karel Zak <kzak@redhat.com>
|
||||
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_succeed_if/pam_succeed_if.c.in-operator Linux-PAM-0.99.8.1/modules/pam_succeed_if/pam_succeed_if.c
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_succeed_if/pam_succeed_if.c.in-operator 2006-08-31 12:20:39.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_succeed_if/pam_succeed_if.c 2007-09-19 19:36:22.000000000 +0200
|
||||
@@ -191,13 +191,19 @@ static int
|
||||
evaluate_inlist(const char *left, const char *right)
|
||||
{
|
||||
char *p;
|
||||
- if ((p=strstr(right, left)) == NULL)
|
||||
- return PAM_AUTH_ERR;
|
||||
- if (p == right || *(p-1) == ':') { /* ':' is a list separator */
|
||||
- p += strlen(left);
|
||||
- if (*p == '\0' || *p == ':') {
|
||||
- return PAM_SUCCESS;
|
||||
+ /* Don't care about left containing ':'. */
|
||||
+ while ((p=strstr(right, left)) != NULL) {
|
||||
+ if (p == right || *(p-1) == ':') { /* ':' is a list separator */
|
||||
+ p += strlen(left);
|
||||
+ if (*p == '\0' || *p == ':') {
|
||||
+ return PAM_SUCCESS;
|
||||
+ }
|
||||
}
|
||||
+ right = strchr(p, ':');
|
||||
+ if (right == NULL)
|
||||
+ break;
|
||||
+ else
|
||||
+ ++right;
|
||||
}
|
||||
return PAM_AUTH_ERR;
|
||||
}
|
@ -1,590 +0,0 @@
|
||||
Written-by: Miloslav Trmac <mitr@redhat.com>
|
||||
Reviewed-by: Tomas Mraz <tmraz@redhat.com>
|
||||
diff -urN Linux-PAM/configure.in Linux-PAM-0.99.8.1/configure.in
|
||||
--- Linux-PAM/configure.in 2007-11-28 13:41:14.000000000 +0100
|
||||
+++ Linux-PAM-0.99.8.1/configure.in 2007-11-28 14:35:30.000000000 +0100
|
||||
@@ -331,7 +331,11 @@
|
||||
WITH_LIBAUDIT=$enableval, WITH_LIBAUDIT=yes)
|
||||
if test x"$WITH_LIBAUDIT" != xno ; then
|
||||
AC_CHECK_HEADER([libaudit.h],
|
||||
- [AC_CHECK_LIB(audit, audit_log_acct_message, LIBAUDIT=-laudit, LIBAUDIT="")]
|
||||
+ [AC_CHECK_LIB(audit, audit_log_acct_message, LIBAUDIT=-laudit, LIBAUDIT="")
|
||||
+ AC_CHECK_TYPE([struct audit_tty_status],
|
||||
+ [HAVE_AUDIT_TTY_STATUS=yes],
|
||||
+ [HAVE_AUDIT_TTY_STATUS=""],
|
||||
+ [#include <libaudit.h>])]
|
||||
)
|
||||
if test ! -z "$LIBAUDIT" -a "ac_cv_header_libaudit_h" != "no" ; then
|
||||
AC_DEFINE([HAVE_LIBAUDIT], 1, [Defined if audit support should be compiled in])
|
||||
@@ -340,6 +344,8 @@
|
||||
LIBAUDIT=""
|
||||
fi
|
||||
AC_SUBST(LIBAUDIT)
|
||||
+AM_CONDITIONAL([HAVE_AUDIT_TTY_STATUS],
|
||||
+ [test "x$HAVE_AUDIT_TTY_STATUS" = xyes])
|
||||
|
||||
BACKUP_LIBS=$LIBS
|
||||
AC_SEARCH_LIBS([crypt],[xcrypt crypt], LIBCRYPT="-l$ac_lib", LIBCRYPT="")
|
||||
@@ -517,7 +523,8 @@
|
||||
modules/pam_securetty/Makefile modules/pam_selinux/Makefile \
|
||||
modules/pam_shells/Makefile modules/pam_stress/Makefile \
|
||||
modules/pam_succeed_if/Makefile modules/pam_tally/Makefile \
|
||||
- modules/pam_time/Makefile modules/pam_umask/Makefile \
|
||||
+ modules/pam_time/Makefile modules/pam_tty_audit/Makefile \
|
||||
+ modules/pam_umask/Makefile \
|
||||
modules/pam_unix/Makefile modules/pam_userdb/Makefile \
|
||||
modules/pam_warn/Makefile modules/pam_wheel/Makefile \
|
||||
modules/pam_xauth/Makefile doc/Makefile doc/specs/Makefile \
|
||||
diff -urN Linux-PAM/modules/Makefile.am Linux-PAM-0.99.8.1/modules/Makefile.am
|
||||
--- Linux-PAM/modules/Makefile.am 2007-11-28 13:41:13.000000000 +0100
|
||||
+++ Linux-PAM-0.99.8.1/modules/Makefile.am 2007-11-28 14:02:48.000000000 +0100
|
||||
@@ -9,8 +9,8 @@
|
||||
pam_lastlog pam_limits pam_listfile pam_localuser pam_mail \
|
||||
pam_mkhomedir pam_motd pam_nologin pam_permit pam_rhosts pam_rootok \
|
||||
pam_securetty pam_selinux pam_shells pam_stress pam_succeed_if \
|
||||
- pam_tally pam_time pam_umask pam_unix pam_userdb pam_warn \
|
||||
- pam_wheel pam_xauth pam_exec pam_namespace pam_loginuid \
|
||||
+ pam_tally pam_time pam_tty_audit pam_umask pam_unix pam_userdb \
|
||||
+ pam_warn pam_wheel pam_xauth pam_exec pam_namespace pam_loginuid \
|
||||
pam_faildelay
|
||||
|
||||
CLEANFILES = *~
|
||||
diff -urN Linux-PAM/modules/pam_tty_audit/Makefile.am Linux-PAM-0.99.8.1/modules/pam_tty_audit/Makefile.am
|
||||
--- Linux-PAM/modules/pam_tty_audit/Makefile.am 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/Makefile.am 2007-11-28 16:05:00.000000000 +0100
|
||||
@@ -0,0 +1,30 @@
|
||||
+#
|
||||
+# Copyright (c) 2005, 2006 Thorsten Kukuk <kukuk@suse.de>
|
||||
+#
|
||||
+
|
||||
+CLEANFILES = *~
|
||||
+
|
||||
+EXTRA_DIST = README ${MANS} $(XMLS)
|
||||
+
|
||||
+man_MANS = pam_tty_audit.8
|
||||
+XMLS = README.xml pam_tty_audit.8.xml
|
||||
+
|
||||
+securelibdir = $(SECUREDIR)
|
||||
+
|
||||
+AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include
|
||||
+AM_LDFLAGS = -no-undefined -avoid-version -module \
|
||||
+ -L$(top_builddir)/libpam -lpam
|
||||
+if HAVE_VERSIONING
|
||||
+ AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
|
||||
+endif
|
||||
+
|
||||
+if HAVE_AUDIT_TTY_STATUS
|
||||
+ securelib_LTLIBRARIES = pam_tty_audit.la
|
||||
+endif
|
||||
+
|
||||
+if ENABLE_REGENERATE_MAN
|
||||
+noinst_DATA = README
|
||||
+README: pam_tty_audit.8.xml
|
||||
+-include $(top_srcdir)/Make.xml.rules
|
||||
+endif
|
||||
+
|
||||
diff -urN Linux-PAM/modules/pam_tty_audit/pam_tty_audit.c Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.c
|
||||
--- Linux-PAM/modules/pam_tty_audit/pam_tty_audit.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.c 2007-11-28 16:10:43.000000000 +0100
|
||||
@@ -0,0 +1,332 @@
|
||||
+/* Copyright © 2007 Red Hat, Inc. All rights reserved.
|
||||
+ Red Hat author: Miloslav Trmač <mitr@redhat.com>
|
||||
+
|
||||
+ Redistribution and use in source and binary forms of Linux-PAM, with
|
||||
+ or without modification, are permitted provided that the following
|
||||
+ conditions are met:
|
||||
+
|
||||
+ 1. Redistributions of source code must retain any existing copyright
|
||||
+ notice, and this entire permission notice in its entirety,
|
||||
+ including the disclaimer of warranties.
|
||||
+
|
||||
+ 2. Redistributions in binary form must reproduce all prior and current
|
||||
+ copyright notices, this list of conditions, and the following
|
||||
+ disclaimer in the documentation and/or other materials provided
|
||||
+ with the distribution.
|
||||
+
|
||||
+ 3. The name of any author may not be used to endorse or promote
|
||||
+ products derived from this software without their specific prior
|
||||
+ written permission.
|
||||
+
|
||||
+ ALTERNATIVELY, this product may be distributed under the terms of the
|
||||
+ GNU General Public License, in which case the provisions of the GNU
|
||||
+ GPL are required INSTEAD OF the above restrictions. (This clause is
|
||||
+ necessary due to a potential conflict between the GNU GPL and the
|
||||
+ restrictions contained in a BSD-style copyright.)
|
||||
+
|
||||
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
+ IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
+ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
+ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
+ DAMAGE. */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <pwd.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <syslog.h>
|
||||
+#include <sys/socket.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#include <libaudit.h>
|
||||
+#include <linux/netlink.h>
|
||||
+#include <security/pam_ext.h>
|
||||
+#include <security/pam_modules.h>
|
||||
+#include <security/pam_modutil.h>
|
||||
+
|
||||
+#define DATANAME "pam_tty_audit_last_state"
|
||||
+
|
||||
+/* Open an audit netlink socket */
|
||||
+static int
|
||||
+nl_open (void)
|
||||
+{
|
||||
+ return socket (AF_NETLINK, SOCK_RAW, NETLINK_AUDIT);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+nl_send (int fd, unsigned type, unsigned flags, const void *data, size_t size)
|
||||
+{
|
||||
+ struct sockaddr_nl addr;
|
||||
+ struct msghdr msg;
|
||||
+ struct nlmsghdr nlm;
|
||||
+ struct iovec iov[2];
|
||||
+ ssize_t res;
|
||||
+
|
||||
+ nlm.nlmsg_len = NLMSG_LENGTH (size);
|
||||
+ nlm.nlmsg_type = type;
|
||||
+ nlm.nlmsg_flags = NLM_F_REQUEST | flags;
|
||||
+ nlm.nlmsg_seq = 0;
|
||||
+ nlm.nlmsg_pid = 0;
|
||||
+ iov[0].iov_base = &nlm;
|
||||
+ iov[0].iov_len = sizeof (nlm);
|
||||
+ iov[1].iov_base = (void *)data;
|
||||
+ iov[1].iov_len = size;
|
||||
+ addr.nl_family = AF_NETLINK;
|
||||
+ addr.nl_pid = 0;
|
||||
+ addr.nl_groups = 0;
|
||||
+ msg.msg_name = &addr;
|
||||
+ msg.msg_namelen = sizeof (addr);
|
||||
+ msg.msg_iov = iov;
|
||||
+ msg.msg_iovlen = 2;
|
||||
+ msg.msg_control = NULL;
|
||||
+ msg.msg_controllen = 0;
|
||||
+ msg.msg_flags = 0;
|
||||
+ res = sendmsg (fd, &msg, 0);
|
||||
+ if (res == -1)
|
||||
+ return -1;
|
||||
+ if ((size_t)res != nlm.nlmsg_len)
|
||||
+ {
|
||||
+ errno = EIO;
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+nl_recv (int fd, unsigned type, void *buf, size_t size)
|
||||
+{
|
||||
+ struct sockaddr_nl addr;
|
||||
+ struct msghdr msg;
|
||||
+ struct nlmsghdr nlm;
|
||||
+ struct iovec iov[2];
|
||||
+ ssize_t res;
|
||||
+
|
||||
+ again:
|
||||
+ iov[0].iov_base = &nlm;
|
||||
+ iov[0].iov_len = sizeof (nlm);
|
||||
+ msg.msg_name = &addr;
|
||||
+ msg.msg_namelen = sizeof (addr);
|
||||
+ msg.msg_iov = iov;
|
||||
+ msg.msg_iovlen = 1;
|
||||
+ msg.msg_control = NULL;
|
||||
+ msg.msg_controllen = 0;
|
||||
+ if (type != NLMSG_ERROR)
|
||||
+ {
|
||||
+ res = recvmsg (fd, &msg, MSG_PEEK);
|
||||
+ if (res == -1)
|
||||
+ return -1;
|
||||
+ if (res != NLMSG_LENGTH (0))
|
||||
+ {
|
||||
+ errno = EIO;
|
||||
+ return -1;
|
||||
+ }
|
||||
+ if (nlm.nlmsg_type == NLMSG_ERROR)
|
||||
+ {
|
||||
+ struct nlmsgerr err;
|
||||
+
|
||||
+ iov[1].iov_base = &err;
|
||||
+ iov[1].iov_len = sizeof (err);
|
||||
+ msg.msg_iovlen = 2;
|
||||
+ res = recvmsg (fd, &msg, 0);
|
||||
+ if (res == -1)
|
||||
+ return -1;
|
||||
+ if ((size_t)res != NLMSG_LENGTH (sizeof (err))
|
||||
+ || nlm.nlmsg_type != NLMSG_ERROR)
|
||||
+ {
|
||||
+ errno = EIO;
|
||||
+ return -1;
|
||||
+ }
|
||||
+ if (err.error == 0)
|
||||
+ goto again;
|
||||
+ errno = -err.error;
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+ if (size != 0)
|
||||
+ {
|
||||
+ iov[1].iov_base = buf;
|
||||
+ iov[1].iov_len = size;
|
||||
+ msg.msg_iovlen = 2;
|
||||
+ }
|
||||
+ res = recvmsg (fd, &msg, 0);
|
||||
+ if (res == -1)
|
||||
+ return -1;
|
||||
+ if ((size_t)res != NLMSG_LENGTH (size)
|
||||
+ || nlm.nlmsg_type != type)
|
||||
+ {
|
||||
+ errno = EIO;
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+nl_recv_ack (int fd)
|
||||
+{
|
||||
+ struct nlmsgerr err;
|
||||
+
|
||||
+ if (nl_recv (fd, NLMSG_ERROR, &err, sizeof (err)) != 0)
|
||||
+ return -1;
|
||||
+ if (err.error != 0)
|
||||
+ {
|
||||
+ errno = -err.error;
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+cleanup_old_status (pam_handle_t *pamh, void *data, int error_status)
|
||||
+{
|
||||
+ (void)pamh;
|
||||
+ (void)error_status;
|
||||
+ free (data);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, const char **argv)
|
||||
+{
|
||||
+ enum command { CMD_NONE, CMD_ENABLE, CMD_DISABLE };
|
||||
+
|
||||
+ enum command command;
|
||||
+ struct audit_tty_status *old_status, new_status;
|
||||
+ const char *user;
|
||||
+ uid_t user_uid;
|
||||
+ struct passwd *pwd;
|
||||
+ int i, fd;
|
||||
+
|
||||
+ (void)flags;
|
||||
+
|
||||
+ if (pam_get_user (pamh, &user, NULL) != PAM_SUCCESS)
|
||||
+ {
|
||||
+ pam_syslog (pamh, LOG_ERR, "error determining target user's name");
|
||||
+ return PAM_SESSION_ERR;
|
||||
+ }
|
||||
+ pwd = pam_modutil_getpwnam (pamh, user);
|
||||
+ if (pwd == NULL)
|
||||
+ {
|
||||
+ pam_syslog (pamh, LOG_ERR, "error determining target user's UID: %m");
|
||||
+ return PAM_SESSION_ERR;
|
||||
+ }
|
||||
+ user_uid = pwd->pw_uid;
|
||||
+
|
||||
+ command = CMD_NONE;
|
||||
+ for (i = 0; i < argc; i++)
|
||||
+ {
|
||||
+ if (strncmp (argv[i], "enable=", 7) == 0
|
||||
+ || strncmp (argv[i], "disable=", 8) == 0)
|
||||
+ {
|
||||
+ enum command this_command;
|
||||
+ char *copy, *tok_data, *tok;
|
||||
+
|
||||
+ this_command = *argv[i] == 'e' ? CMD_ENABLE : CMD_DISABLE;
|
||||
+ copy = strdup (strchr (argv[i], '=') + 1);
|
||||
+ if (copy == NULL)
|
||||
+ return PAM_SESSION_ERR;
|
||||
+ for (tok = strtok_r (copy, ",", &tok_data); tok != NULL;
|
||||
+ tok = strtok_r (NULL, ",", &tok_data))
|
||||
+ {
|
||||
+ pwd = pam_modutil_getpwnam (pamh, tok);
|
||||
+ if (pwd == NULL)
|
||||
+ {
|
||||
+ pam_syslog (pamh, LOG_WARNING, "unknown user %s", tok);
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (pwd->pw_uid == user_uid)
|
||||
+ {
|
||||
+ command = this_command;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ free (copy);
|
||||
+ }
|
||||
+ }
|
||||
+ if (command == CMD_NONE)
|
||||
+ return PAM_SUCCESS;
|
||||
+
|
||||
+ old_status = malloc (sizeof (*old_status));
|
||||
+ if (old_status == NULL)
|
||||
+ return PAM_SESSION_ERR;
|
||||
+
|
||||
+ fd = nl_open ();
|
||||
+ if (fd == -1
|
||||
+ || nl_send (fd, AUDIT_TTY_GET, 0, NULL, 0) != 0
|
||||
+ || nl_recv (fd, AUDIT_TTY_GET, old_status, sizeof (*old_status)) != 0)
|
||||
+ {
|
||||
+ pam_syslog (pamh, LOG_ERR, "error reading current audit status: %m");
|
||||
+ if (fd != -1)
|
||||
+ close (fd);
|
||||
+ free (old_status);
|
||||
+ return PAM_SESSION_ERR;
|
||||
+ }
|
||||
+
|
||||
+ if (old_status->enabled == (command == CMD_ENABLE ? 1 : 0))
|
||||
+ {
|
||||
+ free (old_status);
|
||||
+ goto ok_fd;
|
||||
+ }
|
||||
+
|
||||
+ if (pam_set_data (pamh, DATANAME, old_status, cleanup_old_status)
|
||||
+ != PAM_SUCCESS)
|
||||
+ {
|
||||
+ pam_syslog (pamh, LOG_ERR, "error saving old audit status");
|
||||
+ close (fd);
|
||||
+ free (old_status);
|
||||
+ return PAM_SESSION_ERR;
|
||||
+ }
|
||||
+
|
||||
+ new_status.enabled = (command == CMD_ENABLE ? 1 : 0);
|
||||
+ if (nl_send (fd, AUDIT_TTY_SET, NLM_F_ACK, &new_status,
|
||||
+ sizeof (new_status)) != 0
|
||||
+ || nl_recv_ack (fd) != 0)
|
||||
+ {
|
||||
+ pam_syslog (pamh, LOG_ERR, "error setting current audit status: %m");
|
||||
+ close (fd);
|
||||
+ return PAM_SESSION_ERR;
|
||||
+ }
|
||||
+ /* Fall through */
|
||||
+ ok_fd:
|
||||
+ close (fd);
|
||||
+ pam_syslog (pamh, LOG_DEBUG, "changed status from %d to %d",
|
||||
+ old_status->enabled, new_status.enabled);
|
||||
+ return PAM_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+pam_sm_close_session (pam_handle_t *pamh, int flags, int argc,
|
||||
+ const char **argv)
|
||||
+{
|
||||
+ const void *status_;
|
||||
+
|
||||
+ (void)flags;
|
||||
+ (void)argc;
|
||||
+ (void)argv;
|
||||
+ if (pam_get_data (pamh, DATANAME, &status_) == PAM_SUCCESS)
|
||||
+ {
|
||||
+ const struct audit_tty_status *status;
|
||||
+ int fd;
|
||||
+
|
||||
+ status = status_;
|
||||
+
|
||||
+ fd = nl_open ();
|
||||
+ if (fd == -1
|
||||
+ || nl_send (fd, AUDIT_TTY_SET, NLM_F_ACK, status,
|
||||
+ sizeof (*status)) != 0
|
||||
+ || nl_recv_ack (fd) != 0)
|
||||
+ {
|
||||
+ pam_syslog (pamh, LOG_ERR, "error restoring audit status: %m");
|
||||
+ if (fd != -1)
|
||||
+ close (fd);
|
||||
+ return PAM_SESSION_ERR;
|
||||
+ }
|
||||
+ close (fd);
|
||||
+ pam_syslog (pamh, LOG_ERR, "restored status to %d", status->enabled);
|
||||
+ }
|
||||
+ return PAM_SUCCESS;
|
||||
+}
|
||||
diff -urN Linux-PAM/modules/pam_tty_audit/pam_tty_audit.8.xml Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.8.xml
|
||||
--- Linux-PAM/modules/pam_tty_audit/pam_tty_audit.8.xml 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.8.xml 2007-11-28 15:50:22.000000000 +0100
|
||||
@@ -0,0 +1,125 @@
|
||||
+<?xml version="1.0" encoding='UTF-8'?>
|
||||
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
|
||||
+
|
||||
+<refentry id="pam_tty_audit">
|
||||
+
|
||||
+ <refmeta>
|
||||
+ <refentrytitle>pam_tty_audit</refentrytitle>
|
||||
+ <manvolnum>8</manvolnum>
|
||||
+ <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo>
|
||||
+ </refmeta>
|
||||
+
|
||||
+ <refnamediv id="pam_tty_audit-name">
|
||||
+ <refname>pam_tty_audit</refname>
|
||||
+ <refpurpose>Enable or disable TTY auditing for specified users</refpurpose>
|
||||
+ </refnamediv>
|
||||
+
|
||||
+ <refsynopsisdiv>
|
||||
+ <cmdsynopsis id="pam_tty_audit-cmdsynopsis">
|
||||
+ <command>pam_tty_audit.so</command>
|
||||
+ <arg choice="opt">
|
||||
+ disable=<replaceable>usernames</replaceable>
|
||||
+ </arg>
|
||||
+ <arg choice="opt">
|
||||
+ enable=<replaceable>usernames</replaceable>
|
||||
+ </arg>
|
||||
+ </cmdsynopsis>
|
||||
+ </refsynopsisdiv>
|
||||
+
|
||||
+ <refsect1 id="pam_tty_audit-description">
|
||||
+ <title>DESCRIPTION</title>
|
||||
+ <para>
|
||||
+ The pam_tty_audit PAM module is used to enable or disable TTY auditing.
|
||||
+ By default, the kernel does not audit input on any TTY.
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id="pam_tty_audit-options">
|
||||
+ <title>OPTIONS</title>
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>disable=<replaceable>usernames</replaceable></option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ For each user matching one of comma-separated
|
||||
+ <option><replaceable>usernames</replaceable></option>, disable
|
||||
+ TTY auditing. This overrides any older <option>enable</option>
|
||||
+ option for the same user name.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>enable=<replaceable>usernames</replaceable></option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ For each user matching one of comma-separated
|
||||
+ <option><replaceable>usernames</replaceable></option>, enable
|
||||
+ TTY auditing. This overrides any older <option>disable</option>
|
||||
+ option for the same user name.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id="pam_tty_audit-services">
|
||||
+ <title>MODULE SERVICES PROVIDED</title>
|
||||
+ <para>
|
||||
+ Only the <emphasis remap='B'>session</emphasis> service is supported.
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id='pam_tty_audit-return_values'>
|
||||
+ <title>RETURN VALUES</title>
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term>PAM_SESSION_ERR</term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Error reading or modifying the TTY audit flag. See the system log
|
||||
+ for more details.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term>PAM_SUCCESS</term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Success.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id='pam_tty_audit-examples'>
|
||||
+ <title>EXAMPLES</title>
|
||||
+ <para>
|
||||
+ Audit all administrative actions.
|
||||
+ <programlisting>
|
||||
+login root required pam_tty_audit.so enable=root
|
||||
+su root required pam_tty_audit.so enable=root
|
||||
+su-l root required pam_tty_audit.so enable=root
|
||||
+sudo root required pam_tty_audit.so enable=root
|
||||
+sudo-l root required pam_tty_audit.so enable=root
|
||||
+sshd root required pam_tty_audit.so enable=root
|
||||
+ </programlisting>
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id='pam_tty_audit-author'>
|
||||
+ <title>AUTHOR</title>
|
||||
+ <para>
|
||||
+ pam_tty_audit was written by Miloslav Trmač
|
||||
+ <mitr@redhat.com>.
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+</refentry>
|
||||
diff -urN Linux-PAM/modules/pam_tty_audit/README.xml Linux-PAM-0.99.8.1/modules/pam_tty_audit/README.xml
|
||||
--- Linux-PAM/modules/pam_tty_audit/README.xml 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/README.xml 2007-11-28 15:52:50.000000000 +0100
|
||||
@@ -0,0 +1,36 @@
|
||||
+<?xml version="1.0" encoding='UTF-8'?>
|
||||
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||
+"http://www.docbook.org/xml/4.3/docbookx.dtd">
|
||||
+
|
||||
+<article>
|
||||
+
|
||||
+ <articleinfo>
|
||||
+
|
||||
+ <title>
|
||||
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
+ href="pam_tty_audit.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_tty_audit-name"]/*)'/>
|
||||
+ </title>
|
||||
+
|
||||
+ </articleinfo>
|
||||
+
|
||||
+ <section>
|
||||
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
+ href="pam_tty_audit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_tty_audit-description"]/*)'/>
|
||||
+ </section>
|
||||
+
|
||||
+ <section>
|
||||
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
+ href="pam_tty_audit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_tty_audit-options"]/*)'/>
|
||||
+ </section>
|
||||
+
|
||||
+ <section>
|
||||
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
+ href="pam_tty_audit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_tty_audit-examples"]/*)'/>
|
||||
+ </section>
|
||||
+
|
||||
+ <section>
|
||||
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
+ href="pam_tty_audit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_tty_audit-author"]/*)'/>
|
||||
+ </section>
|
||||
+
|
||||
+</article>
|
@ -1,233 +0,0 @@
|
||||
Written-by: Miloslav Trmac <mitr@redhat.com>
|
||||
Reviewed-by: Tomas Mraz <tmraz@redhat.com>
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.8.xml.tty-audit2 Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.8.xml
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.8.xml.tty-audit2 2008-01-02 11:28:26.000000000 +0100
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.8.xml 2008-01-02 11:29:55.000000000 +0100
|
||||
@@ -19,10 +19,10 @@
|
||||
<cmdsynopsis id="pam_tty_audit-cmdsynopsis">
|
||||
<command>pam_tty_audit.so</command>
|
||||
<arg choice="opt">
|
||||
- disable=<replaceable>usernames</replaceable>
|
||||
+ disable=<replaceable>patterns</replaceable>
|
||||
</arg>
|
||||
<arg choice="opt">
|
||||
- enable=<replaceable>usernames</replaceable>
|
||||
+ enable=<replaceable>patterns</replaceable>
|
||||
</arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
@@ -40,27 +40,40 @@
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
- <option>disable=<replaceable>usernames</replaceable></option>
|
||||
+ <option>disable=<replaceable>patterns</replaceable></option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
- For each user matching one of comma-separated
|
||||
- <option><replaceable>usernames</replaceable></option>, disable
|
||||
- TTY auditing. This overrides any older <option>enable</option>
|
||||
- option for the same user name.
|
||||
+ For each user matching one of comma-separated glob
|
||||
+ <option><replaceable>patterns</replaceable></option>, disable
|
||||
+ TTY auditing. This overrides any previous <option>enable</option>
|
||||
+ option matchin the same user name on the command line.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
- <option>enable=<replaceable>usernames</replaceable></option>
|
||||
+ <option>enable=<replaceable>patterns</replaceable></option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
- For each user matching one of comma-separated
|
||||
- <option><replaceable>usernames</replaceable></option>, enable
|
||||
- TTY auditing. This overrides any older <option>disable</option>
|
||||
- option for the same user name.
|
||||
+ For each user matching one of comma-separated glob
|
||||
+ <option><replaceable>patterns</replaceable></option>, enable
|
||||
+ TTY auditing. This overrides any previous <option>disable</option>
|
||||
+ option matching the same user name on the command line.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>open_only</option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Set the TTY audit flag when opening the session, but do not restore
|
||||
+ it when closing the session. Using this option is necessary for
|
||||
+ some services that don't <function>fork()</function> to run the
|
||||
+ authenticated session, such as <command>sudo</command>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@@ -99,17 +112,24 @@
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
+ <refsect1 id='pam_tty_audit-notes'>
|
||||
+ <title>NOTES</title>
|
||||
+ <para>
|
||||
+ When TTY auditing is enabled, it is inherited by all processes started by
|
||||
+ that user. In particular, daemons restarted by an user will still have
|
||||
+ TTY auditing enabled, and audit TTY input even by other users unless
|
||||
+ auditing for these users is explicitly disabled. Therefore, it is
|
||||
+ recommended to use <option>disable=*</option> as the first option for
|
||||
+ most daemons using PAM.
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
<refsect1 id='pam_tty_audit-examples'>
|
||||
<title>EXAMPLES</title>
|
||||
<para>
|
||||
Audit all administrative actions.
|
||||
<programlisting>
|
||||
-login root required pam_tty_audit.so enable=root
|
||||
-su root required pam_tty_audit.so enable=root
|
||||
-su-l root required pam_tty_audit.so enable=root
|
||||
-sudo root required pam_tty_audit.so enable=root
|
||||
-sudo-l root required pam_tty_audit.so enable=root
|
||||
-sshd root required pam_tty_audit.so enable=root
|
||||
+session required pam_tty_audit.so disable=* enable=root
|
||||
</programlisting>
|
||||
</para>
|
||||
</refsect1>
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_tty_audit/README.xml.tty-audit2 Linux-PAM-0.99.8.1/modules/pam_tty_audit/README.xml
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_tty_audit/README.xml.tty-audit2 2008-01-02 11:28:26.000000000 +0100
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/README.xml 2008-01-02 11:28:26.000000000 +0100
|
||||
@@ -25,6 +25,11 @@
|
||||
|
||||
<section>
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
+ href="pam_tty_audit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_tty_audit-notes"]/*)'/>
|
||||
+ </section>
|
||||
+
|
||||
+ <section>
|
||||
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
href="pam_tty_audit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_tty_audit-examples"]/*)'/>
|
||||
</section>
|
||||
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.c.tty-audit2 Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.c
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.c.tty-audit2 2008-01-02 11:28:26.000000000 +0100
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.c 2008-01-02 11:28:26.000000000 +0100
|
||||
@@ -1,4 +1,4 @@
|
||||
-/* Copyright © 2007 Red Hat, Inc. All rights reserved.
|
||||
+/* Copyright © 2007, 2008 Red Hat, Inc. All rights reserved.
|
||||
Red Hat author: Miloslav Trmač <mitr@redhat.com>
|
||||
|
||||
Redistribution and use in source and binary forms of Linux-PAM, with
|
||||
@@ -37,7 +37,7 @@
|
||||
DAMAGE. */
|
||||
|
||||
#include <errno.h>
|
||||
-#include <pwd.h>
|
||||
+#include <fnmatch.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
@@ -197,9 +197,7 @@ pam_sm_open_session (pam_handle_t *pamh,
|
||||
enum command command;
|
||||
struct audit_tty_status *old_status, new_status;
|
||||
const char *user;
|
||||
- uid_t user_uid;
|
||||
- struct passwd *pwd;
|
||||
- int i, fd;
|
||||
+ int i, fd, open_only;
|
||||
|
||||
(void)flags;
|
||||
|
||||
@@ -208,15 +206,9 @@ pam_sm_open_session (pam_handle_t *pamh,
|
||||
pam_syslog (pamh, LOG_ERR, "error determining target user's name");
|
||||
return PAM_SESSION_ERR;
|
||||
}
|
||||
- pwd = pam_modutil_getpwnam (pamh, user);
|
||||
- if (pwd == NULL)
|
||||
- {
|
||||
- pam_syslog (pamh, LOG_ERR, "error determining target user's UID: %m");
|
||||
- return PAM_SESSION_ERR;
|
||||
- }
|
||||
- user_uid = pwd->pw_uid;
|
||||
|
||||
command = CMD_NONE;
|
||||
+ open_only = 0;
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
if (strncmp (argv[i], "enable=", 7) == 0
|
||||
@@ -232,13 +224,7 @@ pam_sm_open_session (pam_handle_t *pamh,
|
||||
for (tok = strtok_r (copy, ",", &tok_data); tok != NULL;
|
||||
tok = strtok_r (NULL, ",", &tok_data))
|
||||
{
|
||||
- pwd = pam_modutil_getpwnam (pamh, tok);
|
||||
- if (pwd == NULL)
|
||||
- {
|
||||
- pam_syslog (pamh, LOG_WARNING, "unknown user %s", tok);
|
||||
- continue;
|
||||
- }
|
||||
- if (pwd->pw_uid == user_uid)
|
||||
+ if (fnmatch (tok, user, 0) == 0)
|
||||
{
|
||||
command = this_command;
|
||||
break;
|
||||
@@ -246,6 +232,13 @@ pam_sm_open_session (pam_handle_t *pamh,
|
||||
}
|
||||
free (copy);
|
||||
}
|
||||
+ else if (strcmp (argv[i], "open_only") == 0)
|
||||
+ open_only = 1;
|
||||
+ else
|
||||
+ {
|
||||
+ pam_syslog (pamh, LOG_ERR, "unknown option `%s'", argv[i]);
|
||||
+ return PAM_SESSION_ERR;
|
||||
+ }
|
||||
}
|
||||
if (command == CMD_NONE)
|
||||
return PAM_SUCCESS;
|
||||
@@ -266,13 +259,15 @@ pam_sm_open_session (pam_handle_t *pamh,
|
||||
return PAM_SESSION_ERR;
|
||||
}
|
||||
|
||||
- if (old_status->enabled == (command == CMD_ENABLE ? 1 : 0))
|
||||
+ new_status.enabled = (command == CMD_ENABLE ? 1 : 0);
|
||||
+ if (old_status->enabled == new_status.enabled)
|
||||
{
|
||||
free (old_status);
|
||||
goto ok_fd;
|
||||
}
|
||||
|
||||
- if (pam_set_data (pamh, DATANAME, old_status, cleanup_old_status)
|
||||
+ if (open_only == 0
|
||||
+ && pam_set_data (pamh, DATANAME, old_status, cleanup_old_status)
|
||||
!= PAM_SUCCESS)
|
||||
{
|
||||
pam_syslog (pamh, LOG_ERR, "error saving old audit status");
|
||||
@@ -281,13 +276,14 @@ pam_sm_open_session (pam_handle_t *pamh,
|
||||
return PAM_SESSION_ERR;
|
||||
}
|
||||
|
||||
- new_status.enabled = (command == CMD_ENABLE ? 1 : 0);
|
||||
if (nl_send (fd, AUDIT_TTY_SET, NLM_F_ACK, &new_status,
|
||||
sizeof (new_status)) != 0
|
||||
|| nl_recv_ack (fd) != 0)
|
||||
{
|
||||
pam_syslog (pamh, LOG_ERR, "error setting current audit status: %m");
|
||||
close (fd);
|
||||
+ if (open_only != 0)
|
||||
+ free (old_status);
|
||||
return PAM_SESSION_ERR;
|
||||
}
|
||||
/* Fall through */
|
||||
@@ -295,6 +291,8 @@ pam_sm_open_session (pam_handle_t *pamh,
|
||||
close (fd);
|
||||
pam_syslog (pamh, LOG_DEBUG, "changed status from %d to %d",
|
||||
old_status->enabled, new_status.enabled);
|
||||
+ if (open_only != 0)
|
||||
+ free (old_status);
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
@ -1,50 +0,0 @@
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_unix/passverify.h.unix-hpux-aging Linux-PAM-0.99.8.1/modules/pam_unix/passverify.h
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_unix/passverify.h.unix-hpux-aging 2008-01-08 14:43:36.000000000 +0100
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_unix/passverify.h 2008-01-08 15:49:43.000000000 +0100
|
||||
@@ -13,7 +13,7 @@
|
||||
#define OLD_PASSWORDS_FILE "/etc/security/opasswd"
|
||||
|
||||
int
|
||||
-verify_pwd_hash(const char *p, const char *hash, unsigned int nullok);
|
||||
+verify_pwd_hash(const char *p, char *hash, unsigned int nullok);
|
||||
|
||||
int
|
||||
is_pwd_shadowed(const struct passwd *pwd);
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_unix/passverify.c.unix-hpux-aging Linux-PAM-0.99.8.1/modules/pam_unix/passverify.c
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_unix/passverify.c.unix-hpux-aging 2008-01-08 14:43:36.000000000 +0100
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_unix/passverify.c 2008-01-08 15:49:02.000000000 +0100
|
||||
@@ -44,14 +44,32 @@
|
||||
# include "./lckpwdf.-c"
|
||||
#endif
|
||||
|
||||
+static void
|
||||
+strip_hpux_aging(char *p)
|
||||
+{
|
||||
+ const char *valid = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
+ "abcdefghijklmnopqrstuvwxyz"
|
||||
+ "0123456789./";
|
||||
+ if ((*p != '$') && (strlen(p) > 13)) {
|
||||
+ for (p += 13; *p != '\0'; p++) {
|
||||
+ if (strchr(valid, *p) == NULL) {
|
||||
+ *p = '\0';
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
int
|
||||
-verify_pwd_hash(const char *p, const char *hash, unsigned int nullok)
|
||||
+verify_pwd_hash(const char *p, char *hash, unsigned int nullok)
|
||||
{
|
||||
- size_t hash_len = strlen(hash);
|
||||
+ size_t hash_len;
|
||||
char *pp = NULL;
|
||||
int retval;
|
||||
D(("called"));
|
||||
|
||||
+ strip_hpux_aging(hash);
|
||||
+ hash_len = strlen(hash);
|
||||
if (!hash_len) {
|
||||
/* the stored password is NULL */
|
||||
if (nullok) { /* this means we've succeeded */
|
File diff suppressed because it is too large
Load Diff
@ -1,11 +0,0 @@
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_xauth/pam_xauth.c.no-free Linux-PAM-0.99.8.1/modules/pam_xauth/pam_xauth.c
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_xauth/pam_xauth.c.no-free 2007-09-21 16:02:06.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_xauth/pam_xauth.c 2007-09-21 16:02:47.000000000 +0200
|
||||
@@ -573,6 +573,7 @@ pam_sm_open_session (pam_handle_t *pamh,
|
||||
"can't set environment variable '%s'",
|
||||
xauthority);
|
||||
putenv (xauthority); /* The environment owns this string now. */
|
||||
+ xauthority = NULL;
|
||||
|
||||
/* set $DISPLAY in pam handle to make su - work */
|
||||
{
|
49
pam.spec
49
pam.spec
@ -4,8 +4,8 @@
|
||||
|
||||
Summary: A security tool which provides authentication for applications
|
||||
Name: pam
|
||||
Version: 0.99.8.1
|
||||
Release: 18%{?dist}
|
||||
Version: 0.99.10.0
|
||||
Release: 1%{?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
|
||||
@ -21,28 +21,15 @@ Source7: config-util.pamd
|
||||
Source8: dlopen.sh
|
||||
Source9: system-auth.5
|
||||
Source10: config-util.5
|
||||
Source11: 90-nproc.conf
|
||||
Patch1: pam-0.99.7.0-redhat-modules.patch
|
||||
Patch2: db-4.6.18-glibc.patch
|
||||
Patch4: pam-0.99.8.1-dbpam.patch
|
||||
Patch5: pam-0.99.8.1-audit-no-log.patch
|
||||
Patch24: pam-0.99.8.1-unix-update-helper.patch
|
||||
Patch25: pam-0.99.8.1-unix-hpux-aging.patch
|
||||
Patch31: pam-0.99.3.0-cracklib-try-first-pass.patch
|
||||
Patch32: pam-0.99.3.0-tally-fail-close.patch
|
||||
Patch40: pam-0.99.7.1-namespace-temp-logon.patch
|
||||
Patch41: pam-0.99.8.1-namespace-init.patch
|
||||
Patch42: pam-0.99.8.1-console-hal-handled.patch
|
||||
Patch43: pam-0.99.8.1-console-mfd-scanners.patch
|
||||
Patch44: pam-0.99.7.1-namespace-homedir.patch
|
||||
Patch45: pam-0.99.8.1-selinux-permit.patch
|
||||
Patch46: pam-0.99.8.1-succif-in-operator.patch
|
||||
Patch47: pam-0.99.8.1-xauth-no-free.patch
|
||||
Patch48: pam-0.99.8.1-substack.patch
|
||||
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
|
||||
|
||||
%define _sbindir /sbin
|
||||
%define _moduledir /%{_lib}/security
|
||||
@ -113,24 +100,10 @@ pushd db-%{db_version}
|
||||
popd
|
||||
%patch4 -p1 -b .dbpam
|
||||
%patch5 -p1 -b .no-log
|
||||
%patch24 -p1 -b .update-helper
|
||||
%patch25 -p1 -b .unix-hpux-aging
|
||||
%patch31 -p1 -b .try-first-pass
|
||||
%patch32 -p1 -b .fail-close
|
||||
%patch40 -p1 -b .temp-logon
|
||||
%patch41 -p1 -b .ns-init
|
||||
%patch42 -p1 -b .hal-handled
|
||||
%patch43 -p1 -b .mfd-scanners
|
||||
%patch44 -p1 -b .homedir
|
||||
%patch45 -p1 -b .permit
|
||||
%patch46 -p1 -b .in-operator
|
||||
%patch47 -p1 -b .no-free
|
||||
%patch48 -p0 -b .substack
|
||||
%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
|
||||
|
||||
@ -191,6 +164,11 @@ done
|
||||
# Install the binaries, libraries, and modules.
|
||||
make install DESTDIR=$RPM_BUILD_ROOT LDCONFIG=:
|
||||
|
||||
%if %{WITH_SELINUX}
|
||||
# Temporary compat link
|
||||
ln -sf pam_sepermit.so $RPM_BUILD_ROOT%{_moduledir}/pam_selinux_permit.so
|
||||
%endif
|
||||
|
||||
# RPM uses docs from source tree
|
||||
rm -rf $RPM_BUILD_ROOT%{_datadir}/doc/Linux-PAM
|
||||
# Included in setup package
|
||||
@ -201,6 +179,7 @@ install -d -m 755 $RPM_BUILD_ROOT%{_pamconfdir}
|
||||
install -m 644 %{SOURCE5} $RPM_BUILD_ROOT%{_pamconfdir}/other
|
||||
install -m 644 %{SOURCE6} $RPM_BUILD_ROOT%{_pamconfdir}/system-auth
|
||||
install -m 644 %{SOURCE7} $RPM_BUILD_ROOT%{_pamconfdir}/config-util
|
||||
install -m 644 %{SOURCE11} $RPM_BUILD_ROOT%{_secconfdir}/limits.d/90-nproc.conf
|
||||
install -m 600 /dev/null $RPM_BUILD_ROOT%{_secconfdir}/opasswd
|
||||
install -d -m 755 $RPM_BUILD_ROOT/var/log
|
||||
install -m 600 /dev/null $RPM_BUILD_ROOT/var/log/faillog
|
||||
@ -331,12 +310,12 @@ fi
|
||||
%{_moduledir}/pam_permit.so
|
||||
%{_moduledir}/pam_postgresok.so
|
||||
%{_moduledir}/pam_rhosts.so
|
||||
%{_moduledir}/pam_rhosts_auth.so
|
||||
%{_moduledir}/pam_rootok.so
|
||||
%{_moduledir}/pam_rps.so
|
||||
%if %{WITH_SELINUX}
|
||||
%{_moduledir}/pam_selinux.so
|
||||
%{_moduledir}/pam_selinux_permit.so
|
||||
%{_moduledir}/pam_sepermit.so
|
||||
%endif
|
||||
%{_moduledir}/pam_securetty.so
|
||||
%{_moduledir}/pam_shells.so
|
||||
@ -365,7 +344,10 @@ fi
|
||||
%config(noreplace) %{_secconfdir}/console.handlers
|
||||
%config(noreplace) %{_secconfdir}/group.conf
|
||||
%config(noreplace) %{_secconfdir}/limits.conf
|
||||
%dir %{_secconfdir}/limits.d
|
||||
%config(noreplace) %{_secconfdir}/limits.d/90-nproc.conf
|
||||
%config(noreplace) %{_secconfdir}/namespace.conf
|
||||
%dir %{_secconfdir}/namespace.d
|
||||
%attr(755,root,root) %config(noreplace) %{_secconfdir}/namespace.init
|
||||
%config(noreplace) %{_secconfdir}/pam_env.conf
|
||||
%config(noreplace) %{_secconfdir}/sepermit.conf
|
||||
@ -392,6 +374,11 @@ fi
|
||||
%doc doc/adg/*.txt doc/adg/html
|
||||
|
||||
%changelog
|
||||
* Fri Feb 15 2008 Tomas Mraz <tmraz@redhat.com> 0.99.10.0-1
|
||||
- new upstream release
|
||||
- add default soft limit for nproc of 1024 to prevent
|
||||
accidental fork bombs (#432903)
|
||||
|
||||
* Mon Feb 4 2008 Tomas Mraz <tmraz@redhat.com> 0.99.8.1-18
|
||||
- allow the package to build without SELinux and audit support (#431415)
|
||||
- macro usage cleanup
|
||||
|
Loading…
Reference in New Issue
Block a user