[821] | 1 | /* vi: set sw=4 ts=4: */
|
---|
| 2 | /*
|
---|
[1765] | 3 | * Mini su implementation for busybox
|
---|
| 4 | *
|
---|
| 5 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
|
---|
| 6 | */
|
---|
[821] | 7 |
|
---|
[1765] | 8 | #include "libbb.h"
|
---|
[821] | 9 | #include <syslog.h>
|
---|
| 10 |
|
---|
[1765] | 11 | #define SU_OPT_mp (3)
|
---|
| 12 | #define SU_OPT_l (4)
|
---|
[821] | 13 |
|
---|
[1765] | 14 | int su_main(int argc, char **argv);
|
---|
| 15 | int su_main(int argc, char **argv)
|
---|
[821] | 16 | {
|
---|
[1765] | 17 | unsigned flags;
|
---|
| 18 | char *opt_shell = NULL;
|
---|
| 19 | char *opt_command = NULL;
|
---|
| 20 | const char *opt_username = "root";
|
---|
[821] | 21 | struct passwd *pw;
|
---|
| 22 | uid_t cur_uid = getuid();
|
---|
| 23 | const char *tty;
|
---|
[1765] | 24 | char *old_user;
|
---|
[821] | 25 |
|
---|
[1765] | 26 | flags = getopt32(argv, "mplc:s:", &opt_command, &opt_shell);
|
---|
| 27 | argc -= optind;
|
---|
| 28 | argv += optind;
|
---|
[821] | 29 |
|
---|
[1765] | 30 | if (argc && LONE_DASH(argv[0])) {
|
---|
[821] | 31 | flags |= SU_OPT_l;
|
---|
[1765] | 32 | argc--;
|
---|
| 33 | argv++;
|
---|
| 34 | }
|
---|
[821] | 35 |
|
---|
| 36 | /* get user if specified */
|
---|
[1765] | 37 | if (argc) {
|
---|
| 38 | opt_username = argv[0];
|
---|
| 39 | // argc--;
|
---|
| 40 | argv++;
|
---|
| 41 | }
|
---|
[821] | 42 |
|
---|
[1765] | 43 | if (ENABLE_FEATURE_SU_SYSLOG) {
|
---|
| 44 | /* The utmp entry (via getlogin) is probably the best way to identify
|
---|
| 45 | the user, especially if someone su's from a su-shell.
|
---|
| 46 | But getlogin can fail -- usually due to lack of utmp entry.
|
---|
| 47 | in this case resort to getpwuid. */
|
---|
| 48 | old_user = xstrdup(USE_FEATURE_UTMP(getlogin() ? : ) (pw = getpwuid(cur_uid)) ? pw->pw_name : "");
|
---|
| 49 | tty = ttyname(2) ? : "none";
|
---|
| 50 | openlog(applet_name, 0, LOG_AUTH);
|
---|
[821] | 51 | }
|
---|
| 52 |
|
---|
[1765] | 53 | pw = getpwnam(opt_username);
|
---|
| 54 | if (!pw)
|
---|
| 55 | bb_error_msg_and_die("unknown id: %s", opt_username);
|
---|
[821] | 56 |
|
---|
| 57 | /* Make sure pw->pw_shell is non-NULL. It may be NULL when NEW_USER
|
---|
| 58 | is a username that is retrieved via NIS (YP), but that doesn't have
|
---|
| 59 | a default shell listed. */
|
---|
[1765] | 60 | if (!pw->pw_shell || !pw->pw_shell[0])
|
---|
| 61 | pw->pw_shell = (char *)DEFAULT_SHELL;
|
---|
[821] | 62 |
|
---|
[1765] | 63 | if ((cur_uid == 0) || correct_password(pw)) {
|
---|
| 64 | if (ENABLE_FEATURE_SU_SYSLOG)
|
---|
| 65 | syslog(LOG_NOTICE, "%c %s %s:%s",
|
---|
| 66 | '+', tty, old_user, opt_username);
|
---|
[821] | 67 | } else {
|
---|
[1765] | 68 | if (ENABLE_FEATURE_SU_SYSLOG)
|
---|
| 69 | syslog(LOG_NOTICE, "%c %s %s:%s",
|
---|
| 70 | '-', tty, old_user, opt_username);
|
---|
| 71 | bb_error_msg_and_die("incorrect password");
|
---|
[821] | 72 | }
|
---|
| 73 |
|
---|
[1765] | 74 | if (ENABLE_FEATURE_CLEAN_UP && ENABLE_FEATURE_SU_SYSLOG) {
|
---|
| 75 | closelog();
|
---|
| 76 | free(old_user);
|
---|
| 77 | }
|
---|
[821] | 78 |
|
---|
[1765] | 79 | if (!opt_shell && (flags & SU_OPT_mp))
|
---|
| 80 | opt_shell = getenv("SHELL");
|
---|
[821] | 81 |
|
---|
[1765] | 82 | #if ENABLE_FEATURE_SU_CHECKS_SHELLS
|
---|
| 83 | if (opt_shell && cur_uid && restricted_shell(pw->pw_shell)) {
|
---|
[821] | 84 | /* The user being su'd to has a nonstandard shell, and so is
|
---|
| 85 | probably a uucp account or has restricted access. Don't
|
---|
| 86 | compromise the account by allowing access with a standard
|
---|
| 87 | shell. */
|
---|
[1765] | 88 | bb_error_msg("using restricted shell");
|
---|
[821] | 89 | opt_shell = 0;
|
---|
| 90 | }
|
---|
[1765] | 91 | #endif
|
---|
| 92 | if (!opt_shell)
|
---|
[821] | 93 | opt_shell = pw->pw_shell;
|
---|
| 94 |
|
---|
[1765] | 95 | change_identity(pw);
|
---|
| 96 | setup_environment(opt_shell, flags & SU_OPT_l, !(flags & SU_OPT_mp), pw);
|
---|
| 97 | USE_SELINUX(set_current_security_context(NULL);)
|
---|
[821] | 98 |
|
---|
[1765] | 99 | /* Never returns */
|
---|
| 100 | run_shell(opt_shell, flags & SU_OPT_l, opt_command, (const char**)argv);
|
---|
| 101 |
|
---|
[821] | 102 | return EXIT_FAILURE;
|
---|
| 103 | }
|
---|