1 /* vi: set sw=4 ts=4: */
14 #include <sys/resource.h>
17 #include <sys/types.h>
24 #include "tinylogin.h"
28 /* The shell to run if none is given in the user's passwd entry. */
29 #define DEFAULT_SHELL "/bin/sh"
30 #define DEFAULT_USER "root"
32 //#define SYSLOG_SUCCESS
33 #define SYSLOG_FAILURE
36 #if defined( SYSLOG_SUCCESS ) || defined( SYSLOG_FAILURE )
37 /* Log the fact that someone has run su to the user given by PW;
38 if SUCCESSFUL is nonzero, they gave the correct password, etc. */
40 static void log_su ( const struct passwd *pw, int successful )
42 const char *old_user, *tty;
44 #if !defined( SYSLOG_SUCESS )
48 #if !defined( SYSLOG_FAILURE )
53 if ( pw-> pw_uid ) // not to root -> ignored
56 /* The utmp entry (via getlogin) is probably the best way to identify
57 the user, especially if someone su's from a su-shell. */
58 old_user = getlogin ( );
60 /* getlogin can fail -- usually due to lack of utmp entry. Resort to getpwuid. */
61 struct passwd *pwd = getpwuid ( getuid ( ));
62 old_user = ( pwd ? pwd-> pw_name : "" );
67 openlog ( "su", 0, LOG_AUTH );
68 syslog ( LOG_NOTICE, "%s%s on %s", successful ? "" : "FAILED SU ", old_user, tty ? tty : "none" );
74 int su_main ( int argc, char **argv )
78 int opt_loginshell = 0;
80 char *opt_command = 0;
81 char *opt_username = DEFAULT_USER;
83 struct passwd *pw, pw_copy;
86 while (( flag = getopt ( argc, argv, "c:lmps:" )) != -1 ) {
107 if (( optind < argc ) && ( argv [optind][0] == '-' ) && ( argv [optind][1] == 0 )) {
112 /* get user if specified */
114 opt_username = argv [optind++];
117 opt_args = argv + optind;
120 pw = getpwnam ( opt_username );
122 error_msg_and_die ( "user %s does not exist", opt_username );
124 /* Make sure pw->pw_shell is non-NULL. It may be NULL when NEW_USER
125 is a username that is retrieved via NIS (YP), but that doesn't have
126 a default shell listed. */
127 if ( !pw-> pw_shell || !pw->pw_shell [0] )
128 pw-> pw_shell = (char *) DEFAULT_SHELL;
130 /* Make a copy of the password information and point pw at the local
131 copy instead. Otherwise, some systems (e.g. Linux) would clobber
132 the static data through the getlogin call from log_su. */
135 pw-> pw_name = xstrdup ( pw-> pw_name );
136 pw-> pw_dir = xstrdup ( pw-> pw_dir );
137 pw-> pw_shell = xstrdup ( pw-> pw_shell );
139 if (( getuid ( ) == 0 ) || correct_password ( pw ))
143 error_msg_and_die ( "incorrect password" );
146 if ( !opt_shell && opt_preserve )
147 opt_shell = getenv ( "SHELL" );
149 if ( opt_shell && getuid ( ) && restricted_shell ( pw-> pw_shell ))
151 /* The user being su'd to has a nonstandard shell, and so is
152 probably a uucp account or has restricted access. Don't
153 compromise the account by allowing access with a standard
155 fputs ( "using restricted shell\n", stderr );
160 opt_shell = xstrdup ( pw-> pw_shell );
162 change_identity ( pw );
163 setup_environment ( opt_shell, opt_loginshell, !opt_preserve, pw );
164 run_shell ( opt_shell, opt_loginshell, opt_command, opt_args );