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

Last change on this file since 1533 was 821, checked in by Bruno Cornec, 18 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.