summaryrefslogtreecommitdiffstats
path: root/login-utils/su.c
diff options
context:
space:
mode:
Diffstat (limited to 'login-utils/su.c')
-rw-r--r--login-utils/su.c135
1 files changed, 20 insertions, 115 deletions
diff --git a/login-utils/su.c b/login-utils/su.c
index edd6d1067..7bacbc382 100644
--- a/login-utils/su.c
+++ b/login-utils/su.c
@@ -1,5 +1,6 @@
-/* su for GNU. Run a shell with substitute user and group IDs.
+/* su for Linux. Run a shell with substitute user and group IDs.
Copyright (C) 1992-2006 Free Software Foundation, Inc.
+ Copyright (C) 2012 SUSE Linux Products GmbH, Nuernberg
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -34,28 +35,7 @@
(setting argv[0] to "-su", passing -c only to certain shells, etc.).
I don't see the point in doing that, and it's ugly.
- This program intentionally does not support a "wheel group" that
- 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.
-
- -DSYSLOG_NON_ROOT Log all su's, not just those to root (UID 0).
- Never logs attempted su's to nonexistent accounts.
-
- Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
+ Based on an implemenation by David MacKenzie <djm@gnu.ai.mit.edu>. */
#ifndef MAX
# define MAX(a,b) ((a) > (b) ? (a) : (b))
@@ -76,40 +56,16 @@ enum
#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
+#include <security/pam_appl.h>
+#include <security/pam_misc.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/fsuid.h>
-#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
-# undef SYSLOG_NON_ROOT
-#endif
-
-#if HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif
-
-#ifndef HAVE_ENDGRENT
-# define endgrent() ((void) 0)
-#endif
-
-#ifndef HAVE_ENDPWENT
-# define endpwent() ((void) 0)
-#endif
-
-#if HAVE_SHADOW_H
-# include <shadow.h>
-#endif
+#include <syslog.h>
+#define SYSLOG_SUCCESS 1
+#define SYSLOG_FAILURE 1
+#define SYSLOG_NON_ROOT 1
#include "error.h"
@@ -120,11 +76,9 @@ enum
/* The official name of this program (e.g., no `g' prefix). */
#define PROGRAM_NAME "su"
-#define AUTHORS "David MacKenzie"
-
-#if HAVE_PATHS_H
-# include <paths.h>
-#endif
+/* name of the pam configuration files. separate configs for su and su - */
+#define PAM_SERVICE_NAME PROGRAM_NAME
+#define PAM_SERVICE_NAME_L PROGRAM_NAME "-l"
#include "getdef.h"
@@ -140,10 +94,6 @@ enum
/* The user to become if none is specified. */
#define DEFAULT_USER "root"
-#ifndef USE_PAM
-char *crypt ();
-#endif
-
extern char **environ;
static void run_shell (char const *, char const *, char **, size_t)
@@ -164,10 +114,10 @@ static bool change_environment;
/* If true, then don't call setsid() with a command. */
int same_session = 0;
-#ifdef USE_PAM
static bool _pam_session_opened;
static bool _pam_cred_established;
-#endif
+static sig_atomic_t volatile caught_signal = false;
+static pam_handle_t *pamh = NULL;
static struct option const longopts[] =
@@ -246,12 +196,6 @@ log_su (struct passwd const *pw, bool successful)
}
#endif
-#ifdef USE_PAM
-# define PAM_SERVICE_NAME PROGRAM_NAME
-# define PAM_SERVICE_NAME_L PROGRAM_NAME "-l"
-static sig_atomic_t volatile caught_signal = false;
-static pam_handle_t *pamh = NULL;
-static int retval;
static struct pam_conv conv =
{
misc_conv,
@@ -306,6 +250,7 @@ create_watching_parent (void)
pid_t child;
sigset_t ourset;
int status = 0;
+ int retval;
retval = pam_open_session (pamh, 0);
if (retval != PAM_SUCCESS)
@@ -413,20 +358,13 @@ create_watching_parent (void)
}
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. */
static bool
correct_password (const struct passwd *pw)
{
-#ifdef USE_PAM
const struct passwd *lpw;
const char *cp;
+ int retval;
retval = pam_start (simulate_login ? PAM_SERVICE_NAME_L : PAM_SERVICE_NAME,
pw->pw_name, &conv, &pamh);
@@ -465,32 +403,6 @@ correct_password (const struct passwd *pw)
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)
- correct = sp->sp_pwdp;
- else
-# endif
- correct = pw->pw_passwd;
-
- if (getuid () == 0 || !correct || correct[0] == '\0')
- return true;
-
- unencrypted = getpass (_("Password:"));
- if (!unencrypted)
- {
- error (0, 0, _("getpass: cannot open /dev/tty"));
- return false;
- }
- encrypted = crypt (unencrypted, correct);
- memset (unencrypted, 0, strlen (unencrypted));
- return !strcmp (encrypted, correct);
-#endif /* !USE_PAM */
}
/* Add or clear /sbin and /usr/sbin for the su command
@@ -667,9 +579,7 @@ modify_environment (const struct passwd *pw, const char *shell)
}
}
-#ifdef USE_PAM
export_pamenv ();
-#endif
}
/* Become the user and group(s) specified by PW. */
@@ -677,23 +587,20 @@ modify_environment (const struct passwd *pw, const char *shell)
static void
init_groups (const struct passwd *pw)
{
+ int retval;
errno = 0;
if (initgroups (pw->pw_name, pw->pw_gid) == -1)
{
-# ifdef USE_PAM
cleanup_pam (PAM_ABORT);
-# endif
error (EXIT_FAIL, errno, _("cannot set groups"));
}
endgrent ();
-#ifdef USE_PAM
retval = pam_setcred (pamh, PAM_ESTABLISH_CRED);
if (retval != PAM_SUCCESS)
error (EXIT_FAILURE, 0, "%s", pam_strerror (pamh, retval));
else
_pam_cred_established = 1;
-#endif
}
static void
@@ -925,10 +832,8 @@ main (int argc, char **argv)
init_groups (pw);
-#ifdef USE_PAM
create_watching_parent ();
/* Now we're in the child. */
-#endif
change_identity (pw);
if (!same_session)