source: branches/2.2.5/mindi-busybox/loginutils/su.c @ 1765

Last change on this file since 1765 was 1765, checked in by Bruno Cornec, 13 years ago

Update to busybox 1.7.2

File size: 2.7 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 *  Mini su implementation for busybox
4 *
5 *  Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
6 */
7
8#include "libbb.h"
9#include <syslog.h>
10
11#define SU_OPT_mp (3)
12#define SU_OPT_l (4)
13
14int su_main(int argc, char **argv);
15int su_main(int argc, char **argv)
16{
17    unsigned flags;
18    char *opt_shell = NULL;
19    char *opt_command = NULL;
20    const char *opt_username = "root";
21    struct passwd *pw;
22    uid_t cur_uid = getuid();
23    const char *tty;
24    char *old_user;
25
26    flags = getopt32(argv, "mplc:s:", &opt_command, &opt_shell);
27    argc -= optind;
28    argv += optind;
29
30    if (argc && LONE_DASH(argv[0])) {
31        flags |= SU_OPT_l;
32        argc--;
33        argv++;
34    }
35
36    /* get user if specified */
37    if (argc) {
38        opt_username = argv[0];
39//      argc--;
40        argv++;
41    }
42
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);
51    }
52
53    pw = getpwnam(opt_username);
54    if (!pw)
55        bb_error_msg_and_die("unknown id: %s", opt_username);
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.  */
60    if (!pw->pw_shell || !pw->pw_shell[0])
61        pw->pw_shell = (char *)DEFAULT_SHELL;
62
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);
67    } else {
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");
72    }
73
74    if (ENABLE_FEATURE_CLEAN_UP && ENABLE_FEATURE_SU_SYSLOG) {
75        closelog();
76        free(old_user);
77    }
78
79    if (!opt_shell && (flags & SU_OPT_mp))
80        opt_shell = getenv("SHELL");
81
82#if ENABLE_FEATURE_SU_CHECKS_SHELLS
83    if (opt_shell && cur_uid && restricted_shell(pw->pw_shell)) {
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.  */
88        bb_error_msg("using restricted shell");
89        opt_shell = 0;
90    }
91#endif
92    if (!opt_shell)
93        opt_shell = pw->pw_shell;
94
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);)
98
99    /* Never returns */
100    run_shell(opt_shell, flags & SU_OPT_l, opt_command, (const char**)argv);
101
102    return EXIT_FAILURE;
103}
Note: See TracBrowser for help on using the repository browser.