mirror of
https://git.savannah.gnu.org/git/coreutils.git
synced 2025-07-29 12:21:15 +03:00
su: remove program (util-linux is now the best source for it)
* README: Omit "su" from list of programs. * src/su.c: Remove file. * src/Makefile.am: Remove su-related rules and variables. * tests/misc/su-fail: Remove test. * tests/Makefile.am (TESTS): Remove misc/su-fail. * tests/misc/invalid-opt: Remove su-related code. * src/.gitignore: Remove su. * man/su.x: Remove file. * man/Makefile.am (su.1): Remove rule. * po/POTFILES.in: Remove su.c from the list. * TODO: Remove ancient entry. * NEWS (Changes in behavior): Mention it. * doc/coreutils.texi: Remove su-related description. * AUTHORS: Remove su. * m4/lib-check.m4 (cu_LIB_CHECK): Remove file/macro. * configure.ac: Remove su-related code and sole use of cu_LIB_CHECK. * scripts/git-hooks/commit-msg: Remove su from this list, too.
This commit is contained in:
1
AUTHORS
1
AUTHORS
@ -80,7 +80,6 @@ split: Torbjörn Granlund, Richard M. Stallman
|
|||||||
stat: Michael Meskes
|
stat: Michael Meskes
|
||||||
stdbuf: Pádraig Brady
|
stdbuf: Pádraig Brady
|
||||||
stty: David MacKenzie
|
stty: David MacKenzie
|
||||||
su: David MacKenzie
|
|
||||||
sum: Kayvan Aghaiepour, David MacKenzie
|
sum: Kayvan Aghaiepour, David MacKenzie
|
||||||
sync: Jim Meyering
|
sync: Jim Meyering
|
||||||
tac: Jay Lepreau, David MacKenzie
|
tac: Jay Lepreau, David MacKenzie
|
||||||
|
8
NEWS
8
NEWS
@ -30,6 +30,14 @@ GNU coreutils NEWS -*- outline -*-
|
|||||||
|
|
||||||
stat -f recognizes the new remote file system type, panfs.
|
stat -f recognizes the new remote file system type, panfs.
|
||||||
|
|
||||||
|
** Changes in behavior
|
||||||
|
|
||||||
|
su: this program has been removed. We stopped installing "su" by
|
||||||
|
default with the release of coreutils-6.9.90 on 2007-12-01. Now,
|
||||||
|
that the util-linux package has the union of the Suse and Fedora
|
||||||
|
patches as well as enough support to build on the Hurd, we no longer
|
||||||
|
have any reason to include it here.
|
||||||
|
|
||||||
|
|
||||||
* Noteworthy changes in release 8.17 (2012-05-10) [stable]
|
* Noteworthy changes in release 8.17 (2012-05-10) [stable]
|
||||||
|
|
||||||
|
2
README
2
README
@ -13,7 +13,7 @@ The programs that can be built with this package are:
|
|||||||
link ln logname ls md5sum mkdir mkfifo mknod mktemp mv nice nl nohup
|
link ln logname ls md5sum mkdir mkfifo mknod mktemp mv nice nl nohup
|
||||||
nproc od paste pathchk pinky pr printenv printf ptx pwd readlink realpath
|
nproc od paste pathchk pinky pr printenv printf ptx pwd readlink realpath
|
||||||
rm rmdir runcon seq sha1sum sha224sum sha256sum sha384sum sha512sum shred
|
rm rmdir runcon seq sha1sum sha224sum sha256sum sha384sum sha512sum shred
|
||||||
shuf sleep sort split stat stdbuf stty su sum sync tac tail tee test
|
shuf sleep sort split stat stdbuf stty sum sync tac tail tee test
|
||||||
timeout touch tr true truncate tsort tty uname unexpand uniq unlink
|
timeout touch tr true truncate tsort tty uname unexpand uniq unlink
|
||||||
uptime users vdir wc who whoami yes
|
uptime users vdir wc who whoami yes
|
||||||
|
|
||||||
|
3
TODO
3
TODO
@ -78,9 +78,6 @@ unexpand: [http://www.opengroup.org/onlinepubs/007908799/xcu/unexpand.html]
|
|||||||
printf 'x\t \t y\n'|unexpand -t 8,9 should print its input, unmodified.
|
printf 'x\t \t y\n'|unexpand -t 8,9 should print its input, unmodified.
|
||||||
printf 'x\t \t y\n'|unexpand -t 5,8 should print "x\ty\n"
|
printf 'x\t \t y\n'|unexpand -t 5,8 should print "x\ty\n"
|
||||||
|
|
||||||
Let GNU su use the 'wheel' group if appropriate.
|
|
||||||
(there are a couple patches, already)
|
|
||||||
|
|
||||||
sort: Investigate better sorting algorithms; see Knuth vol. 3.
|
sort: Investigate better sorting algorithms; see Knuth vol. 3.
|
||||||
|
|
||||||
We tried list merge sort, but it was about 50% slower than the
|
We tried list merge sort, but it was about 50% slower than the
|
||||||
|
13
configure.ac
13
configure.ac
@ -380,7 +380,6 @@ AC_CHECK_DECLS([strsignal, sys_siglist, _sys_siglist, __sys_siglist], , ,
|
|||||||
[AC_INCLUDES_DEFAULT
|
[AC_INCLUDES_DEFAULT
|
||||||
#include <signal.h>])
|
#include <signal.h>])
|
||||||
|
|
||||||
cu_LIB_CHECK
|
|
||||||
cu_GMP
|
cu_GMP
|
||||||
|
|
||||||
# Build df only if there's a point to it.
|
# Build df only if there's a point to it.
|
||||||
@ -421,7 +420,7 @@ t=`sed -n '/^'$v' =/,/[[^\]]$/p' $mk \
|
|||||||
no_install_progs_default=`echo "$t"|sed 's/ $//'`
|
no_install_progs_default=`echo "$t"|sed 's/ $//'`
|
||||||
|
|
||||||
# Unfortunately, due to the way autoconf's AS_HELP_STRING works, the list
|
# Unfortunately, due to the way autoconf's AS_HELP_STRING works, the list
|
||||||
# of default-not-installed programs, "arch hostname su", must appear in two
|
# of default-not-installed programs, "arch hostname", must appear in two
|
||||||
# places: in this file below, and in $mk. Using "$no_install_progs_default"
|
# places: in this file below, and in $mk. Using "$no_install_progs_default"
|
||||||
# below cannot work. And we can't substitute the names into $mk because
|
# below cannot work. And we can't substitute the names into $mk because
|
||||||
# automake needs the literals, too.
|
# automake needs the literals, too.
|
||||||
@ -448,7 +447,7 @@ esac
|
|||||||
# Note how the second argument below is a literal, with "," separators.
|
# Note how the second argument below is a literal, with "," separators.
|
||||||
# That is required due to the way the macro works, and since the
|
# That is required due to the way the macro works, and since the
|
||||||
# corresponding ./configure option argument is comma-separated on input.
|
# corresponding ./configure option argument is comma-separated on input.
|
||||||
gl_INCLUDE_EXCLUDE_PROG([optional_bin_progs], [arch,hostname,su])
|
gl_INCLUDE_EXCLUDE_PROG([optional_bin_progs], [arch,hostname])
|
||||||
|
|
||||||
# Now that we know which programs will actually be built up, figure out
|
# Now that we know which programs will actually be built up, figure out
|
||||||
# which optional helper progs should be compiled.
|
# which optional helper progs should be compiled.
|
||||||
@ -457,14 +456,6 @@ case " $optional_bin_progs " in
|
|||||||
*' stdbuf '*) gl_ADD_PROG([optional_pkglib_progs], [libstdbuf.so]) ;;
|
*' stdbuf '*) gl_ADD_PROG([optional_pkglib_progs], [libstdbuf.so]) ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Set INSTALL_SU if su installation has been requested via
|
|
||||||
# --enable-install-program=su.
|
|
||||||
AC_SUBST([INSTALL_SU])
|
|
||||||
case " $optional_bin_progs " in
|
|
||||||
*' su '*) INSTALL_SU=yes ;;
|
|
||||||
*) INSTALL_SU=no ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
MAN=`echo "$optional_bin_progs "|sed 's/ /.1 /g;s/ $//'|tr -d '\\015\\012'`
|
MAN=`echo "$optional_bin_progs "|sed 's/ /.1 /g;s/ $//'|tr -d '\\015\\012'`
|
||||||
|
|
||||||
# Change "ginstall.1" to "install.1" in $MAN.
|
# Change "ginstall.1" to "install.1" in $MAN.
|
||||||
|
@ -109,7 +109,6 @@
|
|||||||
* stat: (coreutils)stat invocation. Report file(system) status.
|
* stat: (coreutils)stat invocation. Report file(system) status.
|
||||||
* stdbuf: (coreutils)stdbuf invocation. Modify stdio buffering.
|
* stdbuf: (coreutils)stdbuf invocation. Modify stdio buffering.
|
||||||
* stty: (coreutils)stty invocation. Print/change terminal settings.
|
* stty: (coreutils)stty invocation. Print/change terminal settings.
|
||||||
* su: (coreutils)su invocation. Modify user and group ID.
|
|
||||||
* sum: (coreutils)sum invocation. Print traditional checksum.
|
* sum: (coreutils)sum invocation. Print traditional checksum.
|
||||||
* sync: (coreutils)sync invocation. Synchronize memory and disk.
|
* sync: (coreutils)sync invocation. Synchronize memory and disk.
|
||||||
* tac: (coreutils)tac invocation. Reverse files.
|
* tac: (coreutils)tac invocation. Reverse files.
|
||||||
@ -200,7 +199,7 @@ Free Documentation License''.
|
|||||||
* User information:: id logname whoami groups users who
|
* User information:: id logname whoami groups users who
|
||||||
* System context:: date arch nproc uname hostname hostid uptime
|
* System context:: date arch nproc uname hostname hostid uptime
|
||||||
* SELinux context:: chcon runcon
|
* SELinux context:: chcon runcon
|
||||||
* Modified command invocation:: chroot env nice nohup stdbuf su timeout
|
* Modified command invocation:: chroot env nice nohup stdbuf timeout
|
||||||
* Process control:: kill
|
* Process control:: kill
|
||||||
* Delaying:: sleep
|
* Delaying:: sleep
|
||||||
* Numeric operations:: factor seq
|
* Numeric operations:: factor seq
|
||||||
@ -443,7 +442,6 @@ Modified command invocation
|
|||||||
* nice invocation:: Run a command with modified niceness
|
* nice invocation:: Run a command with modified niceness
|
||||||
* nohup invocation:: Run a command immune to hangups
|
* nohup invocation:: Run a command immune to hangups
|
||||||
* stdbuf invocation:: Run a command with modified I/O buffering
|
* stdbuf invocation:: Run a command with modified I/O buffering
|
||||||
* su invocation:: Run a command with substitute user and group ID
|
|
||||||
* timeout invocation:: Run a command with a time limit
|
* timeout invocation:: Run a command with a time limit
|
||||||
|
|
||||||
Process control
|
Process control
|
||||||
@ -766,7 +764,7 @@ meanings with the values @samp{0} and @samp{1}.
|
|||||||
Here are some of the exceptions:
|
Here are some of the exceptions:
|
||||||
@command{chroot}, @command{env}, @command{expr}, @command{nice},
|
@command{chroot}, @command{env}, @command{expr}, @command{nice},
|
||||||
@command{nohup}, @command{printenv}, @command{sort}, @command{stdbuf},
|
@command{nohup}, @command{printenv}, @command{sort}, @command{stdbuf},
|
||||||
@command{su}, @command{test}, @command{timeout}, @command{tty}.
|
@command{test}, @command{timeout}, @command{tty}.
|
||||||
|
|
||||||
|
|
||||||
@node Backup options
|
@node Backup options
|
||||||
@ -15266,7 +15264,6 @@ user, etc.
|
|||||||
* nice invocation:: Modify niceness.
|
* nice invocation:: Modify niceness.
|
||||||
* nohup invocation:: Immunize to hangups.
|
* nohup invocation:: Immunize to hangups.
|
||||||
* stdbuf invocation:: Modify buffering of standard streams.
|
* stdbuf invocation:: Modify buffering of standard streams.
|
||||||
* su invocation:: Modify user and group ID.
|
|
||||||
* timeout invocation:: Run with time limit.
|
* timeout invocation:: Run with time limit.
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@ -15794,163 +15791,6 @@ the exit status of @var{command} otherwise
|
|||||||
@end display
|
@end display
|
||||||
|
|
||||||
|
|
||||||
@node su invocation
|
|
||||||
@section @command{su}: Run a command with substitute user and group ID
|
|
||||||
|
|
||||||
@pindex su
|
|
||||||
@cindex substitute user and group IDs
|
|
||||||
@cindex user ID, switching
|
|
||||||
@cindex super-user, becoming
|
|
||||||
@cindex root, becoming
|
|
||||||
|
|
||||||
@command{su} allows one user to temporarily become another user. It runs a
|
|
||||||
command (often an interactive shell) with the real and effective user
|
|
||||||
ID, group ID, and supplemental groups of a given @var{user}. Synopsis:
|
|
||||||
|
|
||||||
@example
|
|
||||||
su [@var{option}]@dots{} [@var{user} [@var{arg}]@dots{}]
|
|
||||||
@end example
|
|
||||||
|
|
||||||
@cindex passwd entry, and @command{su} shell
|
|
||||||
@flindex /bin/sh
|
|
||||||
@flindex /etc/passwd
|
|
||||||
If no @var{user} is given, the default is @code{root}, the super-user.
|
|
||||||
The shell to use is taken from @var{user}'s @code{passwd} entry, or
|
|
||||||
@file{/bin/sh} if none is specified there. If @var{user} has a
|
|
||||||
password, @command{su} prompts for the password unless run by a user with
|
|
||||||
effective user ID of zero (the super-user).
|
|
||||||
|
|
||||||
@vindex HOME
|
|
||||||
@vindex SHELL
|
|
||||||
@vindex USER
|
|
||||||
@vindex LOGNAME
|
|
||||||
@cindex login shell
|
|
||||||
By default, @command{su} does not change the current directory.
|
|
||||||
It sets the environment variables @env{HOME} and @env{SHELL}
|
|
||||||
from the password entry for @var{user}, and if @var{user} is not
|
|
||||||
the super-user, sets @env{USER} and @env{LOGNAME} to @var{user}.
|
|
||||||
By default, the shell is not a login shell.
|
|
||||||
|
|
||||||
Any additional @var{arg}s are passed as additional arguments to the
|
|
||||||
shell.
|
|
||||||
|
|
||||||
@cindex @option{-su}
|
|
||||||
GNU @command{su} does not treat @file{/bin/sh} or any other shells specially
|
|
||||||
(e.g., by setting @code{argv[0]} to @option{-su}, passing @option{-c} only
|
|
||||||
to certain shells, etc.).
|
|
||||||
|
|
||||||
@findex syslog
|
|
||||||
@command{su} can optionally be compiled to use @code{syslog} to report
|
|
||||||
failed, and optionally successful, @command{su} attempts. (If the system
|
|
||||||
supports @code{syslog}.) However, GNU @command{su} does not check if the
|
|
||||||
user is a member of the @code{wheel} group; see below.
|
|
||||||
|
|
||||||
The program accepts the following options. Also see @ref{Common options}.
|
|
||||||
|
|
||||||
@table @samp
|
|
||||||
@item -c @var{command}
|
|
||||||
@itemx --command=@var{command}
|
|
||||||
@opindex -c
|
|
||||||
@opindex --command
|
|
||||||
Pass @var{command}, a single command line to run, to the shell with
|
|
||||||
a @option{-c} option instead of starting an interactive shell.
|
|
||||||
|
|
||||||
@item -f
|
|
||||||
@itemx --fast
|
|
||||||
@opindex -f
|
|
||||||
@opindex --fast
|
|
||||||
@flindex .cshrc
|
|
||||||
@cindex file name pattern expansion, disabled
|
|
||||||
@cindex globbing, disabled
|
|
||||||
Pass the @option{-f} option to the shell. This probably only makes sense
|
|
||||||
if the shell run is @command{csh} or @command{tcsh}, for which the @option{-f}
|
|
||||||
option prevents reading the startup file (@file{.cshrc}). With
|
|
||||||
Bourne-like shells, the @option{-f} option disables file name pattern
|
|
||||||
expansion (globbing), which is not likely to be useful.
|
|
||||||
|
|
||||||
@item -
|
|
||||||
@itemx -l
|
|
||||||
@itemx --login
|
|
||||||
@opindex -
|
|
||||||
@opindex -l
|
|
||||||
@opindex --login
|
|
||||||
@c other variables already indexed above
|
|
||||||
@vindex TERM
|
|
||||||
@vindex PATH
|
|
||||||
@cindex login shell, creating
|
|
||||||
Make the shell a login shell. This means the following. Unset all
|
|
||||||
environment variables except @env{TERM}, @env{HOME}, and @env{SHELL}
|
|
||||||
(which are set as described above), and @env{USER} and @env{LOGNAME}
|
|
||||||
(which are set, even for the super-user, as described above), and set
|
|
||||||
@env{PATH} to a compiled-in default value. Change to @var{user}'s home
|
|
||||||
directory. Prepend @samp{-} to the shell's name, intended to make it
|
|
||||||
read its login startup file(s).
|
|
||||||
|
|
||||||
@item -m
|
|
||||||
@itemx -p
|
|
||||||
@itemx --preserve-environment
|
|
||||||
@opindex -m
|
|
||||||
@opindex -p
|
|
||||||
@opindex --preserve-environment
|
|
||||||
@cindex environment, preserving
|
|
||||||
@flindex /etc/shells
|
|
||||||
@cindex restricted shell
|
|
||||||
Do not change the environment variables @env{HOME}, @env{USER},
|
|
||||||
@env{LOGNAME}, or @env{SHELL}. Run the shell given in the environment
|
|
||||||
variable @env{SHELL} instead of the shell from @var{user}'s passwd
|
|
||||||
entry, unless the user running @command{su} is not the super-user and
|
|
||||||
@var{user}'s shell is restricted. A @dfn{restricted shell} is one that
|
|
||||||
is not listed in the file @file{/etc/shells}, or in a compiled-in list
|
|
||||||
if that file does not exist. Parts of what this option does can be
|
|
||||||
overridden by @option{--login} and @option{--shell}.
|
|
||||||
|
|
||||||
@item -s @var{shell}
|
|
||||||
@itemx --shell=@var{shell}
|
|
||||||
@opindex -s
|
|
||||||
@opindex --shell
|
|
||||||
Run @var{shell} instead of the shell from @var{user}'s passwd entry,
|
|
||||||
unless the user running @command{su} is not the super-user and @var{user}'s
|
|
||||||
shell is restricted (see @option{-m} just above).
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
@cindex exit status of @command{su}
|
|
||||||
Exit status:
|
|
||||||
|
|
||||||
@display
|
|
||||||
125 if @command{su} itself fails
|
|
||||||
126 if subshell is found but cannot be invoked
|
|
||||||
127 if subshell cannot be found
|
|
||||||
the exit status of the subshell otherwise
|
|
||||||
@end display
|
|
||||||
|
|
||||||
@cindex wheel group, not supported
|
|
||||||
@cindex group wheel, not supported
|
|
||||||
@cindex fascism
|
|
||||||
@subsection Why GNU @command{su} does not support the @samp{wheel} group
|
|
||||||
|
|
||||||
(This section is by Richard Stallman.)
|
|
||||||
|
|
||||||
@cindex Twenex
|
|
||||||
@cindex MIT AI lab
|
|
||||||
Sometimes a few of the users try to hold total power over all the
|
|
||||||
rest. For example, in 1984, a few users at the MIT AI lab decided to
|
|
||||||
seize power by changing the operator password on the Twenex system and
|
|
||||||
keeping it secret from everyone else. (I was able to thwart this coup
|
|
||||||
and give power back to the users by patching the kernel, but I
|
|
||||||
wouldn't know how to do that in Unix.)
|
|
||||||
|
|
||||||
However, occasionally the rulers do tell someone. Under the usual
|
|
||||||
@command{su} mechanism, once someone learns the root password who
|
|
||||||
sympathizes with the ordinary users, he or she can tell the rest. The
|
|
||||||
``wheel group'' feature would make this impossible, and thus cement the
|
|
||||||
power of the rulers.
|
|
||||||
|
|
||||||
I'm on the side of the masses, not that of the rulers. If you are
|
|
||||||
used to supporting the bosses and sysadmins in whatever they do, you
|
|
||||||
might find this idea strange at first.
|
|
||||||
|
|
||||||
|
|
||||||
@node timeout invocation
|
@node timeout invocation
|
||||||
@section @command{timeout}: Run a command with a time limit
|
@section @command{timeout}: Run a command with a time limit
|
||||||
|
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
#serial 11
|
|
||||||
|
|
||||||
dnl Misc lib-related macros for coreutils.
|
|
||||||
|
|
||||||
# Copyright (C) 1993-2012 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# Written by Jim Meyering.
|
|
||||||
|
|
||||||
AC_DEFUN([cu_LIB_CHECK],
|
|
||||||
[
|
|
||||||
|
|
||||||
# Check for libypsec.a on Dolphin M88K machines.
|
|
||||||
AC_CHECK_LIB([ypsec], [main])
|
|
||||||
|
|
||||||
# m88k running dgux 5.4 needs this
|
|
||||||
AC_CHECK_LIB([ldgc], [main])
|
|
||||||
|
|
||||||
# The -lsun library is required for YP support on Irix-4.0.5 systems.
|
|
||||||
# m88k/svr3 DolphinOS systems using YP need -lypsec for id.
|
|
||||||
AC_SEARCH_LIBS([yp_match], [sun ypsec])
|
|
||||||
|
|
||||||
# SysV needs -lsec, older versions of Linux need -lshadow for
|
|
||||||
# shadow passwords. UnixWare 7 needs -lgen.
|
|
||||||
AC_SEARCH_LIBS([getspnam], [shadow sec gen])
|
|
||||||
|
|
||||||
AC_CHECK_HEADERS([shadow.h])
|
|
||||||
|
|
||||||
# Requirements for su.c.
|
|
||||||
shadow_includes="\
|
|
||||||
$ac_includes_default
|
|
||||||
#if HAVE_SHADOW_H
|
|
||||||
# include <shadow.h>
|
|
||||||
#endif
|
|
||||||
"
|
|
||||||
AC_CHECK_MEMBERS([struct spwd.sp_pwdp],,,[$shadow_includes])
|
|
||||||
AC_CHECK_FUNCS([getspnam])
|
|
||||||
|
|
||||||
# SCO-ODT-3.0 is reported to need -lufc for crypt.
|
|
||||||
# NetBSD needs -lcrypt for crypt.
|
|
||||||
LIB_CRYPT=
|
|
||||||
cu_saved_libs="$LIBS"
|
|
||||||
AC_SEARCH_LIBS([crypt], [ufc crypt],
|
|
||||||
[test "$ac_cv_search_crypt" = "none required" ||
|
|
||||||
LIB_CRYPT="$ac_cv_search_crypt"])
|
|
||||||
LIBS="$cu_saved_libs"
|
|
||||||
AC_SUBST([LIB_CRYPT])
|
|
||||||
])
|
|
1
man/.gitignore
vendored
1
man/.gitignore
vendored
@ -76,7 +76,6 @@ split.1
|
|||||||
stat.1
|
stat.1
|
||||||
stdbuf.1
|
stdbuf.1
|
||||||
stty.1
|
stty.1
|
||||||
su.1
|
|
||||||
sum.1
|
sum.1
|
||||||
sync.1
|
sync.1
|
||||||
tac.1
|
tac.1
|
||||||
|
@ -110,7 +110,6 @@ split.1: $(common_dep) $(srcdir)/split.x ../src/split.c
|
|||||||
stat.1: $(common_dep) $(srcdir)/stat.x ../src/stat.c
|
stat.1: $(common_dep) $(srcdir)/stat.x ../src/stat.c
|
||||||
stdbuf.1: $(common_dep) $(srcdir)/stdbuf.x ../src/stdbuf.c
|
stdbuf.1: $(common_dep) $(srcdir)/stdbuf.x ../src/stdbuf.c
|
||||||
stty.1: $(common_dep) $(srcdir)/stty.x ../src/stty.c
|
stty.1: $(common_dep) $(srcdir)/stty.x ../src/stty.c
|
||||||
su.1: $(common_dep) $(srcdir)/su.x ../src/su.c
|
|
||||||
sum.1: $(common_dep) $(srcdir)/sum.x ../src/sum.c
|
sum.1: $(common_dep) $(srcdir)/sum.x ../src/sum.c
|
||||||
sync.1: $(common_dep) $(srcdir)/sync.x ../src/sync.c
|
sync.1: $(common_dep) $(srcdir)/sync.x ../src/sync.c
|
||||||
tac.1: $(common_dep) $(srcdir)/tac.x ../src/tac.c
|
tac.1: $(common_dep) $(srcdir)/tac.x ../src/tac.c
|
||||||
@ -192,7 +191,7 @@ ASSORT = LC_ALL=C sort
|
|||||||
|
|
||||||
# Ensure that for each .x file in this directory, there is a
|
# Ensure that for each .x file in this directory, there is a
|
||||||
# corresponding .1 file in the definition of $(dist_man1_MANS) above.
|
# corresponding .1 file in the definition of $(dist_man1_MANS) above.
|
||||||
# But since that expansion usually lacks programs like su and arch,
|
# But since that expansion usually lacks programs like arch and hostname,
|
||||||
# add them here manually.
|
# add them here manually.
|
||||||
.PHONY: check-x-vs-1
|
.PHONY: check-x-vs-1
|
||||||
check-x-vs-1:
|
check-x-vs-1:
|
||||||
|
4
man/su.x
4
man/su.x
@ -1,4 +0,0 @@
|
|||||||
[NAME]
|
|
||||||
su \- run a shell with substitute user and group IDs
|
|
||||||
[DESCRIPTION]
|
|
||||||
.\" Add any additional description here
|
|
@ -118,7 +118,6 @@ src/split.c
|
|||||||
src/stat.c
|
src/stat.c
|
||||||
src/stdbuf.c
|
src/stdbuf.c
|
||||||
src/stty.c
|
src/stty.c
|
||||||
src/su.c
|
|
||||||
src/sum.c
|
src/sum.c
|
||||||
src/sync.c
|
src/sync.c
|
||||||
src/system.h
|
src/system.h
|
||||||
|
@ -19,7 +19,7 @@ my @valid = qw(
|
|||||||
mv nice nl nohup nproc od paste pathchk pinky pr printenv printf
|
mv nice nl nohup nproc od paste pathchk pinky pr printenv printf
|
||||||
ptx pwd readlink realpath rm rmdir runcon seq sha1sum sha224sum sha256sum
|
ptx pwd readlink realpath rm rmdir runcon seq sha1sum sha224sum sha256sum
|
||||||
sha384sum sha512sum shred shuf sleep sort split stat stdbuf stty
|
sha384sum sha512sum shred shuf sleep sort split stat stdbuf stty
|
||||||
su sum sync tac tail tee test timeout touch tr true truncate tsort
|
sum sync tac tail tee test timeout touch tr true truncate tsort
|
||||||
tty uname unexpand uniq unlink uptime users vdir wc who whoami yes
|
tty uname unexpand uniq unlink uptime users vdir wc who whoami yes
|
||||||
|
|
||||||
copy gnulib tests maint doc build scripts
|
copy gnulib tests maint doc build scripts
|
||||||
|
1
src/.gitignore
vendored
1
src/.gitignore
vendored
@ -87,7 +87,6 @@ split
|
|||||||
stat
|
stat
|
||||||
stdbuf
|
stdbuf
|
||||||
stty
|
stty
|
||||||
su
|
|
||||||
sum
|
sum
|
||||||
sync
|
sync
|
||||||
tac
|
tac
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
# Hence, if you want to install programs from this list anyway, say A and B,
|
# Hence, if you want to install programs from this list anyway, say A and B,
|
||||||
# use --enable-install-program=A,B
|
# use --enable-install-program=A,B
|
||||||
no_install__progs = \
|
no_install__progs = \
|
||||||
arch hostname su
|
arch hostname
|
||||||
|
|
||||||
build_if_possible__progs = \
|
build_if_possible__progs = \
|
||||||
chroot \
|
chroot \
|
||||||
@ -32,7 +32,6 @@ build_if_possible__progs = \
|
|||||||
pinky \
|
pinky \
|
||||||
stdbuf \
|
stdbuf \
|
||||||
stty \
|
stty \
|
||||||
su \
|
|
||||||
uptime \
|
uptime \
|
||||||
users \
|
users \
|
||||||
who
|
who
|
||||||
@ -164,7 +163,7 @@ noinst_HEADERS = \
|
|||||||
EXTRA_DIST = dcgen dircolors.hin tac-pipe.c \
|
EXTRA_DIST = dcgen dircolors.hin tac-pipe.c \
|
||||||
wheel-gen.pl extract-magic c99-to-c89.diff
|
wheel-gen.pl extract-magic c99-to-c89.diff
|
||||||
BUILT_SOURCES =
|
BUILT_SOURCES =
|
||||||
CLEANFILES = $(SCRIPTS) su
|
CLEANFILES = $(SCRIPTS)
|
||||||
|
|
||||||
# Also remove these sometimes-built programs.
|
# Also remove these sometimes-built programs.
|
||||||
# For example, even when excluded, they're built via _sc_check-AUTHORS.
|
# For example, even when excluded, they're built via _sc_check-AUTHORS.
|
||||||
@ -268,7 +267,6 @@ split_LDADD = $(LDADD)
|
|||||||
stat_LDADD = $(LDADD)
|
stat_LDADD = $(LDADD)
|
||||||
stdbuf_LDADD = $(LDADD)
|
stdbuf_LDADD = $(LDADD)
|
||||||
stty_LDADD = $(LDADD)
|
stty_LDADD = $(LDADD)
|
||||||
su_LDADD = $(LDADD)
|
|
||||||
sum_LDADD = $(LDADD)
|
sum_LDADD = $(LDADD)
|
||||||
sync_LDADD = $(LDADD)
|
sync_LDADD = $(LDADD)
|
||||||
tac_LDADD = $(LDADD)
|
tac_LDADD = $(LDADD)
|
||||||
@ -357,9 +355,6 @@ factor_LDADD += $(LIB_GMP)
|
|||||||
# for getloadavg
|
# for getloadavg
|
||||||
uptime_LDADD += $(GETLOADAVG_LIBS)
|
uptime_LDADD += $(GETLOADAVG_LIBS)
|
||||||
|
|
||||||
# for crypt
|
|
||||||
su_LDADD += $(LIB_CRYPT)
|
|
||||||
|
|
||||||
# for various ACL functions
|
# for various ACL functions
|
||||||
copy_LDADD += $(LIB_ACL)
|
copy_LDADD += $(LIB_ACL)
|
||||||
ls_LDADD += $(LIB_ACL)
|
ls_LDADD += $(LIB_ACL)
|
||||||
@ -402,60 +397,6 @@ RELEASE_YEAR = \
|
|||||||
`sed -n '/.*COPYRIGHT_YEAR = \([0-9][0-9][0-9][0-9]\) };/s//\1/p' \
|
`sed -n '/.*COPYRIGHT_YEAR = \([0-9][0-9][0-9][0-9]\) };/s//\1/p' \
|
||||||
$(top_srcdir)/lib/version-etc.c`
|
$(top_srcdir)/lib/version-etc.c`
|
||||||
|
|
||||||
all-local: su$(EXEEXT)
|
|
||||||
|
|
||||||
installed_su = $(DESTDIR)$(bindir)/`echo su|sed '$(transform)'`
|
|
||||||
|
|
||||||
setuid_root_mode = a=rx,u+s
|
|
||||||
|
|
||||||
install_su = \
|
|
||||||
if test "$(INSTALL_SU)" = yes; then \
|
|
||||||
p=su; \
|
|
||||||
echo " $(INSTALL_PROGRAM) $$p $(installed_su)"; \
|
|
||||||
$(INSTALL_PROGRAM) $$p $(installed_su); \
|
|
||||||
echo " chown root $(installed_su)"; \
|
|
||||||
chown root $(installed_su); \
|
|
||||||
echo " chmod $(setuid_root_mode) $(installed_su)"; \
|
|
||||||
chmod $(setuid_root_mode) $(installed_su); \
|
|
||||||
else \
|
|
||||||
:; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
install-root: su$(EXEEXT)
|
|
||||||
@$(install_su)
|
|
||||||
|
|
||||||
install-exec-hook: su$(EXEEXT)
|
|
||||||
@if test "$(INSTALL_SU)" = yes; then \
|
|
||||||
TMPFILE=$(DESTDIR)$(bindir)/.su-$$$$; \
|
|
||||||
rm -f $$TMPFILE; \
|
|
||||||
echo > $$TMPFILE; \
|
|
||||||
## See if we can create a setuid root executable in $(bindir).
|
|
||||||
## If not, then don't even try to install su.
|
|
||||||
can_create_suid_root_executable=no; \
|
|
||||||
chown root $$TMPFILE > /dev/null 2>&1 \
|
|
||||||
&& chmod $(setuid_root_mode) $$TMPFILE > /dev/null 2>&1 \
|
|
||||||
&& can_create_suid_root_executable=yes; \
|
|
||||||
rm -f $$TMPFILE; \
|
|
||||||
if test $$can_create_suid_root_executable = yes; then \
|
|
||||||
$(install_su); \
|
|
||||||
else \
|
|
||||||
echo "WARNING: insufficient access; not installing su"; \
|
|
||||||
echo "NOTE: to install su, run 'make install-root' as root"; \
|
|
||||||
rm -f $(installed_su); \
|
|
||||||
fi; \
|
|
||||||
else :; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
uninstall-local:
|
|
||||||
# Remove su only if it's one we installed.
|
|
||||||
@if test "$(INSTALL_SU)" = yes; then \
|
|
||||||
if grep '$(PACKAGE_NAME)' $(installed_su) > /dev/null 2>&1; then \
|
|
||||||
echo " rm -f $(installed_su)"; \
|
|
||||||
rm -f $(installed_su); \
|
|
||||||
else :; \
|
|
||||||
fi; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
copy_sources = copy.c cp-hash.c extent-scan.c extent-scan.h
|
copy_sources = copy.c cp-hash.c extent-scan.c extent-scan.h
|
||||||
|
|
||||||
# Use 'ginstall' in the definition of PROGRAMS and in dependencies to avoid
|
# Use 'ginstall' in the definition of PROGRAMS and in dependencies to avoid
|
||||||
|
520
src/su.c
520
src/su.c
@ -1,520 +0,0 @@
|
|||||||
/* su for GNU. Run a shell with substitute user and group IDs.
|
|
||||||
Copyright (C) 1992-2012 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
||||||
|
|
||||||
/* Run a shell with the real and effective UID and GID and groups
|
|
||||||
of USER, default 'root'.
|
|
||||||
|
|
||||||
The shell run is taken from USER's password entry, /bin/sh if
|
|
||||||
none is specified there. If the account has a password, su
|
|
||||||
prompts for a password unless run by a user with real UID 0.
|
|
||||||
|
|
||||||
Does not change the current directory.
|
|
||||||
Sets 'HOME' and 'SHELL' from the password entry for USER, and if
|
|
||||||
USER is not root, sets 'USER' and 'LOGNAME' to USER.
|
|
||||||
The subshell is not a login shell.
|
|
||||||
|
|
||||||
If one or more ARGs are given, they are passed as additional
|
|
||||||
arguments to the subshell.
|
|
||||||
|
|
||||||
Does not handle /bin/sh or other shells specially
|
|
||||||
(setting argv[0] to "-su", passing -c only to certain shells, etc.).
|
|
||||||
I don't see the point in doing that, and it's ugly.
|
|
||||||
|
|
||||||
This program intentionally does not support a "wheel group" that
|
|
||||||
restricts who can su to UID 0 accounts. RMS considers that to
|
|
||||||
be fascist.
|
|
||||||
|
|
||||||
Compile-time options:
|
|
||||||
-DSYSLOG_SUCCESS Log successful su's (by default, to root) with syslog.
|
|
||||||
-DSYSLOG_FAILURE Log failed su's (by default, to root) with syslog.
|
|
||||||
|
|
||||||
-DSYSLOG_NON_ROOT Log all su's, not just those to root (UID 0).
|
|
||||||
Never logs attempted su's to nonexistent accounts.
|
|
||||||
|
|
||||||
Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <grp.h>
|
|
||||||
|
|
||||||
#include "system.h"
|
|
||||||
#include "getpass.h"
|
|
||||||
|
|
||||||
#if HAVE_SYSLOG_H && HAVE_SYSLOG
|
|
||||||
# include <syslog.h>
|
|
||||||
#else
|
|
||||||
# undef SYSLOG_SUCCESS
|
|
||||||
# undef SYSLOG_FAILURE
|
|
||||||
# undef SYSLOG_NON_ROOT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_SYS_PARAM_H
|
|
||||||
# include <sys/param.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef HAVE_ENDGRENT
|
|
||||||
# define endgrent() ((void) 0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef HAVE_ENDPWENT
|
|
||||||
# define endpwent() ((void) 0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_SHADOW_H
|
|
||||||
# include <shadow.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
/* The official name of this program (e.g., no 'g' prefix). */
|
|
||||||
#define PROGRAM_NAME "su"
|
|
||||||
|
|
||||||
#define AUTHORS proper_name ("David MacKenzie")
|
|
||||||
|
|
||||||
#if HAVE_PATHS_H
|
|
||||||
# include <paths.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The default PATH for simulated logins to non-superuser accounts. */
|
|
||||||
#ifdef _PATH_DEFPATH
|
|
||||||
# define DEFAULT_LOGIN_PATH _PATH_DEFPATH
|
|
||||||
#else
|
|
||||||
# define DEFAULT_LOGIN_PATH ":/usr/ucb:/bin:/usr/bin"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The default PATH for simulated logins to superuser accounts. */
|
|
||||||
#ifdef _PATH_DEFPATH_ROOT
|
|
||||||
# define DEFAULT_ROOT_LOGIN_PATH _PATH_DEFPATH_ROOT
|
|
||||||
#else
|
|
||||||
# define DEFAULT_ROOT_LOGIN_PATH "/usr/ucb:/bin:/usr/bin:/etc"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The shell to run if none is given in the user's passwd entry. */
|
|
||||||
#define DEFAULT_SHELL "/bin/sh"
|
|
||||||
|
|
||||||
/* The user to become if none is specified. */
|
|
||||||
#define DEFAULT_USER "root"
|
|
||||||
|
|
||||||
char *crypt (char const *key, char const *salt);
|
|
||||||
|
|
||||||
static void run_shell (char const *, char const *, char **, size_t)
|
|
||||||
ATTRIBUTE_NORETURN;
|
|
||||||
|
|
||||||
/* If true, pass the '-f' option to the subshell. */
|
|
||||||
static bool fast_startup;
|
|
||||||
|
|
||||||
/* If true, simulate a login instead of just starting a shell. */
|
|
||||||
static bool simulate_login;
|
|
||||||
|
|
||||||
/* If true, change some environment vars to indicate the user su'd to. */
|
|
||||||
static bool change_environment;
|
|
||||||
|
|
||||||
static struct option const longopts[] =
|
|
||||||
{
|
|
||||||
{"command", required_argument, NULL, 'c'},
|
|
||||||
{"fast", no_argument, NULL, 'f'},
|
|
||||||
{"login", no_argument, NULL, 'l'},
|
|
||||||
{"preserve-environment", no_argument, NULL, 'p'},
|
|
||||||
{"shell", required_argument, NULL, 's'},
|
|
||||||
{GETOPT_HELP_OPTION_DECL},
|
|
||||||
{GETOPT_VERSION_OPTION_DECL},
|
|
||||||
{NULL, 0, NULL, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Add NAME=VAL to the environment, checking for out of memory errors. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
xsetenv (char const *name, char const *val)
|
|
||||||
{
|
|
||||||
size_t namelen = strlen (name);
|
|
||||||
size_t vallen = strlen (val);
|
|
||||||
char *string = xmalloc (namelen + 1 + vallen + 1);
|
|
||||||
strcpy (string, name);
|
|
||||||
string[namelen] = '=';
|
|
||||||
strcpy (string + namelen + 1, val);
|
|
||||||
if (putenv (string) != 0)
|
|
||||||
xalloc_die ();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined SYSLOG_SUCCESS || defined SYSLOG_FAILURE
|
|
||||||
/* Log the fact that someone has run su to the user given by PW;
|
|
||||||
if SUCCESSFUL is true, they gave the correct password, etc. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
log_su (struct passwd const *pw, bool successful)
|
|
||||||
{
|
|
||||||
const char *new_user, *old_user, *tty;
|
|
||||||
|
|
||||||
# ifndef SYSLOG_NON_ROOT
|
|
||||||
if (pw->pw_uid)
|
|
||||||
return;
|
|
||||||
# endif
|
|
||||||
new_user = pw->pw_name;
|
|
||||||
/* 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. */
|
|
||||||
errno = 0;
|
|
||||||
uid_t ruid = getuid ();
|
|
||||||
uid_t NO_UID = -1;
|
|
||||||
struct passwd *pwd = (ruid == NO_UID && errno ? NULL : getpwuid (ruid));
|
|
||||||
old_user = (pwd ? pwd->pw_name : "");
|
|
||||||
}
|
|
||||||
tty = ttyname (STDERR_FILENO);
|
|
||||||
if (!tty)
|
|
||||||
tty = "none";
|
|
||||||
/* 4.2BSD openlog doesn't have the third parameter. */
|
|
||||||
openlog (last_component (program_name), 0
|
|
||||||
# ifdef LOG_AUTH
|
|
||||||
, LOG_AUTH
|
|
||||||
# endif
|
|
||||||
);
|
|
||||||
syslog (LOG_NOTICE,
|
|
||||||
# ifdef SYSLOG_NON_ROOT
|
|
||||||
"%s(to %s) %s on %s",
|
|
||||||
# else
|
|
||||||
"%s%s on %s",
|
|
||||||
# endif
|
|
||||||
successful ? "" : "FAILED SU ",
|
|
||||||
# ifdef SYSLOG_NON_ROOT
|
|
||||||
new_user,
|
|
||||||
# endif
|
|
||||||
old_user, tty);
|
|
||||||
closelog ();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Ask the user for a password.
|
|
||||||
Return true if the user gives the correct password for entry PW,
|
|
||||||
false if not. Return true without asking for a password if run by UID 0
|
|
||||||
or if PW has an empty password. */
|
|
||||||
|
|
||||||
static bool
|
|
||||||
correct_password (const struct passwd *pw)
|
|
||||||
{
|
|
||||||
char *unencrypted, *encrypted, *correct;
|
|
||||||
#if HAVE_GETSPNAM && HAVE_STRUCT_SPWD_SP_PWDP
|
|
||||||
/* Shadow passwd stuff for SVR3 and maybe other systems. */
|
|
||||||
struct spwd *sp = getspnam (pw->pw_name);
|
|
||||||
|
|
||||||
endspent ();
|
|
||||||
if (sp)
|
|
||||||
correct = sp->sp_pwdp;
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
correct = pw->pw_passwd;
|
|
||||||
|
|
||||||
if (getuid () == 0 || !correct || correct[0] == '\0')
|
|
||||||
return true;
|
|
||||||
|
|
||||||
unencrypted = getpass (_("Password:"));
|
|
||||||
if (!unencrypted)
|
|
||||||
{
|
|
||||||
error (0, 0, _("getpass: cannot open /dev/tty"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
encrypted = crypt (unencrypted, correct);
|
|
||||||
memset (unencrypted, 0, strlen (unencrypted));
|
|
||||||
return STREQ (encrypted, correct);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update 'environ' for the new shell based on PW, with SHELL being
|
|
||||||
the value for the SHELL environment variable. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
modify_environment (const struct passwd *pw, const char *shell)
|
|
||||||
{
|
|
||||||
if (simulate_login)
|
|
||||||
{
|
|
||||||
/* Leave TERM unchanged. Set HOME, SHELL, USER, LOGNAME, PATH.
|
|
||||||
Unset all other environment variables. */
|
|
||||||
char const *term = getenv ("TERM");
|
|
||||||
if (term)
|
|
||||||
term = xstrdup (term);
|
|
||||||
environ = xmalloc ((6 + !!term) * sizeof (char *));
|
|
||||||
environ[0] = NULL;
|
|
||||||
if (term)
|
|
||||||
xsetenv ("TERM", term);
|
|
||||||
xsetenv ("HOME", pw->pw_dir);
|
|
||||||
xsetenv ("SHELL", shell);
|
|
||||||
xsetenv ("USER", pw->pw_name);
|
|
||||||
xsetenv ("LOGNAME", pw->pw_name);
|
|
||||||
xsetenv ("PATH", (pw->pw_uid
|
|
||||||
? DEFAULT_LOGIN_PATH
|
|
||||||
: DEFAULT_ROOT_LOGIN_PATH));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Set HOME, SHELL, and if not becoming a super-user,
|
|
||||||
USER and LOGNAME. */
|
|
||||||
if (change_environment)
|
|
||||||
{
|
|
||||||
xsetenv ("HOME", pw->pw_dir);
|
|
||||||
xsetenv ("SHELL", shell);
|
|
||||||
if (pw->pw_uid)
|
|
||||||
{
|
|
||||||
xsetenv ("USER", pw->pw_name);
|
|
||||||
xsetenv ("LOGNAME", pw->pw_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Become the user and group(s) specified by PW. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
change_identity (const struct passwd *pw)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_INITGROUPS
|
|
||||||
errno = 0;
|
|
||||||
if (initgroups (pw->pw_name, pw->pw_gid) == -1)
|
|
||||||
error (EXIT_CANCELED, errno, _("cannot set groups"));
|
|
||||||
endgrent ();
|
|
||||||
#endif
|
|
||||||
if (setgid (pw->pw_gid))
|
|
||||||
error (EXIT_CANCELED, errno, _("cannot set group id"));
|
|
||||||
if (setuid (pw->pw_uid))
|
|
||||||
error (EXIT_CANCELED, errno, _("cannot set user id"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Run SHELL, or DEFAULT_SHELL if SHELL is empty.
|
|
||||||
If COMMAND is nonzero, pass it to the shell with the -c option.
|
|
||||||
Pass ADDITIONAL_ARGS to the shell as more arguments; there
|
|
||||||
are N_ADDITIONAL_ARGS extra arguments. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
run_shell (char const *shell, char const *command, char **additional_args,
|
|
||||||
size_t n_additional_args)
|
|
||||||
{
|
|
||||||
size_t n_args = 1 + fast_startup + 2 * !!command + n_additional_args + 1;
|
|
||||||
char const **args = xnmalloc (n_args, sizeof *args);
|
|
||||||
size_t argno = 1;
|
|
||||||
|
|
||||||
if (simulate_login)
|
|
||||||
{
|
|
||||||
char *arg0;
|
|
||||||
char *shell_basename;
|
|
||||||
|
|
||||||
shell_basename = last_component (shell);
|
|
||||||
arg0 = xmalloc (strlen (shell_basename) + 2);
|
|
||||||
arg0[0] = '-';
|
|
||||||
strcpy (arg0 + 1, shell_basename);
|
|
||||||
args[0] = arg0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
args[0] = last_component (shell);
|
|
||||||
if (fast_startup)
|
|
||||||
args[argno++] = "-f";
|
|
||||||
if (command)
|
|
||||||
{
|
|
||||||
args[argno++] = "-c";
|
|
||||||
args[argno++] = command;
|
|
||||||
}
|
|
||||||
memcpy (args + argno, additional_args, n_additional_args * sizeof *args);
|
|
||||||
args[argno + n_additional_args] = NULL;
|
|
||||||
execv (shell, (char **) args);
|
|
||||||
|
|
||||||
{
|
|
||||||
int exit_status = (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
|
|
||||||
error (0, errno, "%s", shell);
|
|
||||||
exit (exit_status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return true if SHELL is a restricted shell (one not returned by
|
|
||||||
getusershell), else false, meaning it is a standard shell. */
|
|
||||||
|
|
||||||
static bool
|
|
||||||
restricted_shell (const char *shell)
|
|
||||||
{
|
|
||||||
char *line;
|
|
||||||
|
|
||||||
setusershell ();
|
|
||||||
while ((line = getusershell ()) != NULL)
|
|
||||||
{
|
|
||||||
if (*line != '#' && STREQ (line, shell))
|
|
||||||
{
|
|
||||||
endusershell ();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
endusershell ();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
usage (int status)
|
|
||||||
{
|
|
||||||
if (status != EXIT_SUCCESS)
|
|
||||||
emit_try_help ();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf (_("Usage: %s [OPTION]... [-] [USER [ARG]...]\n"), program_name);
|
|
||||||
fputs (_("\
|
|
||||||
Change the effective user id and group id to that of USER.\n\
|
|
||||||
\n\
|
|
||||||
-, -l, --login make the shell a login shell\n\
|
|
||||||
-c, --command=COMMAND pass a single COMMAND to the shell with -c\n\
|
|
||||||
-f, --fast pass -f to the shell (for csh or tcsh)\n\
|
|
||||||
-m, --preserve-environment do not reset environment variables\n\
|
|
||||||
-p same as -m\n\
|
|
||||||
-s, --shell=SHELL run SHELL if /etc/shells allows it\n\
|
|
||||||
"), stdout);
|
|
||||||
fputs (HELP_OPTION_DESCRIPTION, stdout);
|
|
||||||
fputs (VERSION_OPTION_DESCRIPTION, stdout);
|
|
||||||
fputs (_("\
|
|
||||||
\n\
|
|
||||||
A mere - implies -l. If USER not given, assume root.\n\
|
|
||||||
"), stdout);
|
|
||||||
emit_ancillary_info ();
|
|
||||||
}
|
|
||||||
exit (status);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main (int argc, char **argv)
|
|
||||||
{
|
|
||||||
int optc;
|
|
||||||
const char *new_user = DEFAULT_USER;
|
|
||||||
char *command = NULL;
|
|
||||||
char *shell = NULL;
|
|
||||||
struct passwd *pw;
|
|
||||||
struct passwd pw_copy;
|
|
||||||
|
|
||||||
initialize_main (&argc, &argv);
|
|
||||||
set_program_name (argv[0]);
|
|
||||||
setlocale (LC_ALL, "");
|
|
||||||
bindtextdomain (PACKAGE, LOCALEDIR);
|
|
||||||
textdomain (PACKAGE);
|
|
||||||
|
|
||||||
initialize_exit_failure (EXIT_CANCELED);
|
|
||||||
atexit (close_stdout);
|
|
||||||
|
|
||||||
fast_startup = false;
|
|
||||||
simulate_login = false;
|
|
||||||
change_environment = true;
|
|
||||||
|
|
||||||
while ((optc = getopt_long (argc, argv, "c:flmps:", longopts, NULL)) != -1)
|
|
||||||
{
|
|
||||||
switch (optc)
|
|
||||||
{
|
|
||||||
case 'c':
|
|
||||||
command = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'f':
|
|
||||||
fast_startup = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'l':
|
|
||||||
simulate_login = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'm':
|
|
||||||
case 'p':
|
|
||||||
change_environment = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 's':
|
|
||||||
shell = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case_GETOPT_HELP_CHAR;
|
|
||||||
|
|
||||||
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
|
|
||||||
|
|
||||||
default:
|
|
||||||
usage (EXIT_CANCELED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (optind < argc && STREQ (argv[optind], "-"))
|
|
||||||
{
|
|
||||||
simulate_login = true;
|
|
||||||
++optind;
|
|
||||||
}
|
|
||||||
if (optind < argc)
|
|
||||||
new_user = argv[optind++];
|
|
||||||
|
|
||||||
pw = getpwnam (new_user);
|
|
||||||
if (! (pw && pw->pw_name && pw->pw_name[0] && pw->pw_dir && pw->pw_dir[0]
|
|
||||||
&& pw->pw_passwd))
|
|
||||||
error (EXIT_CANCELED, 0, _("user %s does not exist"), new_user);
|
|
||||||
|
|
||||||
/* Make a copy of the password information and point pw at the local
|
|
||||||
copy instead. Otherwise, some systems (e.g. GNU/Linux) would clobber
|
|
||||||
the static data through the getlogin call from log_su.
|
|
||||||
Also, make sure pw->pw_shell is a nonempty string.
|
|
||||||
It may be NULL when NEW_USER is a username that is retrieved via NIS (YP),
|
|
||||||
but that doesn't have a default shell listed. */
|
|
||||||
pw_copy = *pw;
|
|
||||||
pw = &pw_copy;
|
|
||||||
pw->pw_name = xstrdup (pw->pw_name);
|
|
||||||
pw->pw_passwd = xstrdup (pw->pw_passwd);
|
|
||||||
pw->pw_dir = xstrdup (pw->pw_dir);
|
|
||||||
pw->pw_shell = xstrdup (pw->pw_shell && pw->pw_shell[0]
|
|
||||||
? pw->pw_shell
|
|
||||||
: DEFAULT_SHELL);
|
|
||||||
endpwent ();
|
|
||||||
|
|
||||||
if (!correct_password (pw))
|
|
||||||
{
|
|
||||||
#ifdef SYSLOG_FAILURE
|
|
||||||
log_su (pw, false);
|
|
||||||
#endif
|
|
||||||
error (EXIT_CANCELED, 0, _("incorrect password"));
|
|
||||||
}
|
|
||||||
#ifdef SYSLOG_SUCCESS
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log_su (pw, true);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!shell && !change_environment)
|
|
||||||
shell = getenv ("SHELL");
|
|
||||||
if (shell && getuid () != 0 && 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
|
|
||||||
shell. */
|
|
||||||
error (0, 0, _("using restricted shell %s"), pw->pw_shell);
|
|
||||||
shell = NULL;
|
|
||||||
}
|
|
||||||
shell = xstrdup (shell ? shell : pw->pw_shell);
|
|
||||||
modify_environment (pw, shell);
|
|
||||||
|
|
||||||
change_identity (pw);
|
|
||||||
if (simulate_login && chdir (pw->pw_dir) != 0)
|
|
||||||
error (0, errno, _("warning: cannot change directory to %s"), pw->pw_dir);
|
|
||||||
|
|
||||||
/* error() flushes stderr, but does not check for write failure.
|
|
||||||
Normally, we would catch this via our atexit() hook of
|
|
||||||
close_stdout, but execv() gets in the way. If stderr
|
|
||||||
encountered a write failure, there is no need to try calling
|
|
||||||
error() again. */
|
|
||||||
if (ferror (stderr))
|
|
||||||
exit (EXIT_CANCELED);
|
|
||||||
|
|
||||||
run_shell (shell, command, argv + optind, MAX (0, argc - optind));
|
|
||||||
}
|
|
@ -280,7 +280,6 @@ TESTS = \
|
|||||||
misc/stty-invalid \
|
misc/stty-invalid \
|
||||||
misc/stty-pairs \
|
misc/stty-pairs \
|
||||||
misc/stty-row-col \
|
misc/stty-row-col \
|
||||||
misc/su-fail \
|
|
||||||
misc/sum \
|
misc/sum \
|
||||||
misc/sum-sysv \
|
misc/sum-sysv \
|
||||||
misc/tac \
|
misc/tac \
|
||||||
|
@ -208,7 +208,6 @@ nohup_setup () { args=--version; }
|
|||||||
printf_setup () { args=foo; }
|
printf_setup () { args=foo; }
|
||||||
seq_setup () { args=10; }
|
seq_setup () { args=10; }
|
||||||
sleep_setup () { args=0; }
|
sleep_setup () { args=0; }
|
||||||
su_setup () { args=--version; }
|
|
||||||
stdbuf_setup () { args="-oL true"; }
|
stdbuf_setup () { args="-oL true"; }
|
||||||
timeout_setup () { args=--version; }
|
timeout_setup () { args=--version; }
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@ my %exit_status =
|
|||||||
nohup => 125,
|
nohup => 125,
|
||||||
sort => 2,
|
sort => 2,
|
||||||
stdbuf => 125,
|
stdbuf => 125,
|
||||||
su => 125,
|
|
||||||
test => 0,
|
test => 0,
|
||||||
timeout => 125,
|
timeout => 125,
|
||||||
true => 0,
|
true => 0,
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# Test su failure cases
|
|
||||||
|
|
||||||
# Copyright (C) 2009-2012 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
. "${srcdir=.}/init.sh"; path_prepend_ ../src
|
|
||||||
print_ver_ su
|
|
||||||
|
|
||||||
require_built_ su
|
|
||||||
|
|
||||||
# Very little that we can test without a root password
|
|
||||||
su --- / true # unknown option
|
|
||||||
test $? = 125 || fail=1
|
|
||||||
su no_such_user
|
|
||||||
test $? = 125 || fail=1
|
|
||||||
|
|
||||||
Exit $fail
|
|
Reference in New Issue
Block a user