* src/su.c: environ is provided by <unistd.h>.

* src/su.c: Added function prototypes.
	* src/su.c: Rename shellstr parameter to shellname to avoid
	collision with static variable.
	* NEWS, src/su.c: Added support for PAM modules which change
	PAM_USER.
This commit is contained in:
nekral-guest 2011-06-16 21:21:29 +00:00
parent 66d71aafb7
commit 907025eb40
3 changed files with 60 additions and 14 deletions

View File

@ -1,3 +1,12 @@
2011-06-16 Nicolas François <nicolas.francois@centraliens.net>
* src/su.c: environ is provided by <unistd.h>.
* src/su.c: Added function prototypes.
* src/su.c: Rename shellstr parameter to shellname to avoid
collision with static variable.
* NEWS, src/su.c: Added support for PAM modules which change
PAM_USER.
2011-06-13 Nicolas François <nicolas.francois@centraliens.net> 2011-06-13 Nicolas François <nicolas.francois@centraliens.net>
* src/su.c (prepare_pam_close_session): Extract the creation of a * src/su.c (prepare_pam_close_session): Extract the creation of a

2
NEWS
View File

@ -48,6 +48,7 @@ shadow-4.1.4.3 -> shadow-4.1.5 UNRELEASED
caller's privileges. caller's privileges.
* Close PAM sessions as root. This will be more friendly to PAM modules * Close PAM sessions as root. This will be more friendly to PAM modules
like pam_mount or pam_systemd. like pam_mount or pam_systemd.
* Added support for PAM modules which change PAM_USER.
- newgrp, sg, groupmems - newgrp, sg, groupmems
* Fix parsing of gshadow entries. * Fix parsing of gshadow entries.
- useradd - useradd
@ -67,6 +68,7 @@ shadow-4.1.4.3 -> shadow-4.1.5 UNRELEASED
* Updated Czech translation. * Updated Czech translation.
* Updated Danish translation. * Updated Danish translation.
* Updated French translation. * Updated French translation.
* Updated French man pages translation.
* Updated German translation. * Updated German translation.
* Updated German man pages translation. * Updated German man pages translation.
* Updated Japanese translation. * Updated Japanese translation.

View File

@ -115,13 +115,12 @@ static pid_t pid_child = 0;
* External identifiers * External identifiers
*/ */
extern char **newenvp; extern char **newenvp; /* libmisc/env.c */
extern char **environ; extern size_t newenvc; /* libmisc/env.c */
extern size_t newenvc;
/* local function prototypes */ /* local function prototypes */
static void execve_shell (const char *shellstr, static void execve_shell (const char *shellname,
char *args[], char *args[],
char *const envp[]); char *const envp[]);
#ifdef USE_PAM #ifdef USE_PAM
@ -131,6 +130,8 @@ static void prepare_pam_close_session (void);
static RETSIGTYPE die (int); static RETSIGTYPE die (int);
static bool iswheel (const char *); static bool iswheel (const char *);
#endif /* !USE_PAM */ #endif /* !USE_PAM */
static bool restricted_shell (const char *shellname);
static void su_failure (const char *tty, bool su_to_root);
static struct passwd * check_perms (void); static struct passwd * check_perms (void);
#ifdef USE_PAM #ifdef USE_PAM
static void check_perms_pam (struct passwd *pw); static void check_perms_pam (struct passwd *pw);
@ -139,6 +140,7 @@ static void check_perms_nopam (struct passwd *pw);
#endif /* !USE_PAM */ #endif /* !USE_PAM */
static void save_caller_context (char **argv); static void save_caller_context (char **argv);
static void process_flags (int argc, char **argv); static void process_flags (int argc, char **argv);
static void set_environment (struct passwd *pw);
#ifndef USE_PAM #ifndef USE_PAM
/* /*
@ -190,13 +192,13 @@ static RETSIGTYPE kill_child (int unused(s))
#endif /* USE_PAM */ #endif /* USE_PAM */
/* borrowed from GNU sh-utils' "su.c" */ /* borrowed from GNU sh-utils' "su.c" */
static bool restricted_shell (const char *shellstr) static bool restricted_shell (const char *shellname)
{ {
char *line; char *line;
setusershell (); setusershell ();
while ((line = getusershell ()) != NULL) { while ((line = getusershell ()) != NULL) {
if (('#' != *line) && (strcmp (line, shellstr) == 0)) { if (('#' != *line) && (strcmp (line, shellname) == 0)) {
endusershell (); endusershell ();
return false; return false;
} }
@ -224,15 +226,15 @@ static void su_failure (const char *tty, bool su_to_root)
* execve_shell - Execute a shell with execve, or interpret it with * execve_shell - Execute a shell with execve, or interpret it with
* /bin/sh * /bin/sh
*/ */
static void execve_shell (const char *shellstr, static void execve_shell (const char *shellname,
char *args[], char *args[],
char *const envp[]) char *const envp[])
{ {
int err; int err;
(void) execve (shellstr, (char **) args, envp); (void) execve (shellname, (char **) args, envp);
err = errno; err = errno;
if (access (shellstr, R_OK|X_OK) == 0) { if (access (shellname, R_OK|X_OK) == 0) {
/* /*
* Assume this is a shell script (with no shebang). * Assume this is a shell script (with no shebang).
* Interpret it with /bin/sh * Interpret it with /bin/sh
@ -245,7 +247,7 @@ static void execve_shell (const char *shellstr,
targs = (char **) xmalloc ((n_args + 3) * sizeof (args[0])); targs = (char **) xmalloc ((n_args + 3) * sizeof (args[0]));
targs[0] = "sh"; targs[0] = "sh";
targs[1] = "-"; targs[1] = "-";
targs[2] = xstrdup (shellstr); targs[2] = xstrdup (shellname);
targs[n_args+2] = NULL; targs[n_args+2] = NULL;
while (1 != n_args) { while (1 != n_args) {
targs[n_args+1] = args[n_args - 1]; targs[n_args+1] = args[n_args - 1];
@ -570,24 +572,57 @@ static void check_perms_nopam (struct passwd *pw)
*/ */
static struct passwd * check_perms (void) static struct passwd * check_perms (void)
{ {
#ifdef USE_PAM
const char *tmp_name;
int ret;
#endif /* !USE_PAM */
/* /*
* The password file entries for the user is gotten and the account * The password file entries for the user is gotten and the account
* validated. * validated.
*/ */
struct passwd *pw = xgetpwnam (name); struct passwd *pw = xgetpwnam (name);
if (NULL == pw) { if (NULL == pw) {
(void) fprintf (stderr, _("Unknown id: %s\n"), name); (void) fprintf (stderr,
closelog (); _("No passwd entry for user '%s'\n"), name);
exit (1); SYSLOG ((LOG_ERR, "No passwd entry for user '%s'", name));
su_failure (caller_tty, true);
} }
(void) signal (SIGINT, SIG_IGN); (void) signal (SIGINT, SIG_IGN);
(void) signal (SIGQUIT, SIG_IGN); (void) signal (SIGQUIT, SIG_IGN);
#ifdef USE_PAM #ifdef USE_PAM
check_perms_pam (pw); check_perms_pam (pw);
/* PAM authentication can request a change of account */
ret = pam_get_item(pamh, PAM_USER, (const void **) &tmp_name);
if (ret != PAM_SUCCESS) {
SYSLOG((LOG_ERR, "pam_get_item: internal PAM error\n"));
(void) fprintf (stderr,
"%s: Internal PAM error retrieving username\n",
Prog);
(void) pam_end (pamh, ret);
su_failure (caller_tty, 0 == pw->pw_uid);
}
if (strcmp (name, tmp_name) != 0) {
SYSLOG ((LOG_INFO,
"Change user from '%s' to '%s' as requested by PAM",
name, tmp_name));
strncpy (name, tmp_name, sizeof(name) - 1);
name[sizeof(name) - 1] = '\0';
pw = xgetpwnam (name);
if (NULL == pw) {
(void) fprintf (stderr,
_("No passwd entry for user '%s'\n"),
name);
SYSLOG ((LOG_ERR,
"No passwd entry for user '%s'", name));
su_failure (caller_tty, true);
}
}
#else /* !USE_PAM */ #else /* !USE_PAM */
check_perms_nopam (pw); check_perms_nopam (pw);
#endif /* !USE_PAM */ #endif /* !USE_PAM */
(void) signal (SIGINT, SIG_DFL); (void) signal (SIGINT, SIG_DFL);
(void) signal (SIGQUIT, SIG_DFL); (void) signal (SIGQUIT, SIG_DFL);
@ -659,7 +694,7 @@ static void save_caller_context (char **argv)
Prog); Prog);
SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)", SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)",
(unsigned long) caller_uid)); (unsigned long) caller_uid));
su_failure (caller_tty, true); // FIXME: at this time I do not know the target UID su_failure (caller_tty, true); /* unknown target UID*/
} }
STRFCPY (caller_name, pw->pw_name); STRFCPY (caller_name, pw->pw_name);