1 /* vi: set sw=4 ts=4: */
12 #include <sys/resource.h>
15 #include <sys/types.h>
23 /* The shell to run if none is given in the user's passwd entry. */
24 #define DEFAULT_SHELL "/bin/sh"
25 #define DEFAULT_USER "root"
27 //#define SYSLOG_SUCCESS
28 #define SYSLOG_FAILURE
31 #if defined( SYSLOG_SUCCESS ) || defined( SYSLOG_FAILURE )
32 /* Log the fact that someone has run su to the user given by PW;
33 if SUCCESSFUL is nonzero, they gave the correct password, etc. */
35 static void log_su ( const struct passwd *pw, int successful )
37 const char *old_user, *tty;
39 #if !defined( SYSLOG_SUCESS )
43 #if !defined( SYSLOG_FAILURE )
48 if ( pw-> pw_uid ) // not to root -> ignored
51 /* The utmp entry (via getlogin) is probably the best way to identify
52 the user, especially if someone su's from a su-shell. */
53 old_user = getlogin ( );
55 /* getlogin can fail -- usually due to lack of utmp entry. Resort to getpwuid. */
56 struct passwd *pwd = getpwuid ( getuid ( ));
57 old_user = ( pwd ? pwd-> pw_name : "" );
62 openlog ( "su", 0, LOG_AUTH );
63 syslog ( LOG_NOTICE, "%s%s on %s", successful ? "" : "FAILED SU ", old_user, tty ? tty : "none" );
69 int su_main ( int argc, char **argv )
73 int opt_loginshell = 0;
75 char *opt_command = 0;
76 char *opt_username = DEFAULT_USER;
78 struct passwd *pw, pw_copy;
81 while (( flag = getopt ( argc, argv, "c:lmps:" )) != -1 ) {
102 if (( optind < argc ) && ( argv [optind][0] == '-' ) && ( argv [optind][1] == 0 )) {
107 /* get user if specified */
109 opt_username = argv [optind++];
112 opt_args = argv + optind;
115 pw = getpwnam ( opt_username );
117 error_msg_and_die ( "user %s does not exist", opt_username );
119 /* Make sure pw->pw_shell is non-NULL. It may be NULL when NEW_USER
120 is a username that is retrieved via NIS (YP), but that doesn't have
121 a default shell listed. */
122 if ( !pw-> pw_shell || !pw->pw_shell [0] )
123 pw-> pw_shell = (char *) DEFAULT_SHELL;
125 /* Make a copy of the password information and point pw at the local
126 copy instead. Otherwise, some systems (e.g. Linux) would clobber
127 the static data through the getlogin call from log_su. */
130 pw-> pw_name = xstrdup ( pw-> pw_name );
131 pw-> pw_dir = xstrdup ( pw-> pw_dir );
132 pw-> pw_shell = xstrdup ( pw-> pw_shell );
134 if (( getuid ( ) == 0 ) || correct_password ( pw ))
138 error_msg_and_die ( "incorrect password" );
141 if ( !opt_shell && opt_preserve )
142 opt_shell = getenv ( "SHELL" );
144 if ( opt_shell && getuid ( ) && restricted_shell ( pw-> pw_shell ))
146 /* The user being su'd to has a nonstandard shell, and so is
147 probably a uucp account or has restricted access. Don't
148 compromise the account by allowing access with a standard
150 fputs ( "using restricted shell\n", stderr );
155 opt_shell = xstrdup ( pw-> pw_shell );
157 change_identity ( pw );
158 setup_environment ( opt_shell, opt_loginshell, !opt_preserve, pw );
159 run_shell ( opt_shell, opt_loginshell, opt_command, (const char**)opt_args );