diff --git a/pkgs/tools/misc/su/default.nix b/pkgs/tools/misc/su/default.nix deleted file mode 100644 index ad7dddbde97..00000000000 --- a/pkgs/tools/misc/su/default.nix +++ /dev/null @@ -1,32 +0,0 @@ -{stdenv, fetchurl, pam}: - -# This is just coreutils, except that we only build su, with the PAM -# patch. We build su separately because we don't want to give all of -# coreutils a dependency on PAM. - -stdenv.mkDerivation { - name = "su-7.0"; - - src = fetchurl { - url = "ftp://alpha.gnu.org/gnu/coreutils/coreutils-7.0.tar.gz"; - sha256 = "00cwf8rqbj89ikv8fhdhv26dpc2ghzw1hn48pk1vg3nnmxj55nr7"; - }; - - patches = [ - # PAM patch taken from SUSE's coreutils-6.7-5.src.rpm. - ./su-pam.patch - ]; - - buildInputs = [pam]; - - buildPhase = '' - make -C lib - make -C src version.h - make -C src su su_OBJECTS="su.o getdef.o" CFLAGS="-DUSE_PAM" LDFLAGS="-lpam -lpam_misc -ldl" - ''; - - installPhase = '' - ensureDir $out/bin - cp src/su $out/bin - ''; -} diff --git a/pkgs/tools/misc/su/su-pam.patch b/pkgs/tools/misc/su/su-pam.patch deleted file mode 100644 index 5962d285ebc..00000000000 --- a/pkgs/tools/misc/su/su-pam.patch +++ /dev/null @@ -1,720 +0,0 @@ -diff -rcN coreutils-7.0-orig/src/getdef.c coreutils-7.0/src/getdef.c -*** coreutils-7.0-orig/src/getdef.c 1970-01-01 01:00:00.000000000 +0100 ---- coreutils-7.0/src/getdef.c 2009-02-02 15:28:08.000000000 +0100 -*************** -*** 0 **** ---- 1,257 ---- -+ /* Copyright (C) 2003, 2004, 2005 Thorsten Kukuk -+ Author: Thorsten Kukuk -+ -+ 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 -+ #endif -+ -+ #define _GNU_SOURCE -+ -+ #include -+ #include -+ #include -+ #include -+ #include -+ #include -+ -+ #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-7.0-orig/src/getdef.h coreutils-7.0/src/getdef.h -*** coreutils-7.0-orig/src/getdef.h 1970-01-01 01:00:00.000000000 +0100 ---- coreutils-7.0/src/getdef.h 2009-02-02 15:28:08.000000000 +0100 -*************** -*** 0 **** ---- 1,29 ---- -+ /* Copyright (C) 2003, 2005 Thorsten Kukuk -+ Author: Thorsten Kukuk -+ -+ 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-7.0-orig/src/su.c coreutils-7.0/src/su.c -*** coreutils-7.0-orig/src/su.c 2008-08-24 22:30:10.000000000 +0200 ---- coreutils-7.0/src/su.c 2009-02-02 15:31:08.000000000 +0100 -*************** -*** 37,42 **** ---- 37,48 ---- - 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. -*************** -*** 52,57 **** ---- 58,70 ---- - #include - #include - #include -+ #ifdef USE_PAM -+ #include -+ #include -+ #include -+ #include -+ #include -+ #endif - - /* Hide any system prototype for getusershell. - This is necessary because some Cray systems have a conflicting -*************** -*** 65,70 **** ---- 78,86 ---- - - #if HAVE_SYSLOG_H && HAVE_SYSLOG - # include -+ # define SYSLOG_SUCCESS 1 -+ # define SYSLOG_FAILURE 1 -+ # define SYSLOG_NON_ROOT 1 - #else - # undef SYSLOG_SUCCESS - # undef SYSLOG_FAILURE -*************** -*** 98,116 **** - # include - #endif - - /* 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 - - /* 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 - - /* The shell to run if none is given in the user's passwd entry. */ - #define DEFAULT_SHELL "/bin/sh" ---- 114,126 ---- - # include - #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" -*************** -*** 118,124 **** ---- 128,136 ---- - /* The user to become if none is specified. */ - #define DEFAULT_USER "root" - -+ #ifndef USE_PAM - char *crypt (); -+ #endif - char *getusershell (); - void endusershell (); - void setusershell (); -*************** -*** 212,218 **** ---- 224,249 ---- - } - #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. */ -*************** -*** 220,229 **** - static bool - correct_password (const struct passwd *pw) - { - 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) ---- 251,299 ---- - 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. */ -! const struct spwd *sp = getspnam (pw->pw_name); - - endspent (); - if (sp) -*************** -*** 244,249 **** ---- 314,320 ---- - 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 -*************** -*** 268,275 **** - xsetenv ("USER", pw->pw_name); - xsetenv ("LOGNAME", pw->pw_name); - xsetenv ("PATH", (pw->pw_uid -! ? DEFAULT_LOGIN_PATH -! : DEFAULT_ROOT_LOGIN_PATH)); - } - else - { ---- 339,346 ---- - 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 - { -*************** -*** 279,284 **** ---- 350,361 ---- - { - 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); -*************** -*** 299,310 **** ---- 376,410 ---- - 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)); -+ -+ retval = pam_open_session (pamh,0); -+ if (retval != PAM_SUCCESS) -+ { -+ pam_setcred (pamh, PAM_DELETE_CRED); -+ error (EXIT_FAILURE, 0, "could not open session: %s", -+ pam_strerror (pamh, retval)); -+ } -+ #endif /* USE_PAM */ - if (setgid (pw->pw_gid)) - error (EXIT_FAILURE, errno, _("cannot set group id")); - if (setuid (pw->pw_uid)) - error (EXIT_FAILURE, 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 -*************** -*** 317,322 **** ---- 417,519 ---- - 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 */ -+ -+ /* 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 - - if (simulate_login) - { -*************** -*** 335,340 **** ---- 532,542 ---- - 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; - } -*************** -*** 491,496 **** ---- 693,701 ---- - #ifdef SYSLOG_FAILURE - log_su (pw, false); - #endif -+ #ifdef USE_PAM -+ sleep (getdef_num ("FAIL_DELAY", 1)); -+ #endif - error (EXIT_FAILURE, 0, _("incorrect password")); - } - #ifdef SYSLOG_SUCCESS -*************** -*** 512,520 **** - 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); - ---- 717,728 ---- - 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); - diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 080e290a302..453e07742b2 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -1670,9 +1670,7 @@ let inherit fetchurl stdenv openssl; }; - su = import ../tools/misc/su { - inherit fetchurl stdenv pam; - }; + su = shadow; swec = import ../tools/networking/swec { inherit fetchurl stdenv makeWrapper perl;