coreutils/coreutils-8.6-pam-support-for-su.diff

403 lines
10 KiB
Diff
Raw Normal View History

From 8b1e75c55ea6be5c8639c98b73ecfa0cf15226ce Mon Sep 17 00:00:00 2001
From: Ludwig Nussel <ludwig.nussel@suse.de>
Date: Tue, 17 Aug 2010 13:21:44 +0200
Subject: [PATCH 1/7] pam support for su
---
configure.ac | 14 +++
src/Makefile.am | 4 +-
src/su.c | 266 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 278 insertions(+), 6 deletions(-)
- Update to 8.8. Changes since 8.6: ** Bug fixes cp -u no longer does unnecessary copying merely because the source has finer-grained time stamps than the destination. od now prints floating-point numbers without losing information, and it no longer omits spaces between floating-point columns in some cases. sort -u with at least two threads could attempt to read through a corrupted pointer. [bug introduced in coreutils-8.6] sort with at least two threads and with blocked output would busy-loop (spinlock) all threads, often using 100% of available CPU cycles to do no work. I.e., "sort < big-file | less" could waste a lot of power. [bug introduced in coreutils-8.6] sort with at least two threads no longer segfaults due to use of pointers into the stack of an expired thread. [bug introduced in coreutils-8.6] sort --compress no longer mishandles subprocesses' exit statuses, no longer hangs indefinitely due to a bug in waiting for subprocesses, and no longer generates many more than NMERGE subprocesses. sort -m -o f f ... f no longer dumps core when file descriptors are limited. csplit no longer corrupts heap when writing more than 999 files, nor does it leak memory for every chunk of input processed [the bugs were present in the initial implementation] tail -F once again notices changes in a currently unavailable remote directory [bug introduced in coreutils-7.5] ** Changes in behavior sort will not create more than 8 threads by default due to diminishing performance gains. Also the --parallel option is no longer restricted to the number of available processors. cp --attributes-only now completely overrides --reflink. Previously a reflink was needlessly attempted. OBS-URL: https://build.opensuse.org/package/show/Base:System/coreutils?expand=0&rev=77
2011-01-03 20:39:07 +01:00
Index: configure.ac
===================================================================
--- configure.ac.orig 2011-01-03 13:27:37.268088087 +0100
+++ configure.ac 2011-01-03 13:28:05.256895209 +0100
@@ -134,6 +134,20 @@ fi
AC_FUNC_FORK
+AC_ARG_ENABLE(pam, AS_HELP_STRING([--disable-pam],
+ [Enable PAM support in su (default=auto)]), , [enable_pam=yes])
+if test "x$enable_pam" != xno; then
+ AC_CHECK_LIB([pam], [pam_start], [enable_pam=yes], [enable_pam=no])
+ AC_CHECK_LIB([pam_misc], [misc_conv], [:], [enable_pam=no])
+ if test "x$enable_pam" != xno; then
+ AC_DEFINE(USE_PAM, 1, [Define if you want to use PAM])
+ PAM_LIBS="-lpam -lpam_misc"
+ AC_SUBST(PAM_LIBS)
+ fi
+fi
+AC_MSG_CHECKING([whether to enable PAM support in su])
+AC_MSG_RESULT([$enable_pam])
+
optional_bin_progs=
AC_CHECK_FUNCS([chroot],
gl_ADD_PROG([optional_bin_progs], [chroot]))
- Update to 8.8. Changes since 8.6: ** Bug fixes cp -u no longer does unnecessary copying merely because the source has finer-grained time stamps than the destination. od now prints floating-point numbers without losing information, and it no longer omits spaces between floating-point columns in some cases. sort -u with at least two threads could attempt to read through a corrupted pointer. [bug introduced in coreutils-8.6] sort with at least two threads and with blocked output would busy-loop (spinlock) all threads, often using 100% of available CPU cycles to do no work. I.e., "sort < big-file | less" could waste a lot of power. [bug introduced in coreutils-8.6] sort with at least two threads no longer segfaults due to use of pointers into the stack of an expired thread. [bug introduced in coreutils-8.6] sort --compress no longer mishandles subprocesses' exit statuses, no longer hangs indefinitely due to a bug in waiting for subprocesses, and no longer generates many more than NMERGE subprocesses. sort -m -o f f ... f no longer dumps core when file descriptors are limited. csplit no longer corrupts heap when writing more than 999 files, nor does it leak memory for every chunk of input processed [the bugs were present in the initial implementation] tail -F once again notices changes in a currently unavailable remote directory [bug introduced in coreutils-7.5] ** Changes in behavior sort will not create more than 8 threads by default due to diminishing performance gains. Also the --parallel option is no longer restricted to the number of available processors. cp --attributes-only now completely overrides --reflink. Previously a reflink was needlessly attempted. OBS-URL: https://build.opensuse.org/package/show/Base:System/coreutils?expand=0&rev=77
2011-01-03 20:39:07 +01:00
Index: src/Makefile.am
===================================================================
--- src/Makefile.am.orig 2011-01-03 13:27:37.268088087 +0100
+++ src/Makefile.am 2011-01-03 13:28:16.038206110 +0100
@@ -351,8 +351,8 @@ factor_LDADD += $(LIB_GMP)
# for getloadavg
uptime_LDADD += $(GETLOADAVG_LIBS)
-# for crypt
-su_LDADD += $(LIB_CRYPT)
+# for crypt and pam
+su_LDADD += $(LIB_CRYPT) $(PAM_LIBS)
# for various ACL functions
copy_LDADD += $(LIB_ACL)
- Update to 8.8. Changes since 8.6: ** Bug fixes cp -u no longer does unnecessary copying merely because the source has finer-grained time stamps than the destination. od now prints floating-point numbers without losing information, and it no longer omits spaces between floating-point columns in some cases. sort -u with at least two threads could attempt to read through a corrupted pointer. [bug introduced in coreutils-8.6] sort with at least two threads and with blocked output would busy-loop (spinlock) all threads, often using 100% of available CPU cycles to do no work. I.e., "sort < big-file | less" could waste a lot of power. [bug introduced in coreutils-8.6] sort with at least two threads no longer segfaults due to use of pointers into the stack of an expired thread. [bug introduced in coreutils-8.6] sort --compress no longer mishandles subprocesses' exit statuses, no longer hangs indefinitely due to a bug in waiting for subprocesses, and no longer generates many more than NMERGE subprocesses. sort -m -o f f ... f no longer dumps core when file descriptors are limited. csplit no longer corrupts heap when writing more than 999 files, nor does it leak memory for every chunk of input processed [the bugs were present in the initial implementation] tail -F once again notices changes in a currently unavailable remote directory [bug introduced in coreutils-7.5] ** Changes in behavior sort will not create more than 8 threads by default due to diminishing performance gains. Also the --parallel option is no longer restricted to the number of available processors. cp --attributes-only now completely overrides --reflink. Previously a reflink was needlessly attempted. OBS-URL: https://build.opensuse.org/package/show/Base:System/coreutils?expand=0&rev=77
2011-01-03 20:39:07 +01:00
Index: src/su.c
===================================================================
--- src/su.c.orig 2011-01-03 13:27:37.268088087 +0100
+++ src/su.c 2011-01-03 13:28:16.177210120 +0100
@@ -37,6 +37,16 @@
restricts who can su to UID 0 accounts. RMS considers that to
be fascist.
+#ifdef USE_PAM
+
+ Actually, with PAM, su has nothing to do with whether or not a
+ wheel group is enforced by su. RMS tries to restrict your access
+ to a su which implements the wheel group, but PAM considers that
+ to be fascist, and gives the user/sysadmin the opportunity to
+ enforce a wheel group by proper editing of /etc/pam.d/su
+
+#endif
+
Compile-time options:
-DSYSLOG_SUCCESS Log successful su's (by default, to root) with syslog.
-DSYSLOG_FAILURE Log failed su's (by default, to root) with syslog.
@@ -52,6 +62,13 @@
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
+#ifdef USE_PAM
+#include <security/pam_appl.h>
+#include <security/pam_misc.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/fsuid.h>
+#endif
#include "system.h"
#include "getpass.h"
@@ -111,7 +128,9 @@
/* The user to become if none is specified. */
#define DEFAULT_USER "root"
+#ifndef USE_PAM
char *crypt (char const *key, char const *salt);
+#endif
static void run_shell (char const *, char const *, char **, size_t)
ATTRIBUTE_NORETURN;
@@ -125,6 +144,11 @@ static bool simulate_login;
/* If true, change some environment vars to indicate the user su'd to. */
static bool change_environment;
+#ifdef USE_PAM
+static bool _pam_session_opened;
+static bool _pam_cred_established;
+#endif
+
static struct option const longopts[] =
{
{"command", required_argument, NULL, 'c'},
- Update to 8.8. Changes since 8.6: ** Bug fixes cp -u no longer does unnecessary copying merely because the source has finer-grained time stamps than the destination. od now prints floating-point numbers without losing information, and it no longer omits spaces between floating-point columns in some cases. sort -u with at least two threads could attempt to read through a corrupted pointer. [bug introduced in coreutils-8.6] sort with at least two threads and with blocked output would busy-loop (spinlock) all threads, often using 100% of available CPU cycles to do no work. I.e., "sort < big-file | less" could waste a lot of power. [bug introduced in coreutils-8.6] sort with at least two threads no longer segfaults due to use of pointers into the stack of an expired thread. [bug introduced in coreutils-8.6] sort --compress no longer mishandles subprocesses' exit statuses, no longer hangs indefinitely due to a bug in waiting for subprocesses, and no longer generates many more than NMERGE subprocesses. sort -m -o f f ... f no longer dumps core when file descriptors are limited. csplit no longer corrupts heap when writing more than 999 files, nor does it leak memory for every chunk of input processed [the bugs were present in the initial implementation] tail -F once again notices changes in a currently unavailable remote directory [bug introduced in coreutils-7.5] ** Changes in behavior sort will not create more than 8 threads by default due to diminishing performance gains. Also the --parallel option is no longer restricted to the number of available processors. cp --attributes-only now completely overrides --reflink. Previously a reflink was needlessly attempted. OBS-URL: https://build.opensuse.org/package/show/Base:System/coreutils?expand=0&rev=77
2011-01-03 20:39:07 +01:00
@@ -200,7 +224,164 @@ log_su (struct passwd const *pw, bool su
}
#endif
+#ifdef USE_PAM
+#define PAM_SERVICE_NAME PROGRAM_NAME
+#define PAM_SERVICE_NAME_L PROGRAM_NAME "-l"
+static sig_atomic_t volatile caught_signal = false;
+static pam_handle_t *pamh = NULL;
+static int retval;
+static struct pam_conv conv =
+{
+ misc_conv,
+ NULL
+};
+
+#define PAM_BAIL_P(a) \
+ if (retval) \
+ { \
+ pam_end (pamh, retval); \
+ a; \
+ }
+
+static void
+cleanup_pam (int retcode)
+{
+ if (_pam_session_opened)
+ pam_close_session (pamh, 0);
+
+ if (_pam_cred_established)
+ pam_setcred (pamh, PAM_DELETE_CRED | PAM_SILENT);
+
+ pam_end(pamh, retcode);
+}
+
+/* Signal handler for parent process. */
+static void
+su_catch_sig (int sig)
+{
+ caught_signal = true;
+}
+
+/* Export env variables declared by PAM modules. */
+static void
+export_pamenv (void)
+{
+ char **env;
+
+ /* This is a copy but don't care to free as we exec later anyways. */
+ env = pam_getenvlist (pamh);
+ while (env && *env)
+ {
+ if (putenv (*env) != 0)
+ xalloc_die ();
+ env++;
+ }
+}
+
+static void
+create_watching_parent (void)
+{
+ pid_t child;
+ sigset_t ourset;
+ int status = 0;
+
+ retval = pam_open_session (pamh, 0);
+ if (retval != PAM_SUCCESS)
+ {
+ cleanup_pam (retval);
+ error (EXIT_FAILURE, 0, _("cannot not open session: %s"),
+ pam_strerror (pamh, retval));
+ }
+ else
+ _pam_session_opened = 1;
+
+ child = fork ();
+ if (child == (pid_t) -1)
+ {
+ cleanup_pam (PAM_ABORT);
+ error (EXIT_FAILURE, errno, _("cannot create child process"));
+ }
+
+ /* the child proceeds to run the shell */
+ if (child == 0)
+ return;
+
+ /* In the parent watch the child. */
+
+ /* su without pam support does not have a helper that keeps
+ sitting on any directory so let's go to /. */
+ if (chdir ("/") != 0)
+ error (0, errno, _("warning: cannot change directory to %s"), "/");
+
+ sigfillset (&ourset);
+ if (sigprocmask (SIG_BLOCK, &ourset, NULL))
+ {
+ error (0, errno, _("cannot block signals"));
+ caught_signal = true;
+ }
+ if (!caught_signal)
+ {
+ struct sigaction action;
+ action.sa_handler = su_catch_sig;
+ sigemptyset (&action.sa_mask);
+ action.sa_flags = 0;
+ sigemptyset (&ourset);
+ if (sigaddset (&ourset, SIGTERM)
+ || sigaddset (&ourset, SIGALRM)
+ || sigaction (SIGTERM, &action, NULL)
+ || sigprocmask (SIG_UNBLOCK, &ourset, NULL))
+ {
+ error (0, errno, _("cannot set signal handler"));
+ caught_signal = true;
+ }
+ }
+ if (!caught_signal)
+ {
+ pid_t pid;
+ for (;;)
+ {
+ pid = waitpid (child, &status, WUNTRACED);
+
+ if (pid != (pid_t)-1 && WIFSTOPPED (status))
+ {
+ kill (getpid (), SIGSTOP);
+ /* once we get here, we must have resumed */
+ kill (pid, SIGCONT);
+ }
+ else
+ break;
+ }
+ if (pid != (pid_t)-1)
+ if (WIFSIGNALED (status))
+ status = WTERMSIG (status) + 128;
+ else
+ status = WEXITSTATUS (status);
+ else
+ status = 1;
+ }
+ else
+ status = 1;
+
+ if (caught_signal)
+ {
+ fprintf (stderr, _("\nSession terminated, killing shell..."));
+ kill (child, SIGTERM);
+ }
+
+ cleanup_pam (PAM_SUCCESS);
+
+ if (caught_signal)
+ {
+ sleep (2);
+ kill (child, SIGKILL);
+ fprintf (stderr, _(" ...killed.\n"));
+ }
+ exit (status);
+}
+#endif
+
/* Ask the user for a password.
+ If PAM is in use, let PAM ask for the password if necessary.
Return true if the user gives the correct password for entry PW,
false if not. Return true without asking for a password if run by UID 0
or if PW has an empty password. */
- Update to 8.8. Changes since 8.6: ** Bug fixes cp -u no longer does unnecessary copying merely because the source has finer-grained time stamps than the destination. od now prints floating-point numbers without losing information, and it no longer omits spaces between floating-point columns in some cases. sort -u with at least two threads could attempt to read through a corrupted pointer. [bug introduced in coreutils-8.6] sort with at least two threads and with blocked output would busy-loop (spinlock) all threads, often using 100% of available CPU cycles to do no work. I.e., "sort < big-file | less" could waste a lot of power. [bug introduced in coreutils-8.6] sort with at least two threads no longer segfaults due to use of pointers into the stack of an expired thread. [bug introduced in coreutils-8.6] sort --compress no longer mishandles subprocesses' exit statuses, no longer hangs indefinitely due to a bug in waiting for subprocesses, and no longer generates many more than NMERGE subprocesses. sort -m -o f f ... f no longer dumps core when file descriptors are limited. csplit no longer corrupts heap when writing more than 999 files, nor does it leak memory for every chunk of input processed [the bugs were present in the initial implementation] tail -F once again notices changes in a currently unavailable remote directory [bug introduced in coreutils-7.5] ** Changes in behavior sort will not create more than 8 threads by default due to diminishing performance gains. Also the --parallel option is no longer restricted to the number of available processors. cp --attributes-only now completely overrides --reflink. Previously a reflink was needlessly attempted. OBS-URL: https://build.opensuse.org/package/show/Base:System/coreutils?expand=0&rev=77
2011-01-03 20:39:07 +01:00
@@ -208,10 +389,52 @@ log_su (struct passwd const *pw, bool su
static bool
correct_password (const struct passwd *pw)
{
+#ifdef USE_PAM
+ const struct passwd *lpw;
+ const char *cp;
+
+ retval = pam_start (simulate_login ? PAM_SERVICE_NAME_L : PAM_SERVICE_NAME,
+ pw->pw_name, &conv, &pamh);
+ PAM_BAIL_P (return false);
+
+ if (isatty (0) && (cp = ttyname (0)) != NULL)
+ {
+ const char *tty;
+
+ if (strncmp (cp, "/dev/", 5) == 0)
+ tty = cp + 5;
+ else
+ tty = cp;
+ retval = pam_set_item (pamh, PAM_TTY, tty);
+ PAM_BAIL_P (return false);
+ }
+#if 0 /* Manpage discourages use of getlogin. */
+ cp = getlogin ();
+ if (!(cp && *cp && (lpw = getpwnam (cp)) != NULL && lpw->pw_uid == getuid ()))
+#endif
+ lpw = getpwuid (getuid ());
+ if (lpw && lpw->pw_name)
+ {
+ retval = pam_set_item (pamh, PAM_RUSER, (const void *) lpw->pw_name);
+ PAM_BAIL_P (return false);
+ }
+ retval = pam_authenticate (pamh, 0);
+ PAM_BAIL_P (return false);
+ retval = pam_acct_mgmt (pamh, 0);
+ if (retval == PAM_NEW_AUTHTOK_REQD)
+ {
+ /* Password has expired. Offer option to change it. */
+ retval = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
+ PAM_BAIL_P (return false);
+ }
+ PAM_BAIL_P (return false);
+ /* Must be authenticated if this point was reached. */
+ return true;
+#else /* !USE_PAM */
char *unencrypted, *encrypted, *correct;
#if HAVE_GETSPNAM && HAVE_STRUCT_SPWD_SP_PWDP
/* Shadow passwd stuff for SVR3 and maybe other systems. */
- struct spwd *sp = getspnam (pw->pw_name);
+ const struct spwd *sp = getspnam (pw->pw_name);
endspent ();
if (sp)
- Update to 8.8. Changes since 8.6: ** Bug fixes cp -u no longer does unnecessary copying merely because the source has finer-grained time stamps than the destination. od now prints floating-point numbers without losing information, and it no longer omits spaces between floating-point columns in some cases. sort -u with at least two threads could attempt to read through a corrupted pointer. [bug introduced in coreutils-8.6] sort with at least two threads and with blocked output would busy-loop (spinlock) all threads, often using 100% of available CPU cycles to do no work. I.e., "sort < big-file | less" could waste a lot of power. [bug introduced in coreutils-8.6] sort with at least two threads no longer segfaults due to use of pointers into the stack of an expired thread. [bug introduced in coreutils-8.6] sort --compress no longer mishandles subprocesses' exit statuses, no longer hangs indefinitely due to a bug in waiting for subprocesses, and no longer generates many more than NMERGE subprocesses. sort -m -o f f ... f no longer dumps core when file descriptors are limited. csplit no longer corrupts heap when writing more than 999 files, nor does it leak memory for every chunk of input processed [the bugs were present in the initial implementation] tail -F once again notices changes in a currently unavailable remote directory [bug introduced in coreutils-7.5] ** Changes in behavior sort will not create more than 8 threads by default due to diminishing performance gains. Also the --parallel option is no longer restricted to the number of available processors. cp --attributes-only now completely overrides --reflink. Previously a reflink was needlessly attempted. OBS-URL: https://build.opensuse.org/package/show/Base:System/coreutils?expand=0&rev=77
2011-01-03 20:39:07 +01:00
@@ -232,6 +455,7 @@ correct_password (const struct passwd *p
encrypted = crypt (unencrypted, correct);
memset (unencrypted, 0, strlen (unencrypted));
return STREQ (encrypted, correct);
+#endif /* !USE_PAM */
}
/* Update `environ' for the new shell based on PW, with SHELL being
- Update to 8.8. Changes since 8.6: ** Bug fixes cp -u no longer does unnecessary copying merely because the source has finer-grained time stamps than the destination. od now prints floating-point numbers without losing information, and it no longer omits spaces between floating-point columns in some cases. sort -u with at least two threads could attempt to read through a corrupted pointer. [bug introduced in coreutils-8.6] sort with at least two threads and with blocked output would busy-loop (spinlock) all threads, often using 100% of available CPU cycles to do no work. I.e., "sort < big-file | less" could waste a lot of power. [bug introduced in coreutils-8.6] sort with at least two threads no longer segfaults due to use of pointers into the stack of an expired thread. [bug introduced in coreutils-8.6] sort --compress no longer mishandles subprocesses' exit statuses, no longer hangs indefinitely due to a bug in waiting for subprocesses, and no longer generates many more than NMERGE subprocesses. sort -m -o f f ... f no longer dumps core when file descriptors are limited. csplit no longer corrupts heap when writing more than 999 files, nor does it leak memory for every chunk of input processed [the bugs were present in the initial implementation] tail -F once again notices changes in a currently unavailable remote directory [bug introduced in coreutils-7.5] ** Changes in behavior sort will not create more than 8 threads by default due to diminishing performance gains. Also the --parallel option is no longer restricted to the number of available processors. cp --attributes-only now completely overrides --reflink. Previously a reflink was needlessly attempted. OBS-URL: https://build.opensuse.org/package/show/Base:System/coreutils?expand=0&rev=77
2011-01-03 20:39:07 +01:00
@@ -274,19 +498,41 @@ modify_environment (const struct passwd
}
}
}
+
+#ifdef USE_PAM
+ export_pamenv ();
+#endif
}
/* Become the user and group(s) specified by PW. */
static void
-change_identity (const struct passwd *pw)
+init_groups (const struct passwd *pw)
{
#ifdef HAVE_INITGROUPS
errno = 0;
if (initgroups (pw->pw_name, pw->pw_gid) == -1)
- error (EXIT_CANCELED, errno, _("cannot set groups"));
+ {
+#ifdef USE_PAM
+ cleanup_pam (PAM_ABORT);
+#endif
+ error (EXIT_FAILURE, errno, _("cannot set groups"));
+ }
endgrent ();
#endif
+
+#ifdef USE_PAM
+ retval = pam_setcred (pamh, PAM_ESTABLISH_CRED);
+ if (retval != PAM_SUCCESS)
+ error (EXIT_FAILURE, 0, "%s", pam_strerror (pamh, retval));
+ else
+ _pam_cred_established = 1;
+#endif
+}
+
+static void
+change_identity (const struct passwd *pw)
+{
if (setgid (pw->pw_gid))
error (EXIT_CANCELED, errno, _("cannot set group id"));
if (setuid (pw->pw_uid))
@@ -500,9 +746,21 @@ main (int argc, char **argv)
shell = NULL;
}
shell = xstrdup (shell ? shell : pw->pw_shell);
- modify_environment (pw, shell);
+
+ init_groups (pw);
+
+#ifdef USE_PAM
+ create_watching_parent ();
+ /* Now we're in the child. */
+#endif
change_identity (pw);
+
+ /* Set environment after pam_open_session, which may put KRB5CCNAME
+ into the pam_env, etc. */
+
+ modify_environment (pw, shell);
+
if (simulate_login && chdir (pw->pw_dir) != 0)
error (0, errno, _("warning: cannot change directory to %s"), pw->pw_dir);