diff options
-rw-r--r-- | include/applets.h | 2 | ||||
-rw-r--r-- | loginutils/su.c | 140 |
2 files changed, 67 insertions, 75 deletions
diff --git a/include/applets.h b/include/applets.h index cd5065103..0b65266f3 100644 --- a/include/applets.h +++ b/include/applets.h @@ -392,7 +392,7 @@ APPLET(more, more_main, _BB_DIR_BIN, _BB_SUID_NEVER) #endif #ifdef CONFIG_MOUNT - APPLET(mount, mount_main, _BB_DIR_BIN, _BB_SUID_MAYBE) + APPLET(mount, mount_main, _BB_DIR_BIN, _BB_SUID_NEVER) #endif #ifdef CONFIG_MSH APPLET_NOUSAGE("msh", msh_main, _BB_DIR_BIN, _BB_SUID_NEVER) diff --git a/loginutils/su.c b/loginutils/su.c index 85f5cbe7b..04c213e4e 100644 --- a/loginutils/su.c +++ b/loginutils/su.c @@ -29,77 +29,57 @@ #if defined( SYSLOG_SUCCESS ) || defined( SYSLOG_FAILURE ) -/* Log the fact that someone has run su to the user given by PW; - if SUCCESSFUL is nonzero, they gave the correct password, etc. */ +/* Log the fact that someone has run su */ -static void log_su ( const struct passwd *pw, int successful ) +# if defined( SYSLOG_SUCCESS ) && defined( SYSLOG_FAILURE ) +static void log_su (const char *successful, const char *old_user, const char *tty) { - const char *old_user, *tty; - -#if !defined( SYSLOG_SUCESS ) - if ( successful ) - return; -#endif -#if !defined( SYSLOG_FAILURE ) - if ( !successful ) - return; -#endif - - if ( pw-> pw_uid ) // not to root -> ignored - return; - - /* The utmp entry (via getlogin) is probably the best way to identify - the user, especially if someone su's from a su-shell. */ - old_user = getlogin ( ); - if ( !old_user ) { - /* getlogin can fail -- usually due to lack of utmp entry. Resort to getpwuid. */ - struct passwd *pwd = getpwuid ( getuid ( )); - old_user = ( pwd ? pwd-> pw_name : "" ); - } - - tty = ttyname ( 2 ); - - openlog ( "su", 0, LOG_AUTH ); - syslog ( LOG_NOTICE, "%s%s on %s", successful ? "" : "FAILED SU ", old_user, tty ? tty : "none" ); + syslog ( LOG_NOTICE, "%s%s on %s", successful, old_user, tty); } +# define log_su_successful(cu, u, tty) if(!cu) log_su("", u, tty) +# define log_su_failure(cu, u, tty) if(!cu) log_su("FAILED SU ", u, tty) +# else + /* partial logging */ +# if !defined( SYSLOG_SUCESS ) +# define log_su_successful(cu, u, tty) +# define log_su_failure(cu, u, t) if(!cu) \ + syslog(LOG_NOTICE, "FAILED SU %s on %s", u, t) +# else +# define log_su_successful(cu, u, t) if(!cu) \ + syslog(LOG_NOTICE, "%s on %s", u, t) +# define log_su_failure(cu, u, tty) +# endif +# endif +#else + /* logging not used */ +# define log_su_successful(cu, u, tty) +# define log_su_failure(cu, u, tty) #endif - int su_main ( int argc, char **argv ) { - int flag; - int opt_preserve = 0; - int opt_loginshell = 0; + unsigned long flags; + int opt_preserve; + int opt_loginshell; char *opt_shell = 0; char *opt_command = 0; char *opt_username = DEFAULT_USER; char **opt_args = 0; - struct passwd *pw, pw_copy; - - - while (( flag = getopt ( argc, argv, "c:lmps:" )) != -1 ) { - switch ( flag ) { - case 'c': - opt_command = optarg; - break; - case 'm': - case 'p': - opt_preserve = 1; - break; - case 's': - opt_shell = optarg; - break; - case 'l': - opt_loginshell = 1; - break; - default: - bb_show_usage( ); - break; - } - } + struct passwd *pw; + uid_t cur_uid = getuid(); + +#if defined( SYSLOG_SUCCESS ) || defined( SYSLOG_FAILURE ) + const char *tty; + const char *old_user; +#endif - if (( optind < argc ) && ( argv [optind][0] == '-' ) && ( argv [optind][1] == 0 )) { + flags = bb_getopt_ulflags(argc, argv, "mplc:s:", + &opt_command, &opt_shell); + opt_preserve = flags & 3; + opt_loginshell = (flags & 4 ? 1 : 0); + + if (optind < argc && argv[optind][0] == '-' && argv[optind][1] == 0) { opt_loginshell = 1; ++optind; } @@ -111,6 +91,24 @@ int su_main ( int argc, char **argv ) if ( optind < argc ) opt_args = argv + optind; +#if defined( SYSLOG_SUCCESS ) || defined( SYSLOG_FAILURE ) +#ifdef CONFIG_FEATURE_U_W_TMP + /* The utmp entry (via getlogin) is probably the best way to identify + the user, especially if someone su's from a su-shell. */ + old_user = getlogin ( ); + if ( !old_user ) +#endif + { + /* getlogin can fail -- usually due to lack of utmp entry. Resort to getpwuid. */ + pw = getpwuid ( cur_uid ); + old_user = ( pw ? pw->pw_name : "" ); + } + tty = ttyname ( 2 ); + if(!tty) + tty = "none"; + + openlog ( bb_applet_name, 0, LOG_AUTH ); +#endif pw = getpwnam ( opt_username ); if ( !pw ) @@ -122,27 +120,21 @@ int su_main ( int argc, char **argv ) if ( !pw-> pw_shell || !pw->pw_shell [0] ) pw-> pw_shell = (char *) DEFAULT_SHELL; - /* Make a copy of the password information and point pw at the local - copy instead. Otherwise, some systems (e.g. Linux) would clobber - the static data through the getlogin call from log_su. */ - pw_copy = *pw; - pw = &pw_copy; - pw-> pw_name = bb_xstrdup ( pw-> pw_name ); - pw-> pw_dir = bb_xstrdup ( pw-> pw_dir ); - pw-> pw_shell = bb_xstrdup ( pw-> pw_shell ); - - if (( getuid ( ) == 0 ) || correct_password ( pw )) - log_su ( pw, 1 ); - else { - log_su ( pw, 0 ); + if ((( cur_uid == 0 ) || correct_password ( pw ))) { + log_su_successful(pw->pw_uid, old_user, tty ); + } else { + log_su_failure (pw->pw_uid, old_user, tty ); bb_error_msg_and_die ( "incorrect password" ); } +#if defined( SYSLOG_SUCCESS ) || defined( SYSLOG_FAILURE ) + closelog(); +#endif + if ( !opt_shell && opt_preserve ) opt_shell = getenv ( "SHELL" ); - if ( opt_shell && getuid ( ) && restricted_shell ( pw-> pw_shell )) - { + if ( opt_shell && cur_uid && restricted_shell ( pw-> pw_shell )) { /* The user being su'd to has a nonstandard shell, and so is probably a uucp account or has restricted access. Don't compromise the account by allowing access with a standard @@ -152,7 +144,7 @@ int su_main ( int argc, char **argv ) } if ( !opt_shell ) - opt_shell = bb_xstrdup ( pw-> pw_shell ); + opt_shell = pw->pw_shell; change_identity ( pw ); setup_environment ( opt_shell, opt_loginshell, !opt_preserve, pw ); |