* src/su.c (save_caller_context): Extract from main() the code
used to save the caller's context.
This commit is contained in:
parent
b661b913b5
commit
6be3ac560b
@ -1,3 +1,8 @@
|
||||
2011-06-12 Nicolas François <nicolas.francois@centraliens.net>
|
||||
|
||||
* src/su.c (save_caller_context): Extract from main() the code
|
||||
used to save the caller's context.
|
||||
|
||||
2011-06-10 Nicolas François <nicolas.francois@centraliens.net>
|
||||
|
||||
* src/su.c: Group some of the environment processing blocks. The
|
||||
|
207
src/su.c
207
src/su.c
@ -75,10 +75,20 @@
|
||||
* Global variables
|
||||
*/
|
||||
const char *Prog;
|
||||
const char *caller_tty = NULL; /* Name of tty SU is run from */
|
||||
bool caller_is_root = false;
|
||||
uid_t caller_uid;
|
||||
#ifndef USE_PAM
|
||||
int caller_on_console = 0;
|
||||
#ifdef SU_ACCESS
|
||||
char *caller_pass;
|
||||
#endif
|
||||
#endif /* !USE_PAM */
|
||||
|
||||
|
||||
/* not needed by sulog.c anymore */
|
||||
static char name[BUFSIZ];
|
||||
static char oldname[BUFSIZ];
|
||||
static char caller_name[BUFSIZ];
|
||||
|
||||
/* If nonzero, change some environment vars to indicate the user su'd to. */
|
||||
static bool change_environment;
|
||||
@ -110,6 +120,7 @@ static RETSIGTYPE die (int);
|
||||
static bool iswheel (const char *);
|
||||
#endif /* !USE_PAM */
|
||||
static struct passwd * check_perms (void);
|
||||
static void save_caller_context (char **argv);
|
||||
|
||||
#ifndef USE_PAM
|
||||
/*
|
||||
@ -178,12 +189,12 @@ static bool restricted_shell (const char *shellstr)
|
||||
|
||||
static void su_failure (const char *tty, bool su_to_root)
|
||||
{
|
||||
sulog (tty, false, oldname, name); /* log failed attempt */
|
||||
sulog (tty, false, caller_name, name); /* log failed attempt */
|
||||
#ifdef USE_SYSLOG
|
||||
if (getdef_bool ("SYSLOG_SU_ENAB")) {
|
||||
SYSLOG ((su_to_root ? LOG_NOTICE : LOG_INFO,
|
||||
"- %s %s:%s", tty,
|
||||
('\0' != oldname[0]) ? oldname : "???",
|
||||
('\0' != caller_name[0]) ? caller_name : "???",
|
||||
('\0' != name[0]) ? name : "???"));
|
||||
}
|
||||
closelog ();
|
||||
@ -440,10 +451,10 @@ static struct passwd * check_perms (void)
|
||||
* to Chris Evans <lady0110@sable.ox.ac.uk>.
|
||||
*/
|
||||
|
||||
if (!amroot) {
|
||||
if (!caller_is_root) {
|
||||
if ( (0 == pw->pw_uid)
|
||||
&& getdef_bool ("SU_WHEEL_ONLY")
|
||||
&& !iswheel (oldname)) {
|
||||
&& !iswheel (caller_name)) {
|
||||
fprintf (stderr,
|
||||
_("You are not authorized to su %s\n"),
|
||||
name);
|
||||
@ -457,7 +468,7 @@ static struct passwd * check_perms (void)
|
||||
}
|
||||
}
|
||||
|
||||
switch (check_su_auth (oldname, name, 0 == pw->pw_uid)) {
|
||||
switch (check_su_auth (caller_name, name, 0 == pw->pw_uid)) {
|
||||
case 0: /* normal su, require target user's password */
|
||||
break;
|
||||
case 1: /* require no password */
|
||||
@ -465,7 +476,7 @@ static struct passwd * check_perms (void)
|
||||
break;
|
||||
case 2: /* require own password */
|
||||
puts (_("(Enter your own password)"));
|
||||
pw->pw_passwd = oldpass;
|
||||
pw->pw_passwd = caller_pass;
|
||||
break;
|
||||
default: /* access denied (-1) or unexpected value */
|
||||
fprintf (stderr,
|
||||
@ -486,12 +497,12 @@ static struct passwd * check_perms (void)
|
||||
pam_strerror (pamh, ret)));
|
||||
fprintf (stderr, _("%s: %s\n"), Prog, pam_strerror (pamh, ret));
|
||||
(void) pam_end (pamh, ret);
|
||||
su_failure (tty, 0 == pw->pw_uid);
|
||||
su_failure (caller_tty, 0 == pw->pw_uid);
|
||||
}
|
||||
|
||||
ret = pam_acct_mgmt (pamh, 0);
|
||||
if (PAM_SUCCESS != ret) {
|
||||
if (amroot) {
|
||||
if (caller_is_root) {
|
||||
fprintf (stderr,
|
||||
_("%s: %s\n(Ignored)\n"),
|
||||
Prog, pam_strerror (pamh, ret));
|
||||
@ -504,7 +515,7 @@ static struct passwd * check_perms (void)
|
||||
_("%s: %s\n"),
|
||||
Prog, pam_strerror (pamh, ret));
|
||||
(void) pam_end (pamh, ret);
|
||||
su_failure (tty, 0 == pw->pw_uid);
|
||||
su_failure (caller_tty, 0 == pw->pw_uid);
|
||||
}
|
||||
} else {
|
||||
SYSLOG ((LOG_ERR, "pam_acct_mgmt: %s",
|
||||
@ -513,7 +524,7 @@ static struct passwd * check_perms (void)
|
||||
_("%s: %s\n"),
|
||||
Prog, pam_strerror (pamh, ret));
|
||||
(void) pam_end (pamh, ret);
|
||||
su_failure (tty, 0 == pw->pw_uid);
|
||||
su_failure (caller_tty, 0 == pw->pw_uid);
|
||||
}
|
||||
}
|
||||
#else /* !USE_PAM */
|
||||
@ -528,12 +539,12 @@ static struct passwd * check_perms (void)
|
||||
* The first character of an administrator defined method is an '@'
|
||||
* character.
|
||||
*/
|
||||
if ( !amroot
|
||||
if ( !caller_is_root
|
||||
&& (pw_auth (pw->pw_passwd, name, PW_SU, (char *) 0) != 0)) {
|
||||
SYSLOG (((pw->pw_uid != 0)? LOG_NOTICE : LOG_WARN,
|
||||
"Authentication failed for %s", name));
|
||||
fprintf(stderr, _("%s: Authentication failure\n"), Prog);
|
||||
su_failure (tty, 0 == pw->pw_uid);
|
||||
su_failure (caller_tty, 0 == pw->pw_uid);
|
||||
}
|
||||
(void) signal (SIGQUIT, oldsig);
|
||||
|
||||
@ -542,7 +553,7 @@ static struct passwd * check_perms (void)
|
||||
* expired accounts, but normal users can't become a user with an
|
||||
* expired password.
|
||||
*/
|
||||
if ((!amroot) && (NULL != spwd)) {
|
||||
if ((!caller_is_root) && (NULL != spwd)) {
|
||||
(void) expire (pw, spwd);
|
||||
}
|
||||
|
||||
@ -552,15 +563,15 @@ static struct passwd * check_perms (void)
|
||||
* there is a "SU" entry in the /etc/porttime file denying access to
|
||||
* the account.
|
||||
*/
|
||||
if (!amroot) {
|
||||
if (!caller_is_root) {
|
||||
if (!isttytime (name, "SU", time ((time_t *) 0))) {
|
||||
SYSLOG (((0 != pw->pw_uid) ? LOG_WARN : LOG_CRIT,
|
||||
"SU by %s to restricted account %s",
|
||||
oldname, name));
|
||||
caller_name, name));
|
||||
fprintf (stderr,
|
||||
_("%s: You are not authorized to su at that time\n"),
|
||||
Prog);
|
||||
su_failure (tty, 0 == pw->pw_uid);
|
||||
su_failure (caller_tty, 0 == pw->pw_uid);
|
||||
}
|
||||
}
|
||||
#endif /* !USE_PAM */
|
||||
@ -583,6 +594,80 @@ static struct passwd * check_perms (void)
|
||||
return pw;
|
||||
}
|
||||
|
||||
/*
|
||||
* save_caller_context - save information from the call context
|
||||
*
|
||||
* Save the program's name (Prog), caller's UID (caller_uid /
|
||||
* caller_is_root), name (caller_name), and password (caller_pass),
|
||||
* the TTY (ttyp), and whether su was called from a console
|
||||
* (is_console) for further processing and before they might change.
|
||||
*/
|
||||
static void save_caller_context (char **argv)
|
||||
{
|
||||
struct passwd *pw = NULL;
|
||||
/*
|
||||
* Get the program name. The program name is used as a prefix to
|
||||
* most error messages.
|
||||
*/
|
||||
Prog = Basename (argv[0]);
|
||||
|
||||
caller_uid = getuid ();
|
||||
caller_is_root = (caller_uid == 0);
|
||||
|
||||
/*
|
||||
* Get the tty name. Entries will be logged indicating that the user
|
||||
* tried to change to the named new user from the current terminal.
|
||||
*/
|
||||
caller_tty = ttyname (0);
|
||||
if ((isatty (0) != 0) && (NULL != caller_tty)) {
|
||||
#ifndef USE_PAM
|
||||
caller_on_console = console (caller_tty);
|
||||
#endif
|
||||
} else {
|
||||
/*
|
||||
* Be more paranoid, like su from SimplePAMApps. --marekm
|
||||
*/
|
||||
if (!caller_is_root) {
|
||||
fprintf (stderr,
|
||||
_("%s: must be run from a terminal\n"),
|
||||
Prog);
|
||||
exit (1);
|
||||
}
|
||||
caller_tty = "???";
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the user's real name. The current UID is used to determine
|
||||
* who has executed su. That user ID must exist.
|
||||
*/
|
||||
pw = get_my_pwent ();
|
||||
if (NULL == pw) {
|
||||
fprintf (stderr,
|
||||
_("%s: Cannot determine your user name.\n"),
|
||||
Prog);
|
||||
SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)",
|
||||
(unsigned long) caller_uid));
|
||||
su_failure (caller_tty, true); // FIXME: at this time I do not know the target UID
|
||||
}
|
||||
STRFCPY (caller_name, pw->pw_name);
|
||||
|
||||
#ifndef USE_PAM
|
||||
#ifdef SU_ACCESS
|
||||
/*
|
||||
* Sort out the password of user calling su, in case needed later
|
||||
* -- chris
|
||||
*/
|
||||
if (strcmp (pw->pw_passwd, SHADOW_PASSWD_STRING) == 0) {
|
||||
struct spwd *spwd = getspnam (caller_name);
|
||||
if (NULL != spwd) {
|
||||
pw->pw_passwd = spwd->sp_pwdp;
|
||||
}
|
||||
}
|
||||
caller_pass = xstrdup (pw->pw_passwd);
|
||||
#endif /* SU_ACCESS */
|
||||
#endif /* !USE_PAM */
|
||||
}
|
||||
|
||||
/*
|
||||
* su - switch user id
|
||||
*
|
||||
@ -596,11 +681,8 @@ static struct passwd * check_perms (void)
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
const char *cp;
|
||||
const char *tty = NULL; /* Name of tty SU is run from */
|
||||
bool doshell = false;
|
||||
bool fakelogin = false;
|
||||
bool amroot = false;
|
||||
uid_t my_uid;
|
||||
struct passwd *pw = NULL;
|
||||
char *shellstr = NULL;
|
||||
char *command = NULL;
|
||||
@ -611,11 +693,7 @@ int main (int argc, char **argv)
|
||||
int err = 0;
|
||||
|
||||
RETSIGTYPE (*oldsig) (int);
|
||||
int is_console = 0;
|
||||
|
||||
#ifdef SU_ACCESS
|
||||
char *oldpass;
|
||||
#endif
|
||||
#endif /* !USE_PAM */
|
||||
|
||||
(void) setlocale (LC_ALL, "");
|
||||
@ -624,11 +702,7 @@ int main (int argc, char **argv)
|
||||
|
||||
change_environment = true;
|
||||
|
||||
/*
|
||||
* Get the program name. The program name is used as a prefix to
|
||||
* most error messages.
|
||||
*/
|
||||
Prog = Basename (argv[0]);
|
||||
save_caller_context (argv);
|
||||
|
||||
OPENLOG ("su");
|
||||
|
||||
@ -692,31 +766,6 @@ int main (int argc, char **argv)
|
||||
|
||||
initenv ();
|
||||
|
||||
my_uid = getuid ();
|
||||
amroot = (my_uid == 0);
|
||||
|
||||
/*
|
||||
* Get the tty name. Entries will be logged indicating that the user
|
||||
* tried to change to the named new user from the current terminal.
|
||||
*/
|
||||
tty = ttyname (0);
|
||||
if ((isatty (0) != 0) && (NULL != tty)) {
|
||||
#ifndef USE_PAM
|
||||
is_console = console (tty);
|
||||
#endif
|
||||
} else {
|
||||
/*
|
||||
* Be more paranoid, like su from SimplePAMApps. --marekm
|
||||
*/
|
||||
if (!amroot) {
|
||||
fprintf (stderr,
|
||||
_("%s: must be run from a terminal\n"),
|
||||
Prog);
|
||||
exit (1);
|
||||
}
|
||||
tty = "???";
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
@ -737,7 +786,7 @@ int main (int argc, char **argv)
|
||||
root_pw = getpwuid (0);
|
||||
if (NULL == root_pw) {
|
||||
SYSLOG ((LOG_CRIT, "There is no UID 0 user."));
|
||||
su_failure (tty, true);
|
||||
su_failure (caller_tty, true);
|
||||
}
|
||||
(void) strcpy (name, root_pw->pw_name);
|
||||
}
|
||||
@ -748,37 +797,7 @@ int main (int argc, char **argv)
|
||||
doshell = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the user's real name. The current UID is used to determine
|
||||
* who has executed su. That user ID must exist.
|
||||
*/
|
||||
pw = get_my_pwent ();
|
||||
if (NULL == pw) {
|
||||
fprintf (stderr,
|
||||
_("%s: Cannot determine your user name.\n"),
|
||||
Prog);
|
||||
SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)",
|
||||
(unsigned long) my_uid));
|
||||
su_failure (tty, true); // FIXME: at this time I do not know the target UID
|
||||
}
|
||||
STRFCPY (oldname, pw->pw_name);
|
||||
|
||||
#ifndef USE_PAM
|
||||
#ifdef SU_ACCESS
|
||||
/*
|
||||
* Sort out the password of user calling su, in case needed later
|
||||
* -- chris
|
||||
*/
|
||||
if (strcmp (pw->pw_passwd, SHADOW_PASSWD_STRING) == 0) {
|
||||
struct spwd *spwd = getspnam (oldname);
|
||||
if (NULL != spwd) {
|
||||
pw->pw_passwd = spwd->sp_pwdp;
|
||||
}
|
||||
}
|
||||
oldpass = xstrdup (pw->pw_passwd);
|
||||
#endif /* SU_ACCESS */
|
||||
|
||||
#else /* USE_PAM */
|
||||
#ifdef USE_PAM
|
||||
ret = pam_start ("su", name, &conv, &pamh);
|
||||
if (PAM_SUCCESS != ret) {
|
||||
SYSLOG ((LOG_ERR, "pam_start: error %d", ret);
|
||||
@ -788,9 +807,9 @@ int main (int argc, char **argv)
|
||||
exit (1);
|
||||
}
|
||||
|
||||
ret = pam_set_item (pamh, PAM_TTY, (const void *) tty);
|
||||
ret = pam_set_item (pamh, PAM_TTY, (const void *) caller_tty);
|
||||
if (PAM_SUCCESS == ret) {
|
||||
ret = pam_set_item (pamh, PAM_RUSER, (const void *) oldname);
|
||||
ret = pam_set_item (pamh, PAM_RUSER, (const void *) caller_name);
|
||||
}
|
||||
if (PAM_SUCCESS != ret) {
|
||||
SYSLOG ((LOG_ERR, "pam_set_item: %s",
|
||||
@ -815,7 +834,7 @@ int main (int argc, char **argv)
|
||||
* restricted shell, the environment must be changed and the shell
|
||||
* must be the one specified in /etc/passwd.
|
||||
*/
|
||||
if ( !amroot
|
||||
if ( !caller_is_root
|
||||
&& restricted_shell (pw->pw_shell)) {
|
||||
shellstr = NULL;
|
||||
change_environment = true;
|
||||
@ -910,13 +929,13 @@ int main (int argc, char **argv)
|
||||
addenv ("IFS= \t\n", NULL); /* ... instead, set a safe IFS */
|
||||
}
|
||||
|
||||
sulog (tty, true, oldname, name); /* save SU information */
|
||||
sulog (caller_tty, true, caller_name, name); /* save SU information */
|
||||
endpwent ();
|
||||
endspent ();
|
||||
#ifdef USE_SYSLOG
|
||||
if (getdef_bool ("SYSLOG_SU_ENAB")) {
|
||||
SYSLOG ((LOG_INFO, "+ %s %s:%s", tty,
|
||||
('\0' != oldname[0]) ? oldname : "???",
|
||||
SYSLOG ((LOG_INFO, "+ %s %s:%s", caller_tty,
|
||||
('\0' != caller_name[0]) ? caller_name : "???",
|
||||
('\0' != name[0]) ? name : "???"));
|
||||
}
|
||||
#endif
|
||||
@ -978,11 +997,11 @@ int main (int argc, char **argv)
|
||||
environ = newenvp; /* make new environment active */
|
||||
|
||||
/* no limits if su from root (unless su must fake login's behavior) */
|
||||
if (!amroot || fakelogin) {
|
||||
if (!caller_is_root || fakelogin) {
|
||||
setup_limits (pw);
|
||||
}
|
||||
|
||||
if (setup_uid_gid (pw, is_console) != 0) {
|
||||
if (setup_uid_gid (pw, caller_on_console) != 0) {
|
||||
exit (1);
|
||||
}
|
||||
#endif /* !USE_PAM */
|
||||
|
Loading…
Reference in New Issue
Block a user