* Merge SUSE's coreutils-5.0-pam-env.patch so that PAM modules can

pass environment variables (notably DISPLAY and XAUTHORITY) to the
  child shell.

svn path=/nixpkgs/trunk/; revision=7701
This commit is contained in:
Eelco Dolstra 2007-01-16 22:24:03 +00:00
parent 4d2519baad
commit a71003612b
2 changed files with 1018 additions and 623 deletions

View File

@ -14,7 +14,6 @@ stdenv.mkDerivation {
# PAM patch taken from SUSE's coreutils-6.7-5.src.rpm. # PAM patch taken from SUSE's coreutils-6.7-5.src.rpm.
./su-pam.patch ./su-pam.patch
]; ];
patchFlags = "-p0";
buildInputs = [pam]; buildInputs = [pam];
buildPhase = " buildPhase = "
make -C lib make -C lib

View File

@ -1,7 +1,10 @@
--- src/getdef.c diff -rcN coreutils-6.7-orig/getdef.c coreutils-6.7/getdef.c
+++ src/getdef.c *** coreutils-6.7-orig/getdef.c Thu Jan 1 00:00:00 1970
@@ -0,0 +1,257 @@ --- coreutils-6.7/getdef.c Tue Jan 16 22:18:41 2007
+/* Copyright (C) 2003, 2004, 2005 Thorsten Kukuk ***************
*** 0 ****
--- 1,257 ----
+ /* Copyright (C) 2003, 2004, 2005 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de> + Author: Thorsten Kukuk <kukuk@suse.de>
+ +
+ This program is free software; you can redistribute it and/or modify + This program is free software; you can redistribute it and/or modify
@ -17,32 +20,32 @@
+ along with this program; if not, write to the Free Software Foundation, + along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ +
+#ifdef HAVE_CONFIG_H + #ifdef HAVE_CONFIG_H
+#include <config.h> + #include <config.h>
+#endif + #endif
+ +
+#define _GNU_SOURCE + #define _GNU_SOURCE
+ +
+#include <errno.h> + #include <errno.h>
+#include <ctype.h> + #include <ctype.h>
+#include <stdio.h> + #include <stdio.h>
+#include <stdlib.h> + #include <stdlib.h>
+#include <string.h> + #include <string.h>
+#include <limits.h> + #include <limits.h>
+ +
+#include "getdef.h" + #include "getdef.h"
+ +
+struct item { + struct item {
+ char *name; /* name of the option. */ + char *name; /* name of the option. */
+ char *value; /* value of the option. */ + char *value; /* value of the option. */
+ struct item *next; /* pointer to next option. */ + struct item *next; /* pointer to next option. */
+}; + };
+ +
+static struct item *list = NULL; + static struct item *list = NULL;
+ +
+void + void
+free_getdef_data (void) + free_getdef_data (void)
+{ + {
+ struct item *ptr; + struct item *ptr;
+ +
+ ptr = list; + ptr = list;
@ -57,12 +60,12 @@
+ } + }
+ +
+ list = NULL; + list = NULL;
+} + }
+ +
+/* Add a new entry to the list. */ + /* Add a new entry to the list. */
+static void + static void
+store (const char *name, const char *value) + store (const char *name, const char *value)
+{ + {
+ struct item *new = malloc (sizeof (struct item)); + struct item *new = malloc (sizeof (struct item));
+ +
+ if (new == NULL) + if (new == NULL)
@ -75,12 +78,12 @@
+ new->value = strdup (value?:""); + new->value = strdup (value?:"");
+ new->next = list; + new->next = list;
+ list = new; + list = new;
+} + }
+ +
+/* search a special entry in the list and return the value. */ + /* search a special entry in the list and return the value. */
+static const char * + static const char *
+search (const char *name) + search (const char *name)
+{ + {
+ struct item *ptr; + struct item *ptr;
+ +
+ ptr = list; + ptr = list;
@ -92,12 +95,12 @@
+ } + }
+ +
+ return NULL; + return NULL;
+} + }
+ +
+/* Load the login.defs file (/etc/login.defs) */ + /* Load the login.defs file (/etc/login.defs) */
+static void + static void
+load_defaults_internal (const char *filename) + load_defaults_internal (const char *filename)
+{ + {
+ FILE *fp; + FILE *fp;
+ char *buf = NULL; + char *buf = NULL;
+ size_t buflen = 0; + size_t buflen = 0;
@ -109,11 +112,11 @@
+ while (!feof (fp)) + while (!feof (fp))
+ { + {
+ char *tmp, *cp; + char *tmp, *cp;
+#if defined(HAVE_GETLINE) + #if defined(HAVE_GETLINE)
+ ssize_t n = getline (&buf, &buflen, fp); + ssize_t n = getline (&buf, &buflen, fp);
+#elif defined (HAVE_GETDELIM) + #elif defined (HAVE_GETDELIM)
+ ssize_t n = getdelim (&buf, &buflen, '\n', fp); + ssize_t n = getdelim (&buf, &buflen, '\n', fp);
+#else + #else
+ ssize_t n; + ssize_t n;
+ +
+ if (buf == NULL) + if (buf == NULL)
@ -127,7 +130,7 @@
+ n = strlen (buf); + n = strlen (buf);
+ else + else
+ n = 0; + n = 0;
+#endif /* HAVE_GETLINE / HAVE_GETDELIM */ + #endif /* HAVE_GETLINE / HAVE_GETDELIM */
+ cp = buf; + cp = buf;
+ +
+ if (n < 1) + if (n < 1)
@ -155,18 +158,18 @@
+ +
+ if (buf) + if (buf)
+ free (buf); + free (buf);
+} + }
+ +
+static void + static void
+load_defaults (void) + load_defaults (void)
+{ + {
+ load_defaults_internal ("/etc/default/su"); + load_defaults_internal ("/etc/default/su");
+ load_defaults_internal ("/etc/login.defs"); + load_defaults_internal ("/etc/login.defs");
+} + }
+ +
+int + int
+getdef_bool (const char *name, int dflt) + getdef_bool (const char *name, int dflt)
+{ + {
+ const char *val; + const char *val;
+ +
+ if (list == NULL) + if (list == NULL)
@ -178,11 +181,11 @@
+ return dflt; + return dflt;
+ +
+ return (strcasecmp (val, "yes") == 0); + return (strcasecmp (val, "yes") == 0);
+} + }
+ +
+long + long
+getdef_num (const char *name, long dflt) + getdef_num (const char *name, long dflt)
+{ + {
+ const char *val; + const char *val;
+ char *cp; + char *cp;
+ long retval; + long retval;
@ -205,11 +208,11 @@
+ retval = dflt; + retval = dflt;
+ } + }
+ return retval; + return retval;
+} + }
+ +
+unsigned long + unsigned long
+getdef_unum (const char *name, unsigned long dflt) + getdef_unum (const char *name, unsigned long dflt)
+{ + {
+ const char *val; + const char *val;
+ char *cp; + char *cp;
+ unsigned long retval; + unsigned long retval;
@ -231,11 +234,11 @@
+ retval = dflt; + retval = dflt;
+ } + }
+ return retval; + return retval;
+} + }
+ +
+const char * + const char *
+getdef_str (const char *name, const char *dflt) + getdef_str (const char *name, const char *dflt)
+{ + {
+ const char *retval; + const char *retval;
+ +
+ if (list == NULL) + if (list == NULL)
@ -244,24 +247,27 @@
+ retval = search (name); + retval = search (name);
+ +
+ return retval ?: dflt; + return retval ?: dflt;
+} + }
+ +
+#if defined(TEST) + #if defined(TEST)
+ +
+int + int
+main () + main ()
+{ + {
+ printf ("CYPT=%s\n", getdef_str ("cRypt", "no")); + printf ("CYPT=%s\n", getdef_str ("cRypt", "no"));
+ printf ("LOG_UNKFAIL_ENAB=%s\n", getdef_str ("log_unkfail_enab","")); + printf ("LOG_UNKFAIL_ENAB=%s\n", getdef_str ("log_unkfail_enab",""));
+ printf ("DOESNOTEXIST=%s\n", getdef_str ("DOESNOTEXIST","yes")); + printf ("DOESNOTEXIST=%s\n", getdef_str ("DOESNOTEXIST","yes"));
+ return 0; + return 0;
+} + }
+ +
+#endif + #endif
--- src/getdef.h diff -rcN coreutils-6.7-orig/getdef.h coreutils-6.7/getdef.h
+++ src/getdef.h *** coreutils-6.7-orig/getdef.h Thu Jan 1 00:00:00 1970
@@ -0,0 +1,29 @@ --- coreutils-6.7/getdef.h Tue Jan 16 22:18:41 2007
+/* Copyright (C) 2003, 2005 Thorsten Kukuk ***************
*** 0 ****
--- 1,29 ----
+ /* Copyright (C) 2003, 2005 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de> + Author: Thorsten Kukuk <kukuk@suse.de>
+ +
+ This program is free software; you can redistribute it and/or modify + This program is free software; you can redistribute it and/or modify
@ -277,22 +283,323 @@
+ along with this program; if not, write to the Free Software Foundation, + along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ +
+#ifndef _GETDEF_H_ + #ifndef _GETDEF_H_
+ +
+#define _GETDEF_H_ 1 + #define _GETDEF_H_ 1
+ +
+extern int getdef_bool (const char *name, int dflt); + extern int getdef_bool (const char *name, int dflt);
+extern long getdef_num (const char *name, long dflt); + extern long getdef_num (const char *name, long dflt);
+extern unsigned long getdef_unum (const char *name, unsigned long dflt); + extern unsigned long getdef_unum (const char *name, unsigned long dflt);
+extern const char *getdef_str (const char *name, const char *dflt); + extern const char *getdef_str (const char *name, const char *dflt);
+ +
+/* Free all data allocated by getdef_* calls before. */ + /* Free all data allocated by getdef_* calls before. */
+extern void free_getdef_data (void); + extern void free_getdef_data (void);
+ +
+#endif /* _GETDEF_H_ */ + #endif /* _GETDEF_H_ */
--- src/su.c diff -rcN coreutils-6.7-orig/src/getdef.c coreutils-6.7/src/getdef.c
+++ src/su.c *** coreutils-6.7-orig/src/getdef.c Thu Jan 1 00:00:00 1970
@@ -38,6 +38,12 @@ --- coreutils-6.7/src/getdef.c Tue Jan 16 22:18:57 2007
***************
*** 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
diff -rcN coreutils-6.7-orig/src/getdef.h coreutils-6.7/src/getdef.h
*** coreutils-6.7-orig/src/getdef.h Thu Jan 1 00:00:00 1970
--- coreutils-6.7/src/getdef.h Tue Jan 16 22:18:57 2007
***************
*** 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_ */
diff -rcN coreutils-6.7-orig/src/su.c coreutils-6.7/src/su.c
*** coreutils-6.7-orig/src/su.c Sun Oct 22 16:54:15 2006
--- coreutils-6.7/src/su.c Tue Jan 16 22:19:02 2007
***************
*** 38,43 ****
--- 38,49 ----
restricts who can su to UID 0 accounts. RMS considers that to restricts who can su to UID 0 accounts. RMS considers that to
be fascist. be fascist.
@ -305,96 +612,127 @@
Compile-time options: Compile-time options:
-DSYSLOG_SUCCESS Log successful su's (by default, to root) with syslog. -DSYSLOG_SUCCESS Log successful su's (by default, to root) with syslog.
-DSYSLOG_FAILURE Log failed su's (by default, to root) with syslog. -DSYSLOG_FAILURE Log failed su's (by default, to root) with syslog.
@@ -53,6 +59,13 @@ ***************
*** 53,58 ****
--- 59,71 ----
#include <sys/types.h> #include <sys/types.h>
#include <pwd.h> #include <pwd.h>
#include <grp.h> #include <grp.h>
+#ifdef USE_PAM + #ifdef USE_PAM
+#include <security/pam_appl.h> + #include <security/pam_appl.h>
+#include <security/pam_misc.h> + #include <security/pam_misc.h>
+#include <signal.h> + #include <signal.h>
+#include <sys/wait.h> + #include <sys/wait.h>
+#include <sys/fsuid.h> + #include <sys/fsuid.h>
+#endif + #endif
/* Hide any system prototype for getusershell. /* Hide any system prototype for getusershell.
This is necessary because some Cray systems have a conflicting This is necessary because some Cray systems have a conflicting
@@ -66,6 +79,9 @@ ***************
*** 66,71 ****
--- 79,87 ----
#if HAVE_SYSLOG_H && HAVE_SYSLOG #if HAVE_SYSLOG_H && HAVE_SYSLOG
# include <syslog.h> # include <syslog.h>
+# define SYSLOG_SUCCESS 1 + # define SYSLOG_SUCCESS 1
+# define SYSLOG_FAILURE 1 + # define SYSLOG_FAILURE 1
+# define SYSLOG_NON_ROOT 1 + # define SYSLOG_NON_ROOT 1
#else #else
# undef SYSLOG_SUCCESS # undef SYSLOG_SUCCESS
# undef SYSLOG_FAILURE # undef SYSLOG_FAILURE
@@ -99,19 +115,13 @@ ***************
*** 99,117 ****
# include <paths.h> # include <paths.h>
#endif #endif
+#include "getdef.h"
+
/* The default PATH for simulated logins to non-superuser accounts. */ /* The default PATH for simulated logins to non-superuser accounts. */
-#ifdef _PATH_DEFPATH ! #ifdef _PATH_DEFPATH
-# define DEFAULT_LOGIN_PATH _PATH_DEFPATH ! # define DEFAULT_LOGIN_PATH _PATH_DEFPATH
-#else ! #else
-# define DEFAULT_LOGIN_PATH ":/usr/ucb:/bin:/usr/bin" ! # define DEFAULT_LOGIN_PATH ":/usr/ucb:/bin:/usr/bin"
-#endif ! #endif
+#define DEFAULT_LOGIN_PATH "/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin"
/* The default PATH for simulated logins to superuser accounts. */ /* The default PATH for simulated logins to superuser accounts. */
-#ifdef _PATH_DEFPATH_ROOT ! #ifdef _PATH_DEFPATH_ROOT
-# define DEFAULT_ROOT_LOGIN_PATH _PATH_DEFPATH_ROOT ! # define DEFAULT_ROOT_LOGIN_PATH _PATH_DEFPATH_ROOT
-#else ! #else
-# define DEFAULT_ROOT_LOGIN_PATH "/usr/ucb:/bin:/usr/bin:/etc" ! # define DEFAULT_ROOT_LOGIN_PATH "/usr/ucb:/bin:/usr/bin:/etc"
-#endif ! #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. */ /* The shell to run if none is given in the user's passwd entry. */
#define DEFAULT_SHELL "/bin/sh" #define DEFAULT_SHELL "/bin/sh"
@@ -119,7 +129,9 @@ --- 115,127 ----
# include <paths.h>
#endif
+ #include "getdef.h"
+
/* The default PATH for simulated logins to non-superuser accounts. */
! #define DEFAULT_LOGIN_PATH "/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin"
/* The default PATH for simulated logins to superuser accounts. */
! #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,125 ****
--- 129,137 ----
/* The user to become if none is specified. */ /* The user to become if none is specified. */
#define DEFAULT_USER "root" #define DEFAULT_USER "root"
+#ifndef USE_PAM + #ifndef USE_PAM
char *crypt (); char *crypt ();
+#endif + #endif
char *getusershell (); char *getusershell ();
void endusershell (); void endusershell ();
void setusershell (); void setusershell ();
@@ -216,7 +228,26 @@ ***************
*** 216,222 ****
--- 228,253 ----
} }
#endif #endif
+#ifdef USE_PAM + #ifdef USE_PAM
+ +
+static pam_handle_t *pamh = NULL; + static pam_handle_t *pamh = NULL;
+static int retval; + static int retval;
+static struct pam_conv conv = + static struct pam_conv conv =
+{ + {
+ misc_conv, + misc_conv,
+ NULL + NULL
+}; + };
+ +
+#define PAM_BAIL_P(a) \ + #define PAM_BAIL_P(a) \
+ if (retval) \ + if (retval) \
+ { \ + { \
+ pam_end (pamh, PAM_SUCCESS); \ + pam_end (pamh, PAM_SUCCESS); \
+ a; \ + a; \
+ } + }
+#endif + #endif
+ +
/* Ask the user for a password. /* Ask the user for a password.
+ If PAM is in use, let PAM ask for the password if necessary. + 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, 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 false if not. Return true without asking for a password if run by UID 0
or if PW has an empty password. */ or if PW has an empty password. */
@@ -224,10 +255,49 @@ ***************
*** 224,233 ****
static bool static bool
correct_password (const struct passwd *pw) correct_password (const struct passwd *pw)
{ {
+#ifdef 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);
endspent ();
if (sp)
--- 255,303 ----
static bool
correct_password (const struct passwd *pw)
{
+ #ifdef USE_PAM
+ const struct passwd *lpw; + const struct passwd *lpw;
+ const char *cp; + const char *cp;
+ +
@ -432,35 +770,46 @@
+ PAM_BAIL_P (return false); + PAM_BAIL_P (return false);
+ /* must be authenticated if this point was reached */ + /* must be authenticated if this point was reached */
+ return true; + return true;
+#else /* !USE_PAM */ + #else /* !USE_PAM */
char *unencrypted, *encrypted, *correct; char *unencrypted, *encrypted, *correct;
#if HAVE_GETSPNAM && HAVE_STRUCT_SPWD_SP_PWDP #if HAVE_GETSPNAM && HAVE_STRUCT_SPWD_SP_PWDP
/* Shadow passwd stuff for SVR3 and maybe other systems. */ /* Shadow passwd stuff for SVR3 and maybe other systems. */
- struct spwd *sp = getspnam (pw->pw_name); ! const struct spwd *sp = getspnam (pw->pw_name);
+ const struct spwd *sp = getspnam (pw->pw_name);
endspent (); endspent ();
if (sp) if (sp)
@@ -248,6 +318,7 @@ ***************
*** 248,253 ****
--- 318,324 ----
encrypted = crypt (unencrypted, correct); encrypted = crypt (unencrypted, correct);
memset (unencrypted, 0, strlen (unencrypted)); memset (unencrypted, 0, strlen (unencrypted));
return STREQ (encrypted, correct); return STREQ (encrypted, correct);
+#endif /* !USE_PAM */ + #endif /* !USE_PAM */
} }
/* Update `environ' for the new shell based on PW, with SHELL being /* Update `environ' for the new shell based on PW, with SHELL being
@@ -272,8 +343,8 @@ ***************
*** 272,279 ****
xsetenv ("USER", pw->pw_name); xsetenv ("USER", pw->pw_name);
xsetenv ("LOGNAME", pw->pw_name); xsetenv ("LOGNAME", pw->pw_name);
xsetenv ("PATH", (pw->pw_uid xsetenv ("PATH", (pw->pw_uid
- ? DEFAULT_LOGIN_PATH ! ? DEFAULT_LOGIN_PATH
- : DEFAULT_ROOT_LOGIN_PATH)); ! : DEFAULT_ROOT_LOGIN_PATH));
+ ? getdef_str ("PATH", DEFAULT_LOGIN_PATH)
+ : getdef_str ("SUPATH", DEFAULT_ROOT_LOGIN_PATH)));
} }
else else
{ {
@@ -283,6 +354,12 @@ --- 343,350 ----
xsetenv ("USER", pw->pw_name);
xsetenv ("LOGNAME", pw->pw_name);
xsetenv ("PATH", (pw->pw_uid
! ? getdef_str ("PATH", DEFAULT_LOGIN_PATH)
! : getdef_str ("SUPATH", DEFAULT_ROOT_LOGIN_PATH)));
}
else
{
***************
*** 283,288 ****
--- 354,365 ----
{ {
xsetenv ("HOME", pw->pw_dir); xsetenv ("HOME", pw->pw_dir);
xsetenv ("SHELL", shell); xsetenv ("SHELL", shell);
@ -473,11 +822,13 @@
if (pw->pw_uid) if (pw->pw_uid)
{ {
xsetenv ("USER", pw->pw_name); xsetenv ("USER", pw->pw_name);
@@ -303,12 +380,35 @@ ***************
*** 303,314 ****
--- 380,414 ----
error (EXIT_FAIL, errno, _("cannot set groups")); error (EXIT_FAIL, errno, _("cannot set groups"));
endgrent (); endgrent ();
#endif #endif
+#ifdef USE_PAM + #ifdef USE_PAM
+ retval = pam_setcred (pamh, PAM_ESTABLISH_CRED); + retval = pam_setcred (pamh, PAM_ESTABLISH_CRED);
+ if (retval != PAM_SUCCESS) + if (retval != PAM_SUCCESS)
+ error (EXIT_FAIL, 0, "%s", pam_strerror (pamh, retval)); + error (EXIT_FAIL, 0, "%s", pam_strerror (pamh, retval));
@ -489,31 +840,33 @@
+ error (EXIT_FAIL, 0, "could not open session: %s", + error (EXIT_FAIL, 0, "could not open session: %s",
+ pam_strerror (pamh, retval)); + pam_strerror (pamh, retval));
+ } + }
+#endif /* USE_PAM */ + #endif /* USE_PAM */
if (setgid (pw->pw_gid)) if (setgid (pw->pw_gid))
error (EXIT_FAIL, errno, _("cannot set group id")); error (EXIT_FAIL, errno, _("cannot set group id"));
if (setuid (pw->pw_uid)) if (setuid (pw->pw_uid))
error (EXIT_FAIL, errno, _("cannot set user id")); error (EXIT_FAIL, errno, _("cannot set user id"));
} }
+#ifdef USE_PAM + #ifdef USE_PAM
+static bool caught = false; + static bool caught = false;
+/* Signal handler for parent process later */ + /* Signal handler for parent process later */
+static void + static void
+su_catch_sig (int sig) + su_catch_sig (int sig)
+{ + {
+ caught = true; + caught = true;
+} + }
+#endif + #endif
+ +
/* Run SHELL, or DEFAULT_SHELL if SHELL is empty. /* Run SHELL, or DEFAULT_SHELL if SHELL is empty.
If COMMAND is nonzero, pass it to the shell with the -c option. If COMMAND is nonzero, pass it to the shell with the -c option.
Pass ADDITIONAL_ARGS to the shell as more arguments; there Pass ADDITIONAL_ARGS to the shell as more arguments; there
@@ -321,6 +421,88 @@ ***************
*** 321,326 ****
--- 421,523 ----
size_t n_args = 1 + fast_startup + 2 * !!command + n_additional_args + 1; size_t n_args = 1 + fast_startup + 2 * !!command + n_additional_args + 1;
char const **args = xnmalloc (n_args, sizeof *args); char const **args = xnmalloc (n_args, sizeof *args);
size_t argno = 1; size_t argno = 1;
+#ifdef USE_PAM + #ifdef USE_PAM
+ pid_t child; + pid_t child;
+ sigset_t ourset; + sigset_t ourset;
+ int status; + int status;
@ -593,12 +946,29 @@
+ } + }
+ +
+ /* child shell */ + /* 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); + pam_end (pamh, 0);
+#endif + #endif
if (simulate_login) if (simulate_login)
{ {
@@ -339,6 +521,11 @@ ***************
*** 339,344 ****
--- 536,546 ----
args[argno++] = "-f"; args[argno++] = "-f";
if (command) if (command)
{ {
@ -610,13 +980,39 @@
args[argno++] = "-c"; args[argno++] = "-c";
args[argno++] = command; args[argno++] = command;
} }
@@ -495,6 +682,9 @@ ***************
*** 495,500 ****
--- 697,705 ----
#ifdef SYSLOG_FAILURE #ifdef SYSLOG_FAILURE
log_su (pw, false); log_su (pw, false);
#endif #endif
+#ifdef USE_PAM + #ifdef USE_PAM
+ sleep (getdef_num ("FAIL_DELAY", 1)); + sleep (getdef_num ("FAIL_DELAY", 1));
+#endif + #endif
error (EXIT_FAIL, 0, _("incorrect password")); error (EXIT_FAIL, 0, _("incorrect password"));
} }
#ifdef SYSLOG_SUCCESS #ifdef SYSLOG_SUCCESS
***************
*** 516,524 ****
shell = NULL;
}
shell = xstrdup (shell ? shell : pw->pw_shell);
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);
--- 721,732 ----
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);
if (simulate_login && chdir (pw->pw_dir) != 0)
error (0, errno, _("warning: cannot change directory to %s"), pw->pw_dir);