[Pkg-shadow-commits] r401 - branches/experimental/debian/patches

Nicolas FRANCOIS nekral-guest at costa.debian.org
Sun Jul 24 20:40:09 UTC 2005


Author: nekral-guest
Date: 2005-07-24 20:40:09 +0000 (Sun, 24 Jul 2005)
New Revision: 401

Added:
   branches/experimental/debian/patches/437_su_add_GNU_options_1
   branches/experimental/debian/patches/437_su_add_GNU_options_2
   branches/experimental/debian/patches/437_su_add_GNU_options_3
   branches/experimental/debian/patches/437_su_add_GNU_options_4
   branches/experimental/debian/patches/437_su_add_GNU_options_5
   branches/experimental/debian/patches/437_su_add_GNU_options_6
Removed:
   branches/experimental/debian/patches/437_su_add_GNU_options
Log:
Update the 437_su_add_GNU_options patch.
It was easier for me to split it. The split is not always logical.
But if we are not happy with it, it is simple to make a big patch from
this one.


Deleted: branches/experimental/debian/patches/437_su_add_GNU_options
===================================================================
--- branches/experimental/debian/patches/437_su_add_GNU_options	2005-07-24 20:30:34 UTC (rev 400)
+++ branches/experimental/debian/patches/437_su_add_GNU_options	2005-07-24 20:40:09 UTC (rev 401)
@@ -1,376 +0,0 @@
-Goal: add -m, -p and -s command line options to match GNU options
-Fixes: #45394, #46424
-
-Status wrt upstream: Upstream does not support these options.
-
-Note: As the patch is quite big, and it probably cannot be splitted in
-      smaller parts, I will try to describe the diffs:
-
- * switch to getopt to add the -m, -p and -s options
- * by default (if no -m or -p is provided), the environment is changed
-   (change_environment=1)
- * the user can specify the shell, if he does not have a restricted shell
- * some functions were borrowed to GNU shell-utils' su
-   (this is also the case of current upstream, even if those functions
-   drastically evoled separately in Debian and upstream (run_shell))
-   In debian, more work is performed in run_shell, because all options are
-   parsed earlier with getopt.
- * There is an "usage"
- * if the user don't whant to change the environment (-m or -p options),
-   SHELL is used for the new shell (except if this user has a restricted
-   shell, in this case, she keep her restricted shell).
-   Also, even when the environment is not changed, IFS is reset to the
-   default \t\n value.
-
-Index: shadow-4.0.3/src/su.c
-===================================================================
---- shadow-4.0.3.orig/src/su.c	2005-05-30 23:13:57.716974000 +0200
-+++ shadow-4.0.3/src/su.c	2005-05-30 23:17:27.126974000 +0200
-@@ -49,6 +49,7 @@
- #include <grp.h>
- #include <signal.h>
- #include <pwd.h>
-+#include <getopt.h>
- #include "pwauth.h"
- #include "getdef.h"
- 
-@@ -79,6 +80,18 @@
- 
- /* local function prototypes */
- 
-+/* If nonzero, change some environment vars to indicate the user su'd to.  */
-+static int change_environment;
-+
-+static struct option const longopts[] =
-+{
-+  {"command", required_argument, 0, 'c'},
-+  {"preserve-environment", no_argument, 0, 'p'},
-+  {"shell", required_argument, 0, 's'},
-+  {"help", no_argument, 0, 'h'},
-+  {0, 0, 0, 0}
-+};
-+
- #ifndef USE_PAM
- 
- static RETSIGTYPE die (int);
-@@ -118,6 +131,96 @@
- }
- #endif				/* !USE_PAM */
- 
-+/* borrowed from GNU sh-utils' "su.c" */
-+static int
-+restricted_shell (const char *shell)
-+{
-+       char *line;
-+
-+       setusershell ();
-+       while ((line = getusershell ()) != NULL) {
-+               if (*line != '#' && strcmp (line, shell) == 0) {
-+                       endusershell ();
-+                       return 0;
-+               }
-+       }
-+       endusershell ();
-+       return 1;
-+}
-+
-+/* borrowed from GNU sh-utils' "su.c" */
-+static int
-+elements (char **arr)
-+{
-+  int n = 0;
-+
-+  for (n = 0; *arr; ++arr)
-+    ++n;
-+  return n;
-+}
-+
-+/* borrowed from GNU sh-utils' "su.c" */
-+static void
-+run_shell (char *shell, const char *command, char **additional_args, int login)
-+{
-+  const char **args;
-+  int argno = 1;
-+  char cmd[BUFSIZ];
-+  int cmd_len_left = sizeof(cmd) - 1;
-+
-+  cmd[0] = '\0';
-+
-+  if (additional_args)
-+    args = (const char **) xmalloc (sizeof (char *)
-+                                    * (10 + elements (additional_args)));
-+  else
-+    args = (const char **) xmalloc (sizeof (char *) * 10);
-+
-+  if (login)
-+    {
-+      char *arg0;
-+      char *shell_basename;
-+
-+      shell_basename = getdef_str("SU_NAME");
-+      if (!shell_basename)
-+       shell_basename = Basename(shell);
-+
-+      arg0 = xmalloc (strlen (shell_basename) + 2);
-+      arg0[0] = '-';
-+      strcpy (arg0 + 1, shell_basename);
-+      args[0] = arg0;
-+    }
-+  else
-+    args[0] = Basename(shell);
-+  if (command || additional_args)
-+    args[argno++] = "-c";
-+  if (command) {
-+    if (strlen(command) > cmd_len_left) {
-+      fprintf(stderr, _("Command line args too long\n"));
-+      exit(1);
-+    }
-+    strcat(cmd, command);
-+    cmd_len_left -= strlen(command);
-+  }
-+  if (additional_args)
-+    for (; *additional_args; ++additional_args) {
-+      if ((strlen(*additional_args) + 1) > cmd_len_left) {
-+	fprintf(stderr, _("Command line args too long\n"));
-+	exit(1);
-+      }
-+      if (cmd[0]) {
-+	strcat(cmd, " ");
-+	cmd_len_left--;
-+      }
-+      strcat(cmd, *additional_args);
-+      cmd_len_left -= strlen(*additional_args);
-+    }
-+  if (cmd[0]) args[argno++] = cmd;
-+  args[argno] = NULL;
-+  execv (shell, (char **) args);
-+  fprintf (stderr, _("No shell\n"));
-+  SYSLOG((LOG_WARN, "Cannot execute %s\n", shell));
-+}
- 
- static void su_failure (const char *tty)
- {
-@@ -153,13 +256,14 @@
- {
- 	char *cp;
- 	const char *tty = 0;	/* Name of tty SU is run from        */
--	int doshell = 0;
- 	int fakelogin = 0;
- 	int amroot = 0;
- 	uid_t my_uid;
- 	struct passwd *pw = 0;
- 	char **envp = environ;
--
-+	char *command = 0, *shell = 0, **additional_args = 0;
-+	int optc;
-+	char *tmp_name;
- #ifdef USE_PAM
- 	int ret;
- #else				/* !USE_PAM */
-@@ -180,6 +284,8 @@
- 	bindtextdomain (PACKAGE, LOCALEDIR);
- 	textdomain (PACKAGE);
- 
-+	change_environment = 1;
-+
- 	/*
- 	 * Get the program name. The program name is used as a prefix to
- 	 * most error messages.
-@@ -224,15 +330,55 @@
- 	 * Process the command line arguments. 
- 	 */
- 
--	argc--;
--	argv++;			/* shift out command name */
--
--	if (argc > 0 && strcmp (argv[0], "-") == 0) {
-+	while ((optc = getopt_long (argc, argv, "c:mps:h", longopts, NULL)) != -1) {
-+		switch (optc) {
-+		    case 0:
-+			break;
-+		    case 'c':
-+			command = optarg;
-+			break;
-+		    case 'm':
-+		    case 'p':
-+			change_environment = 0;
-+			break;
-+		    case 's':
-+			shell = optarg;
-+			break;
-+		    default:
-+			fprintf(stderr, _("\
-+Usage: su [OPTS] [-] [username [ARGS]]\n\
-+	-	make this a login shell\n\
-+	-c, --command=<command>\n\
-+		pass command to the invoked shell using its -c\n\
-+		option\n\
-+       -m, -p, --preserve-environment\n\
-+		do not reset environment variables, and keep the\n\
-+		same shell\n\
-+       -s, --shell=<shell>\n\
-+		use shell instead of the default in /etc/passwd\n"));
-+			exit(1);
-+		}
-+	}
-+	
-+        if (optind < argc && !strcmp (argv[optind], "-")) {
- 		fakelogin = 1;
--		argc--;
--		argv++;		/* shift ... */
-+		++optind;
- 	}
- 
-+	if (optind < argc)
-+		strncpy(name, argv[optind++], sizeof(name) - 1);
-+	else {
-+	        struct passwd *root_pw = getpwuid(0);
-+		if (root_pw == NULL) {
-+		  SYSLOG((LOG_CRIT, "There is no UID 0 user."));
-+		  su_failure(tty);
-+		}
-+                strcpy(name, root_pw->pw_name);
-+	}
-+
-+	if (optind < argc)
-+		additional_args = argv + optind;
-+
- 	/*
- 	 * If a new login is being set up, the old environment will be
- 	 * ignored and a new one created later on.
-@@ -258,30 +404,6 @@
- 	}
- 
- 	/*
--	 * The next argument must be either a user ID, or some flag to a
--	 * subshell. Pretty sticky since you can't have an argument which
--	 * doesn't start with a "-" unless you specify the new user name.
--	 * Any remaining arguments will be passed to the user's login shell.
--	 */
--
--	if (argc > 0 && argv[0][0] != '-') {
--		STRFCPY (name, argv[0]);	/* use this login id */
--		argc--;
--		argv++;		/* shift ... */
--	}
--	if (!name[0])		/* use default user ID */
--	{
--		struct passwd *root_pw = getpwuid(0);
--		if (root_pw == NULL) {
--			SYSLOG((LOG_CRIT, "There is no UID 0 user."));
--			su_failure(tty)
--		}
--		strcpy(name, root_pw->pw_name);
--	}
--
--	doshell = argc == 0;	/* any arguments remaining? */
--
--	/*
- 	 * Get the user's real name. The current UID is used to determine
- 	 * who has executed su. That user ID must exist.
- 	 */
-@@ -406,8 +528,15 @@
- 	 * Set the default shell.
- 	 */
- 
--	if (pwent.pw_shell[0] == '\0')
--		pwent.pw_shell = "/bin/sh";	/* XXX warning: const */
-+	if (pwent.pw_shell == NULL || pwent.pw_shell[0] == '\0')
-+		pwent.pw_shell = (char *) "/bin/sh";
-+
-+	if (shell == 0 && change_environment == 0)
-+		shell = getenv ("SHELL");
-+	if (shell != 0 && getuid () && restricted_shell (pwent.pw_shell))
-+		shell = 0;
-+	if (shell == 0)
-+		shell = (char *) strdup (pwent.pw_shell);
- 
- #ifdef USE_PAM
- 	ret = pam_authenticate (pamh, 0);
-@@ -514,10 +643,14 @@
- 	}
- #endif
- 
--	environ = newenvp;	/* make new environment active */
--
--	if (getenv ("IFS"))	/* don't export user IFS ... */
--		addenv ("IFS= \t\n", NULL);	/* ... instead, set a safe IFS */
-+	if (change_environment || restricted_shell(pwent.pw_shell)) {
-+		environ = newenvp;			/* make new environment active */
-+		if (getenv ("IFS"))			/* don't export user IFS ... */
-+			addenv("IFS= \t\n", NULL);	/* ... instead, set a safe IFS */
-+	} else {
-+		if (getenv ("IFS"))
-+			putenv("IFS= \t\n");
-+	}
- 
- 	if (pwent.pw_shell[0] == '*') {	/* subsystem root required */
- 		pwent.pw_shell++;	/* skip the '*' */
-@@ -580,13 +713,13 @@
- 		exit (1);
- #endif				/* !USE_PAM */
- 
--	if (fakelogin)
--		setup_env (&pwent);
-+	if (fakelogin && (change_environment || restricted_shell(pwent.pw_shell)))
-+		setup_env(&pwent);
- #if 1				/* Suggested by Joey Hess. XXX - is this right?  */
--	else {
--		addenv ("HOME", pwent.pw_dir);
--		addenv ("USER", pwent.pw_name);
--		addenv ("SHELL", pwent.pw_shell);
-+	else if (change_environment || restricted_shell(pwent.pw_shell)) {
-+		addenv("HOME", pwent.pw_dir);
-+		addenv("USER", pwent.pw_name);
-+		addenv("SHELL", shell);
- 	}
- #endif
- 
-@@ -599,46 +732,6 @@
- 	 */
- 	closelog ();
- 
--	/*
--	 * See if the user has extra arguments on the command line. In that
--	 * case they will be provided to the new user's shell as arguments.
--	 */
--
--	if (fakelogin) {
--		char *arg0;
--
--#if 0				/* XXX - GNU su doesn't do this.  --marekm */
--		if (!hushed (&pwent)) {
--			motd ();
--			mailcheck ();
--		}
--#endif
--		cp = getdef_str ("SU_NAME");
--		if (!cp)
--			cp = Basename (pwent.pw_shell);
--
--		arg0 = xmalloc (strlen (cp) + 2);
--		arg0[0] = '-';
--		strcpy (arg0 + 1, cp);
--		cp = arg0;
--	} else
--		cp = Basename (pwent.pw_shell);
--
--	if (!doshell) {
--
--		/*
--		 * Use new user's shell from /etc/passwd and create an argv
--		 * with the rest of the command line included.
--		 */
--
--		argv[-1] = pwent.pw_shell;
--		(void) execv (pwent.pw_shell, &argv[-1]);
--		(void) fprintf (stderr, _("No shell\n"));
--		SYSLOG ((LOG_WARN, "Cannot execute %s", pwent.pw_shell));
--		closelog ();
--		exit (1);
--	}
--
--	shell (pwent.pw_shell, cp);
-+	run_shell (shell, command, additional_args, fakelogin);
- 	 /*NOTREACHED*/ exit (1);
- }

Added: branches/experimental/debian/patches/437_su_add_GNU_options_1
===================================================================
--- branches/experimental/debian/patches/437_su_add_GNU_options_1	2005-07-24 20:30:34 UTC (rev 400)
+++ branches/experimental/debian/patches/437_su_add_GNU_options_1	2005-07-24 20:40:09 UTC (rev 401)
@@ -0,0 +1,182 @@
+Goal: First patch to switch to getopt.
+      Still incomplete.
+      Done:
+       * selection of the shell (-s).
+      Broken:
+       * additional_args is set, but not used.
+       * !doshell is broken (argv is not incremented)
+Index: shadow-4.0.10/src/su.c
+===================================================================
+--- shadow-4.0.10.orig/src/su.c	2005-07-19 23:12:26.000000000 +0200
++++ shadow-4.0.10/src/su.c	2005-07-19 23:43:57.000000000 +0200
+@@ -49,6 +49,7 @@
+ #include <grp.h>
+ #include <signal.h>
+ #include <pwd.h>
++#include <getopt.h>
+ #include "pwauth.h"
+ #include "getdef.h"
+ 
+@@ -79,6 +80,18 @@
+ 
+ /* local function prototypes */
+ 
++/* If nonzero, change some environment vars to indicate the user su'd to.  */
++static int change_environment;
++
++static struct option const longopts[] =
++{
++  {"command", required_argument, 0, 'c'},
++  {"preserve-environment", no_argument, 0, 'p'},
++  {"shell", required_argument, 0, 's'},
++  {"help", no_argument, 0, 'h'},
++  {0, 0, 0, 0}
++};
++
+ #ifndef USE_PAM
+ 
+ static RETSIGTYPE die (int);
+@@ -263,6 +276,8 @@
+ 	uid_t my_uid;
+ 	struct passwd *pw = 0;
+ 	char **envp = environ;
++	char *command = 0, *shell = 0, **additional_args = 0;
++	int optc;
+ 
+ #ifdef USE_PAM
+ 	int ret;
+@@ -283,6 +298,8 @@
+ 	bindtextdomain (PACKAGE, LOCALEDIR);
+ 	textdomain (PACKAGE);
+ 
++	change_environment = 1;
++
+ 	/*
+ 	 * Get the program name. The program name is used as a prefix to
+ 	 * most error messages.
+@@ -326,15 +343,56 @@
+ 	 * Process the command line arguments. 
+ 	 */
+ 
+-	argc--;
+-	argv++;			/* shift out command name */
++	while ((optc = getopt_long (argc, argv, "c:mps:h", longopts, NULL)) != -1) {
++		switch (optc) {
++		    case 0:
++			break;
++		    case 'c':
++			command = optarg;
++			break;
++		    case 'm':
++		    case 'p':
++			change_environment = 0;
++			break;
++		    case 's':
++			shell = optarg;
++			break;
++		    default:
++			fprintf(stderr, _("\
++Usage: su [OPTS] [-] [username [ARGS]]\n\
++	-	make this a login shell\n\
++	-c, --command=<command>\n\
++		pass command to the invoked shell using its -c\n\
++		option\n\
++	-m, -p, --preserve-environment\n\
++		do not reset environment variables, and keep the\n\
++		same shell\n\
++	-s, --shell=<shell>\n\
++		use shell instead of the default in /etc/passwd\n"));
++			exit(1);
++		}
++	}
+ 
+-	if (argc > 0 && strcmp (argv[0], "-") == 0) {
++	if (optind < argc && !strcmp (argv[optind], "-")) {
+ 		fakelogin = 1;
+-		argc--;
+-		argv++;		/* shift ... */
++		++optind;
++	}
++
++	if (optind < argc)
++		strncpy(name, argv[optind++], sizeof(name) - 1);
++	else {
++		struct passwd *root_pw = getpwuid(0);
++		if (root_pw == NULL) {
++			SYSLOG((LOG_CRIT, "There is no UID 0 user."));
++			su_failure(tty);
++		}
++		strcpy(name, root_pw->pw_name);
+ 	}
+ 
++	if (optind < argc)
++		additional_args = argv + optind;
++
++
+ 	/*
+ 	 * If a new login is being set up, the old environment will be
+ 	 * ignored and a new one created later on.
+@@ -369,29 +427,7 @@
+ 			addenv (*envp++, NULL);
+ 	}
+ 
+-	/*
+-	 * The next argument must be either a user ID, or some flag to a
+-	 * subshell. Pretty sticky since you can't have an argument which
+-	 * doesn't start with a "-" unless you specify the new user name.
+-	 * Any remaining arguments will be passed to the user's login shell.
+-	 */
+-
+-	if (argc > 0 && argv[0][0] != '-') {
+-		STRFCPY (name, argv[0]);	/* use this login id */
+-		argc--;
+-		argv++;		/* shift ... */
+-	}
+-	if (!name[0])		/* use default user ID */
+-	{
+-		struct passwd *root_pw = getpwuid(0);
+-		if (root_pw == NULL) {
+-			SYSLOG((LOG_CRIT, "There is no UID 0 user."));
+-			su_failure(tty);
+-		}
+-		strcpy(name, root_pw->pw_name);
+-	}
+-
+-	doshell = argc == 0;	/* any arguments remaining? */
++	doshell = optind == argc;	/* any arguments remaining? */
+ 
+ 	/*
+ 	 * Get the user's real name. The current UID is used to determine
+@@ -513,6 +549,23 @@
+ 	if (pwent.pw_shell[0] == '\0')
+ 		pwent.pw_shell = "/bin/sh";	/* XXX warning: const */
+ 
++	/* If the user do not want to change the environment,
++	 * use the current SHELL.
++	 * (unless another shell is required by the command line)
++	 */
++	if (shell == 0 && change_environment == 0)
++		shell = getenv ("SHELL");
++	/* For users whith non null UID, if this user has a restricted
++	 * shell, the shell must be the one specified in /etc/passwd
++	 */
++	if (shell != 0 && getuid () && restricted_shell (pwent.pw_shell))
++		shell = 0;
++	/* If the shell is not set at this time, use the shell specified
++	 * in /etc/passwd.
++	 */
++	if (shell == 0)
++		shell = (char *) strdup (pwent.pw_shell);
++
+ #ifdef USE_PAM
+ 	ret = pam_authenticate (pamh, 0);
+ 	if (ret != PAM_SUCCESS) {
+@@ -692,7 +745,7 @@
+ 	else {
+ 		addenv ("HOME", pwent.pw_dir);
+ 		addenv ("USER", pwent.pw_name);
+-		addenv ("SHELL", pwent.pw_shell);
++		addenv ("SHELL", shell);
+ 	}
+ #endif
+ 

Added: branches/experimental/debian/patches/437_su_add_GNU_options_2
===================================================================
--- branches/experimental/debian/patches/437_su_add_GNU_options_2	2005-07-24 20:30:34 UTC (rev 400)
+++ branches/experimental/debian/patches/437_su_add_GNU_options_2	2005-07-24 20:40:09 UTC (rev 401)
@@ -0,0 +1,196 @@
+Goal: 
+     * need restricted_shell() for --preserve-environment
+     * run_shell has to be available when !USE_PAM
+     * for -c, we need to add arguments. It is safer to allocate a new
+       array than using argv. We need the elements() function to compute the
+       number of additional arguments.
+     * arg0 is computed in run_shell.
+     * There is no more need for doshell. We know that we only need to
+       execute a shell when there is no additional arguments.
+Index: shadow-4.0.10/src/su.c
+===================================================================
+--- shadow-4.0.10.orig/src/su.c	2005-07-22 19:32:04.000000000 +0200
++++ shadow-4.0.10/src/su.c	2005-07-22 19:35:30.000000000 +0200
+@@ -131,6 +131,24 @@
+ }
+ #endif				/* !USE_PAM */
+ 
++/* borrowed from GNU sh-utils' "su.c" */
++static int
++restricted_shell (const char *shell)
++{
++	char *line;
++
++	setusershell ();
++	while ((line = getusershell ()) != NULL) {
++		if (*line != '#' && strcmp (line, shell) == 0) {
++			endusershell ();
++			return 0;
++		}
++	}
++	endusershell ();
++	return 1;
++}
++
++
+ 
+ static void su_failure (const char *tty)
+ {
+@@ -154,23 +172,70 @@
+ {
+ 	++caught;
+ }
++#endif
++
++/* borrowed from GNU sh-utils' "su.c" */
++static int elements (char **arr)
++{
++	int n = 0;
++	if (arr)
++		for (n = 0; *arr; ++arr)
++			++n;
++
++	return n;
++}
+ 
+ /* This I ripped out of su.c from sh-utils after the Mandrake pam patch
+  * have been applied.  Some work was needed to get it integrated into
+  * su.c from shadow.
+  */
+-static void run_shell (const char *shellstr, char *args[], int doshell)
++static void run_shell (const char *shellstr, char **additional_args, int fakelogin)
+ {
++	const char **args;
+ 	int child;
+ 	sigset_t ourset;
+ 	int status;
+ 	int ret;
++	int argno = 0;
++
++	args = (const char **)xmalloc(sizeof (char *)
++	                              * (2 + elements (additional_args)));
+ 
++	if (fakelogin) {
++		char *arg0;
++		char *shell_basename;
++
++		shell_basename = getdef_str ("SU_NAME");
++		if (!shell_basename)
++			shell_basename = Basename (shellstr);
++
++		arg0 = xmalloc (strlen (shell_basename) + 2);
++		arg0[0] = '-';
++		strcpy (arg0 + 1, shell_basename);
++		args[0] = arg0;
++	} else
++		args[0] = Basename (shellstr);
++	argno = 1;
++
++	if (additional_args) {
++		for (; *additional_args; ++additional_args) {
++			args[argno++] = *additional_args;
++		}
++	}
++	args[argno] = NULL;
++
++#ifndef USE_PAM
++	if (argno > 1)
++		(void) execv (shellstr, args);
++	else
++		shell (shellstr, args[0]);
++	/* NOT REACHED */
++#else
+ 	child = fork ();
+ 	if (child == 0) {	/* child shell */
+ 		pam_end (pamh, PAM_SUCCESS);
+ 
+-		if (doshell)
++		if (argno == 1)
+ 			shell (shellstr, (char *) args[0]);
+ 		else
+ 			(void) execv (shellstr, (char **) args);
+@@ -248,8 +313,8 @@
+ 	}
+ 
+ 	exit (WEXITSTATUS (status));
++#endif	/* USE_PAM */
+ }
+-#endif
+ 
+ /*
+  * su - switch user id
+@@ -270,7 +335,6 @@
+ 	char *cp;
+ 	char **envcp;
+ 	const char *tty = 0;	/* Name of tty SU is run from        */
+-	int doshell = 0;
+ 	int fakelogin = 0;
+ 	int amroot = 0;
+ 	uid_t my_uid;
+@@ -392,7 +456,6 @@
+ 	if (optind < argc)
+ 		additional_args = argv + optind;
+ 
+-
+ 	/*
+ 	 * If a new login is being set up, the old environment will be
+ 	 * ignored and a new one created later on.
+@@ -427,8 +490,6 @@
+ 			addenv (*envp++, NULL);
+ 	}
+ 
+-	doshell = optind == argc;	/* any arguments remaining? */
+-
+ 	/*
+ 	 * Get the user's real name. The current UID is used to determine
+ 	 * who has executed su. That user ID must exist.
+@@ -758,48 +819,7 @@
+ 	 */
+ 	closelog ();
+ 
+-	/*
+-	 * See if the user has extra arguments on the command line. In that
+-	 * case they will be provided to the new user's shell as arguments.
+-	 */
+-
+-	if (fakelogin) {
+-		char *arg0;
+-
+-		cp = getdef_str ("SU_NAME");
+-		if (!cp)
+-			cp = Basename (pwent.pw_shell);
+-
+-		arg0 = xmalloc (strlen (cp) + 2);
+-		arg0[0] = '-';
+-		strcpy (arg0 + 1, cp);
+-		cp = arg0;
+-	} else
+-		cp = Basename (pwent.pw_shell);
+-
+-	if (!doshell) {
+-
+-		/*
+-		 * Use new user's shell from /etc/passwd and create an argv
+-		 * with the rest of the command line included.
+-		 */
+-
+-		argv[-1] = pwent.pw_shell;
+-#ifndef USE_PAM
+-		(void) execv (pwent.pw_shell, &argv[-1]);
+-#else
+-		run_shell (pwent.pw_shell, &argv[-1], 0);
+-#endif
+-		(void) fprintf (stderr, _("No shell\n"));
+-		SYSLOG ((LOG_WARN, "Cannot execute %s", pwent.pw_shell));
+-		closelog ();
+-		exit (1);
+-	}
+-#ifndef USE_PAM
+-	shell (pwent.pw_shell, cp);
+-#else
+-	run_shell (pwent.pw_shell, &cp, 1);
+-#endif
++	run_shell (shell, additional_args, fakelogin);
+ 	/* NOT REACHED */
+ 	exit (1);
+ }

Added: branches/experimental/debian/patches/437_su_add_GNU_options_3
===================================================================
--- branches/experimental/debian/patches/437_su_add_GNU_options_3	2005-07-24 20:30:34 UTC (rev 400)
+++ branches/experimental/debian/patches/437_su_add_GNU_options_3	2005-07-24 20:40:09 UTC (rev 401)
@@ -0,0 +1,128 @@
+Goal:
+     * add -c ability to run_shell.
+     * only change environment if the user did not requested to preserve
+       the environment, or if the user has a restricted shell.
+Index: shadow-4.0.10/src/su.c
+===================================================================
+--- shadow-4.0.10.orig/src/su.c	2005-07-22 18:48:13.000000000 +0200
++++ shadow-4.0.10/src/su.c	2005-07-22 18:49:13.000000000 +0200
+@@ -188,7 +188,10 @@
+  * have been applied.  Some work was needed to get it integrated into
+  * su.c from shadow.
+  */
+-static void run_shell (const char *shellstr, char **additional_args, int fakelogin)
++static void run_shell (const char *shellstr,
++                       const char *command,
++                       char **additional_args,
++                       int fakelogin)
+ {
+ 	const char **args;
+ 	int child;
+@@ -197,8 +200,10 @@
+ 	int ret;
+ 	int argno = 0;
+ 
++	/* There is at most 4 arguments (arg0, '-c', <command>, NULL) + the
++	 * number of arguments in the additional_args array. */
+ 	args = (const char **)xmalloc(sizeof (char *)
+-	                              * (2 + elements (additional_args)));
++	                              * (4 + elements (additional_args)));
+ 
+ 	if (fakelogin) {
+ 		char *arg0;
+@@ -216,11 +221,17 @@
+ 		args[0] = Basename (shellstr);
+ 	argno = 1;
+ 
++	if (command) {
++		args[argno++] = "-c";
++		args[argno++] = command;
++	}
++
+ 	if (additional_args) {
+ 		for (; *additional_args; ++additional_args) {
+ 			args[argno++] = *additional_args;
+ 		}
+ 	}
++
+ 	args[argno] = NULL;
+ 
+ #ifndef USE_PAM
+@@ -720,7 +731,9 @@
+ 
+ /* setup the environment for pam later on, else we run into auth problems */
+ #ifndef USE_PAM
+-	environ = newenvp;	/* make new environment active */
++	if (change_environment || restricted_shell(pwent.pw_shell)) {
++		environ = newenvp;	/* make new environment active */
++	}
+ #endif
+ 
+ 	if (getenv ("IFS"))	/* don't export user IFS ... */
+@@ -771,18 +784,20 @@
+ 		exit (1);
+ 	}
+ 
+-	/* we need to setup the environment *after* pam_open_session(),
+-	 * else the UID is changed before stuff like pam_xauth could
+-	 * run, and we cannot access /etc/shadow and co
+-	 */
+-	environ = newenvp;	/* make new environment active */
+-
+-	/* update environment with all pam set variables */
+-	envcp = pam_getenvlist (pamh);
+-	if (envcp) {
+-		while (*envcp) {
+-			addenv (*envcp, NULL);
+-			envcp++;
++	if (change_environment || restricted_shell(pwent.pw_shell)) {
++		/* we need to setup the environment *after* pam_open_session(),
++		 * else the UID is changed before stuff like pam_xauth could
++		 * run, and we cannot access /etc/shadow and co
++		 */
++		environ = newenvp;	/* make new environment active */
++
++		/* update environment with all pam set variables */
++		envcp = pam_getenvlist (pamh);
++		if (envcp) {
++			while (*envcp) {
++				addenv (*envcp, NULL);
++				envcp++;
++			}
+ 		}
+ 	}
+ 
+@@ -800,15 +815,17 @@
+ 		exit (1);
+ #endif				/* !USE_PAM */
+ 
+-	if (fakelogin)
+-		setup_env (&pwent);
++	if (change_environment || restricted_shell (pwent.pw_shell)) {
++		if (fakelogin )
++			setup_env (&pwent);
+ #if 1				/* Suggested by Joey Hess. XXX - is this right?  */
+-	else {
+-		addenv ("HOME", pwent.pw_dir);
+-		addenv ("USER", pwent.pw_name);
+-		addenv ("SHELL", shell);
+-	}
++		else {
++			addenv ("HOME", pwent.pw_dir);
++			addenv ("USER", pwent.pw_name);
++			addenv ("SHELL", shell);
++		}
+ #endif
++	}
+ 
+ 	/*
+ 	 * This is a workaround for Linux libc bug/feature (?) - the
+@@ -819,7 +836,7 @@
+ 	 */
+ 	closelog ();
+ 
+-	run_shell (shell, additional_args, fakelogin);
++	run_shell (shell, command, additional_args, fakelogin);
+ 	/* NOT REACHED */
+ 	exit (1);
+ }

Added: branches/experimental/debian/patches/437_su_add_GNU_options_4
===================================================================
--- branches/experimental/debian/patches/437_su_add_GNU_options_4	2005-07-24 20:30:34 UTC (rev 400)
+++ branches/experimental/debian/patches/437_su_add_GNU_options_4	2005-07-24 20:40:09 UTC (rev 401)
@@ -0,0 +1,139 @@
+Goal:
+      * remove compilation warnings (Basename)
+      * no more use shell() for executing a shell whithout argument.
+        This may have some implications on the environment: shell used to use
+        execle with newenvp as the new environment.
+        I think it is preferable to have the ssame behavior when there are
+        or isn't any argument.
+        if !change_environment (and the user shell is not restricted), we
+        need to add all the environmental variables to newenvp (with addenv)
+        and to copy newenvp to environ.
+      * if fakelogin, some env variables are set. This must not be done if
+        --preserve-environment wasspecified (for users whose shell is not
+        restricted)
+Index: shadow-4.0.10/src/su.c
+===================================================================
+--- shadow-4.0.10.orig/src/su.c	2005-07-22 19:39:09.000000000 +0200
++++ shadow-4.0.10/src/su.c	2005-07-22 19:51:55.000000000 +0200
+@@ -212,14 +212,14 @@
+ 
+ 		shell_basename = getdef_str ("SU_NAME");
+ 		if (!shell_basename)
+-			shell_basename = Basename (shellstr);
++			shell_basename = Basename ((char *)shellstr);
+ 
+ 		arg0 = xmalloc (strlen (shell_basename) + 2);
+ 		arg0[0] = '-';
+ 		strcpy (arg0 + 1, shell_basename);
+ 		args[0] = arg0;
+ 	} else
+-		args[0] = Basename (shellstr);
++		args[0] = Basename ((char *)shellstr);
+ 	argno = 1;
+ 
+ 	if (command) {
+@@ -236,20 +236,14 @@
+ 	args[argno] = NULL;
+ 
+ #ifndef USE_PAM
+-	if (argno > 1)
+-		(void) execv (shellstr, args);
+-	else
+-		shell (shellstr, args[0]);
++	(void) execv (shellstr, args);
+ 	/* NOT REACHED */
+ #else
+ 	child = fork ();
+ 	if (child == 0) {	/* child shell */
+ 		pam_end (pamh, PAM_SUCCESS);
+ 
+-		if (argno == 1)
+-			shell (shellstr, (char *) args[0]);
+-		else
+-			(void) execv (shellstr, (char **) args);
++		(void) execv (shellstr, (char **) args);
+ 		{
+ 			int exit_status = (errno == ENOENT ? 127 : 126);
+ 
+@@ -468,40 +462,6 @@
+ 		additional_args = argv + optind;
+ 
+ 	/*
+-	 * If a new login is being set up, the old environment will be
+-	 * ignored and a new one created later on.
+-	 */
+-
+-	if (fakelogin) {
+-		if ((cp = getdef_str ("ENV_TZ")))
+-			addenv (*cp == '/' ? tz (cp) : cp, NULL);
+-		/*
+-		 * The clock frequency will be reset to the login value if required
+-		 */
+-		if ((cp = getdef_str ("ENV_HZ")))
+-			addenv (cp, NULL);	/* set the default $HZ, if one */
+-		/*
+-		 * The terminal type will be left alone if it is present in
+-		 * the environment already.
+-		 */
+-		if ((cp = getenv ("TERM")))
+-			addenv ("TERM", cp);
+-#ifndef USE_PAM
+-		/*
+-		 * Also leave DISPLAY and XAUTHORITY if present, else
+-		 * pam_xauth will not work.
+-		 */
+-		if ((cp = getenv ("DISPLAY")))
+-			addenv ("DISPLAY", cp);
+-		if ((cp = getenv ("XAUTHORITY")))
+-			addenv ("XAUTHORITY", cp);
+-#endif				/* !USE_PAM */
+-	} else {
+-		while (*envp)
+-			addenv (*envp++, NULL);
+-	}
+-
+-	/*
+ 	 * Get the user's real name. The current UID is used to determine
+ 	 * who has executed su. That user ID must exist.
+ 	 */
+@@ -568,6 +528,40 @@
+ #endif				/* !USE_PAM */
+ 	pwent = *pw;
+ 
++	/*
++	 * If a new login is being set up, the old environment will be
++	 * ignored and a new one created later on.
++	 */
++
++	if (fakelogin && (change_environment || restricted_shell(pwent.pw_shell))) {
++		if ((cp = getdef_str ("ENV_TZ")))
++			addenv (*cp == '/' ? tz (cp) : cp, NULL);
++		/*
++		 * The clock frequency will be reset to the login value if required
++		 */
++		if ((cp = getdef_str ("ENV_HZ")))
++			addenv (cp, NULL);	/* set the default $HZ, if one */
++		/*
++		 * The terminal type will be left alone if it is present in
++		 * the environment already.
++		 */
++		if ((cp = getenv ("TERM")))
++			addenv ("TERM", cp);
++#ifndef USE_PAM
++		/*
++		 * Also leave DISPLAY and XAUTHORITY if present, else
++		 * pam_xauth will not work.
++		 */
++		if ((cp = getenv ("DISPLAY")))
++			addenv ("DISPLAY", cp);
++		if ((cp = getenv ("XAUTHORITY")))
++			addenv ("XAUTHORITY", cp);
++#endif				/* !USE_PAM */
++	} else {
++		while (*envp)
++			addenv (*envp++, NULL);
++	}
++
+ #ifndef USE_PAM
+ 	/*
+ 	 * BSD systems only allow "wheel" to SU to root. USG systems don't,

Added: branches/experimental/debian/patches/437_su_add_GNU_options_5
===================================================================
--- branches/experimental/debian/patches/437_su_add_GNU_options_5	2005-07-24 20:30:34 UTC (rev 400)
+++ branches/experimental/debian/patches/437_su_add_GNU_options_5	2005-07-24 20:40:09 UTC (rev 401)
@@ -0,0 +1,31 @@
+Goal: report failure to execute the shell to the user and to syslog.
+      Also, return a 126 or 127 exit status when !USE_PAM (was mising
+      from another patch.
+
+Index: shadow-4.0.10/src/su.c
+===================================================================
+--- shadow-4.0.10.orig/src/su.c	2005-07-22 10:34:01.000000000 +0200
++++ shadow-4.0.10/src/su.c	2005-07-22 10:36:52.000000000 +0200
+@@ -237,6 +237,13 @@
+ 
+ #ifndef USE_PAM
+ 	(void) execv (shellstr, args);
++	fprintf (stderr, _("No shell\n"));
++	SYSLOG((LOG_WARN, "Cannot execute %s\n", shellstr));
++	{
++		int exit_status = (errno == ENOENT ? 127 : 126);
++
++		exit (exit_status);
++	}
+ 	/* NOT REACHED */
+ #else
+ 	child = fork ();
+@@ -244,6 +251,8 @@
+ 		pam_end (pamh, PAM_SUCCESS);
+ 
+ 		(void) execv (shellstr, (char **) args);
++		fprintf (stderr, _("No shell\n"));
++		SYSLOG((LOG_WARN, "Cannot execute %s\n", shellstr));
+ 		{
+ 			int exit_status = (errno == ENOENT ? 127 : 126);
+ 

Added: branches/experimental/debian/patches/437_su_add_GNU_options_6
===================================================================
--- branches/experimental/debian/patches/437_su_add_GNU_options_6	2005-07-24 20:30:34 UTC (rev 400)
+++ branches/experimental/debian/patches/437_su_add_GNU_options_6	2005-07-24 20:40:09 UTC (rev 401)
@@ -0,0 +1,15 @@
+Goal: I'm not sure if the pw_shell can be NULL, but checking can't arm.
+
+Index: shadow-4.0.10/src/su.c
+===================================================================
+--- shadow-4.0.10.orig/src/su.c	2005-07-22 10:36:52.000000000 +0200
++++ shadow-4.0.10/src/su.c	2005-07-22 10:41:12.000000000 +0200
+@@ -622,7 +622,7 @@
+ 	 * Set the default shell.
+ 	 */
+ 
+-	if (pwent.pw_shell[0] == '\0')
++	if (pwent.pw_shell == NULL || pwent.pw_shell[0] == '\0')
+ 		pwent.pw_shell = "/bin/sh";	/* XXX warning: const */
+ 
+ 	/* If the user do not want to change the environment,




More information about the Pkg-shadow-commits mailing list