OBS User unknown 2007-03-03 11:45:27 +00:00 committed by Git OBS Bridge
parent b45def5b1f
commit bf56cf2642
7 changed files with 823 additions and 711 deletions

View File

@ -1,38 +0,0 @@
--- coreutils-5.3.0/src/su.c
+++ coreutils-5.3.0/src/su.c
@@ -521,6 +521,21 @@
}
/* child shell */
+
+ /* Export env variables declared by PAM modules */
+ {
+ const char *const *env;
+
+ env = (const char *const *) pam_getenvlist (pamh);
+ while (env && *env)
+ {
+
+ if (putenv (*env) != 0)
+ xalloc_die ();
+ env++;
+ }
+ }
+
pam_end (pamh, 0);
#endif
@@ -726,9 +741,12 @@
shell = NULL;
}
shell = xstrdup (shell ? shell : pw->pw_shell);
+ change_identity (pw);
+
+ /* Set environment after pam_open_session, which may put KRB5CCNAME
+ into the pam_env, etc. */
modify_environment (pw, shell);
- change_identity (pw);
if (simulate_login && chdir (pw->pw_dir) != 0)
error (0, errno, _("warning: cannot change directory to %s"), pw->pw_dir);

View File

@ -1,21 +0,0 @@
--- lib/Makefile.am
+++ lib/Makefile.am
@@ -20,6 +20,7 @@
include gnulib.mk
AM_CFLAGS = $(WARNING_CFLAGS) $(WERROR_CFLAGS)
+AM_CFLAGS += -fpie
noinst_PROGRAMS = t-fpending
LDADD = $(noinst_LIBRARIES)
--- src/Makefile.am
+++ src/Makefile.am
@@ -105,6 +105,8 @@
su_SOURCES = su.c getdef.c
su_LDADD = $(LDADD) $(LIB_CRYPT) -lpam -lpam_misc -ldl
+su_CFLAGS = -fpie
+su_LDFLAGS = -pie
dir_LDADD += $(LIB_ACL)
ls_LDADD += $(LIB_ACL)

751
coreutils-6.8-su.diff Normal file
View File

@ -0,0 +1,751 @@
Index: src/Makefile.am
===================================================================
--- src/Makefile.am.orig
+++ src/Makefile.am
@@ -102,7 +102,8 @@ tail_LDADD = $(nanosec_libs)
# If necessary, add -lm to resolve use of pow in lib/strtod.c.
uptime_LDADD = $(LDADD) $(POW_LIB) $(GETLOADAVG_LIBS)
-su_LDADD = $(LDADD) $(LIB_CRYPT)
+su_SOURCES = su.c getdef.c
+su_LDADD = $(LDADD) $(LIB_CRYPT) $(PAM_LIBS)
dir_LDADD += $(LIB_ACL)
ls_LDADD += $(LIB_ACL)
Index: src/getdef.c
===================================================================
--- /dev/null
+++ src/getdef.c
@@ -0,0 +1,257 @@
+/* Copyright (C) 2003, 2004, 2005 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "getdef.h"
+
+struct item {
+ char *name; /* name of the option. */
+ char *value; /* value of the option. */
+ struct item *next; /* pointer to next option. */
+};
+
+static struct item *list = NULL;
+
+void
+free_getdef_data (void)
+{
+ struct item *ptr;
+
+ ptr = list;
+ while (ptr != NULL)
+ {
+ struct item *tmp;
+ tmp = ptr->next;
+ free (ptr->name);
+ free (ptr->value);
+ free (ptr);
+ ptr = tmp;
+ }
+
+ list = NULL;
+}
+
+/* Add a new entry to the list. */
+static void
+store (const char *name, const char *value)
+{
+ struct item *new = malloc (sizeof (struct item));
+
+ if (new == NULL)
+ abort ();
+
+ if (name == NULL)
+ abort ();
+
+ new->name = strdup (name);
+ new->value = strdup (value?:"");
+ new->next = list;
+ list = new;
+}
+
+/* search a special entry in the list and return the value. */
+static const char *
+search (const char *name)
+{
+ struct item *ptr;
+
+ ptr = list;
+ while (ptr != NULL)
+ {
+ if (strcasecmp (name, ptr->name) == 0)
+ return ptr->value;
+ ptr = ptr->next;
+ }
+
+ return NULL;
+}
+
+/* Load the login.defs file (/etc/login.defs) */
+static void
+load_defaults_internal (const char *filename)
+{
+ FILE *fp;
+ char *buf = NULL;
+ size_t buflen = 0;
+
+ fp = fopen (filename, "r");
+ if (NULL == fp)
+ return;
+
+ while (!feof (fp))
+ {
+ char *tmp, *cp;
+#if defined(HAVE_GETLINE)
+ ssize_t n = getline (&buf, &buflen, fp);
+#elif defined (HAVE_GETDELIM)
+ ssize_t n = getdelim (&buf, &buflen, '\n', fp);
+#else
+ ssize_t n;
+
+ if (buf == NULL)
+ {
+ buflen = 8096;
+ buf = malloc (buflen);
+ }
+ buf[0] = '\0';
+ fgets (buf, buflen - 1, fp);
+ if (buf != NULL)
+ n = strlen (buf);
+ else
+ n = 0;
+#endif /* HAVE_GETLINE / HAVE_GETDELIM */
+ cp = buf;
+
+ if (n < 1)
+ break;
+
+ tmp = strchr (cp, '#'); /* remove comments */
+ if (tmp)
+ *tmp = '\0';
+ while (isspace ((int)*cp)) /* remove spaces and tabs */
+ ++cp;
+ if (*cp == '\0') /* ignore empty lines */
+ continue;
+
+ if (cp[strlen (cp) - 1] == '\n')
+ cp[strlen (cp) - 1] = '\0';
+
+ tmp = strsep (&cp, " \t=");
+ if (cp != NULL)
+ while (isspace ((int)*cp) || *cp == '=')
+ ++cp;
+
+ store (tmp, cp);
+ }
+ fclose (fp);
+
+ if (buf)
+ free (buf);
+}
+
+static void
+load_defaults (void)
+{
+ load_defaults_internal ("/etc/default/su");
+ load_defaults_internal ("/etc/login.defs");
+}
+
+int
+getdef_bool (const char *name, int dflt)
+{
+ const char *val;
+
+ if (list == NULL)
+ load_defaults ();
+
+ val = search (name);
+
+ if (val == NULL)
+ return dflt;
+
+ return (strcasecmp (val, "yes") == 0);
+}
+
+long
+getdef_num (const char *name, long dflt)
+{
+ const char *val;
+ char *cp;
+ long retval;
+
+ if (list == NULL)
+ load_defaults ();
+
+ val = search (name);
+
+ if (val == NULL)
+ return dflt;
+
+ retval = strtol (val, &cp, 0);
+ if (*cp != '\0' ||
+ ((retval == LONG_MAX || retval == LONG_MIN) && errno == ERANGE))
+ {
+ fprintf (stderr,
+ "%s contains invalid numerical value: %s!\n",
+ name, val);
+ retval = dflt;
+ }
+ return retval;
+}
+
+unsigned long
+getdef_unum (const char *name, unsigned long dflt)
+{
+ const char *val;
+ char *cp;
+ unsigned long retval;
+
+ if (list == NULL)
+ load_defaults ();
+
+ val = search (name);
+
+ if (val == NULL)
+ return dflt;
+
+ retval = strtoul (val, &cp, 0);
+ if (*cp != '\0' || (retval == ULONG_MAX && errno == ERANGE))
+ {
+ fprintf (stderr,
+ "%s contains invalid numerical value: %s!\n",
+ name, val);
+ retval = dflt;
+ }
+ return retval;
+}
+
+const char *
+getdef_str (const char *name, const char *dflt)
+{
+ const char *retval;
+
+ if (list == NULL)
+ load_defaults ();
+
+ retval = search (name);
+
+ return retval ?: dflt;
+}
+
+#if defined(TEST)
+
+int
+main ()
+{
+ printf ("CYPT=%s\n", getdef_str ("cRypt", "no"));
+ printf ("LOG_UNKFAIL_ENAB=%s\n", getdef_str ("log_unkfail_enab",""));
+ printf ("DOESNOTEXIST=%s\n", getdef_str ("DOESNOTEXIST","yes"));
+ return 0;
+}
+
+#endif
Index: src/getdef.h
===================================================================
--- /dev/null
+++ src/getdef.h
@@ -0,0 +1,29 @@
+/* Copyright (C) 2003, 2005 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _GETDEF_H_
+
+#define _GETDEF_H_ 1
+
+extern int getdef_bool (const char *name, int dflt);
+extern long getdef_num (const char *name, long dflt);
+extern unsigned long getdef_unum (const char *name, unsigned long dflt);
+extern const char *getdef_str (const char *name, const char *dflt);
+
+/* Free all data allocated by getdef_* calls before. */
+extern void free_getdef_data (void);
+
+#endif /* _GETDEF_H_ */
Index: src/su.c
===================================================================
--- src/su.c.orig
+++ src/su.c
@@ -38,6 +38,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.
@@ -53,6 +63,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
/* Hide any system prototype for getusershell.
This is necessary because some Cray systems have a conflicting
@@ -66,6 +83,9 @@
#if HAVE_SYSLOG_H && HAVE_SYSLOG
# include <syslog.h>
+# define SYSLOG_SUCCESS 1
+# define SYSLOG_FAILURE 1
+# define SYSLOG_NON_ROOT 1
#else
# undef SYSLOG_SUCCESS
# undef SYSLOG_FAILURE
@@ -99,19 +119,13 @@
# include <paths.h>
#endif
+#include "getdef.h"
+
/* The default PATH for simulated logins to non-superuser accounts. */
-#ifdef _PATH_DEFPATH
-# define DEFAULT_LOGIN_PATH _PATH_DEFPATH
-#else
-# define DEFAULT_LOGIN_PATH ":/usr/ucb:/bin:/usr/bin"
-#endif
+#define DEFAULT_LOGIN_PATH "/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin"
/* The default PATH for simulated logins to superuser accounts. */
-#ifdef _PATH_DEFPATH_ROOT
-# define DEFAULT_ROOT_LOGIN_PATH _PATH_DEFPATH_ROOT
-#else
-# define DEFAULT_ROOT_LOGIN_PATH "/usr/ucb:/bin:/usr/bin:/etc"
-#endif
+#define DEFAULT_ROOT_LOGIN_PATH "/usr/sbin:/bin:/usr/bin:/sbin:/usr/X11R6/bin"
/* The shell to run if none is given in the user's passwd entry. */
#define DEFAULT_SHELL "/bin/sh"
@@ -119,13 +133,22 @@
/* The user to become if none is specified. */
#define DEFAULT_USER "root"
+#ifndef USE_PAM
char *crypt ();
+#endif
char *getusershell ();
void endusershell ();
void setusershell ();
extern char **environ;
+#ifdef USE_PAM
+static bool _pam_session_opened;
+static bool _pam_cred_established;
+static void export_pamenv(void);
+static void create_watching_parent(void);
+#endif
+
static void run_shell (char const *, char const *, char **, size_t)
ATTRIBUTE_NORETURN;
@@ -216,7 +239,162 @@ 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 bool 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_cred_established)
+ pam_setcred (pamh, PAM_DELETE_CRED | PAM_SILENT);
+
+ if (_pam_session_opened)
+ pam_close_session (pamh, 0);
+
+ 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;
+
+ /* 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"), "/");
+
+ retval = pam_open_session (pamh,0);
+ if (retval != PAM_SUCCESS)
+ {
+ cleanup_pam(retval);
+ error (EXIT_FAIL, 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 */
+ 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)
+ {
+ for (;;)
+ {
+ pid_t pid;
+
+ pid = waitpid (child, &status, WUNTRACED);
+
+ if (WIFSTOPPED (status))
+ {
+ kill (getpid (), SIGSTOP);
+ /* once we get here, we must have resumed */
+ kill (pid, SIGCONT);
+ }
+ else
+ break;
+ }
+ if (WIFSIGNALED (status))
+ status = WTERMSIG (status) + 128;
+ else
+ status = WEXITSTATUS (status);
+ }
+ 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. */
@@ -224,10 +402,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 : PAM_SERVICE_NAME_L,
+ 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)
@@ -248,6 +468,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
@@ -272,8 +493,8 @@ modify_environment (const struct passwd
xsetenv ("USER", pw->pw_name);
xsetenv ("LOGNAME", pw->pw_name);
xsetenv ("PATH", (pw->pw_uid
- ? DEFAULT_LOGIN_PATH
- : DEFAULT_ROOT_LOGIN_PATH));
+ ? getdef_str ("PATH", DEFAULT_LOGIN_PATH)
+ : getdef_str ("SUPATH", DEFAULT_ROOT_LOGIN_PATH)));
}
else
{
@@ -283,6 +504,12 @@ modify_environment (const struct passwd
{
xsetenv ("HOME", pw->pw_dir);
xsetenv ("SHELL", shell);
+ if (getdef_bool ("ALWAYS_SET_PATH", 0))
+ xsetenv ("PATH", (pw->pw_uid
+ ? getdef_str ("PATH",
+ DEFAULT_LOGIN_PATH)
+ : getdef_str ("SUPATH",
+ DEFAULT_ROOT_LOGIN_PATH)));
if (pw->pw_uid)
{
xsetenv ("USER", pw->pw_name);
@@ -290,19 +517,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_FAIL, errno, _("cannot set groups"));
+ {
+#ifdef USE_PAM
+ cleanup_pam(PAM_ABORT);
+#endif
+ error (EXIT_FAIL, errno, _("cannot set groups"));
+ }
endgrent ();
#endif
+
+#ifdef USE_PAM
+ retval = pam_setcred (pamh, PAM_ESTABLISH_CRED);
+ if (retval != PAM_SUCCESS)
+ error (EXIT_FAIL, 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_FAIL, errno, _("cannot set group id"));
if (setuid (pw->pw_uid))
@@ -495,6 +744,7 @@ main (int argc, char **argv)
#ifdef SYSLOG_FAILURE
log_su (pw, false);
#endif
+ sleep (getdef_num ("FAIL_DELAY", 1));
error (EXIT_FAIL, 0, _("incorrect password"));
}
#ifdef SYSLOG_SUCCESS
@@ -516,9 +766,21 @@ main (int argc, char **argv)
shell = NULL;
}
shell = xstrdup (shell ? shell : pw->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);
- change_identity (pw);
if (simulate_login && chdir (pw->pw_dir) != 0)
error (0, errno, _("warning: cannot change directory to %s"), pw->pw_dir);
Index: configure.ac
===================================================================
--- configure.ac.orig
+++ configure.ac
@@ -41,6 +41,20 @@ coreutils_MACROS
AC_FUNC_FORK
+AC_ARG_ENABLE(pam, AS_HELP_STRING([--disable-pam],dnl
+ [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])
+
AC_CHECK_FUNCS(uname,
OPTIONAL_BIN_PROGS="$OPTIONAL_BIN_PROGS uname\$(EXEEXT)"
MAN="$MAN uname.1")

25
coreutils-6.8.0-pie.diff Normal file
View File

@ -0,0 +1,25 @@
Index: lib/Makefile.am
===================================================================
--- lib/Makefile.am.orig
+++ lib/Makefile.am
@@ -20,6 +20,7 @@
include gnulib.mk
AM_CFLAGS = $(WARNING_CFLAGS) $(WERROR_CFLAGS)
+AM_CFLAGS += -fpie
noinst_PROGRAMS = t-fpending
LDADD = $(noinst_LIBRARIES)
Index: src/Makefile.am
===================================================================
--- src/Makefile.am.orig
+++ src/Makefile.am
@@ -104,6 +104,8 @@ uptime_LDADD = $(LDADD) $(POW_LIB) $(GET
su_SOURCES = su.c getdef.c
su_LDADD = $(LDADD) $(LIB_CRYPT) $(PAM_LIBS)
+su_CFLAGS = -fpie
+su_LDFLAGS = -pie
dir_LDADD += $(LIB_ACL)
ls_LDADD += $(LIB_ACL)

View File

@ -1,4 +1,6 @@
--- doc/coreutils.texi
Index: doc/coreutils.texi
===================================================================
--- doc/coreutils.texi.orig
+++ doc/coreutils.texi
@@ -64,8 +64,6 @@
* fold: (coreutils)fold invocation. Wrap long input lines.
@ -9,7 +11,7 @@
* id: (coreutils)id invocation. Print user identity.
* install: (coreutils)install invocation. Copy and change attributes.
* join: (coreutils)join invocation. Join lines on a common field.
@@ -398,8 +396,6 @@
@@ -399,8 +397,6 @@ System context
* date invocation:: Print or set system date and time
* uname invocation:: Print system information
@ -18,7 +20,7 @@
@command{date}: Print or set system date and time
@@ -12190,8 +12186,6 @@
@@ -12299,8 +12295,6 @@ information.
@menu
* date invocation:: Print or set system date and time.
* uname invocation:: Print system information.
@ -27,7 +29,7 @@
@end menu
@@ -12949,55 +12943,6 @@
@@ -13058,55 +13052,6 @@ Print the kernel version.
@exitstatus
@ -83,313 +85,11 @@
@node Modified command invocation
@chapter Modified command invocation
--- src/Makefile.am
+++ src/Makefile.am
@@ -103,7 +103,8 @@
# If necessary, add -lm to resolve use of pow in lib/strtod.c.
uptime_LDADD = $(LDADD) $(POW_LIB) $(GETLOADAVG_LIBS)
-su_LDADD = $(LDADD) $(LIB_CRYPT)
+su_SOURCES = su.c getdef.c
+su_LDADD = $(LDADD) $(LIB_CRYPT) -lpam -lpam_misc -ldl
dir_LDADD += $(LIB_ACL)
ls_LDADD += $(LIB_ACL)
--- src/getdef.c
+++ src/getdef.c
@@ -0,0 +1,257 @@
+/* Copyright (C) 2003, 2004, 2005 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "getdef.h"
+
+struct item {
+ char *name; /* name of the option. */
+ char *value; /* value of the option. */
+ struct item *next; /* pointer to next option. */
+};
+
+static struct item *list = NULL;
+
+void
+free_getdef_data (void)
+{
+ struct item *ptr;
+
+ ptr = list;
+ while (ptr != NULL)
+ {
+ struct item *tmp;
+ tmp = ptr->next;
+ free (ptr->name);
+ free (ptr->value);
+ free (ptr);
+ ptr = tmp;
+ }
+
+ list = NULL;
+}
+
+/* Add a new entry to the list. */
+static void
+store (const char *name, const char *value)
+{
+ struct item *new = malloc (sizeof (struct item));
+
+ if (new == NULL)
+ abort ();
+
+ if (name == NULL)
+ abort ();
+
+ new->name = strdup (name);
+ new->value = strdup (value?:"");
+ new->next = list;
+ list = new;
+}
+
+/* search a special entry in the list and return the value. */
+static const char *
+search (const char *name)
+{
+ struct item *ptr;
+
+ ptr = list;
+ while (ptr != NULL)
+ {
+ if (strcasecmp (name, ptr->name) == 0)
+ return ptr->value;
+ ptr = ptr->next;
+ }
+
+ return NULL;
+}
+
+/* Load the login.defs file (/etc/login.defs) */
+static void
+load_defaults_internal (const char *filename)
+{
+ FILE *fp;
+ char *buf = NULL;
+ size_t buflen = 0;
+
+ fp = fopen (filename, "r");
+ if (NULL == fp)
+ return;
+
+ while (!feof (fp))
+ {
+ char *tmp, *cp;
+#if defined(HAVE_GETLINE)
+ ssize_t n = getline (&buf, &buflen, fp);
+#elif defined (HAVE_GETDELIM)
+ ssize_t n = getdelim (&buf, &buflen, '\n', fp);
+#else
+ ssize_t n;
+
+ if (buf == NULL)
+ {
+ buflen = 8096;
+ buf = malloc (buflen);
+ }
+ buf[0] = '\0';
+ fgets (buf, buflen - 1, fp);
+ if (buf != NULL)
+ n = strlen (buf);
+ else
+ n = 0;
+#endif /* HAVE_GETLINE / HAVE_GETDELIM */
+ cp = buf;
+
+ if (n < 1)
+ break;
+
+ tmp = strchr (cp, '#'); /* remove comments */
+ if (tmp)
+ *tmp = '\0';
+ while (isspace ((int)*cp)) /* remove spaces and tabs */
+ ++cp;
+ if (*cp == '\0') /* ignore empty lines */
+ continue;
+
+ if (cp[strlen (cp) - 1] == '\n')
+ cp[strlen (cp) - 1] = '\0';
+
+ tmp = strsep (&cp, " \t=");
+ if (cp != NULL)
+ while (isspace ((int)*cp) || *cp == '=')
+ ++cp;
+
+ store (tmp, cp);
+ }
+ fclose (fp);
+
+ if (buf)
+ free (buf);
+}
+
+static void
+load_defaults (void)
+{
+ load_defaults_internal ("/etc/default/su");
+ load_defaults_internal ("/etc/login.defs");
+}
+
+int
+getdef_bool (const char *name, int dflt)
+{
+ const char *val;
+
+ if (list == NULL)
+ load_defaults ();
+
+ val = search (name);
+
+ if (val == NULL)
+ return dflt;
+
+ return (strcasecmp (val, "yes") == 0);
+}
+
+long
+getdef_num (const char *name, long dflt)
+{
+ const char *val;
+ char *cp;
+ long retval;
+
+ if (list == NULL)
+ load_defaults ();
+
+ val = search (name);
+
+ if (val == NULL)
+ return dflt;
+
+ retval = strtol (val, &cp, 0);
+ if (*cp != '\0' ||
+ ((retval == LONG_MAX || retval == LONG_MIN) && errno == ERANGE))
+ {
+ fprintf (stderr,
+ "%s contains invalid numerical value: %s!\n",
+ name, val);
+ retval = dflt;
+ }
+ return retval;
+}
+
+unsigned long
+getdef_unum (const char *name, unsigned long dflt)
+{
+ const char *val;
+ char *cp;
+ unsigned long retval;
+
+ if (list == NULL)
+ load_defaults ();
+
+ val = search (name);
+
+ if (val == NULL)
+ return dflt;
+
+ retval = strtoul (val, &cp, 0);
+ if (*cp != '\0' || (retval == ULONG_MAX && errno == ERANGE))
+ {
+ fprintf (stderr,
+ "%s contains invalid numerical value: %s!\n",
+ name, val);
+ retval = dflt;
+ }
+ return retval;
+}
+
+const char *
+getdef_str (const char *name, const char *dflt)
+{
+ const char *retval;
+
+ if (list == NULL)
+ load_defaults ();
+
+ retval = search (name);
+
+ return retval ?: dflt;
+}
+
+#if defined(TEST)
+
+int
+main ()
+{
+ printf ("CYPT=%s\n", getdef_str ("cRypt", "no"));
+ printf ("LOG_UNKFAIL_ENAB=%s\n", getdef_str ("log_unkfail_enab",""));
+ printf ("DOESNOTEXIST=%s\n", getdef_str ("DOESNOTEXIST","yes"));
+ return 0;
+}
+
+#endif
--- src/getdef.h
+++ src/getdef.h
@@ -0,0 +1,29 @@
+/* Copyright (C) 2003, 2005 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _GETDEF_H_
+
+#define _GETDEF_H_ 1
+
+extern int getdef_bool (const char *name, int dflt);
+extern long getdef_num (const char *name, long dflt);
+extern unsigned long getdef_unum (const char *name, unsigned long dflt);
+extern const char *getdef_str (const char *name, const char *dflt);
+
+/* Free all data allocated by getdef_* calls before. */
+extern void free_getdef_data (void);
+
+#endif /* _GETDEF_H_ */
--- src/install.c
Index: src/install.c
===================================================================
--- src/install.c.orig
+++ src/install.c
@@ -572,7 +572,8 @@
@@ -571,7 +571,8 @@ strip (char const *name)
while (pid != wait (&status)) /* Wait for kid to finish. */
/* Do nothing. */ ;
if (status)
@ -399,339 +99,11 @@
break;
}
}
--- src/su.c
+++ src/su.c
@@ -38,6 +38,12 @@
restricts who can su to UID 0 accounts. RMS considers that to
be fascist.
+ 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
+
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.
@@ -53,6 +59,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
/* Hide any system prototype for getusershell.
This is necessary because some Cray systems have a conflicting
@@ -66,6 +79,9 @@
#if HAVE_SYSLOG_H && HAVE_SYSLOG
# include <syslog.h>
+# define SYSLOG_SUCCESS 1
+# define SYSLOG_FAILURE 1
+# define SYSLOG_NON_ROOT 1
#else
# undef SYSLOG_SUCCESS
# undef SYSLOG_FAILURE
@@ -99,19 +115,13 @@
# include <paths.h>
#endif
+#include "getdef.h"
+
/* The default PATH for simulated logins to non-superuser accounts. */
-#ifdef _PATH_DEFPATH
-# define DEFAULT_LOGIN_PATH _PATH_DEFPATH
-#else
-# define DEFAULT_LOGIN_PATH ":/usr/ucb:/bin:/usr/bin"
-#endif
+#define DEFAULT_LOGIN_PATH "/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin"
/* The default PATH for simulated logins to superuser accounts. */
-#ifdef _PATH_DEFPATH_ROOT
-# define DEFAULT_ROOT_LOGIN_PATH _PATH_DEFPATH_ROOT
-#else
-# define DEFAULT_ROOT_LOGIN_PATH "/usr/ucb:/bin:/usr/bin:/etc"
-#endif
+#define DEFAULT_ROOT_LOGIN_PATH "/usr/sbin:/bin:/usr/bin:/sbin:/usr/X11R6/bin"
/* The shell to run if none is given in the user's passwd entry. */
#define DEFAULT_SHELL "/bin/sh"
@@ -119,7 +129,9 @@
/* The user to become if none is specified. */
#define DEFAULT_USER "root"
+#ifndef USE_PAM
char *crypt ();
+#endif
char *getusershell ();
void endusershell ();
void setusershell ();
@@ -216,7 +228,26 @@
}
#endif
+#ifdef USE_PAM
+
+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, PAM_SUCCESS); \
+ a; \
+ }
+#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. */
@@ -224,10 +255,49 @@
static bool
correct_password (const struct passwd *pw)
{
+#ifdef USE_PAM
+ const struct passwd *lpw;
+ const char *cp;
+
+ retval = pam_start ("su", 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);
+ }
+ cp = getlogin ();
+ if (!(cp && *cp && (lpw = getpwnam (cp)) != NULL && lpw->pw_uid == getuid ()))
+ lpw = getpwuid (getuid ());
+ if (lpw)
+ {
+ 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)
@@ -248,6 +318,7 @@
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
@@ -272,8 +343,8 @@
xsetenv ("USER", pw->pw_name);
xsetenv ("LOGNAME", pw->pw_name);
xsetenv ("PATH", (pw->pw_uid
- ? DEFAULT_LOGIN_PATH
- : DEFAULT_ROOT_LOGIN_PATH));
+ ? getdef_str ("PATH", DEFAULT_LOGIN_PATH)
+ : getdef_str ("SUPATH", DEFAULT_ROOT_LOGIN_PATH)));
}
else
{
@@ -283,6 +354,12 @@
{
xsetenv ("HOME", pw->pw_dir);
xsetenv ("SHELL", shell);
+ if (getdef_bool ("ALWAYS_SET_PATH", 0))
+ xsetenv ("PATH", (pw->pw_uid
+ ? getdef_str ("PATH",
+ DEFAULT_LOGIN_PATH)
+ : getdef_str ("SUPATH",
+ DEFAULT_ROOT_LOGIN_PATH)));
if (pw->pw_uid)
{
xsetenv ("USER", pw->pw_name);
@@ -303,12 +380,35 @@
error (EXIT_FAIL, errno, _("cannot set groups"));
endgrent ();
#endif
+#ifdef USE_PAM
+ retval = pam_setcred (pamh, PAM_ESTABLISH_CRED);
+ if (retval != PAM_SUCCESS)
+ error (EXIT_FAIL, 0, "%s", pam_strerror (pamh, retval));
+
+ retval = pam_open_session (pamh,0);
+ if (retval != PAM_SUCCESS)
+ {
+ pam_setcred (pamh, PAM_DELETE_CRED);
+ error (EXIT_FAIL, 0, "could not open session: %s",
+ pam_strerror (pamh, retval));
+ }
+#endif /* USE_PAM */
if (setgid (pw->pw_gid))
error (EXIT_FAIL, errno, _("cannot set group id"));
if (setuid (pw->pw_uid))
error (EXIT_FAIL, errno, _("cannot set user id"));
}
+#ifdef USE_PAM
+static bool caught = false;
+/* Signal handler for parent process later */
+static void
+su_catch_sig (int sig)
+{
+ caught = true;
+}
+#endif
+
/* Run SHELL, or DEFAULT_SHELL if SHELL is empty.
If COMMAND is nonzero, pass it to the shell with the -c option.
Pass ADDITIONAL_ARGS to the shell as more arguments; there
@@ -321,6 +421,88 @@
size_t n_args = 1 + fast_startup + 2 * !!command + n_additional_args + 1;
char const **args = xnmalloc (n_args, sizeof *args);
size_t argno = 1;
+#ifdef USE_PAM
+ pid_t child;
+ sigset_t ourset;
+ int status;
+
+ child = fork ();
+ if (child == (pid_t) -1)
+ error (EXIT_FAILURE, errno, "cannot fork");
+
+ if (child != 0)
+ {
+ /* parent only */
+ sigfillset (&ourset);
+ if (sigprocmask (SIG_BLOCK, &ourset, NULL))
+ {
+ error (0, errno, "cannot block signals");
+ caught = true;
+ }
+ if (!caught)
+ {
+ 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 = true;
+ }
+ }
+ if (!caught)
+ {
+ for (;;)
+ {
+ pid_t pid;
+
+ pid = waitpid (child, &status, WUNTRACED);
+
+ if (WIFSTOPPED (status))
+ {
+ kill (getpid (), SIGSTOP);
+ /* once we get here, we must have resumed */
+ kill (pid, SIGCONT);
+ }
+ else
+ break;
+ }
+ if (WIFSIGNALED (status))
+ status = WTERMSIG (status) + 128;
+ else
+ status = WEXITSTATUS (status);
+ }
+ else
+ status = 1;
+
+ if (caught)
+ {
+ fprintf (stderr, "\nSession terminated, killing shell...");
+ kill (child, SIGTERM);
+ }
+ retval = pam_setcred (pamh, PAM_DELETE_CRED);
+ PAM_BAIL_P (exit (EXIT_FAILURE));
+ retval = pam_close_session (pamh, 0);
+ PAM_BAIL_P (exit (EXIT_FAILURE));
+ retval = pam_end (pamh, PAM_SUCCESS);
+ PAM_BAIL_P (exit (EXIT_FAILURE));
+ if (caught)
+ {
+ sleep (2);
+ kill (child, SIGKILL);
+ fprintf (stderr, " ...killed.\n");
+ }
+ exit (status);
+ }
+
+ /* child shell */
+ pam_end (pamh, 0);
+#endif
if (simulate_login)
{
@@ -339,6 +521,11 @@
args[argno++] = "-f";
if (command)
{
+ if (simulate_login)
+ /* Bash 2.0 have to be invoked as `-su'. See the comments in
+ `shell.c (run_startup_files)'. */
+ args[0] = "-su";
+
args[argno++] = "-c";
args[argno++] = command;
}
@@ -495,6 +682,9 @@
#ifdef SYSLOG_FAILURE
log_su (pw, false);
#endif
+#ifdef USE_PAM
+ sleep (getdef_num ("FAIL_DELAY", 1));
+#endif
error (EXIT_FAIL, 0, _("incorrect password"));
}
#ifdef SYSLOG_SUCCESS
--- src/system.h
Index: src/system.h
===================================================================
--- src/system.h.orig
+++ src/system.h
@@ -173,7 +173,7 @@
@@ -168,7 +168,7 @@ enum
# define DEV_BSIZE BBSIZE
#endif
#ifndef DEV_BSIZE
@ -740,9 +112,11 @@
#endif
/* Extract or fake data from a `struct stat'.
--- tests/help-version
Index: tests/help-version
===================================================================
--- tests/help-version.orig
+++ tests/help-version
@@ -190,7 +190,7 @@
@@ -197,7 +197,7 @@ lbracket_args=": ]"
for i in $all_programs; do
# Skip these.
@ -751,9 +125,11 @@
rm -rf $tmp_in $tmp_in2 $tmp_dir $tmp_out
echo > $tmp_in
--- tests/other-fs-tmpdir
Index: tests/other-fs-tmpdir
===================================================================
--- tests/other-fs-tmpdir.orig
+++ tests/other-fs-tmpdir
@@ -44,6 +44,8 @@
@@ -44,6 +44,8 @@ for d in $CANDIDATE_TMP_DIRS; do
fi
done

View File

@ -1,3 +1,13 @@
-------------------------------------------------------------------
Fri Mar 2 13:47:35 CET 2007 - lnussel@suse.de
- split off and rework PAM patch for su:
* run pam_open_session as root (#245706)
* use separate pam configs for "su" and "su -" (RedHat #198639)
* detect pam libs in configure script, add option to disable it
* don't set argv[0] to "-su", use upstream behavior instead
* don't use getlogin() for setting PAM_RUSER
-------------------------------------------------------------------
Sun Feb 25 10:58:58 CET 2007 - schwab@suse.de

View File

@ -21,7 +21,7 @@ Obsoletes: libselinux <= 1.23.11-3 libselinux-32bit >= 9 libselinux-64bit =
Autoreqprov: on
PreReq: %{install_info_prereq}
Version: 6.8
Release: 1
Release: 3
Summary: GNU Core Utilities
Source: coreutils-%{version}.tar.bz2
Source1: su.pamd
@ -32,13 +32,13 @@ Patch30: coreutils-changelog.diff
Patch4: coreutils-5.3.0-i18n-0.1.patch
Patch5: i18n-uninit.diff
Patch6: i18n-infloop.diff
Patch7: coreutils-5.0-pam-env.patch
Patch8: coreutils-sysinfo.diff
Patch11: i18n-monthsort.diff
Patch16: invalid-ids.diff
Patch17: no-no.diff
Patch20: coreutils-5.3.0-pie.diff
Patch21: coreutils-5.3.0-sbin4su.diff
Patch20: coreutils-6.8-su.diff
Patch21: coreutils-6.8.0-pie.diff
Patch22: coreutils-5.3.0-sbin4su.diff
BuildRoot: %{_tmppath}/%{name}-%{version}-build
%description
@ -98,18 +98,18 @@ Authors:
%patch5
%patch6
%patch
%patch7 -p1
%patch8 -p1
%patch11
%patch16 -p1
%patch17
%patch20
%patch21
%patch22
rm -f po/no.*
%build
AUTOPOINT=true autoreconf -fi
./configure CFLAGS="-DUSE_PAM $RPM_OPT_FLAGS -Wall" \
./configure CFLAGS="$RPM_OPT_FLAGS -Wall" \
DEFAULT_POSIX2_VERSION=199209 \
--prefix=%{_prefix} --mandir=%{_mandir} \
--infodir=%{_infodir} --without-included-regex
@ -139,6 +139,7 @@ done > bin.files
ln -sf ../../bin/basename ../../bin/sort ../../bin/touch $RPM_BUILD_ROOT%{_bindir}
install -d -m 755 $RPM_BUILD_ROOT/etc/pam.d
install -m 644 $RPM_SOURCE_DIR/su.pamd $RPM_BUILD_ROOT/etc/pam.d/su
install -m 644 $RPM_SOURCE_DIR/su.pamd $RPM_BUILD_ROOT/etc/pam.d/su-l
install -d -m 755 $RPM_BUILD_ROOT/etc/default
install -m 644 $RPM_SOURCE_DIR/su.default $RPM_BUILD_ROOT/etc/default/su
ln -sf /bin/su $RPM_BUILD_ROOT%{_bindir}/sux
@ -162,6 +163,7 @@ rm -rf $RPM_BUILD_ROOT
%defattr(-,root,root)
%doc README NEWS
%config /etc/pam.d/su
%config /etc/pam.d/su-l
%config(noreplace) /etc/default/su
%{_bindir}/*
%doc %{_infodir}/coreutils.info*.gz
@ -169,6 +171,13 @@ rm -rf $RPM_BUILD_ROOT
%dir %{_prefix}/share/locale/*/LC_TIME
%changelog
* Fri Mar 02 2007 - lnussel@suse.de
- split off and rework PAM patch for su:
* run pam_open_session as root (#245706)
* use separate pam configs for "su" and "su -" (RedHat #198639)
* detect pam libs in configure script, add option to disable it
* don't set argv[0] to "-su", use upstream behavior instead
* don't use getlogin() for setting PAM_RUSER
* Sun Feb 25 2007 - schwab@suse.de
- Update to coreutils 6.8.
** Bug fixes