source: branches/2.2.2/mindi-busybox/loginutils/su.c @ 1247

Last change on this file since 1247 was 821, checked in by Bruno Cornec, 14 years ago

Addition of busybox 1.2.1 as a mindi-busybox new package
This should avoid delivering binary files in mindi not built there (Fedora and Debian are quite serious about that)

File size: 4.1 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3   Licensed under the GPL v2, see the file LICENSE in this tarball.
4*/
5
6#include <fcntl.h>
7#include <signal.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <syslog.h>
12#include <termios.h>
13#include <unistd.h>
14#include <utmp.h>
15#include <sys/resource.h>
16#include <sys/stat.h>
17#include <sys/types.h>
18#include <ctype.h>
19#include <time.h>
20
21#include "busybox.h"
22
23/* The shell to run if none is given in the user's passwd entry.  */
24#ifndef DEFAULT_SHELL
25#define DEFAULT_SHELL "/bin/sh"
26#endif
27
28/* Default user.  */
29#define DEFAULT_USER  "root"
30
31/* #define SYSLOG_SUCCESS */
32#define SYSLOG_FAILURE
33
34
35#if defined( SYSLOG_SUCCESS ) || defined( SYSLOG_FAILURE )
36/* Log the fact that someone has run su */
37
38# if defined( SYSLOG_SUCCESS ) && defined( SYSLOG_FAILURE )
39static void log_su (const char *successful, const char *old_user,
40                    const char *tty)
41{
42    syslog ( LOG_NOTICE, "%s%s on %s", successful, old_user, tty);
43}
44#  define log_su_successful(cu, u, tty) if(!cu) log_su("", u, tty)
45#  define log_su_failure(cu, u, tty)    if(!cu) log_su("FAILED SU ", u, tty)
46# else
47    /* partial logging */
48#  if !defined( SYSLOG_SUCESS )
49#   define log_su_successful(cu, u, tty)
50#   define log_su_failure(cu, u, t) if(!cu) \
51            syslog(LOG_NOTICE, "FAILED SU %s on %s", u, t)
52#  else
53#   define log_su_successful(cu, u, t) if(!cu) \
54            syslog(LOG_NOTICE, "%s on %s", u, t)
55#   define log_su_failure(cu, u, tty)
56#  endif
57# endif
58#else
59    /* logging not used */
60# define log_su_successful(cu, u, tty)
61# define log_su_failure(cu, u, tty)
62#endif
63
64
65int su_main ( int argc, char **argv )
66{
67    unsigned long flags;
68    char *opt_shell = 0;
69    char *opt_command = 0;
70    char *opt_username = DEFAULT_USER;
71    char **opt_args = 0;
72    struct passwd *pw;
73    uid_t cur_uid = getuid();
74
75#if defined( SYSLOG_SUCCESS ) || defined( SYSLOG_FAILURE )
76    const char *tty;
77    const char *old_user;
78#endif
79
80    flags = bb_getopt_ulflags(argc, argv, "mplc:s:",
81                          &opt_command, &opt_shell);
82#define SU_OPT_m (3)
83#define SU_OPT_p (3)
84#define SU_OPT_l (4)
85
86    if (optind < argc  && argv[optind][0] == '-' && argv[optind][1] == 0) {
87        flags |= SU_OPT_l;
88        ++optind;
89    }
90
91    /* get user if specified */
92    if ( optind < argc )
93        opt_username = argv [optind++];
94
95    if ( optind < argc )
96        opt_args = argv + optind;
97
98#if defined( SYSLOG_SUCCESS ) || defined( SYSLOG_FAILURE )
99#ifdef CONFIG_FEATURE_UTMP
100    /* The utmp entry (via getlogin) is probably the best way to identify
101       the user, especially if someone su's from a su-shell.  */
102    old_user = getlogin ( );
103    if ( !old_user )
104#endif
105        {
106        /* getlogin can fail -- usually due to lack of utmp entry.
107           Resort to getpwuid.  */
108        pw = getpwuid ( cur_uid );
109        old_user = ( pw ? pw->pw_name : "" );
110    }
111    tty = ttyname ( 2 );
112    if(!tty)
113        tty = "none";
114
115    openlog ( bb_applet_name, 0, LOG_AUTH );
116#endif
117
118    pw = getpwnam ( opt_username );
119    if ( !pw )
120        bb_error_msg_and_die ( "user %s does not exist", opt_username );
121
122    /* Make sure pw->pw_shell is non-NULL.  It may be NULL when NEW_USER
123       is a username that is retrieved via NIS (YP), but that doesn't have
124       a default shell listed.  */
125    if ( !pw->pw_shell || !pw->pw_shell [0] )
126        pw->pw_shell = (char *) DEFAULT_SHELL;
127
128    if ((( cur_uid == 0 ) || correct_password ( pw ))) {
129        log_su_successful(pw->pw_uid, old_user, tty );
130    } else {
131        log_su_failure (pw->pw_uid, old_user, tty );
132        bb_error_msg_and_die ( "incorrect password" );
133    }
134
135#if defined( SYSLOG_SUCCESS ) || defined( SYSLOG_FAILURE )
136    closelog();
137#endif
138
139    if ( !opt_shell && (flags & SU_OPT_p))
140        opt_shell = getenv ( "SHELL" );
141
142    if ( opt_shell && cur_uid && restricted_shell ( pw->pw_shell )) {
143        /* The user being su'd to has a nonstandard shell, and so is
144           probably a uucp account or has restricted access.  Don't
145           compromise the account by allowing access with a standard
146           shell.  */
147        fputs ( "using restricted shell\n", stderr );
148        opt_shell = 0;
149    }
150
151    if ( !opt_shell )
152        opt_shell = pw->pw_shell;
153
154    change_identity ( pw );
155    setup_environment(opt_shell, flags & SU_OPT_l, !(flags & SU_OPT_p), pw);
156#if ENABLE_SELINUX
157       set_current_security_context(NULL);
158#endif
159    run_shell(opt_shell, flags & SU_OPT_l, opt_command, (const char**)opt_args);
160
161    return EXIT_FAILURE;
162}
Note: See TracBrowser for help on using the repository browser.