Compare commits

..

1 Commits

Author SHA1 Message Date
nekral-guest
499c6f7938 Tag release 4.1.4.2 2009-07-24 16:22:16 +00:00
10425 changed files with 45471 additions and 477655 deletions

1
.gitignore vendored
View File

@@ -17,7 +17,6 @@ Makefile.in
/ABOUT-NLS
/aclocal.m4
/autom4te.cache
/compile
/config.guess
/config.h
/config.h.in

2601
ChangeLog

File diff suppressed because it is too large Load Diff

205
NEWS
View File

@@ -1,207 +1,6 @@
$Id$
shadow-4.1.5.1 -> shadow-4.2 UNRELEASED
*** general
* Handle libc whose crypt() returns NULL when passed a salt that
violates specs or system requirements (e.g. FIPS140). This is needed
with glibc/eglibc 2.17 for tools checking passwords (passwd (non PAM
enabled) or newgrp), and for tools generating encrypted passwords
(chgpasswd, chpasswd, or gpasswd when non PAM enabled or when a fixed
crypt method is requested on the command line, and newusers, or passwd
in their non PAM enabled versions)
* Fix segfault when reading groups split on multiple lines. This impacts
most user/group management tools when MAX_MEMBERS_PER_GROUP is set.
- su
* When su receives a signal (SIGTERM, or SIGINT/SIGQUIT in non
interactive mode), kill the child process group, rather than just the
immediate child.
* Fix segmentation faults for users without a proper home or shell in
their passwd entries.
- login
* Fix segmentation faults for users without a proper home or shell in
their passwd entries.
*** documentation
* Fixed useradd man page (--home-dir option, instead of --home).
*** translation
* Updated Russian translation.
* Updated German man pages translation.
* Fixed gshadow Japanese man page translation.
shadow-4.1.5 -> shadow-4.1.5.1 2012-05-25
- login
* Log into utmp(x) when PAM is enabled, but do not log into wtmp.
This complete pam_lastlog which logs into wtmp and in into utmp(x).
- su
* non PAM enabled versions: do not fail if su is called without a
controlling terminal.
- userdel
* Fix segfault when userdel removes the user's group.
*** documentation
* .so links now point to paths relative to the top-level manual hierarchy
*** translation
* Updated French man pages translation.
* Updated German man pages translation.
* Updated Polish man pages translation. (logoutd.8)
shadow-4.1.4.3 -> shadow-4.1.5 2012-02-12
*** security
* su -c could be abused by the executed command to invoke commands with
the caller privileges. See below. (CVE-2005-4890)
*** general
* report usage error to stderr, but report usage help to stdout (and return
zero) when explicitly requested (e.g. with --help).
* initial support for tcb (http://openwall.com/tcb/) for useradd,
userdel, usermod, chage, pwck, vipw.
* Added support for ACLs and Extended Attributes in useradd and usermod.
Support shall be enabled with the new --with-acl or --with-attr
configure options.
* Added diagnosis for lock failures.
* use libsemanage instead of the semanage tool.
- chage
* Add --root option.
- chfn
* Add --root option.
- chgpasswd
* When the gshadow file exists but there are no gshadow entries, an entry
is created if the password is changed and group requires a
shadow entry.
* Add --root option.
- chpasswd
* PAM enabled versions: restore the -e option to allow restoring
passwords without knowing those passwords. Restore together the -m
and -c options. (These options were removed in shadow-4.1.4 on PAM
enabled versions)
* When the shadow file exists but there are no shadow entries, an entry
is created if the password is changed and passwd requires a
shadow entry.
* Add --root option.
- chsh
* Add --root option.
- faillog
* The -l, -m, -r, -t options only act on the existing users, unless -a is
specified.
* Add --root option.
- gpasswd
* Add --root option.
- groupadd
* Add --root option.
- groupdel
* Add --root option.
- groupmems
* Fix parsing of gshadow entries.
* Add --root option.
- groupmod
* Fixed groupmod when configured with --enable-account-tools-setuid.
* When the gshadow file exists but there are no gshadow entries, an entry
is created if the password is changed and group requires a
shadow entry.
* Add --root option.
- grpck
* Add --root option.
* NIS entries were dropped by -s (sort).
- grpconv
* Add --root option.
- grpunconv
* Add --root option.
- lastlog
* Add --root option.
- login
* Fixed limits support (non PAM enabled versions only)
* Added support for infinite limits and group based limits (non PAM
enabled versions only)
* Fixed infinite loop when CONSOLE is configured with a colon-separated
list of TTYs.
* Fixed warning and support for CONSOLE_GROUPS for users member of more
than 16 groups.
* Do not log into utmp(x) or wtmp when PAM is enabled. This is done by
pam_lastlog.
- newgrp, sg
* Fix parsing of gshadow entries.
- newusers
* Add --root option.
- passwd
* Add --root option.
- pwpck
* NIS entries were dropped by -s (sort).
* Add --root option.
- pwconv
* Add --root option.
- pwunconv
* Add --root option.
- useradd
* If the skeleton directory contained hardlinked files, copies of the
hardlink were removed from the skeleton directory.
* Add --root option.
- userdel
* Check the existence of the user's mail spool before trying to remove
it. If it does not exist, a warning is issued, but no failure.
* Do not remove a group with the same name as the user (usergroup) if
this group isn't the user's primary group.
* Add --root option.
* Add --selinux-user option.
- usermod
* Accept options in any order (username not necessarily at the end)
* When the shadow file exists but there are no shadow entries, an entry
is created if the password is changed and passwd requires a
shadow entry, or if aging features are used (-e or -f).
* Add --root option.
- su
* Document the su exit values.
* When su receives a signal, wait for the child to terminate (after
sending a SIGTERM), and kill it only if it did not terminate by itself.
No delay will be enforced if the child cooperates.
* Default ENV_SUPATH is /sbin:/bin:/usr/sbin:/usr/bin
* Fixed infinite loop when CONSOLE is configured with a colon-separated
list of TTYs.
* Fixed warning and support for CONSOLE_GROUPS for users member of more
than 16 groups.
* Do not forward the controlling terminal to commands executed with -c.
This prevents tty hijacking which could lead to execution with the
caller's privileges.
* Close PAM sessions as root. This will be more friendly to PAM modules
like pam_mount or pam_systemd.
* Added support for PAM modules which change PAM_USER.
*** translation
* Updated Brazilian Portuguese translation.
* Updated Catalan translation.
* Updated Czech translation.
* Updated Danish translation.
* New Danish man pages translation.
* Updated French translation.
* Updated French man pages translation.
* Updated German translation.
* Updated German man pages translation.
* Updated Greek translation.
* Updated Italian man pages translation.
* Updated Japanese translation.
* Updated Kazakh translation.
* Updated Norwegian Bokmål translation.
* Updated Portuguese translation.
* Updated Russian translation.
* Updated Simplified Chinese translation.
* Updated Simplified Chinese man pages translation.
* Updated Swedish translation.
* Updated Vietnamese translation.
shadow-4.1.4.2 -> shadow-4.1.4.3 2011-02-15
*** security
- CVE-2011-0721: An insufficient input sanitation in chfn can be exploited
to create users or groups in a NIS environment.
shadow-4.1.4.1 -> shadow-4.1.4.2 2009-07-24
shadow-4.1.4.1 -> shadow-4.1.4.2 2009-07-24
- general
* Improved support for large groups (impacts most user/group management
@@ -511,7 +310,7 @@ shadow-4.1.0 -> shadow-4.1.1 02-04-2008
faillog faster.
- gpasswd
* Fix failures when the gshadow file is not present.
* When a password is moved to the gshadow file, use "x" instead of "!"
* When a password is moved to the gshadow file, use "x" instead of "x"
to indicate that the password is shadowed (consistency with grpconv).
* Make sure the group and gshadow files are unlocked on exit.
- groupadd

6
README
View File

@@ -37,7 +37,7 @@ S/Key support:
Authors and contributors
========================
Thanks to at least the following people for sending patches, bug
Thanks to at least the following people for sending me patches, bug
reports and various comments. This list may be incomplete, I received
a lot of mail...
@@ -69,7 +69,6 @@ Greg Mortensen <loki@world.std.com>
Guido van Rooij
Guy Maor <maor@debian.org>
Hrvoje Dogan <hdogan@bjesomar.srce.hr>
Jakub Hrozek <jhrozek@redhat.com>
Janos Farkas <chexum@bankinf.banki.hu>
Jay Soffian <jay@lw.net>
Jesse Thilo <Jesse.Thilo@pobox.com>
@@ -81,7 +80,6 @@ Joshua Cowan <jcowan@hermit.reslife.okstate.edu>
Judd Bourgeois <shagboy@bluesky.net>
Juergen Heinzl <unicorn@noris.net>
Juha Virtanen <jiivee@iki.fi>
Julian Pidancet <julian.pidancet@gmail.com>
Julianne Frances Haugh <jockgrrl@ix.netcom.com>
Leonard N. Zubkoff <lnz@dandelion.com>
Luca Berra <bluca@www.polimi.it>
@@ -97,12 +95,10 @@ Mike Pakovic <mpakovic@users.southeast.net>
Nicolas François <nicolas.francois@centraliens.net>
Nikos Mavroyanopoulos <nmav@i-net.paiko.gr>
Pavel Machek <pavel@bug.ucw.cz>
Peter Vrabec <pvrabec@redhat.com>
Phillip Street
Rafał Maszkowski <rzm@icm.edu.pl>
Rani Chouha <ranibey@smartec.com>
Sami Kerola <kerolasa@rocketmail.com>
Scott Garman <scott.a.garman@intel.com>
Sebastian Rick Rijkers <srrijkers@gmail.com>
Seraphim Mellos <mellos@ceid.upatras.gr>
Shane Watts <shane@nexus.mlckew.edu.au>

15
TODO
View File

@@ -1,10 +1,3 @@
* Create a common usage function that'd take the array of
long options and an array of descriptions and output that so things would
be standardized across the utils.
Usage strings should be normalized and split first.
Investigate optparse.
/etc/default/useradd
* GROUP=1000 should accept a group name.
@@ -115,13 +108,7 @@ ALL:
entry (with a password).
- Add check to move passwd passwords to shadow if there is a shadow
file.
- Support an alternative /etc/tcb directory as second parameter.
- add options -g / -G to specify alternative group / gshadow files
- su
- add a login.defs configuration parameter to add variables to keep in
the environment with "su -l" (TERM/TERMCOLOR/...)
- vipw
- set ACLs and XATTRs on the temporary file (and backups?)
- vipw + selinux -> use lib/selinux.c
the environment with "su -l" (TERM/TERMCOLOR/...

View File

@@ -1,7 +1,5 @@
#! /bin/sh
autoreconf -v -f --install || exit 1
./configure \
CFLAGS="-O2 -Wall" \
--enable-man \

View File

@@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT
AM_INIT_AUTOMAKE(shadow, 4.3.1)
AM_INIT_AUTOMAKE(shadow, 4.1.4.2)
AC_CONFIG_HEADERS([config.h])
dnl Some hacks...
@@ -19,6 +19,7 @@ AC_PROG_CC
AC_ISC_POSIX
AC_PROG_LN_S
AC_PROG_YACC
AM_C_PROTOTYPES
AM_PROG_LIBTOOL
dnl Checks for libraries.
@@ -32,8 +33,7 @@ AC_HEADER_STDBOOL
AC_CHECK_HEADERS(errno.h fcntl.h limits.h unistd.h sys/time.h utmp.h \
utmpx.h termios.h termio.h sgtty.h sys/ioctl.h syslog.h paths.h \
utime.h ulimit.h sys/resource.h gshadow.h lastlog.h \
locale.h rpc/key_prot.h netdb.h acl/libacl.h attr/libattr.h \
attr/error_context.h)
locale.h rpc/key_prot.h netdb.h)
dnl shadow now uses the libc's shadow implementation
AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])])
@@ -41,8 +41,7 @@ AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])])
AC_CHECK_FUNCS(l64a fchmod fchown fsync futimes getgroups gethostname getspnam \
gettimeofday getusershell getutent initgroups lchown lckpwdf lstat \
lutimes memcpy memset setgroups sigaction strchr updwtmp updwtmpx innetgr \
getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo \
ruserok)
getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo)
AC_SYS_LARGEFILE
dnl Checks for typedefs, structures, and compiler characteristics.
@@ -113,6 +112,7 @@ AC_REPLACE_FUNCS(sgetgrent sgetpwent sgetspent)
AC_REPLACE_FUNCS(snprintf strcasecmp strdup strerror strstr)
AC_CHECK_FUNC(setpgrp)
AC_FUNC_SETPGRP
if test "$ac_cv_header_shadow_h" = "yes"; then
AC_CACHE_CHECK(for working shadow group support,
@@ -195,10 +195,8 @@ AC_DEFINE_UNQUOTED(PASSWD_PROGRAM, "$shadow_cv_passwd_dir/passwd",
dnl XXX - quick hack, should disappear before anyone notices :).
AC_DEFINE(USE_SYSLOG, 1, [Define to use syslog().])
if test "$ac_cv_func_ruserok" = "yes"; then
AC_DEFINE(RLOGIN, 1, [Define if login should support the -r flag for rlogind.])
AC_DEFINE(RUSEROK, 0, [Define to the ruserok() "success" return value (0 or 1).])
fi
AC_DEFINE(RLOGIN, 1, [Define if login should support the -r flag for rlogind.])
AC_DEFINE(RUSEROK, 0, [Define to the ruserok() "success" return value (0 or 1).])
AC_ARG_ENABLE(shadowgrp,
[AC_HELP_STRING([--enable-shadowgrp], [enable shadow group support @<:@default=yes@:>@])],
@@ -240,13 +238,6 @@ AC_ARG_ENABLE(utmpx,
[enable_utmpx="no"]
)
AC_ARG_ENABLE(subordinate-ids,
[AC_HELP_STRING([--enable-subordinate-ids],
[support subordinate ids @<:@default=yes@:>@])],
[enable_subids="${enableval}"],
[enable_subids="maybe"]
)
AC_ARG_WITH(audit,
[AC_HELP_STRING([--with-audit], [use auditing support @<:@default=yes if found@:>@])],
[with_audit=$withval], [with_audit=maybe])
@@ -256,20 +247,11 @@ AC_ARG_WITH(libpam,
AC_ARG_WITH(selinux,
[AC_HELP_STRING([--with-selinux], [use SELinux support @<:@default=yes if found@:>@])],
[with_selinux=$withval], [with_selinux=maybe])
AC_ARG_WITH(acl,
[AC_HELP_STRING([--with-acl], [use ACL support @<:@default=yes if found@:>@])],
[with_acl=$withval], [with_acl=maybe])
AC_ARG_WITH(attr,
[AC_HELP_STRING([--with-attr], [use Extended Attribute support @<:@default=yes if found@:>@])],
[with_attr=$withval], [with_attr=maybe])
AC_ARG_WITH(skey,
[AC_HELP_STRING([--with-skey], [use S/Key support @<:@default=no@:>@])],
[with_skey=$withval], [with_skey=no])
AC_ARG_WITH(tcb,
[AC_HELP_STRING([--with-tcb], [use tcb support (incomplete) @<:@default=yes if found@:>@])],
[with_tcb=$withval], [with_tcb=maybe])
AC_ARG_WITH(libcrack,
[AC_HELP_STRING([--with-libcrack], [use libcrack @<:@default=no@:>@])],
[AC_HELP_STRING([--with-libcrack], [use libcrack @<:@default=yes if found and if PAM not enabled@:>@])],
[with_libcrack=$withval], [with_libcrack=no])
AC_ARG_WITH(sha-crypt,
[AC_HELP_STRING([--with-sha-crypt], [allow the SHA256 and SHA512 password encryption algorithms @<:@default=yes@:>@])],
@@ -331,81 +313,10 @@ if test "$enable_man" = "yes"; then
fi
AM_CONDITIONAL(ENABLE_REGENERATE_MAN, test "x$enable_man" != "xno")
if test "$enable_subids" != "no"; then
dnl
dnl FIXME: check if 32 bit UIDs/GIDs are supported by libc
dnl
AC_CHECK_SIZEOF([uid_t],, [#include "sys/types.h"])
AC_CHECK_SIZEOF([gid_t],, [#include "sys/types.h"])
if test "$ac_cv_sizeof_uid_t" -ge 4 && test "$ac_cv_sizeof_gid_t" -ge 4; then
AC_DEFINE(ENABLE_SUBIDS, 1, [Define to support the subordinate IDs.])
enable_subids="yes"
else
if test "x$enable_subids" = "xyes"; then
AC_MSG_ERROR([Cannot enable support the subordinate IDs on systems where gid_t or uid_t has less than 32 bits])
fi
enable_subids="no"
fi
fi
AM_CONDITIONAL(ENABLE_SUBIDS, test "x$enable_subids" != "xno")
AC_SUBST(LIBCRYPT)
AC_CHECK_LIB(crypt, crypt, [LIBCRYPT=-lcrypt],
[AC_MSG_ERROR([crypt() not found])])
AC_SUBST(LIBACL)
if test "$with_acl" != "no"; then
AC_CHECK_HEADERS(acl/libacl.h attr/error_context.h, [acl_header="yes"], [acl_header="no"])
if test "$acl_header$with_acl" = "noyes" ; then
AC_MSG_ERROR([acl/libacl.h or attr/error_context.h is missing])
elif test "$acl_header" = "yes" ; then
AC_CHECK_LIB(acl, perm_copy_file,
[AC_CHECK_LIB(acl, perm_copy_fd,
[acl_lib="yes"],
[acl_lib="no"])],
[acl_lib="no"])
if test "$acl_lib$with_acl" = "noyes" ; then
AC_MSG_ERROR([libacl not found])
elif test "$acl_lib" = "no" ; then
with_acl="no"
else
AC_DEFINE(WITH_ACL, 1,
[Build shadow with ACL support])
LIBACL="-lacl"
with_acl="yes"
fi
else
with_acl="no"
fi
fi
AC_SUBST(LIBATTR)
if test "$with_attr" != "no"; then
AC_CHECK_HEADERS(attr/libattr.h attr/error_context.h, [attr_header="yes"], [attr_header="no"])
if test "$attr_header$with_attr" = "noyes" ; then
AC_MSG_ERROR([attr/libattr.h or attr/error_context.h is missing])
elif test "$attr_header" = "yes" ; then
AC_CHECK_LIB(attr, attr_copy_file,
[AC_CHECK_LIB(attr, attr_copy_fd,
[attr_lib="yes"],
[attr_lib="no"])],
[attr_lib="no"])
if test "$attr_lib$with_attr" = "noyes" ; then
AC_MSG_ERROR([libattr not found])
elif test "$attr_lib" = "no" ; then
with_attr="no"
else
AC_DEFINE(WITH_ATTR, 1,
[Build shadow with Extended Attributes support])
LIBATTR="-lattr"
with_attr="yes"
fi
else
with_attr="no"
fi
fi
AC_SUBST(LIBAUDIT)
if test "$with_audit" != "no"; then
AC_CHECK_HEADER(libaudit.h, [audit_header="yes"], [audit_header="no"])
@@ -450,65 +361,28 @@ if test "$with_libcrack" = "yes"; then
fi
AC_SUBST(LIBSELINUX)
AC_SUBST(LIBSEMANAGE)
if test "$with_selinux" != "no"; then
AC_CHECK_HEADERS(selinux/selinux.h, [selinux_header="yes"], [selinux_header="no"])
if test "$selinux_header$with_selinux" = "noyes" ; then
AC_MSG_ERROR([selinux/selinux.h is missing])
fi
AC_CHECK_HEADERS(semanage/semanage.h, [semanage_header="yes"], [semanage_header="no"])
if test "$semanage_header$with_selinux" = "noyes" ; then
AC_MSG_ERROR([semanage/semanage.h is missing])
fi
if test "$selinux_header$semanage_header" = "yesyes" ; then
AC_CHECK_LIB(selinux, is_selinux_enabled, [selinux_lib="yes"], [selinux_lib="no"])
elif test "$selinux_header" = "yes" ; then
AC_CHECK_LIB(selinux, is_selinux_enabled,
[selinux_lib="yes"], [selinux_lib="no"])
if test "$selinux_lib$with_selinux" = "noyes" ; then
AC_MSG_ERROR([libselinux not found])
fi
AC_CHECK_LIB(semanage, semanage_connect, [semanage_lib="yes"], [semanage_lib="no"])
if test "$semanage_lib$with_selinux" = "noyes" ; then
AC_MSG_ERROR([libsemanage not found])
fi
if test "$selinux_lib$semanage_lib" == "yesyes" ; then
elif test "$selinux_lib" = "no" ; then
with_selinux="no"
else
AC_DEFINE(WITH_SELINUX, 1,
[Build shadow with SELinux support])
LIBSELINUX="-lselinux"
LIBSEMANAGE="-lsemanage"
with_selinux="yes"
else
with_selinux="no"
fi
else
with_selinux="no"
fi
fi
AC_SUBST(LIBTCB)
if test "$with_tcb" != "no"; then
AC_CHECK_HEADERS(tcb.h, [tcb_header="yes"], [tcb_header="no"])
if test "$tcb_header$with_tcb" = "noyes" ; then
AC_MSG_ERROR([tcb.h is missing])
elif test "$tcb_header" = "yes" ; then
AC_CHECK_LIB(tcb, tcb_is_suspect, [tcb_lib="yes"], [tcb_lib="no"])
if test "$tcb_lib$with_tcb" = "noyes" ; then
AC_MSG_ERROR([libtcb not found])
elif test "$tcb_lib" = "no" ; then
with_tcb="no"
else
AC_DEFINE(WITH_TCB, 1, [Build shadow with tcb support (incomplete)])
LIBTCB="-ltcb"
with_tcb="yes"
fi
else
with_tcb="no"
fi
fi
AM_CONDITIONAL(WITH_TCB, test x$with_tcb = xyes)
AC_SUBST(LIBPAM)
if test "$with_libpam" != "no"; then
AC_CHECK_LIB(pam, pam_start,
@@ -629,9 +503,8 @@ AC_CONFIG_FILES([
doc/Makefile
man/Makefile
man/config.xml
man/po/Makefile
man/po/Makefile.in
man/cs/Makefile
man/da/Makefile
man/de/Makefile
man/es/Makefile
man/fi/Makefile
@@ -668,12 +541,8 @@ if test "$with_libpam" = "yes"; then
echo " suid account management tools: $enable_acct_tools_setuid"
fi
echo " SELinux support: $with_selinux"
echo " ACL support: $with_acl"
echo " Extended Attributes support: $with_attr"
echo " tcb support (incomplete): $with_tcb"
echo " shadow group support: $enable_shadowgrp"
echo " S/Key support: $with_skey"
echo " SHA passwords encryption: $with_sha_crypt"
echo " nscd support: $with_nscd"
echo " subordinate IDs support: $enable_subids"
echo

View File

@@ -6,18 +6,18 @@
#
# Delay in seconds before being allowed another attempt after a login failure
# Note: When PAM is used, some modules may enforce a minimum delay (e.g.
# pam_unix(8) enforces a 2s delay)
# Note: When PAM is used, some modules may enfore a minimal delay (e.g.
# pam_unix enforces a 2s delay)
#
FAIL_DELAY 3
#
# Enable logging and display of /var/log/faillog login(1) failure info.
# Enable logging and display of /var/log/faillog login failure info.
#
FAILLOG_ENAB yes
#
# Enable display of unknown usernames when login(1) failures are recorded.
# Enable display of unknown usernames when login failures are recorded.
#
LOG_UNKFAIL_ENAB no
@@ -27,7 +27,7 @@ LOG_UNKFAIL_ENAB no
LOG_OK_LOGINS no
#
# Enable logging and display of /var/log/lastlog login(1) time info.
# Enable logging and display of /var/log/lastlog login time info.
#
LASTLOG_ENAB yes
@@ -50,13 +50,13 @@ OBSCURE_CHECKS_ENAB yes
PORTTIME_CHECKS_ENAB yes
#
# Enable setting of ulimit, umask, and niceness from passwd(5) gecos field.
# Enable setting of ulimit, umask, and niceness from passwd gecos field.
#
QUOTAS_ENAB yes
#
# Enable "syslog" logging of su(1) activity - in addition to sulog file logging.
# SYSLOG_SG_ENAB does the same for newgrp(1) and sg(1).
# Enable "syslog" logging of su activity - in addition to sulog file logging.
# SYSLOG_SG_ENAB does the same for newgrp and sg.
#
SYSLOG_SU_ENAB yes
SYSLOG_SG_ENAB yes
@@ -64,13 +64,13 @@ SYSLOG_SG_ENAB yes
#
# If defined, either full pathname of a file containing device names or
# a ":" delimited list of device names. Root logins will be allowed only
# from these devices.
# upon these devices.
#
CONSOLE /etc/securetty
#CONSOLE console:tty01:tty02:tty03:tty04
#
# If defined, all su(1) activity is logged to this file.
# If defined, all su activity is logged to this file.
#
#SULOG_FILE /var/log/sulog
@@ -82,33 +82,33 @@ MOTD_FILE /etc/motd
#MOTD_FILE /etc/motd:/usr/lib/news/news-motd
#
# If defined, this file will be output before each login(1) prompt.
# If defined, this file will be output before each login prompt.
#
#ISSUE_FILE /etc/issue
#
# If defined, file which maps tty line to TERM environment parameter.
# Each line of the file is in a format similar to "vt100 tty01".
# Each line of the file is in a format something like "vt100 tty01".
#
#TTYTYPE_FILE /etc/ttytype
#
# If defined, login(1) failures will be logged here in a utmp format.
# last(1), when invoked as lastb(1), will read /var/log/btmp, so...
# If defined, login failures will be logged here in a utmp format.
# last, when invoked as lastb, will read /var/log/btmp, so...
#
FTMP_FILE /var/log/btmp
#
# If defined, name of file whose presence will inhibit non-root
# logins. The content of this file should be a message indicating
# If defined, name of file whose presence which will inhibit non-root
# logins. The contents of this file should be a message indicating
# why logins are inhibited.
#
NOLOGINS_FILE /etc/nologin
#
# If defined, the command name to display when running "su -". For
# example, if this is defined as "su" then ps(1) will display the
# command as "-su". If not defined, then ps(1) will display the
# example, if this is defined as "su" then a "ps" will display the
# command is "-su". If not defined, then "ps" would display the
# name of the shell actually being run, e.g. something like "-sh".
#
SU_NAME su
@@ -158,10 +158,10 @@ ENV_PATH PATH=/bin:/usr/bin
# TTYGROUP Login tty will be assigned this group ownership.
# TTYPERM Login tty will be set to this permission.
#
# If you have a write(1) program which is "setgid" to a special group
# which owns the terminals, define TTYGROUP as the number of such group
# and TTYPERM as 0620. Otherwise leave TTYGROUP commented out and
# set TTYPERM to either 622 or 600.
# If you have a "write" program which is "setgid" to a special group
# which owns the terminals, define TTYGROUP to the group number and
# TTYPERM to 0620. Otherwise leave TTYGROUP commented out and assign
# TTYPERM to either 622 or 600.
#
TTYGROUP tty
TTYPERM 0600
@@ -183,13 +183,12 @@ ERASECHAR 0177
KILLCHAR 025
#ULIMIT 2097152
# Default initial "umask" value used by login(1) on non-PAM enabled systems.
# Default "umask" value for pam_umask(8) on PAM enabled systems.
# UMASK is also used by useradd(8) and newusers(8) to set the mode for new
# home directories.
# Default initial "umask" value for non-PAM enabled systems.
# UMASK is also used by useradd and newusers to set the mode of new home
# directories.
# 022 is the default value, but 027, or even 077, could be considered
# for increased privacy. There is no One True Answer here: each sysadmin
# must make up his/her mind.
# better for privacy. There is no One True Answer here: each sysadmin
# must make up her mind.
UMASK 022
#
@@ -214,43 +213,35 @@ PASS_WARN_AGE 7
SU_WHEEL_ONLY no
#
# If compiled with cracklib support, sets the path to the dictionaries
# If compiled with cracklib support, where are the dictionaries
#
CRACKLIB_DICTPATH /var/cache/cracklib/cracklib_dict
#
# Min/max values for automatic uid selection in useradd(8)
# Min/max values for automatic uid selection in useradd
#
UID_MIN 1000
UID_MAX 60000
# System accounts
SYS_UID_MIN 101
SYS_UID_MAX 999
# Extra per user uids
SUB_UID_MIN 100000
SUB_UID_MAX 600100000
SUB_UID_COUNT 65536
#
# Min/max values for automatic gid selection in groupadd(8)
# Min/max values for automatic gid selection in groupadd
#
GID_MIN 1000
GID_MAX 60000
# System accounts
SYS_GID_MIN 101
SYS_GID_MAX 999
# Extra per user group ids
SUB_GID_MIN 100000
SUB_GID_MAX 600100000
SUB_GID_COUNT 65536
#
# Max number of login(1) retries if password is bad
# Max number of login retries if password is bad
#
LOGIN_RETRIES 5
#
# Max time in seconds for login(1)
# Max time in seconds for login
#
LOGIN_TIMEOUT 60
@@ -272,12 +263,12 @@ PASS_ALWAYS_WARN yes
#PASS_MAX_LEN 8
#
# Require password before chfn(1)/chsh(1) can make any changes.
# Require password before chfn/chsh can make any changes.
#
CHFN_AUTH yes
#
# Which fields may be changed by regular users using chfn(1) - use
# Which fields may be changed by regular users using chfn - use
# any combination of letters "frwh" (full name, room number, work
# phone, home phone). If not defined, no changes are allowed.
# For backward compatibility, "yes" = "rwh" and "no" = "frwh".
@@ -302,13 +293,13 @@ CHFN_RESTRICT rwh
# Note: If you use PAM, it is recommended to use a value consistent with
# the PAM modules configuration.
#
# This variable is deprecated. You should use ENCRYPT_METHOD instead.
# This variable is deprecated. You should use ENCRYPT_METHOD.
#
#MD5_CRYPT_ENAB no
#
# Only works if compiled with ENCRYPTMETHOD_SELECT defined:
# If set to MD5, MD5-based algorithm will be used for encrypting password
# If set to MD5 , MD5-based algorithm will be used for encrypting password
# If set to SHA256, SHA256-based algorithm will be used for encrypting password
# If set to SHA512, SHA512-based algorithm will be used for encrypting password
# If set to DES, DES-based algorithm will be used for encrypting password (default)
@@ -323,12 +314,12 @@ CHFN_RESTRICT rwh
# Only works if ENCRYPT_METHOD is set to SHA256 or SHA512.
#
# Define the number of SHA rounds.
# With a lot of rounds, it is more difficult to brute-force the password.
# However, more CPU resources will be needed to authenticate users if
# this value is increased.
# With a lot of rounds, it is more difficult to brute forcing the password.
# But note also that it more CPU resources will be needed to authenticate
# users.
#
# If not specified, the libc will choose the default number of rounds (5000).
# The values must be within the 1000-999999999 range.
# The values must be inside the 1000-999999999 range.
# If only one of the MIN or MAX values is set, then this value will be used.
# If MIN > MAX, the highest value will be used.
#
@@ -337,18 +328,18 @@ CHFN_RESTRICT rwh
#
# List of groups to add to the user's supplementary group set
# when logging in from the console (as determined by the CONSOLE
# when logging in on the console (as determined by the CONSOLE
# setting). Default is none.
#
# Use with caution - it is possible for users to gain permanent
# access to these groups, even when not logged in from the console.
# access to these groups, even when not logged in on the console.
# How to do it is left as an exercise for the reader...
#
#CONSOLE_GROUPS floppy:audio:cdrom
#
# Should login be allowed if we can't cd to the home directory?
# Default is no.
# Default in no.
#
DEFAULT_HOME yes
@@ -370,14 +361,14 @@ ENVIRON_FILE /etc/environment
# (examples: 022 -> 002, 077 -> 007) for non-root users, if the uid is
# the same as gid, and username is the same as the primary group name.
#
# This also enables userdel(8) to remove user groups if no members exist.
# This also enables userdel to remove user groups if no members exist.
#
USERGROUPS_ENAB yes
#
# If set to a non-zero number, the shadow utilities will make sure that
# If set to a non-nul number, the shadow utilities will make sure that
# groups never have more than this number of users on one line.
# This permits to support split groups (groups split into multiple lines,
# This permit to support split groups (groups split into multiple lines,
# with the same group ID, to avoid limitation of the line length in the
# group file).
#
@@ -386,15 +377,10 @@ USERGROUPS_ENAB yes
#MAX_MEMBERS_PER_GROUP 0
#
# If useradd(8) should create home directories for users by default (non
# system users only).
# This option is overridden with the -M or -m flags on the useradd(8)
# command-line.
# If useradd should create home directories for users by default (non
# system users only)
# This option is overridden with the -M or -m flags on the useradd command
# line.
#
#CREATE_HOME yes
#
# Force use shadow, even if shadow passwd & shadow group files are
# missing.
#
#FORCE_SHADOW yes

View File

@@ -14,7 +14,6 @@ libshadow_la_SOURCES = \
encrypt.c \
exitcodes.h \
faillog.h \
fields.c \
fputsx.c \
getdef.c \
getdef.h \
@@ -39,10 +38,6 @@ libshadow_la_SOURCES = \
pwio.c \
pwio.h \
pwmem.c \
subordinateio.h \
subordinateio.c \
selinux.c \
semanage.c \
sgetgrent.c \
sgetpwent.c \
sgetspent.c \
@@ -52,13 +47,8 @@ libshadow_la_SOURCES = \
shadowio.c \
shadowio.h \
shadowmem.c \
spawn.c \
utent.c
if WITH_TCB
libshadow_la_SOURCES += tcbfuncs.c tcbfuncs.h
endif
# These files are unneeded for some reason, listed in
# order of appearance:
#

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2001, Marek Michałkiewicz
* Copyright (c) 2001 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2011, Nicolas François
* Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -45,16 +45,16 @@
#include <stdio.h>
#include <signal.h>
#include "nscd.h"
#ifdef WITH_TCB
#include <tcb.h>
#endif /* WITH_TCB */
#ifdef WITH_SELINUX
#include <selinux/selinux.h>
#endif
#include "prototypes.h"
#include "commonio.h"
/* local function prototypes */
static int lrename (const char *, const char *);
static int check_link_count (const char *file);
static int do_lock_file (const char *file, const char *lock, bool log);
static int do_lock_file (const char *file, const char *lock);
static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms (
const char *name,
const char *mode,
@@ -132,7 +132,7 @@ static int check_link_count (const char *file)
}
static int do_lock_file (const char *file, const char *lock, bool log)
static int do_lock_file (const char *file, const char *lock)
{
int fd;
pid_t pid;
@@ -142,11 +142,6 @@ static int do_lock_file (const char *file, const char *lock, bool log)
fd = open (file, O_CREAT | O_EXCL | O_WRONLY, 0600);
if (-1 == fd) {
if (log) {
(void) fprintf (stderr,
"%s: %s: %s\n",
Prog, file, strerror (errno));
}
return 0;
}
@@ -154,11 +149,6 @@ static int do_lock_file (const char *file, const char *lock, bool log)
snprintf (buf, sizeof buf, "%lu", (unsigned long) pid);
len = (ssize_t) strlen (buf) + 1;
if (write (fd, buf, (size_t) len) != len) {
if (log) {
(void) fprintf (stderr,
"%s: %s: %s\n",
Prog, file, strerror (errno));
}
(void) close (fd);
unlink (file);
return 0;
@@ -167,22 +157,12 @@ static int do_lock_file (const char *file, const char *lock, bool log)
if (link (file, lock) == 0) {
retval = check_link_count (file);
if ((0==retval) && log) {
(void) fprintf (stderr,
"%s: %s: lock file already used\n",
Prog, file);
}
unlink (file);
return retval;
}
fd = open (lock, O_RDWR);
if (-1 == fd) {
if (log) {
(void) fprintf (stderr,
"%s: %s: %s\n",
Prog, lock, strerror (errno));
}
unlink (file);
errno = EINVAL;
return 0;
@@ -190,60 +170,29 @@ static int do_lock_file (const char *file, const char *lock, bool log)
len = read (fd, buf, sizeof (buf) - 1);
close (fd);
if (len <= 0) {
if (log) {
(void) fprintf (stderr,
"%s: existing lock file %s without a PID\n",
Prog, lock);
}
unlink (file);
errno = EINVAL;
return 0;
}
buf[len] = '\0';
if (get_pid (buf, &pid) == 0) {
if (log) {
(void) fprintf (stderr,
"%s: existing lock file %s with an invalid PID '%s'\n",
Prog, lock, buf);
}
unlink (file);
errno = EINVAL;
return 0;
}
if (kill (pid, 0) == 0) {
if (log) {
(void) fprintf (stderr,
"%s: lock %s already used by PID %lu\n",
Prog, lock, (unsigned long) pid);
}
unlink (file);
errno = EEXIST;
return 0;
}
if (unlink (lock) != 0) {
if (log) {
(void) fprintf (stderr,
"%s: cannot get lock %s: %s\n",
Prog, lock, strerror (errno));
}
unlink (file);
return 0;
}
retval = 0;
if (link (file, lock) == 0) {
retval = check_link_count (file);
if ((0==retval) && log) {
(void) fprintf (stderr,
"%s: %s: lock file already used\n",
Prog, file);
}
} else {
if (log) {
(void) fprintf (stderr,
"%s: cannot get lock %s: %s\n",
Prog, lock, strerror (errno));
}
if ((link (file, lock) == 0) && (check_link_count (file) != 0)) {
retval = 1;
}
unlink (file);
@@ -270,21 +219,21 @@ static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms (
if (fchown (fileno (fp), sb->st_uid, sb->st_gid) != 0) {
goto fail;
}
#else /* !HAVE_FCHOWN */
#else
if (chown (name, sb->st_mode) != 0) {
goto fail;
}
#endif /* !HAVE_FCHOWN */
#endif
#ifdef HAVE_FCHMOD
if (fchmod (fileno (fp), sb->st_mode & 0664) != 0) {
goto fail;
}
#else /* !HAVE_FCHMOD */
#else
if (chmod (name, sb->st_mode & 0664) != 0) {
goto fail;
}
#endif /* !HAVE_FCHMOD */
#endif
return fp;
fail:
@@ -376,7 +325,7 @@ bool commonio_present (const struct commonio_db *db)
}
int commonio_lock_nowait (struct commonio_db *db, bool log)
int commonio_lock_nowait (struct commonio_db *db)
{
char file[1024];
char lock[1024];
@@ -388,7 +337,7 @@ int commonio_lock_nowait (struct commonio_db *db, bool log)
snprintf (file, sizeof file, "%s.%lu",
db->filename, (unsigned long) getpid ());
snprintf (lock, sizeof lock, "%s.lock", db->filename);
if (do_lock_file (file, lock, log) != 0) {
if (do_lock_file (file, lock) != 0) {
db->locked = true;
lock_count++;
return 1;
@@ -412,22 +361,17 @@ int commonio_lock (struct commonio_db *db)
*/
if (0 == lock_count) {
if (lckpwdf () == -1) {
if (geteuid () != 0) {
(void) fprintf (stderr,
"%s: Permission denied.\n",
Prog);
}
return 0; /* failure */
}
}
if (commonio_lock_nowait (db, true) != 0) {
if (commonio_lock_nowait (db) != 0) {
return 1; /* success */
}
ulckpwdf ();
return 0; /* failure */
#else /* !HAVE_LCKPWDF */
#else
int i;
/*
@@ -444,18 +388,16 @@ int commonio_lock (struct commonio_db *db)
if (i > 0) {
sleep (LOCK_SLEEP); /* delay between retries */
}
if (commonio_lock_nowait (db, i==LOCK_TRIES-1) != 0) {
if (commonio_lock_nowait (db) != 0) {
return 1; /* success */
}
/* no unnecessary retries on "permission denied" errors */
if (geteuid () != 0) {
(void) fprintf (stderr, "%s: Permission denied.\n",
Prog);
return 0;
}
}
return 0; /* failure */
#endif /* !HAVE_LCKPWDF */
#endif
}
static void dec_lock_count (void)
@@ -472,7 +414,7 @@ static void dec_lock_count (void)
}
#ifdef HAVE_LCKPWDF
ulckpwdf ();
#endif /* HAVE_LCKPWDF */
#endif
}
}
}
@@ -591,7 +533,6 @@ int commonio_open (struct commonio_db *db, int mode)
void *eptr = NULL;
int flags = mode;
size_t buflen;
int fd;
int saved_errno;
mode &= ~O_CREAT;
@@ -608,31 +549,11 @@ int commonio_open (struct commonio_db *db, int mode)
return 0;
}
db->head = NULL;
db->tail = NULL;
db->head = db->tail = NULL;
db->cursor = NULL;
db->changed = false;
fd = open (db->filename,
(db->readonly ? O_RDONLY : O_RDWR)
| O_NOCTTY | O_NONBLOCK | O_NOFOLLOW);
saved_errno = errno;
db->fp = NULL;
if (fd >= 0) {
#ifdef WITH_TCB
if (tcb_is_suspect (fd) != 0) {
(void) close (fd);
errno = EINVAL;
return 0;
}
#endif /* WITH_TCB */
db->fp = fdopen (fd, db->readonly ? "r" : "r+");
saved_errno = errno;
if (NULL == db->fp) {
(void) close (fd);
}
}
errno = saved_errno;
db->fp = fopen (db->filename, db->readonly ? "r" : "r+");
/*
* If O_CREAT was specified and the file didn't exist, it will be
@@ -647,7 +568,16 @@ int commonio_open (struct commonio_db *db, int mode)
}
/* Do not inherit fd in spawned processes (e.g. nscd) */
fcntl (fileno (db->fp), F_SETFD, FD_CLOEXEC);
fcntl(fileno(db->fp), F_SETFD, FD_CLOEXEC);
#ifdef WITH_SELINUX
db->scontext = NULL;
if ((is_selinux_enabled () > 0) && (!db->readonly)) {
if (fgetfilecon (fileno (db->fp), &db->scontext) < 0) {
goto cleanup_errno;
}
}
#endif
buflen = BUFLEN;
buf = (char *) malloc (buflen);
@@ -733,6 +663,12 @@ int commonio_open (struct commonio_db *db, int mode)
cleanup_errno:
saved_errno = errno;
free_linked_list (db);
#ifdef WITH_SELINUX
if (db->scontext != NULL) {
freecon (db->scontext);
db->scontext = NULL;
}
#endif
fclose (db->fp);
db->fp = NULL;
errno = saved_errno;
@@ -747,26 +683,10 @@ commonio_sort (struct commonio_db *db, int (*cmp) (const void *, const void *))
{
struct commonio_entry **entries, *ptr;
size_t n = 0, i;
#if KEEP_NIS_AT_END
struct commonio_entry *nis = NULL;
#endif
for (ptr = db->head;
(NULL != ptr)
#if KEEP_NIS_AT_END
&& (NULL != ptr->line)
&& ( ('+' != ptr->line[0])
&& ('-' != ptr->line[0]))
#endif
;
ptr = ptr->next) {
for (ptr = db->head; NULL != ptr; ptr = ptr->next) {
n++;
}
#if KEEP_NIS_AT_END
if ((NULL != ptr) && (NULL != ptr->line)) {
nis = ptr;
}
#endif
if (n <= 1) {
return 0;
@@ -778,40 +698,18 @@ commonio_sort (struct commonio_db *db, int (*cmp) (const void *, const void *))
}
n = 0;
for (ptr = db->head;
#if KEEP_NIS_AT_END
nis != ptr;
#else
NULL != ptr;
#endif
/*@ -nullderef @*/
ptr = ptr->next
/*@ +nullderef @*/
) {
entries[n] = ptr;
n++;
for (ptr = db->head; NULL != ptr; ptr = ptr->next) {
entries[n++] = ptr;
}
qsort (entries, n, sizeof (struct commonio_entry *), cmp);
/* Take care of the head and tail separately */
db->head = entries[0];
n--;
#if KEEP_NIS_AT_END
if (NULL == nis)
#endif
{
db->tail = entries[n];
}
db->tail = entries[--n];
db->head->prev = NULL;
db->head->next = entries[1];
entries[n]->prev = entries[n - 1];
#if KEEP_NIS_AT_END
entries[n]->next = nis;
#else
entries[n]->next = NULL;
#endif
db->tail->prev = entries[n - 1];
db->tail->next = NULL;
/* Now other elements have prev and next entries */
for (i = 1; i < n; i++) {
entries[i]->prev = entries[i - 1];
entries[i]->next = entries[i + 1];
@@ -826,8 +724,7 @@ commonio_sort (struct commonio_db *db, int (*cmp) (const void *, const void *))
/*
* Sort entries in db according to order in another.
*/
int commonio_sort_wrt (struct commonio_db *shadow,
const struct commonio_db *passwd)
int commonio_sort_wrt (struct commonio_db *shadow, struct commonio_db *passwd)
{
struct commonio_entry *head = NULL, *pw_ptr, *spw_ptr;
const char *name;
@@ -914,6 +811,10 @@ int commonio_close (struct commonio_db *db)
int errors = 0;
struct stat sb;
#ifdef WITH_SELINUX
/*@null@*/security_context_t old_context = NULL;
#endif
if (!db->isopen) {
errno = EINVAL;
return 0;
@@ -921,7 +822,7 @@ int commonio_close (struct commonio_db *db)
db->isopen = false;
if (!db->changed || db->readonly) {
(void) fclose (db->fp);
fclose (db->fp);
db->fp = NULL;
goto success;
}
@@ -933,21 +834,27 @@ int commonio_close (struct commonio_db *db)
memzero (&sb, sizeof sb);
if (NULL != db->fp) {
if (fstat (fileno (db->fp), &sb) != 0) {
(void) fclose (db->fp);
fclose (db->fp);
db->fp = NULL;
goto fail;
}
#ifdef WITH_SELINUX
if (db->scontext != NULL) {
if (getfscreatecon (&old_context) < 0) {
errors++;
goto fail;
}
if (setfscreatecon (db->scontext) < 0) {
errors++;
goto fail;
}
}
#endif
/*
* Create backup file.
*/
snprintf (buf, sizeof buf, "%s-", db->filename);
#ifdef WITH_SELINUX
if (set_selinux_file_context (buf) != 0) {
errors++;
}
#endif
if (create_backup (buf, db->fp) != 0) {
errors++;
}
@@ -956,11 +863,6 @@ int commonio_close (struct commonio_db *db)
errors++;
}
#ifdef WITH_SELINUX
if (reset_selinux_file_context () != 0) {
errors++;
}
#endif
if (errors != 0) {
db->fp = NULL;
goto fail;
@@ -968,20 +870,15 @@ int commonio_close (struct commonio_db *db)
} else {
/*
* Default permissions for new [g]shadow files.
* (passwd and group always exist...)
*/
sb.st_mode = db->st_mode;
sb.st_uid = db->st_uid;
sb.st_gid = db->st_gid;
sb.st_mode = 0400;
sb.st_uid = 0;
sb.st_gid = 0;
}
snprintf (buf, sizeof buf, "%s+", db->filename);
#ifdef WITH_SELINUX
if (set_selinux_file_context (buf) != 0) {
errors++;
}
#endif
db->fp = fopen_set_perms (buf, "w", &sb);
if (NULL == db->fp) {
goto fail;
@@ -998,9 +895,9 @@ int commonio_close (struct commonio_db *db)
if (fsync (fileno (db->fp)) != 0) {
errors++;
}
#else /* !HAVE_FSYNC */
#else
sync ();
#endif /* !HAVE_FSYNC */
#endif
if (fclose (db->fp) != 0) {
errors++;
}
@@ -1016,18 +913,25 @@ int commonio_close (struct commonio_db *db)
goto fail;
}
#ifdef WITH_SELINUX
if (reset_selinux_file_context () != 0) {
goto fail;
}
#endif
nscd_need_reload = true;
goto success;
fail:
errors++;
success:
#ifdef WITH_SELINUX
if (db->scontext != NULL) {
if (NULL != old_context) {
if (setfscreatecon (old_context) < 0) {
errors++;
}
freecon (old_context);
old_context = NULL;
}
freecon (db->scontext);
db->scontext = NULL;
}
#endif
free_linked_list (db);
return errors == 0;
}
@@ -1058,7 +962,7 @@ static /*@dependent@*/ /*@null@*/struct commonio_entry *find_entry_by_name (
struct commonio_db *db,
const char *name)
{
return next_entry_by_name (db, db->head, name);
return next_entry_by_name(db, db->head, name);
}
@@ -1080,7 +984,6 @@ int commonio_update (struct commonio_db *db, const void *eptr)
if (NULL != p) {
if (next_entry_by_name (db, p->next, db->ops->getname (eptr)) != NULL) {
fprintf (stderr, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), db->ops->getname (eptr), db->filename);
db->ops->free (nentry);
return 0;
}
db->ops->free (p->eptr);
@@ -1105,46 +1008,14 @@ int commonio_update (struct commonio_db *db, const void *eptr)
#if KEEP_NIS_AT_END
add_one_entry_nis (db, p);
#else /* !KEEP_NIS_AT_END */
#else
add_one_entry (db, p);
#endif /* !KEEP_NIS_AT_END */
#endif
db->changed = true;
return 1;
}
#ifdef ENABLE_SUBIDS
int commonio_append (struct commonio_db *db, const void *eptr)
{
struct commonio_entry *p;
void *nentry;
if (!db->isopen || db->readonly) {
errno = EINVAL;
return 0;
}
nentry = db->ops->dup (eptr);
if (NULL == nentry) {
errno = ENOMEM;
return 0;
}
/* new entry */
p = (struct commonio_entry *) malloc (sizeof *p);
if (NULL == p) {
db->ops->free (nentry);
errno = ENOMEM;
return 0;
}
p->eptr = nentry;
p->line = NULL;
p->changed = true;
add_one_entry (db, p);
db->changed = true;
return 1;
}
#endif /* ENABLE_SUBIDS */
void commonio_del_entry (struct commonio_db *db, const struct commonio_entry *p)
{

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -123,17 +123,10 @@ struct commonio_db {
#ifdef WITH_SELINUX
/*@null@*/security_context_t scontext;
#endif
/*
* Default permissions and owner for newly created data file.
*/
mode_t st_mode;
uid_t st_uid;
gid_t st_gid;
/*
* Head, tail, current position in linked list.
*/
/*@owned@*/ /*@null@*/struct commonio_entry *head;
/*@dependent@*/ /*@null@*/struct commonio_entry *tail;
/*@owned@*/ /*@null@*/struct commonio_entry *head, *tail;
/*@dependent@*/ /*@null@*/struct commonio_entry *cursor;
/*
@@ -148,23 +141,20 @@ struct commonio_db {
extern int commonio_setname (struct commonio_db *, const char *);
extern bool commonio_present (const struct commonio_db *db);
extern int commonio_lock (struct commonio_db *);
extern int commonio_lock_nowait (struct commonio_db *, bool log);
extern int commonio_lock_nowait (struct commonio_db *);
extern int commonio_open (struct commonio_db *, int);
extern /*@observer@*/ /*@null@*/const void *commonio_locate (struct commonio_db *, const char *);
extern int commonio_update (struct commonio_db *, const void *);
#ifdef ENABLE_SUBIDS
extern int commonio_append (struct commonio_db *, const void *);
#endif /* ENABLE_SUBIDS */
extern int commonio_remove (struct commonio_db *, const char *);
extern int commonio_rewind (struct commonio_db *);
extern /*@observer@*/ /*@null@*/const void *commonio_next (struct commonio_db *);
extern int commonio_close (struct commonio_db *);
extern int commonio_unlock (struct commonio_db *);
extern void commonio_del_entry (struct commonio_db *,
const struct commonio_entry *);
const struct commonio_entry *);
extern int commonio_sort_wrt (struct commonio_db *shadow,
const struct commonio_db *passwd);
struct commonio_db *passwd);
extern int commonio_sort (struct commonio_db *db,
int (*cmp) (const void *, const void *));
int (*cmp) (const void *, const void *));
#endif

View File

@@ -177,7 +177,7 @@ char *strchr (), *strrchr (), *strtok ();
* --Nekral */
#define SYSLOG(x) \
do { \
char *old_locale = setlocale (LC_ALL, NULL); \
char *old_locale = setlocale(LC_ALL, NULL); \
char *saved_locale = NULL; \
if (NULL != old_locale) { \
saved_locale = strdup (old_locale); \

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1990 - 1993, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,26 +40,27 @@
#include "prototypes.h"
#include "defines.h"
/*@exposed@*//*@null@*/char *pw_encrypt (const char *clear, const char *salt)
char *pw_encrypt (const char *clear, const char *salt)
{
static char cipher[128];
char *cp;
cp = crypt (clear, salt);
if (NULL == cp) {
if (!cp) {
/*
* Single Unix Spec: crypt() may return a null pointer,
* and set errno to indicate an error. In this case return
* the NULL so the caller can handle appropriately.
* and set errno to indicate an error. The caller doesn't
* expect us to return NULL, so...
*/
return NULL;
perror ("crypt");
exit (EXIT_FAILURE);
}
/* Some crypt() do not return NULL if the algorithm is not
/* The GNU crypt does not return NULL if the algorithm is not
* supported, and return a DES encrypted password. */
if ((NULL != salt) && (salt[0] == '$') && (strlen (cp) <= 13))
{
/*@observer@*/const char *method;
const char *method;
switch (salt[1])
{
case '1':
@@ -78,9 +79,9 @@
method = &nummethod[0];
}
}
(void) fprintf (stderr,
_("crypt method not supported by libcrypt? (%s)\n"),
method);
fprintf (stderr,
_("crypt method not supported by libcrypt? (%s)\n"),
method);
exit (EXIT_FAILURE);
}

View File

@@ -49,32 +49,6 @@ struct itemdef {
/*@null@*/char *value; /* value given, or NULL if no value */
};
#define PAMDEFS \
{"CHFN_AUTH", NULL}, \
{"CHSH_AUTH", NULL}, \
{"CRACKLIB_DICTPATH", NULL}, \
{"ENV_HZ", NULL}, \
{"ENVIRON_FILE", NULL}, \
{"ENV_TZ", NULL}, \
{"FAILLOG_ENAB", NULL}, \
{"FTMP_FILE", NULL}, \
{"ISSUE_FILE", NULL}, \
{"LASTLOG_ENAB", NULL}, \
{"LOGIN_STRING", NULL}, \
{"MAIL_CHECK_ENAB", NULL}, \
{"MOTD_FILE", NULL}, \
{"NOLOGINS_FILE", NULL}, \
{"OBSCURE_CHECKS_ENAB", NULL}, \
{"PASS_ALWAYS_WARN", NULL}, \
{"PASS_CHANGE_TRIES", NULL}, \
{"PASS_MAX_LEN", NULL}, \
{"PASS_MIN_LEN", NULL}, \
{"PORTTIME_CHECKS_ENAB", NULL}, \
{"QUOTAS_ENAB", NULL}, \
{"SU_WHEEL_ONLY", NULL}, \
{"ULIMIT", NULL},
#define NUMDEFS (sizeof(def_table)/sizeof(def_table[0]))
static struct itemdef def_table[] = {
{"CHFN_RESTRICT", NULL},
@@ -107,12 +81,6 @@ static struct itemdef def_table[] = {
{"SHA_CRYPT_MAX_ROUNDS", NULL},
{"SHA_CRYPT_MIN_ROUNDS", NULL},
#endif
{"SUB_GID_COUNT", NULL},
{"SUB_GID_MAX", NULL},
{"SUB_GID_MIN", NULL},
{"SUB_UID_COUNT", NULL},
{"SUB_UID_MAX", NULL},
{"SUB_UID_MIN", NULL},
{"SULOG_FILE", NULL},
{"SU_NAME", NULL},
{"SYS_GID_MAX", NULL},
@@ -128,28 +96,37 @@ static struct itemdef def_table[] = {
{"USERDEL_CMD", NULL},
{"USERGROUPS_ENAB", NULL},
#ifndef USE_PAM
PAMDEFS
{"CHFN_AUTH", NULL},
{"CHSH_AUTH", NULL},
{"CRACKLIB_DICTPATH", NULL},
{"ENV_HZ", NULL},
{"ENVIRON_FILE", NULL},
{"ENV_TZ", NULL},
{"FAILLOG_ENAB", NULL},
{"FTMP_FILE", NULL},
{"ISSUE_FILE", NULL},
{"LASTLOG_ENAB", NULL},
{"LOGIN_STRING", NULL},
{"MAIL_CHECK_ENAB", NULL},
{"MOTD_FILE", NULL},
{"NOLOGINS_FILE", NULL},
{"OBSCURE_CHECKS_ENAB", NULL},
{"PASS_ALWAYS_WARN", NULL},
{"PASS_CHANGE_TRIES", NULL},
{"PASS_MAX_LEN", NULL},
{"PASS_MIN_LEN", NULL},
{"PORTTIME_CHECKS_ENAB", NULL},
{"QUOTAS_ENAB", NULL},
{"SU_WHEEL_ONLY", NULL},
{"ULIMIT", NULL},
#endif
#ifdef USE_SYSLOG
{"SYSLOG_SG_ENAB", NULL},
{"SYSLOG_SU_ENAB", NULL},
#endif
#ifdef WITH_TCB
{"TCB_AUTH_GROUP", NULL},
{"TCB_SYMLINKS", NULL},
{"USE_TCB", NULL},
#endif
{"FORCE_SHADOW", NULL},
{NULL, NULL}
};
#define NUMKNOWNDEFS (sizeof(knowndef_table)/sizeof(knowndef_table[0]))
static struct itemdef knowndef_table[] = {
#ifdef USE_PAM
PAMDEFS
#endif
};
#ifndef LOGINDEFS
#define LOGINDEFS "/etc/login.defs"
#endif
@@ -409,17 +386,10 @@ static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name)
* Item was never found.
*/
for (ptr = knowndef_table; NULL != ptr->name; ptr++) {
if (strcmp (ptr->name, name) == 0) {
goto out;
}
}
fprintf (stderr,
_("configuration error - unknown item '%s' (notify administrator)\n"),
name);
SYSLOG ((LOG_CRIT, "unknown configuration item `%s'", name));
out:
return (struct itemdef *) NULL;
}
@@ -435,26 +405,23 @@ static void def_load (void)
FILE *fp;
char buf[1024], *name, *value, *s;
/*
* Set the initialized flag.
* (do it early to prevent recursion in putdef_str())
*/
def_loaded = true;
/*
* Open the configuration definitions file.
*/
fp = fopen (def_fname, "r");
if (NULL == fp) {
if (errno == ENOENT)
return;
int err = errno;
SYSLOG ((LOG_CRIT, "cannot open login definitions %s [%s]",
def_fname, strerror (err)));
exit (EXIT_FAILURE);
}
/*
* Set the initialized flag.
* (do it early to prevent recursion in putdef_str())
*/
def_loaded = true;
/*
* Go through all of the lines in the file.
*/

View File

@@ -44,19 +44,22 @@
*/
int getulong (const char *numstr, /*@out@*/unsigned long int *result)
{
unsigned long int val;
long long int val;
char *endptr;
errno = 0;
val = strtoul (numstr, &endptr, 0);
val = strtoll (numstr, &endptr, 0);
if ( ('\0' == *numstr)
|| ('\0' != *endptr)
|| (ERANGE == errno)
/*@+ignoresigns@*/
|| (val != (unsigned long int)val)
/*@=ignoresigns@*/
) {
return 0;
}
*result = val;
*result = (unsigned long int)val;
return 1;
}

View File

@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François
* Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -80,23 +80,6 @@ static int group_put (const void *ent, FILE * file)
{
const struct group *gr = ent;
if ( (NULL == gr)
|| (valid_field (gr->gr_name, ":\n") == -1)
|| (valid_field (gr->gr_passwd, ":\n") == -1)
|| (gr->gr_gid == (gid_t)-1)) {
return -1;
}
/* FIXME: fail also if gr->gr_mem == NULL ?*/
if (NULL != gr->gr_mem) {
size_t i;
for (i = 0; NULL != gr->gr_mem[i]; i++) {
if (valid_field (gr->gr_mem[i], ",:\n") == -1) {
return -1;
}
}
}
return (putgrent (gr, file) == -1) ? -1 : 0;
}
@@ -130,9 +113,6 @@ static /*@owned@*/struct commonio_db group_db = {
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif
0644, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
@@ -333,7 +313,7 @@ static /*@null@*/struct commonio_entry *merge_group_entries (
/* Concatenate the 2 lines */
new_line_len = strlen (gr1->line) + strlen (gr2->line) +1;
new_line = (char *)malloc (new_line_len + 1);
new_line = (char *)malloc ((new_line_len + 1) * sizeof(char*));
if (NULL == new_line) {
errno = ENOMEM;
return NULL;
@@ -356,7 +336,7 @@ static /*@null@*/struct commonio_entry *merge_group_entries (
members++;
}
}
new_members = (char **)calloc ( (members+1), sizeof(char*) );
new_members = (char **)malloc ( (members+1) * sizeof(char*) );
if (NULL == new_members) {
free (new_line);
errno = ENOMEM;
@@ -365,8 +345,6 @@ static /*@null@*/struct commonio_entry *merge_group_entries (
for (i=0; NULL != gptr1->gr_mem[i]; i++) {
new_members[i] = gptr1->gr_mem[i];
}
/* NULL termination enforced by above calloc */
members = i;
for (i=0; NULL != gptr2->gr_mem[i]; i++) {
char **pmember = new_members;
@@ -404,19 +382,15 @@ static int split_groups (unsigned int max_members)
struct commonio_entry *new;
struct group *new_gptr;
unsigned int members = 0;
unsigned int i;
/* Check if this group must be split */
if (!gr->changed) {
if (!gr->changed)
continue;
}
if (NULL == gptr) {
if (NULL == gptr)
continue;
}
for (members = 0; NULL != gptr->gr_mem[members]; members++);
if (members <= max_members) {
if (members <= max_members)
continue;
}
new = (struct commonio_entry *) malloc (sizeof *new);
if (NULL == new) {
@@ -434,23 +408,9 @@ static int split_groups (unsigned int max_members)
new->changed = true;
/* Enforce the maximum number of members on gptr */
for (i = max_members; NULL != gptr->gr_mem[i]; i++) {
free (gptr->gr_mem[i]);
gptr->gr_mem[i] = NULL;
}
/* Shift all the members */
gptr->gr_mem[max_members] = NULL;
/* The number of members in new_gptr will be check later */
for (i = 0; NULL != new_gptr->gr_mem[i + max_members]; i++) {
if (NULL != new_gptr->gr_mem[i]) {
free (new_gptr->gr_mem[i]);
}
new_gptr->gr_mem[i] = new_gptr->gr_mem[i + max_members];
new_gptr->gr_mem[i + max_members] = NULL;
}
for (; NULL != new_gptr->gr_mem[i]; i++) {
free (new_gptr->gr_mem[i]);
new_gptr->gr_mem[i] = NULL;
}
new_gptr->gr_mem = &new_gptr->gr_mem[max_members];
/* insert the new entry in the list */
new->prev = gr;

View File

@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2007 - 2013, Nicolas François
* Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -48,37 +48,25 @@
if (NULL == gr) {
return NULL;
}
/* The libc might define other fields. They won't be copied. */
memset (gr, 0, sizeof *gr);
gr->gr_gid = grent->gr_gid;
/*@-mustfreeonly@*/
*gr = *grent;
gr->gr_name = strdup (grent->gr_name);
/*@=mustfreeonly@*/
if (NULL == gr->gr_name) {
gr_free(gr);
return NULL;
}
/*@-mustfreeonly@*/
gr->gr_passwd = strdup (grent->gr_passwd);
/*@=mustfreeonly@*/
if (NULL == gr->gr_passwd) {
gr_free(gr);
return NULL;
}
for (i = 0; grent->gr_mem[i]; i++);
/*@-mustfreeonly@*/
gr->gr_mem = (char **) malloc ((i + 1) * sizeof (char *));
/*@=mustfreeonly@*/
if (NULL == gr->gr_mem) {
gr_free(gr);
return NULL;
}
for (i = 0; grent->gr_mem[i]; i++) {
gr->gr_mem[i] = strdup (grent->gr_mem[i]);
if (NULL == gr->gr_mem[i]) {
gr_free(gr);
return NULL;
}
}
@@ -90,16 +78,11 @@
void gr_free (/*@out@*/ /*@only@*/struct group *grent)
{
free (grent->gr_name);
if (NULL != grent->gr_passwd) {
memzero (grent->gr_passwd, strlen (grent->gr_passwd));
free (grent->gr_passwd);
}
if (NULL != grent->gr_mem) {
size_t i;
for (i = 0; NULL != grent->gr_mem[i]; i++) {
free (grent->gr_mem[i]);
}
free (grent->gr_mem);
memzero (grent->gr_passwd, strlen (grent->gr_passwd));
free (grent->gr_passwd);
while (*(grent->gr_mem)) {
free (*(grent->gr_mem));
grent->gr_mem++;
}
free (grent);
}

View File

@@ -216,13 +216,13 @@ void endsgent (void)
static char *buf = NULL;
char *cp;
struct sgrp *ret;
if (0 == buflen) {
buf = (char *) malloc (BUFSIZ);
if (NULL == buf) {
return NULL;
}
buflen = BUFSIZ;
}
if (NULL == fp) {
@@ -230,9 +230,9 @@ void endsgent (void)
}
#ifdef USE_NIS
while (fgetsx (buf, (int) buflen, fp) == buf)
while (fgetsx (buf, (int) sizeof buf, fp) == buf)
#else
if (fgetsx (buf, (int) buflen, fp) == buf)
if (fgetsx (buf, (int) sizeof buf, fp) == buf)
#endif
{
while ( ((cp = strrchr (buf, '\n')) == NULL)

View File

@@ -43,7 +43,7 @@
struct sgrp {
char *sg_name; /* group name */
char *sg_passwd; /* group password */
char **sg_adm; /* group administrator list */
char **sg_adm; /* group administator list */
char **sg_mem; /* group membership list */
};

View File

@@ -3,49 +3,57 @@
#include <config.h>
#ifdef USE_NSCD
/* because of TEMP_FAILURE_RETRY */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <features.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <spawn.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/types.h>
#include "exitcodes.h"
#include "defines.h"
#include "prototypes.h"
#include "nscd.h"
#define MSG_NSCD_FLUSH_CACHE_FAILED "%s: Failed to flush the nscd cache.\n"
#define MSG_NSCD_FLUSH_CACHE_FAILED "Failed to flush the nscd cache.\n"
/*
* nscd_flush_cache - flush specified service buffer in nscd cache
*/
int nscd_flush_cache (const char *service)
{
int status, code;
const char *cmd = "/usr/sbin/nscd";
const char *spawnedArgs[] = {"nscd", "-i", service, NULL};
const char *spawnedEnv[] = {NULL};
pid_t pid, termpid;
int err, status;
char *spawnedArgs[] = {"/usr/sbin/nscd", "nscd", "-i", service, NULL};
char *spawnedEnv[] = {NULL};
if (run_command (cmd, spawnedArgs, spawnedEnv, &status) != 0) {
/* run_command writes its own more detailed message. */
(void) fprintf (stderr, _(MSG_NSCD_FLUSH_CACHE_FAILED), Prog);
/* spawn process */
err = posix_spawn (&pid, spawnedArgs[0], NULL, NULL,
spawnedArgs, spawnedEnv);
if(0 != err)
{
(void) fputs (_(MSG_NSCD_FLUSH_CACHE_FAILED), stderr);
(void) fprintf (stderr, "posix_spawn() error=%d\n", err);
return -1;
}
code = WEXITSTATUS (status);
if (!WIFEXITED (status)) {
(void) fprintf (stderr,
_("%s: nscd did not terminate normally (signal %d)\n"),
Prog, WTERMSIG (status));
/* Wait for the spawned process to exit */
termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
if (-1 == termpid)
{
(void) fputs (_(MSG_NSCD_FLUSH_CACHE_FAILED), stderr);
perror("waitpid");
return -1;
} else if (code == E_CMD_NOTFOUND) {
/* nscd is not installed, or it is installed but uses an
interpreter that is missing. Probably the former. */
return 0;
} else if (code == 1) {
/* nscd is installed, but it isn't active. */
return 0;
} else if (code != 0) {
(void) fprintf (stderr, _("%s: nscd exited with status %d\n"),
Prog, code);
(void) fprintf (stderr, _(MSG_NSCD_FLUSH_CACHE_FAILED), Prog);
}
else if (termpid != pid)
{
(void) fputs (_(MSG_NSCD_FLUSH_CACHE_FAILED), stderr);
(void) fprintf (stderr, "waitpid returned %ld != %ld\n",
(long int) termpid, (long int) pid);
return -1;
}

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François
* Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,8 +42,6 @@
#ifndef _PROTOTYPES_H
#define _PROTOTYPES_H
#include <config.h>
#include <sys/stat.h>
#ifdef USE_UTMPX
#include <utmpx.h>
@@ -59,7 +57,7 @@
#include "defines.h"
#include "commonio.h"
extern /*@observer@*/ const char *Prog;
extern char *Prog;
/* addgrps.c */
#if defined (HAVE_SETGROUPS) && ! defined (USE_PAM)
@@ -74,27 +72,25 @@ extern int isexpired (const struct passwd *, /*@null@*/const struct spwd *);
/* basename() renamed to Basename() to avoid libc name space confusion */
/* basename.c */
extern /*@observer@*/const char *Basename (const char *str);
extern char *Basename (char *str);
/* chowndir.c */
extern int chown_tree (const char *root,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
extern int chown_tree (const char *, uid_t, uid_t, gid_t, gid_t);
/* chowntty.c */
extern void chown_tty (const struct passwd *);
/* cleanup.c */
typedef /*@null@*/void (*cleanup_function) (/*@null@*/void *arg);
void add_cleanup (/*@notnull@*/cleanup_function pcf, /*@null@*/void *arg);
void del_cleanup (/*@notnull@*/cleanup_function pcf);
typedef void (*cleanup_function) (/*@null@*/void *arg);
void add_cleanup (cleanup_function pcf, /*@null@*/void *arg);
void del_cleanup (cleanup_function pcf);
void do_cleanups (void);
/* cleanup_group.c */
struct cleanup_info_mod {
char *audit_msg;
char *action;
/*@observer@*/const char *name;
char *name;
};
void cleanup_report_add_group (void *group_name);
void cleanup_report_add_group_group (void *group_name);
@@ -120,13 +116,15 @@ extern bool console (const char *);
/* copydir.c */
extern int copy_tree (const char *src_root, const char *dst_root,
bool copy_root,
bool reset_selinux,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
long int uid, long int gid);
extern int remove_tree (const char *root);
#ifdef WITH_SELINUX
extern int selinux_file_context (const char *dst_name);
#endif
/* encrypt.c */
extern /*@exposed@*//*@null@*/char *pw_encrypt (const char *, const char *);
extern char *pw_encrypt (const char *, const char *);
/* entry.c */
extern void pw_entry (const char *, struct passwd *);
@@ -151,22 +149,11 @@ extern int find_new_uid (bool sys_user,
uid_t *uid,
/*@null@*/uid_t const *preferred_uid);
#ifdef ENABLE_SUBIDS
/* find_new_sub_gids.c */
extern int find_new_sub_gids (const char *owner,
gid_t *range_start, unsigned long *range_count);
/* find_new_sub_uids.c */
extern int find_new_sub_uids (const char *owner,
uid_t *range_start, unsigned long *range_count);
#endif /* ENABLE_SUBIDS */
/* get_gid.c */
extern int get_gid (const char *gidstr, gid_t *gid);
/* getgr_nam_gid.c */
extern /*@only@*//*@null@*/struct group *getgr_nam_gid (/*@null@*/const char *grname);
extern /*@null@*/struct group *getgr_nam_gid (const char *grname);
/* getlong.c */
extern int getlong (const char *numstr, /*@out@*/long int *result);
@@ -249,7 +236,7 @@ extern void mailcheck (void);
extern void motd (void);
/* myname.c */
extern /*@null@*//*@only@*/struct passwd *get_my_pwent (void);
extern /*@null@*/struct passwd *get_my_pwent (void);
/* pam_pass_non_interractive.c */
#ifdef USE_PAM
@@ -260,7 +247,7 @@ extern int do_pam_passwd_non_interractive (const char *pam_service,
/* obscure.c */
#ifndef USE_PAM
extern bool obscure (const char *, const char *, const struct passwd *);
extern int obscure (const char *, const char *, const struct passwd *);
#endif
/* pam_pass.c */
@@ -293,30 +280,12 @@ extern /*@dependent@*/ /*@null@*/struct commonio_entry *__pw_get_head (void);
extern /*@null@*/ /*@only@*/struct passwd *__pw_dup (const struct passwd *pwent);
extern void pw_free (/*@out@*/ /*@only@*/struct passwd *pwent);
/* remove_tree.c */
extern int remove_tree (const char *root, bool remove_root);
/* rlogin.c */
extern int do_rlogin (const char *remote_host, char *name, size_t namelen,
char *term, size_t termlen);
/* root_flag.c */
extern void process_root_flag (const char* short_opt, int argc, char **argv);
/* salt.c */
extern /*@observer@*/const char *crypt_make_salt (/*@null@*//*@observer@*/const char *meth, /*@null@*/void *arg);
/* selinux.c */
#ifdef WITH_SELINUX
extern int set_selinux_file_context (const char *dst_name);
extern int reset_selinux_file_context (void);
#endif
/* semanage.c */
#ifdef WITH_SELINUX
extern int set_seuser(const char *login_name, const char *seuser_name);
extern int del_seuser(const char *login_name);
#endif
extern /*@observer@*/const char *crypt_make_salt (/*@null@*/const char *meth, /*@null@*/void *arg);
/* setugid.c */
extern int setup_groups (const struct passwd *info);
@@ -362,17 +331,17 @@ extern void spw_free (/*@out@*/ /*@only@*/struct spwd *spent);
/* shell.c */
extern int shell (const char *file, /*@null@*/const char *arg, char *const envp[]);
/* spawn.c */
extern int run_command (const char *cmd, const char *argv[],
/*@null@*/const char *envp[], /*@out@*/int *status);
/* system.c */
extern int safe_system (const char *command,
const char *argv[],
const char *env[],
int ignore_stderr);
/* strtoday.c */
extern long strtoday (const char *);
/* suauth.c */
extern int check_su_auth (const char *actual_id,
const char *wanted_id,
bool su_to_root);
extern int check_su_auth (const char *actual_id, const char *wanted_id);
/* sulog.c */
extern void sulog (const char *tty,
@@ -388,7 +357,7 @@ extern void ttytype (const char *);
/* tz.c */
#ifndef USE_PAM
extern /*@observer@*/const char *tz (const char *);
extern char *tz (const char *);
#endif
/* ulimit.c */
@@ -416,9 +385,9 @@ extern int setutmpx (struct utmpx *utx);
extern bool valid (const char *, const struct passwd *);
/* xmalloc.c */
extern /*@maynotreturn@*/ /*@only@*//*@out@*//*@notnull@*/char *xmalloc (size_t size)
extern /*@maynotreturn@*/ /*@out@*//*@only@*/char *xmalloc (size_t size)
/*@ensures MaxSet(result) == (size - 1); @*/;
extern /*@maynotreturn@*/ /*@only@*//*@notnull@*/char *xstrdup (const char *);
extern /*@maynotreturn@*/ /*@only@*/char *xstrdup (const char *);
/* xgetpwnam.c */
extern /*@null@*/ /*@only@*/struct passwd *xgetpwnam (const char *);

View File

@@ -73,7 +73,6 @@ int pw_auth (const char *cipher,
char prompt[1024];
char *clear = NULL;
const char *cp;
const char *encrypted;
int retval;
#ifdef SKEY
@@ -178,12 +177,7 @@ int pw_auth (const char *cipher,
* the results there as well.
*/
encrypted = pw_encrypt (input, cipher);
if (NULL != encrypted) {
retval = strcmp (encrypted, cipher);
} else {
retval = -1;
}
retval = strcmp (pw_encrypt (input, cipher), cipher);
#ifdef SKEY
/*

View File

@@ -72,17 +72,6 @@ static int passwd_put (const void *ent, FILE * file)
{
const struct passwd *pw = ent;
if ( (NULL == pw)
|| (valid_field (pw->pw_name, ":\n") == -1)
|| (valid_field (pw->pw_passwd, ":\n") == -1)
|| (pw->pw_uid == (uid_t)-1)
|| (pw->pw_gid == (gid_t)-1)
|| (valid_field (pw->pw_gecos, ":\n") == -1)
|| (valid_field (pw->pw_dir, ":\n") == -1)
|| (valid_field (pw->pw_shell, ":\n") == -1)) {
return -1;
}
return (putpwent (pw, file) == -1) ? -1 : 0;
}
@@ -105,9 +94,6 @@ static struct commonio_db passwd_db = {
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif
0644, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */

View File

@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2013, Nicolas François
* Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -48,43 +48,25 @@
if (NULL == pw) {
return NULL;
}
/* The libc might define other fields. They won't be copied. */
memset (pw, 0, sizeof *pw);
pw->pw_uid = pwent->pw_uid;
pw->pw_gid = pwent->pw_gid;
/*@-mustfreeonly@*/
*pw = *pwent;
pw->pw_name = strdup (pwent->pw_name);
/*@=mustfreeonly@*/
if (NULL == pw->pw_name) {
pw_free(pw);
return NULL;
}
/*@-mustfreeonly@*/
pw->pw_passwd = strdup (pwent->pw_passwd);
/*@=mustfreeonly@*/
if (NULL == pw->pw_passwd) {
pw_free(pw);
return NULL;
}
/*@-mustfreeonly@*/
pw->pw_gecos = strdup (pwent->pw_gecos);
/*@=mustfreeonly@*/
if (NULL == pw->pw_gecos) {
pw_free(pw);
return NULL;
}
/*@-mustfreeonly@*/
pw->pw_dir = strdup (pwent->pw_dir);
/*@=mustfreeonly@*/
if (NULL == pw->pw_dir) {
pw_free(pw);
return NULL;
}
/*@-mustfreeonly@*/
pw->pw_shell = strdup (pwent->pw_shell);
/*@=mustfreeonly@*/
if (NULL == pw->pw_shell) {
pw_free(pw);
return NULL;
}
@@ -94,10 +76,8 @@
void pw_free (/*@out@*/ /*@only@*/struct passwd *pwent)
{
free (pwent->pw_name);
if (pwent->pw_passwd) {
memzero (pwent->pw_passwd, strlen (pwent->pw_passwd));
free (pwent->pw_passwd);
}
memzero (pwent->pw_passwd, strlen (pwent->pw_passwd));
free (pwent->pw_passwd);
free (pwent->pw_gecos);
free (pwent->pw_dir);
free (pwent->pw_shell);

View File

@@ -1,103 +0,0 @@
/*
* Copyright (c) 2011 , Peter Vrabec <pvrabec@redhat.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ifdef WITH_SELINUX
#include "defines.h"
#include <selinux/selinux.h>
#include "prototypes.h"
static bool selinux_checked = false;
static bool selinux_enabled;
/*
* set_selinux_file_context - Set the security context before any file or
* directory creation.
*
* set_selinux_file_context () should be called before any creation
* of file, symlink, directory, ...
*
* Callers may have to Reset SELinux to create files with default
* contexts with reset_selinux_file_context
*/
int set_selinux_file_context (const char *dst_name)
{
/*@null@*/security_context_t scontext = NULL;
if (!selinux_checked) {
selinux_enabled = is_selinux_enabled () > 0;
selinux_checked = true;
}
if (selinux_enabled) {
/* Get the default security context for this file */
if (matchpathcon (dst_name, 0, &scontext) < 0) {
if (security_getenforce () != 0) {
return 1;
}
}
/* Set the security context for the next created file */
if (setfscreatecon (scontext) < 0) {
if (security_getenforce () != 0) {
return 1;
}
}
freecon (scontext);
}
return 0;
}
/*
* reset_selinux_file_context - Reset the security context to the default
* policy behavior
*
* reset_selinux_file_context () should be called after the context
* was changed with set_selinux_file_context ()
*/
int reset_selinux_file_context (void)
{
if (!selinux_checked) {
selinux_enabled = is_selinux_enabled () > 0;
selinux_checked = true;
}
if (selinux_enabled) {
if (setfscreatecon (NULL) != 0) {
return 1;
}
}
return 0;
}
#else /* !WITH_SELINUX */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !WITH_SELINUX */

View File

@@ -1,378 +0,0 @@
/*
* Copyright (c) 2010 , Jakub Hrozek <jhrozek@redhat.com>
* Copyright (c) 2011 , Peter Vrabec <pvrabec@redhat.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ifdef WITH_SELINUX
#include "defines.h"
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <stdarg.h>
#include <selinux/selinux.h>
#include <semanage/semanage.h>
#include "prototypes.h"
#ifndef DEFAULT_SERANGE
#define DEFAULT_SERANGE "s0"
#endif
static void semanage_error_callback (unused void *varg,
semanage_handle_t *handle,
const char *fmt, ...)
{
int ret;
char * message = NULL;
va_list ap;
va_start (ap, fmt);
ret = vasprintf (&message, fmt, ap);
va_end (ap);
if (ret < 0) {
/* ENOMEM */
return;
}
switch (semanage_msg_get_level (handle)) {
case SEMANAGE_MSG_ERR:
case SEMANAGE_MSG_WARN:
fprintf (stderr, _("[libsemanage]: %s\n"), message);
break;
case SEMANAGE_MSG_INFO:
/* nop */
break;
}
free (message);
}
static semanage_handle_t *semanage_init (void)
{
int ret;
semanage_handle_t *handle = NULL;
handle = semanage_handle_create ();
if (NULL == handle) {
fprintf (stderr,
_("Cannot create SELinux management handle\n"));
return NULL;
}
semanage_msg_set_callback (handle, semanage_error_callback, NULL);
ret = semanage_is_managed (handle);
if (ret != 1) {
fprintf (stderr, _("SELinux policy not managed\n"));
goto fail;
}
ret = semanage_access_check (handle);
if (ret < SEMANAGE_CAN_READ) {
fprintf (stderr, _("Cannot read SELinux policy store\n"));
goto fail;
}
ret = semanage_connect (handle);
if (ret != 0) {
fprintf (stderr,
_("Cannot establish SELinux management connection\n"));
goto fail;
}
ret = semanage_begin_transaction (handle);
if (ret != 0) {
fprintf (stderr, _("Cannot begin SELinux transaction\n"));
goto fail;
}
return handle;
fail:
semanage_handle_destroy (handle);
return NULL;
}
static int semanage_user_mod (semanage_handle_t *handle,
semanage_seuser_key_t *key,
const char *login_name,
const char *seuser_name)
{
int ret;
semanage_seuser_t *seuser = NULL;
semanage_seuser_query (handle, key, &seuser);
if (NULL == seuser) {
fprintf (stderr,
_("Could not query seuser for %s\n"), login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
if (ret != 0) {
fprintf (stderr,
_("Could not set serange for %s\n"), login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_set_sename (handle, seuser, seuser_name);
if (ret != 0) {
fprintf (stderr,
_("Could not set sename for %s\n"),
login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_modify_local (handle, key, seuser);
if (ret != 0) {
fprintf (stderr,
_("Could not modify login mapping for %s\n"),
login_name);
ret = 1;
goto done;
}
ret = 0;
done:
semanage_seuser_free (seuser);
return ret;
}
static int semanage_user_add (semanage_handle_t *handle,
semanage_seuser_key_t *key,
const char *login_name,
const char *seuser_name)
{
int ret;
semanage_seuser_t *seuser = NULL;
ret = semanage_seuser_create (handle, &seuser);
if (ret != 0) {
fprintf (stderr,
_("Cannot create SELinux login mapping for %s\n"),
login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_set_name (handle, seuser, login_name);
if (ret != 0) {
fprintf (stderr, _("Could not set name for %s\n"), login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
if (ret != 0) {
fprintf (stderr,
_("Could not set serange for %s\n"),
login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_set_sename (handle, seuser, seuser_name);
if (ret != 0) {
fprintf (stderr,
_("Could not set SELinux user for %s\n"),
login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_modify_local (handle, key, seuser);
if (ret != 0) {
fprintf (stderr,
_("Could not add login mapping for %s\n"),
login_name);
ret = 1;
goto done;
}
ret = 0;
done:
semanage_seuser_free (seuser);
return ret;
}
int set_seuser (const char *login_name, const char *seuser_name)
{
semanage_handle_t *handle = NULL;
semanage_seuser_key_t *key = NULL;
int ret;
int seuser_exists = 0;
if (NULL == seuser_name) {
/* don't care, just let system pick the defaults */
return 0;
}
handle = semanage_init ();
if (NULL == handle) {
fprintf (stderr, _("Cannot init SELinux management\n"));
ret = 1;
goto done;
}
ret = semanage_seuser_key_create (handle, login_name, &key);
if (ret != 0) {
fprintf (stderr, _("Cannot create SELinux user key\n"));
ret = 1;
goto done;
}
ret = semanage_seuser_exists (handle, key, &seuser_exists);
if (ret < 0) {
fprintf (stderr, _("Cannot verify the SELinux user\n"));
ret = 1;
goto done;
}
if (0 != seuser_exists) {
ret = semanage_user_mod (handle, key, login_name, seuser_name);
if (ret != 0) {
fprintf (stderr,
_("Cannot modify SELinux user mapping\n"));
ret = 1;
goto done;
}
} else {
ret = semanage_user_add (handle, key, login_name, seuser_name);
if (ret != 0) {
fprintf (stderr,
_("Cannot add SELinux user mapping\n"));
ret = 1;
goto done;
}
}
ret = semanage_commit (handle);
if (ret < 0) {
fprintf (stderr, _("Cannot commit SELinux transaction\n"));
ret = 1;
goto done;
}
ret = 0;
done:
semanage_seuser_key_free (key);
semanage_handle_destroy (handle);
return ret;
}
int del_seuser (const char *login_name)
{
semanage_handle_t *handle = NULL;
semanage_seuser_key_t *key = NULL;
int ret;
int exists = 0;
handle = semanage_init ();
if (NULL == handle) {
fprintf (stderr, _("Cannot init SELinux management\n"));
ret = 1;
goto done;
}
ret = semanage_seuser_key_create (handle, login_name, &key);
if (ret != 0) {
fprintf (stderr, _("Cannot create SELinux user key\n"));
ret = 1;
goto done;
}
ret = semanage_seuser_exists (handle, key, &exists);
if (ret < 0) {
fprintf (stderr, _("Cannot verify the SELinux user\n"));
ret = 1;
goto done;
}
if (0 == exists) {
fprintf (stderr,
_("Login mapping for %s is not defined, OK if default mapping was used\n"),
login_name);
ret = 0; /* probably default mapping */
goto done;
}
ret = semanage_seuser_exists_local (handle, key, &exists);
if (ret < 0) {
fprintf (stderr, _("Cannot verify the SELinux user\n"));
ret = 1;
goto done;
}
if (0 == exists) {
fprintf (stderr,
_("Login mapping for %s is defined in policy, cannot be deleted\n"),
login_name);
ret = 0; /* Login mapping defined in policy can't be deleted */
goto done;
}
ret = semanage_seuser_del_local (handle, key);
if (ret != 0) {
fprintf (stderr,
_("Could not delete login mapping for %s"),
login_name);
ret = 1;
goto done;
}
ret = semanage_commit (handle);
if (ret < 0) {
fprintf (stderr, _("Cannot commit SELinux transaction\n"));
ret = 1;
goto done;
}
ret = 0;
done:
semanage_handle_destroy (handle);
return ret;
}
#else /* !WITH_SELINUX */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !WITH_SELINUX */

View File

@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2007 - 2013, Nicolas François
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -51,19 +51,13 @@
if (NULL == sg) {
return NULL;
}
/* Do the same as the other _dup function, even if we know the
* structure. */
memset (sg, 0, sizeof *sg);
/*@-mustfreeonly@*/
*sg = *sgent;
sg->sg_name = strdup (sgent->sg_name);
/*@=mustfreeonly@*/
if (NULL == sg->sg_name) {
free (sg);
return NULL;
}
/*@-mustfreeonly@*/
sg->sg_passwd = strdup (sgent->sg_passwd);
/*@=mustfreeonly@*/
if (NULL == sg->sg_passwd) {
free (sg->sg_name);
free (sg);
@@ -71,9 +65,7 @@
}
for (i = 0; NULL != sgent->sg_adm[i]; i++);
/*@-mustfreeonly@*/
sg->sg_adm = (char **) malloc ((i + 1) * sizeof (char *));
/*@=mustfreeonly@*/
if (NULL == sg->sg_adm) {
free (sg->sg_passwd);
free (sg->sg_name);
@@ -96,9 +88,7 @@
sg->sg_adm[i] = NULL;
for (i = 0; NULL != sgent->sg_mem[i]; i++);
/*@-mustfreeonly@*/
sg->sg_mem = (char **) malloc ((i + 1) * sizeof (char *));
/*@=mustfreeonly@*/
if (NULL == sg->sg_mem) {
for (i = 0; NULL != sg->sg_adm[i]; i++) {
free (sg->sg_adm[i]);
@@ -147,20 +137,17 @@ static void gshadow_free (/*@out@*/ /*@only@*/void *ent)
void sgr_free (/*@out@*/ /*@only@*/struct sgrp *sgent)
{
size_t i;
free (sgent->sg_name);
if (NULL != sgent->sg_passwd) {
memzero (sgent->sg_passwd, strlen (sgent->sg_passwd));
free (sgent->sg_passwd);
memzero (sgent->sg_passwd, strlen (sgent->sg_passwd));
free (sgent->sg_passwd);
while (NULL != *(sgent->sg_adm)) {
free (*(sgent->sg_adm));
sgent->sg_adm++;
}
for (i = 0; NULL != sgent->sg_adm[i]; i++) {
free (sgent->sg_adm[i]);
while (NULL != *(sgent->sg_mem)) {
free (*(sgent->sg_mem));
sgent->sg_mem++;
}
free (sgent->sg_adm);
for (i = 0; NULL != sgent->sg_mem[i]; i++) {
free (sgent->sg_mem[i]);
}
free (sgent->sg_mem);
free (sgent);
}
@@ -180,32 +167,6 @@ static int gshadow_put (const void *ent, FILE * file)
{
const struct sgrp *sg = ent;
if ( (NULL == sg)
|| (valid_field (sg->sg_name, ":\n") == -1)
|| (valid_field (sg->sg_passwd, ":\n") == -1)) {
return -1;
}
/* FIXME: fail also if sg->sg_adm == NULL ?*/
if (NULL != sg->sg_adm) {
size_t i;
for (i = 0; NULL != sg->sg_adm[i]; i++) {
if (valid_field (sg->sg_adm[i], ",:\n") == -1) {
return -1;
}
}
}
/* FIXME: fail also if sg->sg_mem == NULL ?*/
if (NULL != sg->sg_mem) {
size_t i;
for (i = 0; NULL != sg->sg_mem[i]; i++) {
if (valid_field (sg->sg_mem[i], ",:\n") == -1) {
return -1;
}
}
}
return (putsgent (sg, file) == -1) ? -1 : 0;
}
@@ -228,9 +189,6 @@ static struct commonio_db gshadow_db = {
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif
0400, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
@@ -252,8 +210,6 @@ int sgr_setdbname (const char *filename)
bool sgr_file_present (void)
{
if (getdef_bool ("FORCE_SHADOW"))
return true;
return commonio_present (&gshadow_db);
}

View File

@@ -37,7 +37,7 @@
extern int sgr_close (void);
extern bool sgr_file_present (void);
extern /*@observer@*/ /*@null@*/const struct sgrp *sgr_locate (const char *name);
extern /*@null@*/const struct sgrp *sgr_locate (const char *name);
extern int sgr_lock (void);
extern int sgr_setdbname (const char *filename);
extern /*@observer@*/const char *sgr_dbname (void);

View File

@@ -42,10 +42,10 @@
#include "defines.h"
#include <stdio.h>
#ifdef USE_NIS
static bool nis_used;
static bool nis_ignore;
static int nis_used;
static int nis_ignore;
static enum { native, start, middle, native2 } nis_state;
static bool nis_bound;
static int nis_bound;
static char *nis_domain;
static char *nis_key;
static int nis_keylen;
@@ -66,12 +66,12 @@ static FILE *shadow;
* __setspNIS - turn on or off NIS searches
*/
void __setspNIS (bool flag)
void __setspNIS (int flag)
{
nis_ignore = !flag;
if (nis_ignore) {
nis_used = false;
nis_used = 0;
}
}
@@ -81,11 +81,10 @@ void __setspNIS (bool flag)
static int bind_nis (void)
{
if (yp_get_default_domain (&nis_domain)) {
if (yp_get_default_domain (&nis_domain))
return -1;
}
nis_bound = true;
nis_bound = 1;
return 0;
}
#endif
@@ -96,11 +95,10 @@ static int bind_nis (void)
void setspent (void)
{
if (NULL != shadow) {
if (shadow)
rewind (shadow);
}else {
else
shadow = fopen (SHADOW_FILE, "r");
}
#ifdef USE_NIS
nis_state = native;
@@ -113,9 +111,8 @@ void setspent (void)
void endspent (void)
{
if (NULL != shadow) {
if (shadow)
(void) fclose (shadow);
}
shadow = (FILE *) 0;
}
@@ -175,9 +172,8 @@ static struct spwd *my_sgetspent (const char *string)
spwd.sp_namp = fields[0];
#ifdef USE_NIS
if (IS_NISCHAR (fields[0][0])) {
nis_used = true;
}
if (IS_NISCHAR (fields[0][0]))
nis_used = 1;
#endif
spwd.sp_pwdp = fields[1];
@@ -215,9 +211,7 @@ static struct spwd *my_sgetspent (const char *string)
spwd.sp_min = -1;
} else
#endif
{
return 0;
}
} else if (spwd.sp_min < 0) {
return 0;
}
@@ -269,9 +263,7 @@ static struct spwd *my_sgetspent (const char *string)
spwd.sp_warn = -1;
} else
#endif
{
return 0;
}
} else if (spwd.sp_warn < 0) {
return 0;
}
@@ -291,9 +283,7 @@ static struct spwd *my_sgetspent (const char *string)
spwd.sp_inact = -1;
} else
#endif
{
return 0;
}
} else if (spwd.sp_inact < 0) {
return 0;
}
@@ -313,9 +303,7 @@ static struct spwd *my_sgetspent (const char *string)
spwd.sp_expire = -1;
} else
#endif
{
return 0;
}
} else if (spwd.sp_expire < 0) {
return 0;
}
@@ -336,9 +324,7 @@ static struct spwd *my_sgetspent (const char *string)
spwd.sp_flag = SHADOW_SP_FLAG_UNSET;
} else
#endif
{
return 0;
}
} else if (spwd.sp_flag < 0) {
return 0;
}
@@ -391,9 +377,8 @@ struct spwd *getspent (void)
struct spwd *val;
char buf[BUFSIZ];
#endif
if (NULL == shadow) {
if (!shadow)
setspent ();
}
#ifdef USE_NIS
again:
@@ -447,7 +432,7 @@ struct spwd *getspent (void)
return 0;
} else {
if (!nis_bound) {
if (nis_bound == 0) {
if (bind_nis ()) {
nis_state = native2;
goto again;
@@ -455,15 +440,15 @@ struct spwd *getspent (void)
}
if (nis_state == start) {
if (yp_first (nis_domain, "shadow.bynam", &nis_key,
&nis_keylen, &nis_val, &nis_vallen)) {
&nis_keylen, &nis_val, &nis_vallen)) {
nis_state = native2;
goto again;
}
nis_state = middle;
} else if (nis_state == middle) {
if (yp_next (nis_domain, "shadow.bynam", nis_key,
nis_keylen, &nis_key, &nis_keylen,
&nis_val, &nis_vallen)) {
nis_keylen, &nis_key, &nis_keylen,
&nis_val, &nis_vallen)) {
nis_state = native2;
goto again;
}
@@ -486,7 +471,7 @@ struct spwd *getspnam (const char *name)
#ifdef USE_NIS
char buf[BUFSIZ];
static char save_name[16];
bool nis_disabled = false;
int nis_disabled = 0;
#endif
setspent ();
@@ -496,20 +481,18 @@ struct spwd *getspnam (const char *name)
* Search the shadow.byname map for this user.
*/
if (!nis_ignore && !nis_bound) {
if (!nis_ignore && !nis_bound)
bind_nis ();
}
if (!nis_ignore && nis_bound) {
char *cp;
if (yp_match (nis_domain, "shadow.byname", name,
strlen (name), &nis_val, &nis_vallen) == 0) {
strlen (name), &nis_val, &nis_vallen) == 0) {
cp = strchr (nis_val, '\n');
if (NULL != cp) {
if (NULL != cp)
*cp = '\0';
}
nis_state = middle;
sp = my_sgetspent (nis_val);
@@ -520,9 +503,8 @@ struct spwd *getspnam (const char *name)
}
endspent ();
return sp;
} else {
} else
nis_state = native2;
}
}
#endif
#ifdef USE_NIS
@@ -534,19 +516,17 @@ struct spwd *getspnam (const char *name)
*/
if (nis_used) {
nis_ignore = true;
nis_disabled = true;
nis_ignore++;
nis_disabled++;
}
#endif
while ((sp = getspent ()) != (struct spwd *) 0) {
if (strcmp (name, sp->sp_namp) == 0) {
if (strcmp (name, sp->sp_namp) == 0)
break;
}
}
#ifdef USE_NIS
if (nis_disabled) {
nis_ignore = false;
}
if (nis_disabled)
nis_ignore--;
#endif
endspent ();
return (sp);

View File

@@ -41,10 +41,6 @@
#include <stdio.h>
#include "commonio.h"
#include "shadowio.h"
#ifdef WITH_TCB
#include <tcb.h>
#include "tcbfuncs.h"
#endif /* WITH_TCB */
static /*@null@*/ /*@only@*/void *shadow_dup (const void *ent)
{
@@ -76,12 +72,6 @@ static int shadow_put (const void *ent, FILE * file)
{
const struct spwd *sp = ent;
if ( (NULL == sp)
|| (valid_field (sp->sp_namp, ":\n") == -1)
|| (valid_field (sp->sp_pwdp, ":\n") == -1)) {
return -1;
}
return (putspent (sp, file) == -1) ? -1 : 0;
}
@@ -103,10 +93,7 @@ static struct commonio_db shadow_db = {
NULL, /* fp */
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif /* WITH_SELINUX */
0400, /* st_mode */
0, /* st_uid */
0, /* st_gid */
#endif
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
@@ -128,52 +115,17 @@ int spw_setdbname (const char *filename)
bool spw_file_present (void)
{
if (getdef_bool ("FORCE_SHADOW"))
return true;
return commonio_present (&shadow_db);
}
int spw_lock (void)
{
#ifdef WITH_TCB
int retval = 0;
if (!getdef_bool ("USE_TCB")) {
#endif /* WITH_TCB */
return commonio_lock (&shadow_db);
#ifdef WITH_TCB
}
if (shadowtcb_drop_priv () == SHADOWTCB_FAILURE) {
return 0;
}
if (lckpwdf_tcb (shadow_db.filename) == 0) {
shadow_db.locked = 1;
retval = 1;
}
if (shadowtcb_gain_priv () == SHADOWTCB_FAILURE) {
return 0;
}
return retval;
#endif /* WITH_TCB */
return commonio_lock (&shadow_db);
}
int spw_open (int mode)
{
int retval = 0;
#ifdef WITH_TCB
bool use_tcb = getdef_bool ("USE_TCB");
if (use_tcb && (shadowtcb_drop_priv () == SHADOWTCB_FAILURE)) {
return 0;
}
#endif /* WITH_TCB */
retval = commonio_open (&shadow_db, mode);
#ifdef WITH_TCB
if (use_tcb && (shadowtcb_gain_priv () == SHADOWTCB_FAILURE)) {
return 0;
}
#endif /* WITH_TCB */
return retval;
return commonio_open (&shadow_db, mode);
}
/*@observer@*/ /*@null@*/const struct spwd *spw_locate (const char *name)
@@ -203,45 +155,12 @@ int spw_rewind (void)
int spw_close (void)
{
int retval = 0;
#ifdef WITH_TCB
bool use_tcb = getdef_bool ("USE_TCB");
if (use_tcb && (shadowtcb_drop_priv () == SHADOWTCB_FAILURE)) {
return 0;
}
#endif /* WITH_TCB */
retval = commonio_close (&shadow_db);
#ifdef WITH_TCB
if (use_tcb && (shadowtcb_gain_priv () == SHADOWTCB_FAILURE)) {
return 0;
}
#endif /* WITH_TCB */
return retval;
return commonio_close (&shadow_db);
}
int spw_unlock (void)
{
#ifdef WITH_TCB
int retval = 0;
if (!getdef_bool ("USE_TCB")) {
#endif /* WITH_TCB */
return commonio_unlock (&shadow_db);
#ifdef WITH_TCB
}
if (shadowtcb_drop_priv () == SHADOWTCB_FAILURE) {
return 0;
}
if (ulckpwdf_tcb () == 0) {
shadow_db.locked = 0;
retval = 1;
}
if (shadowtcb_gain_priv () == SHADOWTCB_FAILURE) {
return 0;
}
return retval;
#endif /* WITH_TCB */
return commonio_unlock (&shadow_db);
}
struct commonio_entry *__spw_get_head (void)
@@ -257,10 +176,5 @@ void __spw_del_entry (const struct commonio_entry *ent)
/* Sort with respect to passwd ordering. */
int spw_sort ()
{
#ifdef WITH_TCB
if (getdef_bool ("USE_TCB")) {
return 0;
}
#endif /* WITH_TCB */
return commonio_sort_wrt (&shadow_db, __pw_get_db ());
}

View File

@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2007 - 2013, Nicolas François
* Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -49,28 +49,13 @@
if (NULL == sp) {
return NULL;
}
/* The libc might define other fields. They won't be copied. */
memset (sp, 0, sizeof *sp);
sp->sp_lstchg = spent->sp_lstchg;
sp->sp_min = spent->sp_min;
sp->sp_max = spent->sp_max;
sp->sp_warn = spent->sp_warn;
sp->sp_inact = spent->sp_inact;
sp->sp_expire = spent->sp_expire;
sp->sp_flag = spent->sp_flag;
/*@-mustfreeonly@*/
sp->sp_namp = strdup (spent->sp_namp);
/*@=mustfreeonly@*/
*sp = *spent;
sp->sp_namp = strdup (spent->sp_namp);
if (NULL == sp->sp_namp) {
free(sp);
return NULL;
}
/*@-mustfreeonly@*/
sp->sp_pwdp = strdup (spent->sp_pwdp);
/*@=mustfreeonly@*/
if (NULL == sp->sp_pwdp) {
free(sp->sp_namp);
free(sp);
return NULL;
}
@@ -80,10 +65,8 @@
void spw_free (/*@out@*/ /*@only@*/struct spwd *spent)
{
free (spent->sp_namp);
if (NULL != spent->sp_pwdp) {
memzero (spent->sp_pwdp, strlen (spent->sp_pwdp));
free (spent->sp_pwdp);
}
memzero (spent->sp_pwdp, strlen (spent->sp_pwdp));
free (spent->sp_pwdp);
free (spent);
}

View File

@@ -1,82 +0,0 @@
/*
* Copyright (c) 2011 , Jonathan Nieder
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "exitcodes.h"
#include "prototypes.h"
int run_command (const char *cmd, const char *argv[],
/*@null@*/const char *envp[], /*@out@*/int *status)
{
pid_t pid, wpid;
if (NULL == envp) {
envp = (const char **)environ;
}
(void) fflush (stdout);
(void) fflush (stderr);
pid = fork ();
if (0 == pid) {
(void) execve (cmd, (char * const *) argv,
(char * const *) envp);
if (ENOENT == errno) {
exit (E_CMD_NOTFOUND);
}
fprintf (stderr, "%s: cannot execute %s: %s\n",
Prog, cmd, strerror (errno));
exit (E_CMD_NOEXEC);
} else if ((pid_t)-1 == pid) {
fprintf (stderr, "%s: cannot execute %s: %s\n",
Prog, cmd, strerror (errno));
return -1;
}
do {
wpid = waitpid (pid, status, 0);
} while ( ((pid_t)-1 == wpid && errno == EINTR)
|| (wpid != pid));
if ((pid_t)-1 == wpid) {
fprintf (stderr, "%s: waitpid (status: %d): %s\n",
Prog, *status, strerror (errno));
return -1;
}
return 0;
}

View File

@@ -1,701 +0,0 @@
/*
* Copyright (c) 2012 - Eric Biederman
*/
#include <config.h>
#ifdef ENABLE_SUBIDS
#include "prototypes.h"
#include "defines.h"
#include <stdio.h>
#include "commonio.h"
#include "subordinateio.h"
#include <sys/types.h>
#include <pwd.h>
struct subordinate_range {
const char *owner;
unsigned long start;
unsigned long count;
};
#define NFIELDS 3
/*
* subordinate_dup: create a duplicate range
*
* @ent: a pointer to a subordinate_range struct
*
* Returns a pointer to a newly allocated duplicate subordinate_range struct
* or NULL on failure
*/
static /*@null@*/ /*@only@*/void *subordinate_dup (const void *ent)
{
const struct subordinate_range *rangeent = ent;
struct subordinate_range *range;
range = (struct subordinate_range *) malloc (sizeof *range);
if (NULL == range) {
return NULL;
}
range->owner = strdup (rangeent->owner);
if (NULL == range->owner) {
free(range);
return NULL;
}
range->start = rangeent->start;
range->count = rangeent->count;
return range;
}
/*
* subordinate_free: free a subordinate_range struct
*
* @ent: pointer to a subordinate_range struct to free.
*/
static void subordinate_free (/*@out@*/ /*@only@*/void *ent)
{
struct subordinate_range *rangeent = ent;
free ((void *)(rangeent->owner));
free (rangeent);
}
/*
* subordinate_parse:
*
* @line: a line to parse
*
* Returns a pointer to a subordinate_range struct representing the values
* in @line, or NULL on failure. Note that the returned value should not
* be freed by the caller.
*/
static void *subordinate_parse (const char *line)
{
static struct subordinate_range range;
static char rangebuf[1024];
int i;
char *cp;
char *fields[NFIELDS];
/*
* Copy the string to a temporary buffer so the substrings can
* be modified to be NULL terminated.
*/
if (strlen (line) >= sizeof rangebuf)
return NULL; /* fail if too long */
strcpy (rangebuf, line);
/*
* Save a pointer to the start of each colon separated
* field. The fields are converted into NUL terminated strings.
*/
for (cp = rangebuf, i = 0; (i < NFIELDS) && (NULL != cp); i++) {
fields[i] = cp;
while (('\0' != *cp) && (':' != *cp)) {
cp++;
}
if ('\0' != *cp) {
*cp = '\0';
cp++;
} else {
cp = NULL;
}
}
/*
* There must be exactly NFIELDS colon separated fields or
* the entry is invalid. Also, fields must be non-blank.
*/
if (i != NFIELDS || *fields[0] == '\0' || *fields[1] == '\0' || *fields[2] == '\0')
return NULL;
range.owner = fields[0];
if (getulong (fields[1], &range.start) == 0)
return NULL;
if (getulong (fields[2], &range.count) == 0)
return NULL;
return &range;
}
/*
* subordinate_put: print a subordinate_range value to a file
*
* @ent: a pointer to a subordinate_range struct to print out.
* @file: file to which to print.
*
* Returns 0 on success, -1 on error.
*/
static int subordinate_put (const void *ent, FILE * file)
{
const struct subordinate_range *range = ent;
return fprintf(file, "%s:%lu:%lu\n",
range->owner,
range->start,
range->count) < 0 ? -1 : 0;
}
static struct commonio_ops subordinate_ops = {
subordinate_dup, /* dup */
subordinate_free, /* free */
NULL, /* getname */
subordinate_parse, /* parse */
subordinate_put, /* put */
fgets, /* fgets */
fputs, /* fputs */
NULL, /* open_hook */
NULL, /* close_hook */
};
static /*@observer@*/ /*@null*/const struct subordinate_range *subordinate_next(struct commonio_db *db)
{
return (const struct subordinate_range *)commonio_next (db);
}
/*
* range_exists: Check whether @owner owns any ranges
*
* @db: database to query
* @owner: owner being queried
*
* Returns true if @owner owns any subuid ranges, false otherwise.
*/
static const bool range_exists(struct commonio_db *db, const char *owner)
{
const struct subordinate_range *range;
commonio_rewind(db);
while ((range = commonio_next(db)) != NULL) {
if (0 == strcmp(range->owner, owner))
return true;
}
return false;
}
/*
* find_range: find a range which @owner is authorized to use which includes
* subuid @val.
*
* @db: database to query
* @owner: owning uid being queuried
* @val: subuid being searched for.
*
* Returns a range of subuids belonging to @owner and including the subuid
* @val, or NULL if no such range exists.
*/
static const struct subordinate_range *find_range(struct commonio_db *db,
const char *owner, unsigned long val)
{
const struct subordinate_range *range;
/*
* Search for exact username/group specification
*
* This is the original method - go fast through the db, doing only
* exact username/group string comparison. Therefore we leave it as-is
* for the time being, in order to keep it equally fast as it was
* before.
*/
commonio_rewind(db);
while ((range = commonio_next(db)) != NULL) {
unsigned long first = range->start;
unsigned long last = first + range->count - 1;
if (0 != strcmp(range->owner, owner))
continue;
if ((val >= first) && (val <= last))
return range;
}
/*
* We only do special handling for these two files
*/
if ((0 != strcmp(db->filename, "/etc/subuid")) && (0 != strcmp(db->filename, "/etc/subgid")))
return NULL;
/*
* Search loop above did not produce any result. Let's rerun it,
* but this time try to matcha actual UIDs. The first entry that
* matches is considered a success.
* (It may be specified as literal UID or as another username which
* has the same UID as the username we are looking for.)
*/
struct passwd *pwd;
uid_t owner_uid;
char owner_uid_string[33] = "";
/* Get UID of the username we are looking for */
pwd = getpwnam(owner);
if (NULL == pwd) {
/* Username not defined in /etc/passwd, or error occured during lookup */
return NULL;
}
owner_uid = pwd->pw_uid;
sprintf(owner_uid_string, "%lu", (unsigned long int)owner_uid);
commonio_rewind(db);
while ((range = commonio_next(db)) != NULL) {
unsigned long first = range->start;
unsigned long last = first + range->count - 1;
/* For performance reasons check range before using getpwnam() */
if ((val < first) || (val > last)) {
continue;
}
/*
* Range matches. Check if range owner is specified
* as numeric UID and if it matches.
*/
if (0 == strcmp(range->owner, owner_uid_string)) {
return range;
}
/*
* Ok, this range owner is not specified as numeric UID
* we are looking for. It may be specified as another
* UID or as a literal username.
*
* If specified as another UID, the call to getpwnam()
* will return NULL.
*
* If specified as literal username, we will get its
* UID and compare that to UID we are looking for.
*/
const struct passwd *range_owner_pwd;
range_owner_pwd = getpwnam(range->owner);
if (NULL == range_owner_pwd) {
continue;
}
if (owner_uid == range_owner_pwd->pw_uid) {
return range;
}
}
return NULL;
}
/*
* have_range: check whether @owner is authorized to use the range
* (@start .. @start+@count-1).
* @db: database to check
* @owner: owning uid being queried
* @start: start of range
* @count: number of uids in range
*
* Returns true if @owner is authorized to use the range, false otherwise.
*/
static bool have_range(struct commonio_db *db,
const char *owner, unsigned long start, unsigned long count)
{
const struct subordinate_range *range;
unsigned long end;
if (count == 0)
return false;
end = start + count - 1;
range = find_range (db, owner, start);
while (range) {
unsigned long last;
last = range->start + range->count - 1;
if (last >= (start + count - 1))
return true;
count = end - last;
start = last + 1;
range = find_range(db, owner, start);
}
return false;
}
/*
* subordinate_range_cmp: compare uid ranges
*
* @p1: pointer to a commonio_entry struct to compare
* @p2: pointer to second commonio_entry struct to compare
*
* Returns 0 if the entries are the same. Otherwise return -1
* if the range in p1 is lower than that in p2, or (if the ranges are
* equal) if the owning uid in p1 is lower than p2's. Return 1 if p1's
* range or owning uid is great than p2's.
*/
static int subordinate_range_cmp (const void *p1, const void *p2)
{
struct subordinate_range *range1, *range2;
if ((*(struct commonio_entry **) p1)->eptr == NULL)
return 1;
if ((*(struct commonio_entry **) p2)->eptr == NULL)
return -1;
range1 = ((struct subordinate_range *) (*(struct commonio_entry **) p1)->eptr);
range2 = ((struct subordinate_range *) (*(struct commonio_entry **) p2)->eptr);
if (range1->start < range2->start)
return -1;
else if (range1->start > range2->start)
return 1;
else if (range1->count < range2->count)
return -1;
else if (range1->count > range2->count)
return 1;
else
return strcmp(range1->owner, range2->owner);
}
/*
* find_free_range: find an unused consecutive sequence of ids to allocate
* to a user.
* @db: database to search
* @min: the first uid in the range to find
* @max: the highest uid to find
* @count: the number of uids needed
*
* Return the lowest new uid, or ULONG_MAX on failure.
*/
static unsigned long find_free_range(struct commonio_db *db,
unsigned long min, unsigned long max,
unsigned long count)
{
const struct subordinate_range *range;
unsigned long low, high;
/* When given invalid parameters fail */
if ((count == 0) || (max < min))
goto fail;
/* Sort by range then by owner */
commonio_sort (db, subordinate_range_cmp);
commonio_rewind(db);
low = min;
while ((range = commonio_next(db)) != NULL) {
unsigned long first = range->start;
unsigned long last = first + range->count - 1;
/* Find the top end of the hole before this range */
high = first;
/* Don't allocate IDs after max (included) */
if (high > max + 1) {
high = max + 1;
}
/* Is the hole before this range large enough? */
if ((high > low) && ((high - low) >= count))
return low;
/* Compute the low end of the next hole */
if (low < (last + 1))
low = last + 1;
if (low > max)
goto fail;
}
/* Is the remaining unclaimed area large enough? */
if (((max - low) + 1) >= count)
return low;
fail:
return ULONG_MAX;
}
/*
* add_range: add a subuid range to an owning uid's list of authorized
* subuids.
* @db: database to which to add
* @owner: uid which owns the subuid
* @start: the first uid in the owned range
* @count: the number of uids in the range
*
* Return 1 if the range is already present or on succcess. On error
* return 0 and set errno appropriately.
*/
static int add_range(struct commonio_db *db,
const char *owner, unsigned long start, unsigned long count)
{
struct subordinate_range range;
range.owner = owner;
range.start = start;
range.count = count;
/* See if the range is already present */
if (have_range(db, owner, start, count))
return 1;
/* Otherwise append the range */
return commonio_append(db, &range);
}
/*
* remove_range: remove a range of subuids from an owning uid's list
* of authorized subuids.
* @db: database to work on
* @owner: owning uid whose range is being removed
* @start: start of the range to be removed
* @count: number of uids in the range.
*
* Returns 0 on failure, 1 on success. Failure means that we needed to
* create a new range to represent the new limits, and failed doing so.
*/
static int remove_range (struct commonio_db *db,
const char *owner,
unsigned long start, unsigned long count)
{
struct commonio_entry *ent;
unsigned long end;
if (count == 0) {
return 1;
}
end = start + count - 1;
for (ent = db->head; NULL != ent; ent = ent->next) {
struct subordinate_range *range = ent->eptr;
unsigned long first;
unsigned long last;
/* Skip unparsed entries */
if (NULL == range) {
continue;
}
first = range->start;
last = first + range->count - 1;
/* Skip entries with a different owner */
if (0 != strcmp (range->owner, owner)) {
continue;
}
/* Skip entries outside of the range to remove */
if ((end < first) || (start > last)) {
continue;
}
if (start <= first) {
if (end >= last) {
/* to be removed: [start, end]
* range: [first, last] */
/* entry completely contained in the
* range to remove */
commonio_del_entry (db, ent);
} else {
/* to be removed: [start, end]
* range: [first, last] */
/* Remove only the start of the entry */
range->start = end + 1;
range->count = (last - range->start) + 1;
ent->changed = true;
db->changed = true;
}
} else {
if (end >= last) {
/* to be removed: [start, end]
* range: [first, last] */
/* Remove only the end of the entry */
range->count = start - range->start;
ent->changed = true;
db->changed = true;
} else {
/* to be removed: [start, end]
* range: [first, last] */
/* Remove the middle of the range
* This requires to create a new range */
struct subordinate_range tail;
tail.owner = range->owner;
tail.start = end + 1;
tail.count = (last - tail.start) + 1;
if (commonio_append (db, &tail) == 0) {
return 0;
}
range->count = start - range->start;
ent->changed = true;
db->changed = true;
}
}
}
return 1;
}
static struct commonio_db subordinate_uid_db = {
"/etc/subuid", /* filename */
&subordinate_ops, /* ops */
NULL, /* fp */
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif
0644, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
false, /* changed */
false, /* isopen */
false, /* locked */
false /* readonly */
};
int sub_uid_setdbname (const char *filename)
{
return commonio_setname (&subordinate_uid_db, filename);
}
/*@observer@*/const char *sub_uid_dbname (void)
{
return subordinate_uid_db.filename;
}
bool sub_uid_file_present (void)
{
return commonio_present (&subordinate_uid_db);
}
int sub_uid_lock (void)
{
return commonio_lock (&subordinate_uid_db);
}
int sub_uid_open (int mode)
{
return commonio_open (&subordinate_uid_db, mode);
}
bool sub_uid_assigned(const char *owner)
{
return range_exists (&subordinate_uid_db, owner);
}
bool have_sub_uids(const char *owner, uid_t start, unsigned long count)
{
return have_range (&subordinate_uid_db, owner, start, count);
}
int sub_uid_add (const char *owner, uid_t start, unsigned long count)
{
return add_range (&subordinate_uid_db, owner, start, count);
}
int sub_uid_remove (const char *owner, uid_t start, unsigned long count)
{
return remove_range (&subordinate_uid_db, owner, start, count);
}
int sub_uid_close (void)
{
return commonio_close (&subordinate_uid_db);
}
int sub_uid_unlock (void)
{
return commonio_unlock (&subordinate_uid_db);
}
uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count)
{
unsigned long start;
start = find_free_range (&subordinate_uid_db, min, max, count);
return start == ULONG_MAX ? (uid_t) -1 : start;
}
static struct commonio_db subordinate_gid_db = {
"/etc/subgid", /* filename */
&subordinate_ops, /* ops */
NULL, /* fp */
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif
0644, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
false, /* changed */
false, /* isopen */
false, /* locked */
false /* readonly */
};
int sub_gid_setdbname (const char *filename)
{
return commonio_setname (&subordinate_gid_db, filename);
}
/*@observer@*/const char *sub_gid_dbname (void)
{
return subordinate_gid_db.filename;
}
bool sub_gid_file_present (void)
{
return commonio_present (&subordinate_gid_db);
}
int sub_gid_lock (void)
{
return commonio_lock (&subordinate_gid_db);
}
int sub_gid_open (int mode)
{
return commonio_open (&subordinate_gid_db, mode);
}
bool have_sub_gids(const char *owner, gid_t start, unsigned long count)
{
return have_range(&subordinate_gid_db, owner, start, count);
}
bool sub_gid_assigned(const char *owner)
{
return range_exists (&subordinate_gid_db, owner);
}
int sub_gid_add (const char *owner, gid_t start, unsigned long count)
{
return add_range (&subordinate_gid_db, owner, start, count);
}
int sub_gid_remove (const char *owner, gid_t start, unsigned long count)
{
return remove_range (&subordinate_gid_db, owner, start, count);
}
int sub_gid_close (void)
{
return commonio_close (&subordinate_gid_db);
}
int sub_gid_unlock (void)
{
return commonio_unlock (&subordinate_gid_db);
}
gid_t sub_gid_find_free_range(gid_t min, gid_t max, unsigned long count)
{
unsigned long start;
start = find_free_range (&subordinate_gid_db, min, max, count);
return start == ULONG_MAX ? (gid_t) -1 : start;
}
#else /* !ENABLE_SUBIDS */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !ENABLE_SUBIDS */

View File

@@ -1,41 +0,0 @@
/*
* Copyright (c) 2012- Eric W. Biederman
*/
#ifndef _SUBORDINATEIO_H
#define _SUBORDINATEIO_H
#include <config.h>
#ifdef ENABLE_SUBIDS
#include <sys/types.h>
extern int sub_uid_close(void);
extern bool have_sub_uids(const char *owner, uid_t start, unsigned long count);
extern bool sub_uid_file_present (void);
extern bool sub_uid_assigned(const char *owner);
extern int sub_uid_lock (void);
extern int sub_uid_setdbname (const char *filename);
extern /*@observer@*/const char *sub_uid_dbname (void);
extern int sub_uid_open (int mode);
extern int sub_uid_unlock (void);
extern int sub_uid_add (const char *owner, uid_t start, unsigned long count);
extern int sub_uid_remove (const char *owner, uid_t start, unsigned long count);
extern uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count);
extern int sub_gid_close(void);
extern bool have_sub_gids(const char *owner, gid_t start, unsigned long count);
extern bool sub_gid_file_present (void);
extern bool sub_gid_assigned(const char *owner);
extern int sub_gid_lock (void);
extern int sub_gid_setdbname (const char *filename);
extern /*@observer@*/const char *sub_gid_dbname (void);
extern int sub_gid_open (int mode);
extern int sub_gid_unlock (void);
extern int sub_gid_add (const char *owner, gid_t start, unsigned long count);
extern int sub_gid_remove (const char *owner, gid_t start, unsigned long count);
extern uid_t sub_gid_find_free_range(gid_t min, gid_t max, unsigned long count);
#endif /* ENABLE_SUBIDS */
#endif

View File

@@ -1,613 +0,0 @@
/*
* Copyright (c) 2001 Rafal Wojtczuk, Solar Designer
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <tcb.h>
#include <unistd.h>
#include "config.h"
#include "defines.h"
#include "prototypes.h"
#include "getdef.h"
#include "shadowio.h"
#include "tcbfuncs.h"
#define SHADOWTCB_HASH_BY 1000
#define SHADOWTCB_LOCK_SUFFIX ".lock"
static /*@null@*//*@only@*/char *stored_tcb_user = NULL;
shadowtcb_status shadowtcb_drop_priv (void)
{
if (!getdef_bool ("USE_TCB")) {
return SHADOWTCB_SUCCESS;
}
if (NULL != stored_tcb_user) {
if (tcb_drop_priv (stored_tcb_user) == 0) {
return SHADOWTCB_SUCCESS;
}
}
return SHADOWTCB_FAILURE;
}
shadowtcb_status shadowtcb_gain_priv (void)
{
if (!getdef_bool ("USE_TCB")) {
return SHADOWTCB_SUCCESS;
}
return (tcb_gain_priv () == 0) ? SHADOWTCB_SUCCESS : SHADOWTCB_FAILURE;
}
/* In case something goes wrong, we return immediately, not polluting the
* code with free(). All errors are fatal, so the application is expected
* to exit soon.
*/
#define OUT_OF_MEMORY do { \
fprintf (stderr, _("%s: out of memory\n"), Prog); \
(void) fflush (stderr); \
} while (false)
/* Returns user's tcb directory path relative to TCB_DIR. */
static /*@null@*/ char *shadowtcb_path_rel (const char *name, uid_t uid)
{
char *ret;
if (!getdef_bool ("TCB_SYMLINKS") || uid < SHADOWTCB_HASH_BY) {
if (asprintf (&ret, "%s", name) == -1) {
OUT_OF_MEMORY;
return NULL;
}
} else if (uid < SHADOWTCB_HASH_BY * SHADOWTCB_HASH_BY) {
if (asprintf (&ret, ":%dK/%s",
uid / SHADOWTCB_HASH_BY, name) == -1) {
OUT_OF_MEMORY;
return NULL;
}
} else {
if (asprintf (&ret, ":%dM/:%dK/%s",
uid / (SHADOWTCB_HASH_BY * SHADOWTCB_HASH_BY),
(uid % (SHADOWTCB_HASH_BY * SHADOWTCB_HASH_BY)) / SHADOWTCB_HASH_BY,
name) == -1) {
OUT_OF_MEMORY;
return NULL;
}
}
return ret;
}
static /*@null@*/ char *shadowtcb_path_rel_existing (const char *name)
{
char *path, *rval;
struct stat st;
char link[8192];
ssize_t ret;
if (asprintf (&path, TCB_DIR "/%s", name) == -1) {
OUT_OF_MEMORY;
return NULL;
}
if (lstat (path, &st) != 0) {
fprintf (stderr,
_("%s: Cannot stat %s: %s\n"),
Prog, path, strerror (errno));
free (path);
return NULL;
}
if (S_ISDIR (st.st_mode)) {
free (path);
rval = strdup (name);
if (NULL == rval) {
OUT_OF_MEMORY;
return NULL;
}
return rval;
}
if (!S_ISLNK (st.st_mode)) {
fprintf (stderr,
_("%s: %s is neither a directory, nor a symlink.\n"),
Prog, path);
free (path);
return NULL;
}
ret = readlink (path, link, sizeof (link) - 1);
if (-1 == ret) {
fprintf (stderr,
_("%s: Cannot read symbolic link %s: %s\n"),
Prog, path, strerror (errno));
free (path);
return NULL;
}
free (path);
if ((size_t)ret >= sizeof(link) - 1) {
link[sizeof(link) - 1] = '\0';
fprintf (stderr,
_("%s: Suspiciously long symlink: %s\n"),
Prog, link);
return NULL;
}
link[(size_t)ret] = '\0';
rval = strdup (link);
if (NULL == rval) {
OUT_OF_MEMORY;
return NULL;
}
return rval;
}
static /*@null@*/ char *shadowtcb_path (const char *name, uid_t uid)
{
char *ret, *rel;
rel = shadowtcb_path_rel (name, uid);
if (NULL == rel) {
return NULL;
}
if (asprintf (&ret, TCB_DIR "/%s", rel) == -1) {
OUT_OF_MEMORY;
free (rel);
return NULL;
}
free (rel);
return ret;
}
static /*@null@*/ char *shadowtcb_path_existing (const char *name)
{
char *ret, *rel;
rel = shadowtcb_path_rel_existing (name);
if (NULL == rel) {
return NULL;
}
if (asprintf (&ret, TCB_DIR "/%s", rel) == -1) {
OUT_OF_MEMORY;
free (rel);
return NULL;
}
free (rel);
return ret;
}
static shadowtcb_status mkdir_leading (const char *name, uid_t uid)
{
char *ind, *dir, *ptr, *path = shadowtcb_path_rel (name, uid);
struct stat st;
if (NULL == path) {
return SHADOWTCB_FAILURE;
}
ptr = path;
if (stat (TCB_DIR, &st) != 0) {
fprintf (stderr,
_("%s: Cannot stat %s: %s\n"),
Prog, TCB_DIR, strerror (errno));
goto out_free_path;
}
while ((ind = strchr (ptr, '/'))) {
*ind = '\0';
if (asprintf (&dir, TCB_DIR "/%s", path) == -1) {
OUT_OF_MEMORY;
return SHADOWTCB_FAILURE;
}
if ((mkdir (dir, 0700) != 0) && (errno != EEXIST)) {
fprintf (stderr,
_("%s: Cannot create directory %s: %s\n"),
Prog, dir, strerror (errno));
goto out_free_dir;
}
if (chown (dir, 0, st.st_gid) != 0) {
fprintf (stderr,
_("%s: Cannot change owner of %s: %s\n"),
Prog, dir, strerror (errno));
goto out_free_dir;
}
if (chmod (dir, 0711) != 0) {
fprintf (stderr,
_("%s: Cannot change mode of %s: %s\n"),
Prog, dir, strerror (errno));
goto out_free_dir;
}
free (dir);
*ind = '/';
ptr = ind + 1;
}
free (path);
return SHADOWTCB_SUCCESS;
out_free_dir:
free (dir);
out_free_path:
free (path);
return SHADOWTCB_FAILURE;
}
static shadowtcb_status unlink_suffs (const char *user)
{
static char *suffs[] = { "+", "-", SHADOWTCB_LOCK_SUFFIX };
char *tmp;
int i;
for (i = 0; i < 3; i++) {
if (asprintf (&tmp, TCB_FMT "%s", user, suffs[i]) == -1) {
OUT_OF_MEMORY;
return SHADOWTCB_FAILURE;
}
if ((unlink (tmp) != 0) && (errno != ENOENT)) {
fprintf (stderr,
_("%s: unlink: %s: %s\n"),
Prog, tmp, strerror (errno));
free (tmp);
return SHADOWTCB_FAILURE;
}
free (tmp);
}
return SHADOWTCB_SUCCESS;
}
/* path should be a relative existing tcb directory */
static shadowtcb_status rmdir_leading (char *path)
{
char *ind, *dir;
shadowtcb_status ret = SHADOWTCB_SUCCESS;
while ((ind = strrchr (path, '/'))) {
*ind = '\0';
if (asprintf (&dir, TCB_DIR "/%s", path) == -1) {
OUT_OF_MEMORY;
return SHADOWTCB_FAILURE;
}
if (rmdir (dir) != 0) {
if (errno != ENOTEMPTY) {
fprintf (stderr,
_("%s: Cannot remove directory %s: %s\n"),
Prog, dir, strerror (errno));
ret = SHADOWTCB_FAILURE;
}
free (dir);
break;
}
free (dir);
}
return ret;
}
static shadowtcb_status move_dir (const char *user_newname, uid_t user_newid)
{
char *olddir = NULL, *newdir = NULL;
char *real_old_dir = NULL, *real_new_dir = NULL;
char *real_old_dir_rel = NULL, *real_new_dir_rel = NULL;
uid_t old_uid, the_newid;
struct stat oldmode;
shadowtcb_status ret = SHADOWTCB_FAILURE;
if (NULL == stored_tcb_user) {
return SHADOWTCB_FAILURE;
}
if (asprintf (&olddir, TCB_DIR "/%s", stored_tcb_user) == -1) {
goto out_free_nomem;
}
if (stat (olddir, &oldmode) != 0) {
fprintf (stderr,
_("%s: Cannot stat %s: %s\n"),
Prog, olddir, strerror (errno));
goto out_free;
}
old_uid = oldmode.st_uid;
the_newid = (user_newid == -1) ? old_uid : user_newid;
real_old_dir = shadowtcb_path_existing (stored_tcb_user);
if (NULL == real_old_dir) {
goto out_free;
}
real_new_dir = shadowtcb_path (user_newname, the_newid);
if (NULL == real_new_dir) {
goto out_free;
}
if (strcmp (real_old_dir, real_new_dir) == 0) {
ret = SHADOWTCB_SUCCESS;
goto out_free;
}
real_old_dir_rel = shadowtcb_path_rel_existing (stored_tcb_user);
if (NULL == real_old_dir_rel) {
goto out_free;
}
if (mkdir_leading (user_newname, the_newid) == SHADOWTCB_FAILURE) {
goto out_free;
}
if (rename (real_old_dir, real_new_dir) != 0) {
fprintf (stderr,
_("%s: Cannot rename %s to %s: %s\n"),
Prog, real_old_dir, real_new_dir, strerror (errno));
goto out_free;
}
if (rmdir_leading (real_old_dir_rel) == SHADOWTCB_FAILURE) {
goto out_free;
}
if ((unlink (olddir) != 0) && (errno != ENOENT)) {
fprintf (stderr,
_("%s: Cannot remove %s: %s\n"),
Prog, olddir, strerror (errno));
goto out_free;
}
if (asprintf (&newdir, TCB_DIR "/%s", user_newname) == -1) {
goto out_free_nomem;
}
real_new_dir_rel = shadowtcb_path_rel (user_newname, the_newid);
if (NULL == real_new_dir_rel) {
goto out_free;
}
if ( (strcmp (real_new_dir, newdir) != 0)
&& (symlink (real_new_dir_rel, newdir) != 0)) {
fprintf (stderr,
_("%s: Cannot create symbolic link %s: %s\n"),
Prog, real_new_dir_rel, strerror (errno));
goto out_free;
}
ret = SHADOWTCB_SUCCESS;
goto out_free;
out_free_nomem:
OUT_OF_MEMORY;
out_free:
free (olddir);
free (newdir);
free (real_old_dir);
free (real_new_dir);
free (real_old_dir_rel);
free (real_new_dir_rel);
return ret;
}
shadowtcb_status shadowtcb_set_user (const char* name)
{
char *buf;
shadowtcb_status retval;
if (!getdef_bool ("USE_TCB")) {
return SHADOWTCB_SUCCESS;
}
if (NULL != stored_tcb_user) {
free (stored_tcb_user);
}
stored_tcb_user = strdup (name);
if (NULL == stored_tcb_user) {
OUT_OF_MEMORY;
return SHADOWTCB_FAILURE;
}
if (asprintf (&buf, TCB_FMT, name) == -1) {
OUT_OF_MEMORY;
return SHADOWTCB_FAILURE;
}
retval = (spw_setdbname (buf) != 0) ? SHADOWTCB_SUCCESS : SHADOWTCB_FAILURE;
free (buf);
return retval;
}
/* tcb directory must be empty before shadowtcb_remove is called. */
shadowtcb_status shadowtcb_remove (const char *name)
{
shadowtcb_status ret = SHADOWTCB_SUCCESS;
char *path = shadowtcb_path_existing (name);
char *rel = shadowtcb_path_rel_existing (name);
if ((NULL == path) || (NULL == rel) || (rmdir (path) != 0)) {
return SHADOWTCB_FAILURE;
}
if (rmdir_leading (rel) == SHADOWTCB_FAILURE) {
return SHADOWTCB_FAILURE;
}
free (path);
free (rel);
if (asprintf (&path, TCB_DIR "/%s", name) == -1) {
OUT_OF_MEMORY;
return SHADOWTCB_FAILURE;
}
if ((unlink (path) != 0) && (errno != ENOENT)) {
ret = SHADOWTCB_FAILURE;
}
free (path);
return ret;
}
shadowtcb_status shadowtcb_move (/*@NULL@*/const char *user_newname, uid_t user_newid)
{
struct stat dirmode, filemode;
char *tcbdir, *shadow;
shadowtcb_status ret = SHADOWTCB_FAILURE;
if (!getdef_bool ("USE_TCB")) {
return SHADOWTCB_SUCCESS;
}
if (NULL == stored_tcb_user) {
return SHADOWTCB_FAILURE;
}
if (NULL == user_newname) {
user_newname = stored_tcb_user;
}
if (move_dir (user_newname, user_newid) == SHADOWTCB_FAILURE) {
return SHADOWTCB_FAILURE;
}
if (-1 == user_newid) {
return SHADOWTCB_SUCCESS;
}
if ( (asprintf (&tcbdir, TCB_DIR "/%s", user_newname) == -1)
|| (asprintf (&shadow, TCB_FMT, user_newname) == -1)) {
OUT_OF_MEMORY;
return SHADOWTCB_FAILURE;
}
if (stat (tcbdir, &dirmode) != 0) {
fprintf (stderr,
_("%s: Cannot stat %s: %s\n"),
Prog, tcbdir, strerror (errno));
goto out_free;
}
if (chown (tcbdir, 0, 0) != 0) {
fprintf (stderr,
_("%s: Cannot change owners of %s: %s\n"),
Prog, tcbdir, strerror (errno));
goto out_free;
}
if (chmod (tcbdir, 0700) != 0) {
fprintf (stderr,
_("%s: Cannot change mode of %s: %s\n"),
Prog, tcbdir, strerror (errno));
goto out_free;
}
if (lstat (shadow, &filemode) != 0) {
if (errno != ENOENT) {
fprintf (stderr,
_("%s: Cannot lstat %s: %s\n"),
Prog, shadow, strerror (errno));
goto out_free;
}
fprintf (stderr,
_("%s: Warning, user %s has no tcb shadow file.\n"),
Prog, user_newname);
} else {
if (!S_ISREG (filemode.st_mode) ||
filemode.st_nlink != 1) {
fprintf (stderr,
_("%s: Emergency: %s's tcb shadow is not a "
"regular file with st_nlink=1.\n"
"The account is left locked.\n"),
Prog, user_newname);
goto out_free;
}
if (chown (shadow, user_newid, filemode.st_gid) != 0) {
fprintf (stderr,
_("%s: Cannot change owner of %s: %s\n"),
Prog, shadow, strerror (errno));
goto out_free;
}
if (chmod (shadow, filemode.st_mode & 07777) != 0) {
fprintf (stderr,
_("%s: Cannot change mode of %s: %s\n"),
Prog, shadow, strerror (errno));
goto out_free;
}
}
if (unlink_suffs (user_newname) == SHADOWTCB_FAILURE) {
goto out_free;
}
if (chown (tcbdir, user_newid, dirmode.st_gid) != 0) {
fprintf (stderr,
_("%s: Cannot change owner of %s: %s\n"),
Prog, tcbdir, strerror (errno));
goto out_free;
}
ret = SHADOWTCB_SUCCESS;
out_free:
free (tcbdir);
free (shadow);
return ret;
}
shadowtcb_status shadowtcb_create (const char *name, uid_t uid)
{
char *dir, *shadow;
struct stat tcbdir_stat;
gid_t shadowgid, authgid;
struct group *gr;
int fd;
shadowtcb_status ret = SHADOWTCB_FAILURE;
if (!getdef_bool ("USE_TCB")) {
return SHADOWTCB_SUCCESS;
}
if (stat (TCB_DIR, &tcbdir_stat) != 0) {
fprintf (stderr,
_("%s: Cannot stat %s: %s\n"),
Prog, TCB_DIR, strerror (errno));
return SHADOWTCB_FAILURE;
}
shadowgid = tcbdir_stat.st_gid;
authgid = shadowgid;
if (getdef_bool ("TCB_AUTH_GROUP")) {
gr = getgrnam ("auth");
if (NULL != gr) {
authgid = gr->gr_gid;
}
}
if ( (asprintf (&dir, TCB_DIR "/%s", name) == -1)
|| (asprintf (&shadow, TCB_FMT, name) == -1)) {
OUT_OF_MEMORY;
return SHADOWTCB_FAILURE;
}
if (mkdir (dir, 0700) != 0) {
fprintf (stderr,
_("%s: mkdir: %s: %s\n"),
Prog, dir, strerror (errno));
goto out_free;
}
fd = open (shadow, O_RDWR | O_CREAT | O_TRUNC, 0600);
if (fd < 0) {
fprintf (stderr,
_("%s: Cannot open %s: %s\n"),
Prog, shadow, strerror (errno));
goto out_free;
}
close (fd);
if (chown (shadow, 0, authgid) != 0) {
fprintf (stderr,
_("%s: Cannot change owner of %s: %s\n"),
Prog, shadow, strerror (errno));
goto out_free;
}
if (chmod (shadow, (mode_t) ((authgid == shadowgid) ? 0600 : 0640)) != 0) {
fprintf (stderr,
_("%s: Cannot change mode of %s: %s\n"),
Prog, shadow, strerror (errno));
goto out_free;
}
if (chown (dir, 0, authgid) != 0) {
fprintf (stderr,
_("%s: Cannot change owner of %s: %s\n"),
Prog, dir, strerror (errno));
goto out_free;
}
if (chmod (dir, (mode_t) ((authgid == shadowgid) ? 02700 : 02710)) != 0) {
fprintf (stderr,
_("%s: Cannot change mode of %s: %s\n"),
Prog, dir, strerror (errno));
goto out_free;
}
if ( (shadowtcb_set_user (name) == SHADOWTCB_FAILURE)
|| (shadowtcb_move (NULL, uid) == SHADOWTCB_FAILURE)) {
goto out_free;
}
ret = SHADOWTCB_SUCCESS;
out_free:
free (dir);
free (shadow);
return ret;
}

View File

@@ -1,19 +0,0 @@
#ifndef _TCBFUNCS_H
#define _TCBFUNCS_H
#include <sys/types.h>
typedef enum {
SHADOWTCB_FAILURE = 0,
SHADOWTCB_SUCCESS = 1
} shadowtcb_status;
extern shadowtcb_status shadowtcb_drop_priv (void);
extern shadowtcb_status shadowtcb_gain_priv (void);
extern shadowtcb_status shadowtcb_set_user (const char *name);
extern shadowtcb_status shadowtcb_remove (const char *name);
extern shadowtcb_status shadowtcb_move (/*@null@*/const char *user_newname,
uid_t user_newid);
extern shadowtcb_status shadowtcb_create (const char *name, uid_t uid);
#endif

View File

@@ -88,6 +88,25 @@ struct utmp *getutent (void)
return &utmp_buf;
}
/*
* getutline - get the utmp entry matching ut_line
*/
struct utmp *getutline (const struct utmp *utent)
{
struct utmp save;
struct utmp *new;
save = *utent;
while (new = getutent ())
if (strncmp (new->ut_line, save.ut_line, sizeof new->ut_line))
continue;
else
return new;
return (struct utmp *) 0;
}
#else
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif

View File

@@ -23,17 +23,14 @@ libmisc_a_SOURCES = \
env.c \
failure.c \
failure.h \
fields.c \
find_new_gid.c \
find_new_uid.c \
find_new_sub_gids.c \
find_new_sub_uids.c \
getdate.h \
getdate.y \
getgr_nam_gid.c \
getrange.c \
hushed.c \
idmapping.h \
idmapping.c \
isexpired.c \
limits.c \
list.c log.c \
@@ -47,13 +44,12 @@ libmisc_a_SOURCES = \
pwd2spwd.c \
pwdcheck.c \
pwd_init.c \
remove_tree.c \
rlogin.c \
root_flag.c \
salt.c \
setugid.c \
setupenv.c \
shell.c \
system.c \
strtoday.c \
sub.c \
sulog.c \

View File

@@ -71,11 +71,7 @@ int add_groups (const char *list)
return -1;
}
ngroups = getgroups (i, grouplist);
if ( ( (-1 == ngroups)
&& (EINVAL != errno))
|| (i > (size_t)ngroups)) {
/* Unexpected failure of getgroups or successful
* reception of the groups */
if ((-1 == ngroups) || (i > (size_t)ngroups)) {
break;
}
/* not enough room, so try allocating a larger buffer */

View File

@@ -76,7 +76,7 @@ void audit_help_open (void)
* id - uid or gid that the operation is being performed on. This is used
* only when user is NULL.
*/
void audit_logger (int type, unused const char *pgname, const char *op,
void audit_logger (int type, const char *pgname, const char *op,
const char *name, unsigned int id,
shadow_audit_result result)
{
@@ -84,7 +84,7 @@ void audit_logger (int type, unused const char *pgname, const char *op,
return;
} else {
audit_log_acct_message (audit_fd, type, NULL, op, name, id,
NULL, NULL, NULL, (int) result);
NULL, NULL, NULL, (int) result);
}
}

View File

@@ -42,9 +42,9 @@
#include "defines.h"
#include "prototypes.h"
/*@observer@*/const char *Basename (const char *str)
char *Basename (char *str)
{
char *cp = strrchr (str, '/');
return (NULL != cp) ? cp + 1 : str;
return cp ? cp + 1 : str;
}

View File

@@ -2,7 +2,6 @@
* Copyright (c) 1992 - 1993, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2010 - , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -45,92 +44,59 @@
*
* chown_dir() walks a directory tree and changes the ownership
* of all files owned by the provided user ID.
*
* Only files owned (resp. group-owned) by old_uid (resp. by old_gid)
* will have their ownership (resp. group-ownership) modified, unless
* old_uid (resp. old_gid) is set to -1.
*
* new_uid and new_gid can be set to -1 to indicate that no owner or
* group-owner shall be changed.
*/
int chown_tree (const char *root,
uid_t old_uid,
uid_t new_uid,
gid_t old_gid,
gid_t new_gid)
int
chown_tree (const char *root, uid_t old_uid, uid_t new_uid, gid_t old_gid,
gid_t new_gid)
{
char *new_name;
size_t new_name_len;
char new_name[1024];
int rc = 0;
struct DIRECT *ent;
struct stat sb;
DIR *dir;
new_name = malloc (1024);
if (NULL == new_name) {
return -1;
}
new_name_len = 1024;
/*
* Make certain the directory exists. This routine is called
* directly by the invoker, or recursively.
* directory by the invoker, or recursively.
*/
if (access (root, F_OK) != 0) {
free (new_name);
if (access (root, F_OK) != 0)
return -1;
}
/*
* Open the directory and read each entry. Every entry is tested
* to see if it is a directory, and if so this routine is called
* recursively. If not, it is checked to see if an ownership
* shall be changed.
* recursively. If not, it is checked to see if it is owned by
* old user ID.
*/
dir = opendir (root);
if (NULL == dir) {
free (new_name);
if (!(dir = opendir (root)))
return -1;
}
while ((ent = readdir (dir))) {
size_t ent_name_len;
uid_t tmpuid = (uid_t) -1;
gid_t tmpgid = (gid_t) -1;
/*
* Skip the "." and ".." entries
*/
if ( (strcmp (ent->d_name, ".") == 0)
|| (strcmp (ent->d_name, "..") == 0)) {
if (strcmp (ent->d_name, ".") == 0 ||
strcmp (ent->d_name, "..") == 0)
continue;
}
/*
* Make the filename for both the source and the
* destination files.
*/
ent_name_len = strlen (root) + strlen (ent->d_name) + 2;
if (ent_name_len > new_name_len) {
/*@only@*/char *tmp = realloc (new_name, ent_name_len);
if (NULL == tmp) {
rc = -1;
break;
}
new_name = tmp;
new_name_len = ent_name_len;
}
if (strlen (root) + strlen (ent->d_name) + 2 > sizeof new_name)
break;
(void) snprintf (new_name, new_name_len, "%s/%s", root, ent->d_name);
snprintf (new_name, sizeof new_name, "%s/%s", root,
ent->d_name);
/* Don't follow symbolic links! */
if (LSTAT (new_name, &sb) == -1) {
if (LSTAT (new_name, &sb) == -1)
continue;
}
if (S_ISDIR (sb.st_mode) && !S_ISLNK (sb.st_mode)) {
@@ -146,56 +112,25 @@ int chown_tree (const char *root,
}
#ifndef HAVE_LCHOWN
/* don't use chown (follows symbolic links!) */
if (S_ISLNK (sb.st_mode)) {
if (S_ISLNK (sb.st_mode))
continue;
}
#endif
/*
* By default, the IDs are not changed (-1).
*
* If the file is not owned by the user, the owner is not
* changed.
*
* If the file is not group-owned by the group, the
* group-owner is not changed.
*/
if (((uid_t) -1 == old_uid) || (sb.st_uid == old_uid)) {
tmpuid = new_uid;
}
if (((gid_t) -1 == old_gid) || (sb.st_gid == old_gid)) {
tmpgid = new_gid;
}
if (((uid_t) -1 != tmpuid) || ((gid_t) -1 != tmpgid)) {
rc = LCHOWN (new_name, tmpuid, tmpgid);
if (0 != rc) {
break;
}
}
if (sb.st_uid == old_uid)
LCHOWN (new_name, new_uid,
sb.st_gid == old_gid ? new_gid : sb.st_gid);
}
free (new_name);
(void) closedir (dir);
/*
* Now do the root of the tree
*/
if ((0 == rc) && (stat (root, &sb) == 0)) {
uid_t tmpuid = (uid_t) -1;
gid_t tmpgid = (gid_t) -1;
if (((uid_t) -1 == old_uid) || (sb.st_uid == old_uid)) {
tmpuid = new_uid;
if (stat (root, &sb) == 0) {
if (sb.st_uid == old_uid) {
LCHOWN (root, new_uid,
sb.st_gid == old_gid ? new_gid : sb.st_gid);
}
if (((gid_t) -1 == old_gid) || (sb.st_gid == old_gid)) {
tmpgid = new_gid;
}
if (((uid_t) -1 != tmpuid) || ((gid_t) -1 != tmpgid)) {
rc = LCHOWN (root, tmpuid, tmpgid);
}
} else {
rc = -1;
}
return rc;
}

View File

@@ -72,7 +72,7 @@ void chown_tty (const struct passwd *info)
*/
if ( (fchown (STDIN_FILENO, info->pw_uid, gid) != 0)
|| (fchmod (STDIN_FILENO, (mode_t)getdef_num ("TTYPERM", 0600)) != 0)) {
|| (fchmod (STDIN_FILENO, getdef_num ("TTYPERM", 0600)) != 0)) {
int err = errno;
fprintf (stderr,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008 - 2011, Nicolas François
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,12 +38,8 @@
* The cleanup_functions stack.
*/
#define CLEANUP_FUNCTIONS 10
typedef /*@null@*/void * parg_t;
static cleanup_function cleanup_functions[CLEANUP_FUNCTIONS];
static parg_t cleanup_function_args[CLEANUP_FUNCTIONS];
static pid_t cleanup_pid = 0;
static void * cleanup_function_args[CLEANUP_FUNCTIONS];
/*
* - Cleanup functions shall not fail.
@@ -57,9 +53,6 @@ static pid_t cleanup_pid = 0;
/*
* do_cleanups - perform the actions stored in the cleanup_functions stack.
*
* Cleanup action are not executed on exit of the processes started by the
* parent (first caller of add_cleanup).
*
* It is intended to be used as:
* atexit (do_cleanups);
*/
@@ -70,10 +63,6 @@ void do_cleanups (void)
/* Make sure there were no overflow */
assert (NULL == cleanup_functions[CLEANUP_FUNCTIONS-1]);
if (getpid () != cleanup_pid) {
return;
}
i = CLEANUP_FUNCTIONS;
do {
i--;
@@ -86,17 +75,13 @@ void do_cleanups (void)
/*
* add_cleanup - Add a cleanup_function to the cleanup_functions stack.
*/
void add_cleanup (/*@notnull@*/cleanup_function pcf, /*@null@*/void *arg)
void add_cleanup (cleanup_function pcf, /*@null@*/void *arg)
{
unsigned int i;
assert (NULL != pcf);
assert (NULL == cleanup_functions[CLEANUP_FUNCTIONS-2]);
if (0 == cleanup_pid) {
cleanup_pid = getpid ();
}
/* Add the cleanup_function at the end of the stack */
for (i=0; NULL != cleanup_functions[i]; i++);
cleanup_functions[i] = pcf;
@@ -106,7 +91,7 @@ void add_cleanup (/*@notnull@*/cleanup_function pcf, /*@null@*/void *arg)
/*
* del_cleanup - Remove a cleanup_function from the cleanup_functions stack.
*/
void del_cleanup (/*@notnull@*/cleanup_function pcf)
void del_cleanup (cleanup_function pcf)
{
unsigned int i;
assert (NULL != pcf);
@@ -124,8 +109,7 @@ void del_cleanup (/*@notnull@*/cleanup_function pcf)
/* Move the rest of the cleanup functions */
for (; i<CLEANUP_FUNCTIONS; i++) {
/* Make sure the cleanup function was specified only once */
assert ( (i == (CLEANUP_FUNCTIONS -1))
|| (cleanup_functions[i+1] != pcf));
assert (cleanup_functions[i+1] != pcf);
if (i == (CLEANUP_FUNCTIONS -1)) {
cleanup_functions[i] = NULL;

View File

@@ -3,7 +3,7 @@
* Copyright (c) 1991 , Chip Rosenthal
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -50,8 +50,7 @@ static bool is_listed (const char *cfgin, const char *tty, bool def);
static bool is_listed (const char *cfgin, const char *tty, bool def)
{
FILE *fp;
char buf[200], *s;
const char *cons;
char buf[200], *cons, *s;
/*
* If the CONSOLE configuration definition isn't given,
@@ -69,15 +68,13 @@ static bool is_listed (const char *cfgin, const char *tty, bool def)
*/
if (*cons != '/') {
char *pbuf;
strcpy (buf, cons);
pbuf = &buf[0];
while ((s = strtok (pbuf, ":")) != NULL) {
while ((s = strtok (buf, ":")) != NULL) {
if (strcmp (s, tty) == 0) {
return true;
}
pbuf = NULL;
cons = NULL;
}
return false;
}

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2001, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,19 +44,7 @@
#include "defines.h"
#ifdef WITH_SELINUX
#include <selinux/selinux.h>
#endif /* WITH_SELINUX */
#if defined(WITH_ACL) || defined(WITH_ATTR)
#include <stdarg.h>
#include <attr/error_context.h>
#endif /* WITH_ACL || WITH_ATTR */
#ifdef WITH_ACL
#include <acl/libacl.h>
#endif /* WITH_ACL */
#ifdef WITH_ATTR
#include <attr/libattr.h>
#endif /* WITH_ATTR */
#endif
static /*@null@*/const char *src_orig;
static /*@null@*/const char *dst_orig;
@@ -70,73 +58,66 @@ struct link_name {
static /*@exposed@*/struct link_name *links;
static int copy_entry (const char *src, const char *dst,
bool reset_selinux,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
long int uid, long int gid);
static int copy_dir (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
long int uid, long int gid);
#ifdef S_IFLNK
static /*@null@*/char *readlink_malloc (const char *filename);
static char *readlink_malloc (const char *filename);
static int copy_symlink (const char *src, const char *dst,
unused bool reset_selinux,
const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
#endif /* S_IFLNK */
static int copy_hardlink (const char *dst,
unused bool reset_selinux,
long int uid, long int gid);
#endif
static int copy_hardlink (const char *src, const char *dst,
struct link_name *lp);
static int copy_special (const char *src, const char *dst,
bool reset_selinux,
static int copy_special (const char *dst,
const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
long int uid, long int gid);
static int copy_file (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static int chown_if_needed (const char *dst, const struct stat *statp,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static int lchown_if_needed (const char *dst, const struct stat *statp,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static int fchown_if_needed (int fdst, const struct stat *statp,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
long int uid, long int gid);
#if defined(WITH_ACL) || defined(WITH_ATTR)
#ifdef WITH_SELINUX
/*
* error_acl - format the error messages for the ACL and EQ libraries.
* selinux_file_context - Set the security context before any file or
* directory creation.
*
* selinux_file_context () should be called before any creation of file,
* symlink, directory, ...
*
* Callers may have to Reset SELinux to create files with default
* contexts:
* setfscreatecon (NULL);
*/
static void error_acl (struct error_context *ctx, const char *fmt, ...)
int selinux_file_context (const char *dst_name)
{
va_list ap;
static bool selinux_checked = false;
static bool selinux_enabled;
security_context_t scontext = NULL;
/* ignore the case when destination does not support ACLs
* or extended attributes */
if (ENOTSUP == errno) {
errno = 0;
return;
if (!selinux_checked) {
selinux_enabled = is_selinux_enabled () > 0;
selinux_checked = true;
}
va_start (ap, fmt);
(void) fprintf (stderr, _("%s: "), Prog);
if (vfprintf (stderr, fmt, ap) != 0) {
(void) fputs (_(": "), stderr);
if (selinux_enabled) {
/* Get the default security context for this file */
if (matchpathcon (dst_name, 0, &scontext) < 0) {
if (security_getenforce () != 0) {
return 1;
}
}
/* Set the security context for the next created file */
if (setfscreatecon (scontext) < 0) {
if (security_getenforce () != 0) {
return 1;
}
}
freecon (scontext);
}
(void) fprintf (stderr, "%s\n", strerror (errno));
va_end (ap);
return 0;
}
static struct error_context ctx = {
error_acl
};
#endif /* WITH_ACL || WITH_ATTR */
#endif
/*
* remove_link - delete a link from the linked list
@@ -203,7 +184,7 @@ static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, c
lp->ln_count = sb->st_nlink;
len = name_len - src_len + dst_len + 1;
lp->ln_name = (char *) xmalloc (len);
(void) snprintf (lp->ln_name, len, "%s%s", dst_orig, name + src_len);
snprintf (lp->ln_name, len, "%s%s", dst_orig, name + src_len);
lp->ln_next = links;
links = lp;
@@ -215,49 +196,15 @@ static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, c
*
* copy_tree() walks a directory tree and copies ordinary files
* as it goes.
*
* When reset_selinux is enabled, extended attributes (and thus
* SELinux attributes) are not copied.
*
* old_uid and new_uid are used to set the ownership of the copied
* files. Unless old_uid is set to -1, only the files owned by
* old_uid have their ownership changed to new_uid. In addition, if
* new_uid is set to -1, no ownership will be changed.
*
* The same logic applies for the group-ownership and
* old_gid/new_gid.
*/
int copy_tree (const char *src_root, const char *dst_root,
bool copy_root, bool reset_selinux,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
long int uid, long int gid)
{
int err = 0;
bool set_orig = false;
struct DIRECT *ent;
DIR *dir;
if (copy_root) {
struct stat sb;
if (access (dst_root, F_OK) == 0) {
return -1;
}
if (LSTAT (src_root, &sb) == -1) {
return -1;
}
if (!S_ISDIR (sb.st_mode)) {
fprintf (stderr,
"%s: %s is not a directory",
Prog, src_root);
return -1;
}
return copy_entry (src_root, dst_root, reset_selinux,
old_uid, new_uid, old_gid, new_gid);
}
/*
* Make certain both directories exist. This routine is called
* after the home directory is created, or recursively after the
@@ -309,15 +256,12 @@ int copy_tree (const char *src_root, const char *dst_root,
* Build the filename for both the source and
* the destination files.
*/
(void) snprintf (src_name, src_len, "%s/%s",
src_root, ent->d_name);
(void) snprintf (dst_name, dst_len, "%s/%s",
dst_root, ent->d_name);
snprintf (src_name, src_len, "%s/%s",
src_root, ent->d_name);
snprintf (dst_name, dst_len, "%s/%s",
dst_root, ent->d_name);
err = copy_entry (src_name, dst_name,
reset_selinux,
old_uid, new_uid,
old_gid, new_gid);
err = copy_entry (src_name, dst_name, uid, gid);
}
if (NULL != src_name) {
free (src_name);
@@ -332,25 +276,16 @@ int copy_tree (const char *src_root, const char *dst_root,
if (set_orig) {
src_orig = NULL;
dst_orig = NULL;
/* FIXME: clean links
* Since there can be hardlinks elsewhere on the device,
* we cannot check that all the hardlinks were found:
assert (NULL == links);
*/
}
#ifdef WITH_SELINUX
/* Reset SELinux to create files with default contexts.
* Note that the context is only reset on exit of copy_tree (it is
* assumed that the program would quit without needing a restored
* context if copy_tree failed previously), and that copy_tree can
* be called recursively (hence the context is set on the
* sub-functions of copy_entry).
*/
if (reset_selinux_file_context () != 0) {
err = -1;
}
#endif /* WITH_SELINUX */
/* Reset SELinux to create files with default contexts */
setfscreatecon (NULL);
#endif
/* FIXME: with the call to remove_link, we could also check that
* no links remain in links.
* assert (NULL == links); */
return err;
}
@@ -365,19 +300,13 @@ int copy_tree (const char *src_root, const char *dst_root,
*
* The access and modification time will not be modified.
*
* The permissions will be set to new_uid/new_gid.
* The permissions will be set to uid/gid.
*
* If new_uid (resp. new_gid) is equal to -1, the user (resp. group) will
* If uid (resp. gid) is equal to -1, the user (resp. group) will
* not be modified.
*
* Only the files owned (resp. group-owned) by old_uid (resp.
* old_gid) will be modified, unless old_uid (resp. old_gid) is set
* to -1.
*/
static int copy_entry (const char *src, const char *dst,
bool reset_selinux,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
long int uid, long int gid)
{
int err = 0;
struct stat sb;
@@ -390,30 +319,29 @@ static int copy_entry (const char *src, const char *dst,
#ifdef HAVE_STRUCT_STAT_ST_ATIM
mt[0].tv_sec = sb.st_atim.tv_sec;
mt[0].tv_usec = sb.st_atim.tv_nsec / 1000;
#else /* !HAVE_STRUCT_STAT_ST_ATIM */
#else
mt[0].tv_sec = sb.st_atime;
# ifdef HAVE_STRUCT_STAT_ST_ATIMENSEC
#ifdef HAVE_STRUCT_STAT_ST_ATIMENSEC
mt[0].tv_usec = sb.st_atimensec / 1000;
# else /* !HAVE_STRUCT_STAT_ST_ATIMENSEC */
#else
mt[0].tv_usec = 0;
# endif /* !HAVE_STRUCT_STAT_ST_ATIMENSEC */
#endif /* !HAVE_STRUCT_STAT_ST_ATIM */
#endif
#endif
#ifdef HAVE_STRUCT_STAT_ST_MTIM
mt[1].tv_sec = sb.st_mtim.tv_sec;
mt[1].tv_usec = sb.st_mtim.tv_nsec / 1000;
#else /* !HAVE_STRUCT_STAT_ST_MTIM */
#else
mt[1].tv_sec = sb.st_mtime;
# ifdef HAVE_STRUCT_STAT_ST_MTIMENSEC
#ifdef HAVE_STRUCT_STAT_ST_MTIMENSEC
mt[1].tv_usec = sb.st_mtimensec / 1000;
# else /* !HAVE_STRUCT_STAT_ST_MTIMENSEC */
#else
mt[1].tv_usec = 0;
# endif /* !HAVE_STRUCT_STAT_ST_MTIMENSEC */
#endif /* !HAVE_STRUCT_STAT_ST_MTIM */
#endif
#endif
if (S_ISDIR (sb.st_mode)) {
err = copy_dir (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
err = copy_dir (src, dst, &sb, mt, uid, gid);
}
#ifdef S_IFLNK
@@ -422,17 +350,16 @@ static int copy_entry (const char *src, const char *dst,
*/
else if (S_ISLNK (sb.st_mode)) {
err = copy_symlink (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
err = copy_symlink (src, dst, &sb, mt, uid, gid);
}
#endif /* S_IFLNK */
#endif
/*
* See if this is a previously copied link
*/
else if ((lp = check_link (src, &sb)) != NULL) {
err = copy_hardlink (dst, reset_selinux, lp);
err = copy_hardlink (src, dst, lp);
}
/*
@@ -442,8 +369,7 @@ static int copy_entry (const char *src, const char *dst,
*/
else if (!S_ISREG (sb.st_mode)) {
err = copy_special (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
err = copy_special (dst, &sb, mt, uid, gid);
}
/*
@@ -452,8 +378,7 @@ static int copy_entry (const char *src, const char *dst,
*/
else {
err = copy_file (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
err = copy_file (src, dst, &sb, mt, uid, gid);
}
}
@@ -465,16 +390,14 @@ static int copy_entry (const char *src, const char *dst,
*
* Copy a directory (recursively) from src to dst.
*
* statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
* the access and modification and the access rights.
* statp, mt, uid, gid are used to set the access and modification and the
* access rights.
*
* Return 0 on success, -1 on error.
*/
static int copy_dir (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
long int uid, long int gid)
{
int err = 0;
@@ -484,33 +407,14 @@ static int copy_dir (const char *src, const char *dst,
*/
#ifdef WITH_SELINUX
if (set_selinux_file_context (dst) != 0) {
return -1;
}
#endif /* WITH_SELINUX */
selinux_file_context (dst);
#endif
if ( (mkdir (dst, statp->st_mode) != 0)
|| (chown_if_needed (dst, statp,
old_uid, new_uid, old_gid, new_gid) != 0)
#ifdef WITH_ACL
|| ( (perm_copy_file (src, dst, &ctx) != 0)
&& (errno != 0))
#else /* !WITH_ACL */
|| (chown (dst,
(uid == - 1) ? statp->st_uid : (uid_t) uid,
(gid == - 1) ? statp->st_gid : (gid_t) gid) != 0)
|| (chmod (dst, statp->st_mode) != 0)
#endif /* !WITH_ACL */
#ifdef WITH_ATTR
/*
* If the third parameter is NULL, all extended attributes
* except those that define Access Control Lists are copied.
* ACLs are excluded by default because copying them between
* file systems with and without ACL support needs some
* additional logic so that no unexpected permissions result.
*/
|| ( !reset_selinux
&& (attr_copy_file (src, dst, NULL, &ctx) != 0)
&& (errno != 0))
#endif /* WITH_ATTR */
|| (copy_tree (src, dst, false, reset_selinux,
old_uid, new_uid, old_gid, new_gid) != 0)
|| (copy_tree (src, dst, uid, gid) != 0)
|| (utimes (dst, mt) != 0)) {
err = -1;
}
@@ -525,11 +429,11 @@ static int copy_dir (const char *src, const char *dst,
* return NULL on error.
* The return string shall be freed by the caller.
*/
static /*@null@*/char *readlink_malloc (const char *filename)
static char *readlink_malloc (const char *filename)
{
size_t size = 1024;
while (true) {
while (1) {
ssize_t nchars;
char *buffer = (char *) malloc (size);
if (NULL == buffer) {
@@ -539,11 +443,10 @@ static /*@null@*/char *readlink_malloc (const char *filename)
nchars = readlink (filename, buffer, size);
if (nchars < 0) {
free(buffer);
return NULL;
}
if ((size_t) nchars < size) { /* The buffer was large enough */
if ( (size_t) nchars < size) { /* The buffer was large enough */
/* readlink does not nul-terminate */
buffer[nchars] = '\0';
return buffer;
@@ -560,16 +463,14 @@ static /*@null@*/char *readlink_malloc (const char *filename)
*
* Copy a symlink from src to dst.
*
* statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
* the access and modification and the access rights.
* statp, mt, uid, gid are used to set the access and modification and the
* access rights.
*
* Return 0 on success, -1 on error.
*/
static int copy_symlink (const char *src, const char *dst,
unused bool reset_selinux,
const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
long int uid, long int gid)
{
char *oldlink;
@@ -593,33 +494,25 @@ static int copy_symlink (const char *src, const char *dst,
/* If src was a link to an entry of the src_orig directory itself,
* create a link to the corresponding entry in the dst_orig
* directory.
* FIXME: This may change a relative link to an absolute link
*/
if (strncmp (oldlink, src_orig, strlen (src_orig)) == 0) {
size_t len = strlen (dst_orig) + strlen (oldlink) - strlen (src_orig) + 1;
char *dummy = (char *) xmalloc (len);
(void) snprintf (dummy, len, "%s%s",
dst_orig,
oldlink + strlen (src_orig));
char *dummy = (char *) malloc (len);
snprintf (dummy, len, "%s%s",
dst_orig,
oldlink + strlen (src_orig));
free (oldlink);
oldlink = dummy;
}
#ifdef WITH_SELINUX
if (set_selinux_file_context (dst) != 0) {
free (oldlink);
return -1;
}
#endif /* WITH_SELINUX */
selinux_file_context (dst);
#endif
if ( (symlink (oldlink, dst) != 0)
|| (lchown_if_needed (dst, statp,
old_uid, new_uid, old_gid, new_gid) != 0)) {
/* FIXME: there are no modes on symlinks, right?
* ACL could be copied, but this would be much more
* complex than calling perm_copy_file.
* Ditto for Extended Attributes.
* We currently only document that ACL and Extended
* Attributes are not copied.
*/
|| (lchown (dst,
(uid == -1) ? statp->st_uid : (uid_t) uid,
(gid == -1) ? statp->st_gid : (gid_t) gid) != 0)) {
free (oldlink);
return -1;
}
@@ -631,12 +524,12 @@ static int copy_symlink (const char *src, const char *dst,
* it returns ENOSYS on many system
* - not implemented
*/
(void) lutimes (dst, mt);
#endif /* HAVE_LUTIMES */
lutimes (dst, mt);
#endif
return 0;
}
#endif /* S_IFLNK */
#endif
/*
* copy_hardlink - copy a hardlink
@@ -645,18 +538,23 @@ static int copy_symlink (const char *src, const char *dst,
*
* Return 0 on success, -1 on error.
*/
static int copy_hardlink (const char *dst,
unused bool reset_selinux,
static int copy_hardlink (const char *src, const char *dst,
struct link_name *lp)
{
/* FIXME: selinux, ACL, Extended Attributes needed? */
/* TODO: selinux needed? */
if (link (lp->ln_name, dst) != 0) {
return -1;
}
/* FIXME: why is it unlinked? This is a copy, not a move */
if (unlink (src) != 0) {
return -1;
}
/* FIXME: idem, although it may never be used again */
/* If the file could be unlinked, decrement the links counter,
* and forget about this link if it was the last reference */
* and delete the file if it was the last reference */
lp->ln_count--;
if (lp->ln_count <= 0) {
remove_link (lp);
@@ -670,46 +568,26 @@ static int copy_hardlink (const char *dst,
*
* Copy a special file from src to dst.
*
* statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
* the access and modification and the access rights.
* statp, mt, uid, gid are used to set the access and modification and the
* access rights.
*
* Return 0 on success, -1 on error.
*/
static int copy_special (const char *src, const char *dst,
bool reset_selinux,
static int copy_special (const char *dst,
const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
long int uid, long int gid)
{
int err = 0;
#ifdef WITH_SELINUX
if (set_selinux_file_context (dst) != 0) {
return -1;
}
#endif /* WITH_SELINUX */
selinux_file_context (dst);
#endif
if ( (mknod (dst, statp->st_mode & ~07777, statp->st_rdev) != 0)
|| (chown_if_needed (dst, statp,
old_uid, new_uid, old_gid, new_gid) != 0)
#ifdef WITH_ACL
|| ( (perm_copy_file (src, dst, &ctx) != 0)
&& (errno != 0))
#else /* !WITH_ACL */
|| (chown (dst,
(uid == -1) ? statp->st_uid : (uid_t) uid,
(gid == -1) ? statp->st_gid : (gid_t) gid) != 0)
|| (chmod (dst, statp->st_mode & 07777) != 0)
#endif /* !WITH_ACL */
#ifdef WITH_ATTR
/*
* If the third parameter is NULL, all extended attributes
* except those that define Access Control Lists are copied.
* ACLs are excluded by default because copying them between
* file systems with and without ACL support needs some
* additional logic so that no unexpected permissions result.
*/
|| ( !reset_selinux
&& (attr_copy_file (src, dst, NULL, &ctx) != 0)
&& (errno != 0))
#endif /* WITH_ATTR */
|| (utimes (dst, mt) != 0)) {
err = -1;
}
@@ -722,16 +600,14 @@ static int copy_special (const char *src, const char *dst,
*
* Copy a file from src to dst.
*
* statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
* the access and modification and the access rights.
* statp, mt, uid, gid are used to set the access and modification and the
* access rights.
*
* Return 0 on success, -1 on error.
*/
static int copy_file (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
long int uid, long int gid)
{
int err = 0;
int ifd;
@@ -744,40 +620,20 @@ static int copy_file (const char *src, const char *dst,
return -1;
}
#ifdef WITH_SELINUX
if (set_selinux_file_context (dst) != 0) {
return -1;
}
#endif /* WITH_SELINUX */
selinux_file_context (dst);
#endif
ofd = open (dst, O_WRONLY | O_CREAT | O_TRUNC, statp->st_mode & 07777);
if ( (ofd < 0)
|| (fchown_if_needed (ofd, statp,
old_uid, new_uid, old_gid, new_gid) != 0)
#ifdef WITH_ACL
|| ( (perm_copy_fd (src, ifd, dst, ofd, &ctx) != 0)
&& (errno != 0))
#else /* !WITH_ACL */
|| (fchmod (ofd, statp->st_mode & 07777) != 0)
#endif /* !WITH_ACL */
#ifdef WITH_ATTR
/*
* If the third parameter is NULL, all extended attributes
* except those that define Access Control Lists are copied.
* ACLs are excluded by default because copying them between
* file systems with and without ACL support needs some
* additional logic so that no unexpected permissions result.
*/
|| ( !reset_selinux
&& (attr_copy_fd (src, ifd, dst, ofd, NULL, &ctx) != 0)
&& (errno != 0))
#endif /* WITH_ATTR */
) {
|| (fchown (ofd,
(uid == -1) ? statp->st_uid : (uid_t) uid,
(gid == -1) ? statp->st_gid : (gid_t) gid) != 0)
|| (fchmod (ofd, statp->st_mode & 07777) != 0)) {
(void) close (ifd);
return -1;
}
while ((cnt = read (ifd, buf, sizeof buf)) > 0) {
if (write (ofd, buf, (size_t)cnt) != cnt) {
(void) close (ifd);
return -1;
}
}
@@ -788,7 +644,7 @@ static int copy_file (const char *src, const char *dst,
if (futimes (ofd, mt) != 0) {
return -1;
}
#endif /* HAVE_FUTIMES */
#endif
if (close (ofd) != 0) {
return -1;
@@ -798,42 +654,97 @@ static int copy_file (const char *src, const char *dst,
if (utimes(dst, mt) != 0) {
return -1;
}
#endif /* !HAVE_FUTIMES */
#endif
return err;
}
#define def_chown_if_needed(chown_function, type_dst) \
static int chown_function ## _if_needed (type_dst dst, \
const struct stat *statp, \
uid_t old_uid, uid_t new_uid, \
gid_t old_gid, gid_t new_gid) \
{ \
uid_t tmpuid = (uid_t) -1; \
gid_t tmpgid = (gid_t) -1; \
\
/* Use new_uid if old_uid is set to -1 or if the file was \
* owned by the user. */ \
if (((uid_t) -1 == old_uid) || (statp->st_uid == old_uid)) { \
tmpuid = new_uid; \
} \
/* Otherwise, or if new_uid was set to -1, we keep the same \
* owner. */ \
if ((uid_t) -1 == tmpuid) { \
tmpuid = statp->st_uid; \
} \
\
if (((gid_t) -1 == old_gid) || (statp->st_gid == old_gid)) { \
tmpgid = new_gid; \
} \
if ((gid_t) -1 == tmpgid) { \
tmpgid = statp->st_gid; \
} \
\
return chown_function (dst, tmpuid, tmpgid); \
/*
* remove_tree - delete a directory tree
*
* remove_tree() walks a directory tree and deletes all the files
* and directories.
* At the end, it deletes the root directory itself.
*/
int remove_tree (const char *root)
{
char *new_name = NULL;
int err = 0;
struct DIRECT *ent;
struct stat sb;
DIR *dir;
/*
* Open the source directory and read each entry. Every file
* entry in the directory is copied with the UID and GID set
* to the provided values. As an added security feature only
* regular files (and directories ...) are copied, and no file
* is made set-ID.
*/
dir = opendir (root);
if (NULL == dir) {
return -1;
}
while ((ent = readdir (dir))) {
size_t new_len = strlen (root) + strlen (ent->d_name) + 2;
/*
* Skip the "." and ".." entries
*/
if (strcmp (ent->d_name, ".") == 0 ||
strcmp (ent->d_name, "..") == 0) {
continue;
}
/*
* Make the filename for the current entry.
*/
if (NULL != new_name) {
free (new_name);
}
new_name = (char *) malloc (new_len);
if (NULL == new_name) {
err = -1;
break;
}
snprintf (new_name, new_len, "%s/%s", root, ent->d_name);
if (LSTAT (new_name, &sb) == -1) {
continue;
}
if (S_ISDIR (sb.st_mode)) {
/*
* Recursively delete this directory.
*/
if (remove_tree (new_name) != 0) {
err = -1;
break;
}
} else {
/*
* Delete the file.
*/
if (unlink (new_name) != 0) {
err = -1;
break;
}
}
}
if (NULL != new_name) {
free (new_name);
}
(void) closedir (dir);
if (0 == err) {
if (rmdir (root) != 0) {
err = -1;
}
}
return err;
}
def_chown_if_needed (chown, const char *)
def_chown_if_needed (lchown, const char *)
def_chown_if_needed (fchown, int)

View File

@@ -115,9 +115,6 @@ void addenv (const char *string, /*@null@*/const char *value)
n = (size_t) (cp - newstring);
/*
* If this environment variable is already set, change its value.
*/
for (i = 0; i < newenvc; i++) {
if ( (strncmp (newstring, newenvp[i], n) == 0)
&& (('=' == newenvp[i][n]) || ('\0' == newenvp[i][n]))) {
@@ -131,15 +128,8 @@ void addenv (const char *string, /*@null@*/const char *value)
return;
}
/*
* Otherwise, save the new environment variable
*/
newenvp[newenvc++] = newstring;
/*
* And extend the environment if needed.
*/
/*
* Check whether newenvc is a multiple of NEWENVP_STEP.
* If so we have to resize the vector.
@@ -153,14 +143,14 @@ void addenv (const char *string, /*@null@*/const char *value)
size_t newsize;
/*
* If the resize operation succeeds we can
* If the resize operation succeds we can
* happily go on, else print a message.
*/
newsize = (newenvc + NEWENVP_STEP) * sizeof (char *);
__newenvp = (char **) realloc (newenvp, newsize);
if (NULL != __newenvp) {
if (__newenvp) {
/*
* If this is our current environment, update
* environ so that it doesn't point to some
@@ -261,7 +251,7 @@ void sanitize_env (void)
if (strncmp (*cur, *bad, strlen (*bad)) != 0) {
continue;
}
if (strchr (*cur, '/') == NULL) {
if (strchr (*cur, '/') != NULL) {
continue; /* OK */
}
for (move = cur; NULL != *move; move++) {

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2002 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2010, Nicolas François
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -273,14 +273,12 @@ void failprint (const struct faillog *fail)
lasttime++;
}
#endif
/*@-formatconst@*/
(void) printf (ngettext ("%d failure since last login.\n"
"Last was %s on %s.\n",
"%d failures since last login.\n"
"Last was %s on %s.\n",
(unsigned long) fail->fail_cnt),
fail->fail_cnt, lasttime, fail->fail_line);
/*@=formatconst@*/
}
/*
@@ -298,7 +296,7 @@ void failtmp (const char *username,
#endif /* !USE_UTMPX */
)
{
const char *ftmp;
char *ftmp;
int fd;
/*

View File

@@ -54,10 +54,6 @@ int valid_field (const char *field, const char *illegal)
const char *cp;
int err = 0;
if (NULL == field) {
return -1;
}
/* For each character of field, search if it appears in the list
* of illegal characters. */
for (cp = field; '\0' != *cp; cp++) {

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 2008 - 2011, Nicolas François
* Copyright (c) 2008 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,7 +32,6 @@
#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include "prototypes.h"
#include "groupio.h"
@@ -53,7 +52,7 @@ int find_new_gid (bool sys_group,
/*@null@*/gid_t const *preferred_gid)
{
const struct group *grp;
gid_t gid_min, gid_max, group_id;
gid_t gid_min, gid_max, group_id, id;
bool *used_gids;
assert (gid != NULL);
@@ -61,30 +60,12 @@ int find_new_gid (bool sys_group,
if (!sys_group) {
gid_min = (gid_t) getdef_ulong ("GID_MIN", 1000UL);
gid_max = (gid_t) getdef_ulong ("GID_MAX", 60000UL);
if (gid_max < gid_min) {
(void) fprintf (stderr,
_("%s: Invalid configuration: GID_MIN (%lu), GID_MAX (%lu)\n"),
Prog, (unsigned long) gid_min, (unsigned long) gid_max);
return -1;
}
} else {
gid_min = (gid_t) getdef_ulong ("SYS_GID_MIN", 101UL);
gid_max = (gid_t) getdef_ulong ("GID_MIN", 1000UL) - 1;
gid_max = (gid_t) getdef_ulong ("SYS_GID_MAX", (unsigned long) gid_max);
if (gid_max < gid_min) {
(void) fprintf (stderr,
_("%s: Invalid configuration: SYS_GID_MIN (%lu), GID_MIN (%lu), SYS_GID_MAX (%lu)\n"),
Prog, (unsigned long) gid_min, getdef_ulong ("GID_MIN", 1000UL), (unsigned long) gid_max);
return -1;
}
}
used_gids = malloc (sizeof (bool) * (gid_max +1));
if (NULL == used_gids) {
fprintf (stderr,
_("%s: failed to allocate memory: %s\n"),
Prog, strerror (errno));
return -1;
}
used_gids = alloca (sizeof (bool) * (gid_max +1));
memset (used_gids, false, sizeof (bool) * (gid_max + 1));
if ( (NULL != preferred_gid)
@@ -96,7 +77,6 @@ int find_new_gid (bool sys_group,
* changes */
&& (gr_locate_gid (*preferred_gid) == NULL)) {
*gid = *preferred_gid;
free (used_gids);
return 0;
}
@@ -110,7 +90,6 @@ int find_new_gid (bool sys_group,
* some groups were created but the changes were not committed yet.
*/
if (sys_group) {
gid_t id;
/* setgrent / getgrent / endgrent can be very slow with
* LDAP configurations (and many accounts).
* Since there is a limited amount of IDs to be tested
@@ -125,7 +104,7 @@ int find_new_gid (bool sys_group,
}
}
(void) gr_rewind ();
gr_rewind ();
while ((grp = gr_next ()) != NULL) {
if ((grp->gr_gid <= group_id) && (grp->gr_gid >= gid_min)) {
group_id = grp->gr_gid - 1;
@@ -149,7 +128,7 @@ int find_new_gid (bool sys_group,
}
endgrent ();
(void) gr_rewind ();
gr_rewind ();
while ((grp = gr_next ()) != NULL) {
if ((grp->gr_gid >= group_id) && (grp->gr_gid <= gid_max)) {
group_id = grp->gr_gid + 1;
@@ -162,47 +141,43 @@ int find_new_gid (bool sys_group,
}
/*
* If a group (resp. system group) with GID equal to GID_MAX (resp.
* GID_MIN) exists, the above algorithm will give us GID_MAX+1
* (resp. GID_MIN-1) even if not unique. Search for the first free
* GID starting with GID_MIN (resp. GID_MAX).
* If a group with GID equal to GID_MAX exists, the above algorithm
* will give us GID_MAX+1 even if not unique. Search for the first
* free GID starting with GID_MIN.
*/
if (sys_group) {
if (group_id < gid_min) {
if (group_id == gid_min - 1) {
for (group_id = gid_max; group_id >= gid_min; group_id--) {
if (false == used_gids[group_id]) {
break;
}
}
if (group_id < gid_min) {
if ( group_id < gid_min ) {
fprintf (stderr,
_("%s: Can't get unique system GID (no more available GIDs)\n"),
Prog);
SYSLOG ((LOG_WARN,
"no more available GID on the system"));
free (used_gids);
return -1;
}
}
} else {
if (group_id > gid_max) {
for (group_id = gid_min; group_id <= gid_max; group_id++) {
if (group_id == gid_max + 1) {
for (group_id = gid_min; group_id < gid_max; group_id++) {
if (false == used_gids[group_id]) {
break;
}
}
if (group_id > gid_max) {
if (group_id == gid_max) {
fprintf (stderr,
_("%s: Can't get unique GID (no more available GIDs)\n"),
Prog);
SYSLOG ((LOG_WARN, "no more available GID on the system"));
free (used_gids);
return -1;
}
}
}
free (used_gids);
*gid = group_id;
return 0;
}

View File

@@ -1,86 +0,0 @@
/*
* Copyright (c) 2012 Eric Biederman
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ifdef ENABLE_SUBIDS
#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include "prototypes.h"
#include "subordinateio.h"
#include "getdef.h"
/*
* find_new_sub_gids - Find a new unused range of GIDs.
*
* If successful, find_new_sub_gids provides a range of unused
* user IDs in the [SUB_GID_MIN:SUB_GID_MAX] range.
*
* Return 0 on success, -1 if no unused GIDs are available.
*/
int find_new_sub_gids (const char *owner,
gid_t *range_start, unsigned long *range_count)
{
unsigned long min, max;
unsigned long count;
gid_t start;
assert (range_start != NULL);
assert (range_count != NULL);
min = getdef_ulong ("SUB_GID_MIN", 100000UL);
max = getdef_ulong ("SUB_GID_MAX", 600100000UL);
count = getdef_ulong ("SUB_GID_COUNT", 65536);
if (min > max || count >= max || (min + count - 1) > max) {
(void) fprintf (stderr,
_("%s: Invalid configuration: SUB_GID_MIN (%lu),"
" SUB_GID_MAX (%lu), SUB_GID_COUNT (%lu)\n"),
Prog, min, max, count);
return -1;
}
start = sub_gid_find_free_range(min, max, count);
if (start == (gid_t)-1) {
fprintf (stderr,
_("%s: Can't get unique subordinate GID range\n"),
Prog);
SYSLOG ((LOG_WARN, "no more available subordinate GIDs on the system"));
return -1;
}
*range_start = start;
*range_count = count;
return 0;
}
#else /* !ENABLE_SUBIDS */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !ENABLE_SUBIDS */

View File

@@ -1,86 +0,0 @@
/*
* Copyright (c) 2012 Eric Biederman
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ifdef ENABLE_SUBIDS
#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include "prototypes.h"
#include "subordinateio.h"
#include "getdef.h"
/*
* find_new_sub_uids - Find a new unused range of UIDs.
*
* If successful, find_new_sub_uids provides a range of unused
* user IDs in the [SUB_UID_MIN:SUB_UID_MAX] range.
*
* Return 0 on success, -1 if no unused UIDs are available.
*/
int find_new_sub_uids (const char *owner,
uid_t *range_start, unsigned long *range_count)
{
unsigned long min, max;
unsigned long count;
uid_t start;
assert (range_start != NULL);
assert (range_count != NULL);
min = getdef_ulong ("SUB_UID_MIN", 100000UL);
max = getdef_ulong ("SUB_UID_MAX", 600100000UL);
count = getdef_ulong ("SUB_UID_COUNT", 65536);
if (min > max || count >= max || (min + count - 1) > max) {
(void) fprintf (stderr,
_("%s: Invalid configuration: SUB_UID_MIN (%lu),"
" SUB_UID_MAX (%lu), SUB_UID_COUNT (%lu)\n"),
Prog, min, max, count);
return -1;
}
start = sub_uid_find_free_range(min, max, count);
if (start == (uid_t)-1) {
fprintf (stderr,
_("%s: Can't get unique subordinate UID range\n"),
Prog);
SYSLOG ((LOG_WARN, "no more available subordinate UIDs on the system"));
return -1;
}
*range_start = start;
*range_count = count;
return 0;
}
#else /* !ENABLE_SUBIDS */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !ENABLE_SUBIDS */

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 2008 - 2011, Nicolas François
* Copyright (c) 2008 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,7 +32,6 @@
#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include "prototypes.h"
#include "pwio.h"
@@ -53,7 +52,7 @@ int find_new_uid (bool sys_user,
/*@null@*/uid_t const *preferred_uid)
{
const struct passwd *pwd;
uid_t uid_min, uid_max, user_id;
uid_t uid_min, uid_max, user_id, id;
bool *used_uids;
assert (uid != NULL);
@@ -61,30 +60,12 @@ int find_new_uid (bool sys_user,
if (!sys_user) {
uid_min = (uid_t) getdef_ulong ("UID_MIN", 1000UL);
uid_max = (uid_t) getdef_ulong ("UID_MAX", 60000UL);
if (uid_max < uid_min) {
(void) fprintf (stderr,
_("%s: Invalid configuration: UID_MIN (%lu), UID_MAX (%lu)\n"),
Prog, (unsigned long) uid_min, (unsigned long) uid_max);
return -1;
}
} else {
uid_min = (uid_t) getdef_ulong ("SYS_UID_MIN", 101UL);
uid_max = (uid_t) getdef_ulong ("UID_MIN", 1000UL) - 1;
uid_max = (uid_t) getdef_ulong ("SYS_UID_MAX", (unsigned long) uid_max);
if (uid_max < uid_min) {
(void) fprintf (stderr,
_("%s: Invalid configuration: SYS_UID_MIN (%lu), UID_MIN (%lu), SYS_UID_MAX (%lu)\n"),
Prog, (unsigned long) uid_min, getdef_ulong ("UID_MIN", 1000UL), (unsigned long) uid_max);
return -1;
}
}
used_uids = malloc (sizeof (bool) * (uid_max +1));
if (NULL == used_uids) {
fprintf (stderr,
_("%s: failed to allocate memory: %s\n"),
Prog, strerror (errno));
return -1;
}
used_uids = alloca (sizeof (bool) * (uid_max +1));
memset (used_uids, false, sizeof (bool) * (uid_max + 1));
if ( (NULL != preferred_uid)
@@ -96,7 +77,6 @@ int find_new_uid (bool sys_user,
* changes */
&& (pw_locate_uid (*preferred_uid) == NULL)) {
*uid = *preferred_uid;
free (used_uids);
return 0;
}
@@ -110,7 +90,6 @@ int find_new_uid (bool sys_user,
* some users were created but the changes were not committed yet.
*/
if (sys_user) {
uid_t id;
/* setpwent / getpwent / endpwent can be very slow with
* LDAP configurations (and many accounts).
* Since there is a limited amount of IDs to be tested
@@ -125,7 +104,7 @@ int find_new_uid (bool sys_user,
}
}
(void) pw_rewind ();
pw_rewind ();
while ((pwd = pw_next ()) != NULL) {
if ((pwd->pw_uid <= user_id) && (pwd->pw_uid >= uid_min)) {
user_id = pwd->pw_uid - 1;
@@ -149,7 +128,7 @@ int find_new_uid (bool sys_user,
}
endpwent ();
(void) pw_rewind ();
pw_rewind ();
while ((pwd = pw_next ()) != NULL) {
if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) {
user_id = pwd->pw_uid + 1;
@@ -162,13 +141,12 @@ int find_new_uid (bool sys_user,
}
/*
* If a user (resp. system user) with UID equal to UID_MAX (resp.
* UID_MIN) exists, the above algorithm will give us UID_MAX+1
* (resp. UID_MIN-1) even if not unique. Search for the first free
* UID starting with UID_MIN (resp. UID_MAX).
* If a user with UID equal to UID_MAX exists, the above algorithm
* will give us UID_MAX+1 even if not unique. Search for the first
* free UID starting with UID_MIN.
*/
if (sys_user) {
if (user_id < uid_min) {
if (user_id == uid_min - 1) {
for (user_id = uid_max; user_id >= uid_min; user_id--) {
if (false == used_uids[user_id]) {
break;
@@ -180,29 +158,26 @@ int find_new_uid (bool sys_user,
Prog);
SYSLOG ((LOG_WARN,
"no more available UID on the system"));
free (used_uids);
return -1;
}
}
} else {
if (user_id > uid_max) {
for (user_id = uid_min; user_id <= uid_max; user_id++) {
if (user_id == uid_max + 1) {
for (user_id = uid_min; user_id < uid_max; user_id++) {
if (false == used_uids[user_id]) {
break;
}
}
if (user_id > uid_max) {
if (user_id == uid_max) {
fprintf (stderr,
_("%s: Can't get unique UID (no more available UIDs)\n"),
Prog);
SYSLOG ((LOG_WARN, "no more available UID on the system"));
free (used_uids);
return -1;
}
}
}
free (used_uids);
*uid = user_id;
return 0;
}

View File

@@ -35,5 +35,5 @@
#include <config.h>
#include "defines.h"
time_t get_date (const char *p, /*@null@*/const time_t *now);
time_t get_date (const char *, const time_t *);
#endif

View File

@@ -44,7 +44,7 @@
* The string may be a valid GID or a valid groupname.
* If the group does not exist on the system, NULL is returned.
*/
extern /*@only@*//*@null@*/struct group *getgr_nam_gid (/*@null@*/const char *grname)
extern /*@null@*/struct group *getgr_nam_gid (const char *grname)
{
long long int gid;
char *endptr;

View File

@@ -3,7 +3,7 @@
* Copyright (c) 1991 - 1993, Chip Rosenthal
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2010, Nicolas François
* Copyright (c) 2008 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -50,7 +50,7 @@
bool hushed (const char *username)
{
struct passwd *pw;
const char *hushfile;
char *hushfile;
char buf[BUFSIZ];
bool found;
FILE *fp;
@@ -76,7 +76,7 @@ bool hushed (const char *username)
*/
if (hushfile[0] != '/') {
(void) snprintf (buf, sizeof (buf), "%s/%s", pw->pw_dir, hushfile);
snprintf (buf, sizeof (buf), "%s/%s", pw->pw_dir, hushfile);
return (access (buf, F_OK) == 0);
}

View File

@@ -1,164 +0,0 @@
/*
* Copyright (c) 2013 Eric Biederman
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include "prototypes.h"
#include "idmapping.h"
struct map_range *get_map_ranges(int ranges, int argc, char **argv)
{
struct map_range *mappings, *mapping;
int idx, argidx;
if (ranges < 0 || argc < 0) {
fprintf(stderr, "%s: error calculating number of arguments\n", Prog);
return NULL;
}
if (ranges != ((argc + 2) / 3)) {
fprintf(stderr, "%s: ranges: %u is wrong for argc: %d\n", Prog, ranges, argc);
return NULL;
}
if ((ranges * 3) > argc) {
fprintf(stderr, "ranges: %u argc: %d\n",
ranges, argc);
fprintf(stderr,
_( "%s: Not enough arguments to form %u mappings\n"),
Prog, ranges);
return NULL;
}
mappings = calloc(ranges, sizeof(*mappings));
if (!mappings) {
fprintf(stderr, _( "%s: Memory allocation failure\n"),
Prog);
exit(EXIT_FAILURE);
}
/* Gather up the ranges from the command line */
mapping = mappings;
for (idx = 0, argidx = 0; idx < ranges; idx++, argidx += 3, mapping++) {
if (!getulong(argv[argidx + 0], &mapping->upper)) {
free(mappings);
return NULL;
}
if (!getulong(argv[argidx + 1], &mapping->lower)) {
free(mappings);
return NULL;
}
if (!getulong(argv[argidx + 2], &mapping->count)) {
free(mappings);
return NULL;
}
if (ULONG_MAX - mapping->upper <= mapping->count || ULONG_MAX - mapping->lower <= mapping->count) {
fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog);
exit(EXIT_FAILURE);
}
if (mapping->upper > UINT_MAX ||
mapping->lower > UINT_MAX ||
mapping->count > UINT_MAX) {
fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog);
exit(EXIT_FAILURE);
}
if (mapping->lower + mapping->count > UINT_MAX ||
mapping->upper + mapping->count > UINT_MAX) {
fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog);
exit(EXIT_FAILURE);
}
if (mapping->lower + mapping->count < mapping->lower ||
mapping->upper + mapping->count < mapping->upper) {
/* this one really shouldn't be possible given previous checks */
fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog);
exit(EXIT_FAILURE);
}
}
return mappings;
}
/* Number of ascii digits needed to print any unsigned long in decimal.
* There are approximately 10 bits for every 3 decimal digits.
* So from bits to digits the formula is roundup((Number of bits)/10) * 3.
* For common sizes of integers this works out to:
* 2bytes --> 6 ascii estimate -> 65536 (5 real)
* 4bytes --> 12 ascii estimated -> 4294967296 (10 real)
* 8bytes --> 21 ascii estimated -> 18446744073709551616 (20 real)
* 16bytes --> 39 ascii estimated -> 340282366920938463463374607431768211456 (39 real)
*/
#define ULONG_DIGITS ((((sizeof(unsigned long) * CHAR_BIT) + 9)/10)*3)
void write_mapping(int proc_dir_fd, int ranges, struct map_range *mappings,
const char *map_file)
{
int idx;
struct map_range *mapping;
size_t bufsize;
char *buf, *pos;
int fd;
bufsize = ranges * ((ULONG_DIGITS + 1) * 3);
pos = buf = xmalloc(bufsize);
/* Build the mapping command */
mapping = mappings;
for (idx = 0; idx < ranges; idx++, mapping++) {
/* Append this range to the string that will be written */
int written = snprintf(pos, bufsize - (pos - buf),
"%lu %lu %lu\n",
mapping->upper,
mapping->lower,
mapping->count);
if ((written <= 0) || (written >= (bufsize - (pos - buf)))) {
fprintf(stderr, _("%s: snprintf failed!\n"), Prog);
exit(EXIT_FAILURE);
}
pos += written;
}
/* Write the mapping to the maping file */
fd = openat(proc_dir_fd, map_file, O_WRONLY);
if (fd < 0) {
fprintf(stderr, _("%s: open of %s failed: %s\n"),
Prog, map_file, strerror(errno));
exit(EXIT_FAILURE);
}
if (write(fd, buf, pos - buf) != (pos - buf)) {
fprintf(stderr, _("%s: write to %s failed: %s\n"),
Prog, map_file, strerror(errno));
exit(EXIT_FAILURE);
}
close(fd);
}

View File

@@ -107,7 +107,7 @@ int isexpired (const struct passwd *pw, /*@null@*/const struct spwd *sp)
if ( (-1 == sp->sp_lstchg)
|| (-1 == sp->sp_max)
|| (sp->sp_max >= ((10000L * DAY) / SCALE))) {
|| (sp->sp_max >= (10000L * DAY / SCALE))) {
return 0;
}

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1999, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,7 +33,6 @@
/*
* Separated from setup.c. --marekm
* Resource limits thanks to Cristian Gafton.
* Enhancements of resource limit code by Thomas Orgis <thomas@orgis.org>
*/
#include <config.h>
@@ -45,7 +44,6 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <ctype.h>
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
@@ -66,46 +64,22 @@
* value - string value to be read
* multiplier - value*multiplier is the actual limit
*/
static int setrlimit_value (unsigned int resource,
const char *value,
unsigned int multiplier)
static int
setrlimit_value (unsigned int resource, const char *value,
unsigned int multiplier)
{
struct rlimit rlim;
rlim_t limit;
long limit;
/* The "-" is special, not belonging to a strange negative limit.
* It is infinity, in a controlled way.
*/
if ('-' == value[0]) {
limit = RLIM_INFINITY;
if (getlong (value, &limit) == 0) {
return 0;
}
else {
/* We cannot use getlong here because it fails when there
* is more to the value than just this number!
* Also, we are limited to base 10 here (hex numbers will not
* work with the limit string parser as is anyway)
*/
char *endptr;
long longlimit = strtol (value, &endptr, 10);
if ((0 == longlimit) && (value == endptr)) {
/* No argument at all. No-op.
* FIXME: We could instead throw an error, though.
*/
return 0;
}
longlimit *= multiplier;
limit = (rlim_t)longlimit;
if (longlimit != limit)
{
/* FIXME: Again, silent error handling...
* Wouldn't screaming make more sense?
*/
return 0;
}
limit *= multiplier;
if (limit != (rlim_t) limit) {
return 0;
}
rlim.rlim_cur = limit;
rlim.rlim_max = limit;
rlim.rlim_cur = (rlim_t) limit;
rlim.rlim_max = (rlim_t) limit;
if (setrlimit (resource, &rlim) != 0) {
return LOGIN_ERROR_RLIMIT;
}
@@ -164,12 +138,11 @@ static int check_logins (const char *name, const char *maxlogins)
count = 0;
#ifdef USE_UTMPX
setutxent ();
while ((ut = getutxent ()))
while ((ut = getutxent ())) {
#else /* !USE_UTMPX */
setutent ();
while ((ut = getutent ()))
while ((ut = getutent ())) {
#endif /* !USE_UTMPX */
{
if (USER_PROCESS != ut->ut_type) {
continue;
}
@@ -194,9 +167,8 @@ static int check_logins (const char *name, const char *maxlogins)
* includes the user who is currently trying to log in.
*/
if (count > limit) {
SYSLOG ((LOG_WARN,
"Too many logins (max %lu) for %s\n",
limit, name));
SYSLOG ((LOG_WARN, "Too many logins (max %d) for %s\n",
limit, name));
return LOGIN_ERROR_LOGIN;
}
return 0;
@@ -214,20 +186,17 @@ static int check_logins (const char *name, const char *maxlogins)
* [Cc]: c = RLIMIT_CORE max core file size (KB)
* [Dd]: d = RLIMIT_DATA max data size (KB)
* [Ff]: f = RLIMIT_FSIZE max file size (KB)
* [Ii]: i = RLIMIT_NICE max nice value (0..39 translates to 20..-19)
* [Kk]: k = file creation masK (umask)
* [Ll]: l = max number of logins for this user
* [Mm]: m = RLIMIT_MEMLOCK max locked-in-memory address space (KB)
* [Nn]: n = RLIMIT_NOFILE max number of open files
* [Oo]: o = RLIMIT_RTPRIO max real time priority (linux/sched.h 0..MAX_RT_PRIO)
* [Pp]: p = process priority -20..20 (negative = high, positive = low)
* [Rr]: r = RLIMIT_RSS max resident set size (KB)
* [Ss]: s = RLIMIT_STACK max stack size (KB)
* [Tt]: t = RLIMIT_CPU max CPU time (MIN)
* [Uu]: u = RLIMIT_NPROC max number of processes
*
* NOTE: Remember to extend the "no-limits" string below when adding a new
* limit...
* [Kk]: k = file creation masK (umask)
* [Ll]: l = max number of logins for this user
* [Pp]: p = process priority -20..20 (negative = high, positive = low)
* [Ii]: i = RLIMIT_NICE max nice value (0..39 translates to 20..-19)
* [Oo]: o = RLIMIT_RTPRIO max real time priority (linux/sched.h 0..MAX_RT_PRIO)
*
* Return value:
* 0 = okay, of course
@@ -244,24 +213,6 @@ static int do_user_limits (const char *buf, const char *name)
bool reported = false;
pp = buf;
/* Skip leading whitespace. */
while ((' ' == *pp) || ('\t' == *pp)) {
pp++;
}
/* The special limit string "-" results in no limit for all known
* limits.
* We achieve that by parsing a full limit string, parts of it
* being ignored if a limit type is not known to the system.
* Though, there will be complaining for unknown limit types.
*/
if (strcmp (pp, "-") == 0) {
/* Remember to extend this, too, when adding new limits!
* Oh... but "unlimited" does not make sense for umask,
* or does it? (K-)
*/
pp = "A- C- D- F- I- L- M- N- O- P- R- S- T- U-";
}
while ('\0' != *pp) {
switch (*pp++) {
@@ -272,11 +223,11 @@ static int do_user_limits (const char *buf, const char *name)
retval |= setrlimit_value (RLIMIT_AS, pp, 1024);
break;
#endif
#ifdef RLIMIT_CORE
case 'c':
case 'C':
/* RLIMIT_CORE - max core file size (KB) */
retval |= setrlimit_value (RLIMIT_CORE, pp, 1024);
#ifdef RLIMIT_CPU
case 't':
case 'T':
/* RLIMIT_CPU - max CPU time (MIN) */
retval |= setrlimit_value (RLIMIT_CPU, pp, 60);
break;
#endif
#ifdef RLIMIT_DATA
@@ -293,22 +244,20 @@ static int do_user_limits (const char *buf, const char *name)
retval |= setrlimit_value (RLIMIT_FSIZE, pp, 1024);
break;
#endif
#ifdef RLIMIT_NICE
case 'i':
case 'I':
/* RLIMIT_NICE - max scheduling priority (0..39) */
retval |= setrlimit_value (RLIMIT_NICE, pp, 1);
#ifdef RLIMIT_NPROC
case 'u':
case 'U':
/* RLIMIT_NPROC - max number of processes */
retval |= setrlimit_value (RLIMIT_NPROC, pp, 1);
break;
#endif
case 'k':
case 'K':
retval |= set_umask (pp);
break;
case 'l':
case 'L':
/* LIMIT the number of concurrent logins */
retval |= check_logins (name, pp);
#ifdef RLIMIT_CORE
case 'c':
case 'C':
/* RLIMIT_CORE - max core file size (KB) */
retval |= setrlimit_value (RLIMIT_CORE, pp, 1024);
break;
#endif
#ifdef RLIMIT_MEMLOCK
case 'm':
case 'M':
@@ -323,17 +272,6 @@ static int do_user_limits (const char *buf, const char *name)
retval |= setrlimit_value (RLIMIT_NOFILE, pp, 1);
break;
#endif
#ifdef RLIMIT_RTPRIO
case 'o':
case 'O':
/* RLIMIT_RTPRIO - max real time priority (0..MAX_RT_PRIO) */
retval |= setrlimit_value (RLIMIT_RTPRIO, pp, 1);
break;
#endif
case 'p':
case 'P':
retval |= set_prio (pp);
break;
#ifdef RLIMIT_RSS
case 'r':
case 'R':
@@ -348,28 +286,35 @@ static int do_user_limits (const char *buf, const char *name)
retval |= setrlimit_value (RLIMIT_STACK, pp, 1024);
break;
#endif
#ifdef RLIMIT_CPU
case 't':
case 'T':
/* RLIMIT_CPU - max CPU time (MIN) */
retval |= setrlimit_value (RLIMIT_CPU, pp, 60);
#ifdef RLIMIT_NICE
case 'i':
case 'I':
/* RLIMIT_NICE - max scheduling priority (0..39) */
retval |= setrlimit_value (RLIMIT_NICE, pp, 1);
break;
#endif
#ifdef RLIMIT_NPROC
case 'u':
case 'U':
/* RLIMIT_NPROC - max number of processes */
retval |= setrlimit_value (RLIMIT_NPROC, pp, 1);
#ifdef RLIMIT_RTPRIO
case 'o':
case 'O':
/* RLIMIT_RTPRIO - max real time priority (0..MAX_RT_PRIO) */
retval |= setrlimit_value (RLIMIT_RTPRIO, pp, 1);
break;
#endif
case 'k':
case 'K':
retval |= set_umask (pp);
break;
case 'l':
case 'L':
/* LIMIT the number of concurrent logins */
retval |= check_logins (name, pp);
break;
case 'p':
case 'P':
retval |= set_prio (pp);
break;
default:
/* Only report invalid strings once */
/* Note: A string can be invalid just because a
* specific (theoretically valid) setting is not
* supported by this build.
* It is just a warning in syslog anyway. The line
* is still processed
*/
if (!reported) {
SYSLOG ((LOG_WARN,
"Invalid limit string: '%s'",
@@ -378,51 +323,13 @@ static int do_user_limits (const char *buf, const char *name)
retval |= LOGIN_ERROR_RLIMIT;
}
}
/* After parsing one limit setting (or just complaining
* about it), one still needs to skip its argument to
* prevent a bogus warning on trying to parse that as
* limit specification.
* So, let's skip all digits, "-" and our limited set of
* whitespace.
*/
while ( isdigit (*pp)
|| ('-' == *pp)
|| (' ' == *pp)
|| ('\t' ==*pp)) {
pp++;
}
}
return retval;
}
/* Check if user uname is in the group gname.
* Can I be sure that gr_mem contains no UID as string?
* Returns true when user is in the group, false when not.
* Any error is treated as false.
*/
static bool user_in_group (const char *uname, const char *gname)
{
struct group *groupdata;
if (uname == NULL || gname == NULL){
return false;
}
/* We are not claiming to be re-entrant!
* In case of paranoia or a multithreaded login program,
* one needs to add some mess for getgrnam_r. */
groupdata = getgrnam (gname);
if (NULL == groupdata) {
SYSLOG ((LOG_WARN, "Nonexisting group `%s' in limits file.",
gname));
return false;
}
return is_on_list (groupdata->gr_mem, uname);
}
static int setup_user_limits (const char *uname)
{
/* TODO: allow and use @group syntax --cristiang */
FILE *fil;
char buf[1024];
char name[1024];
@@ -444,10 +351,8 @@ static int setup_user_limits (const char *uname)
}
/* The limits file have the following format:
* - '#' (comment) chars only as first chars on a line;
* - username must start on first column (or *, or @group)
*
* FIXME: A better (smarter) checking should be done
*/
* - username must start on first column
* A better (smarter) checking should be done --cristiang */
while (fgets (buf, 1024, fil) != NULL) {
if (('#' == buf[0]) || ('\n' == buf[0])) {
continue;
@@ -459,35 +364,15 @@ static int setup_user_limits (const char *uname)
* username L2 D2048 R4096
* where spaces={' ',\t}. Also, we reject invalid limits.
* Imposing a limit should be done with care, so a wrong
* entry means no care anyway :-).
*
* A '-' as a limits strings means no limits
*
* The username can also be:
* '*': the default limits (only the last is taken into
* account)
* @group: the limit applies to the members of the group
*
* To clarify: The first entry with matching user name rules,
* everything after it is ignored. If there is no user entry,
* the last encountered entry for a matching group rules.
* If there is no matching group entry, the default limits rule.
*/
if (sscanf (buf, "%s%[ACDFIKLMNOPRSTUacdfiklmnoprstu0-9 \t-]",
name, tempbuf) == 2) {
* entry means no care anyway :-). A '-' as a limits
* strings means no limits --cristiang */
if (sscanf (buf, "%s%[ACDFMNRSTULPIOacdfmnrstulpio0-9 \t-]",
name, tempbuf) == 2) {
if (strcmp (name, uname) == 0) {
strcpy (limits, tempbuf);
break;
} else if (strcmp (name, "*") == 0) {
strcpy (deflimits, tempbuf);
} else if (name[0] == '@') {
/* If the user is in the group, the group
* limits apply unless later a line for
* the specific user is found.
*/
if (user_in_group (uname, name+1)) {
strcpy (limits, tempbuf);
}
}
}
}
@@ -507,6 +392,7 @@ static int setup_user_limits (const char *uname)
static void setup_usergroups (const struct passwd *info)
{
const struct group *grp;
mode_t tmpmask;
/*
* if not root, and UID == GID, and username is the same as primary
@@ -518,7 +404,6 @@ static void setup_usergroups (const struct passwd *info)
grp = getgrgid (info->pw_gid);
if ( (NULL != grp)
&& (strcmp (info->pw_name, grp->gr_name) == 0)) {
mode_t tmpmask;
tmpmask = umask (0777);
tmpmask = (tmpmask & ~070) | ((tmpmask >> 3) & 070);
(void) umask (tmpmask);
@@ -547,7 +432,8 @@ void setup_limits (const struct passwd *info)
if (getdef_bool ("QUOTAS_ENAB")) {
#ifdef LIMITS
if (info->pw_uid != 0) {
if ((setup_user_limits (info->pw_name) & LOGIN_ERROR_LOGIN) != 0) {
if (setup_user_limits (info->pw_name) &
LOGIN_ERROR_LOGIN) {
(void) fputs (_("Too many logins.\n"), stderr);
(void) sleep (2); /* XXX: Should be FAIL_DELAY */
exit (EXIT_FAILURE);

View File

@@ -141,12 +141,6 @@
return tmp;
}
/*
* Duplicate a list.
* The input list is not modified, but in order to allow the use of this
* function with list of members, the list elements are not enforced to be
* constant strings here.
*/
/*@only@*/ /*@out@*/char **dup_list (char *const *list)
{
int i;
@@ -169,12 +163,6 @@
return tmp;
}
/*
* Check if member is part of the input list
* The input list is not modified, but in order to allow the use of this
* function with list of members, the list elements are not enforced to be
* constant strings here.
*/
bool is_on_list (char *const *list, const char *member)
{
assert (NULL != member);
@@ -199,7 +187,7 @@ bool is_on_list (char *const *list, const char *member)
char *members;
char **array;
int i;
char *cp;
const char *cp;
char *cp2;
assert (NULL != comma);

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1993, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2011, Nicolas François
* Copyright (c) 2008 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -60,6 +60,7 @@ void login_prompt (const char *prompt, char *name, int namesize)
#define MAX_ENV 32
char *envp[MAX_ENV];
int envc;
char *cp;
int i;
FILE *fp;
@@ -87,9 +88,9 @@ void login_prompt (const char *prompt, char *name, int namesize)
*/
if (NULL != prompt) {
const char *fname = getdef_str ("ISSUE_FILE");
if (NULL != fname) {
fp = fopen (fname, "r");
cp = getdef_str ("ISSUE_FILE");
if (NULL != cp) {
fp = fopen (cp, "r");
if (NULL != fp) {
while ((i = getc (fp)) != EOF) {
(void) putc (i, stdout);
@@ -98,7 +99,7 @@ void login_prompt (const char *prompt, char *name, int namesize)
(void) fclose (fp);
}
}
(void) gethostname (buf, sizeof buf);
gethostname (buf, sizeof buf);
printf (prompt, buf);
(void) fflush (stdout);
}
@@ -147,7 +148,6 @@ void login_prompt (const char *prompt, char *name, int namesize)
if ('\0' != *cp) { /* process new variables */
char *nvar;
int count = 1;
int envc;
for (envc = 0; envc < MAX_ENV; envc++) {
nvar = strtok ((0 != envc) ? (char *) 0 : cp, " \t,");
@@ -158,9 +158,10 @@ void login_prompt (const char *prompt, char *name, int namesize)
envp[envc] = nvar;
} else {
size_t len = strlen (nvar) + 32;
int wlen;
envp[envc] = xmalloc (len);
(void) snprintf (envp[envc], len,
"L%d=%s", count++, nvar);
wlen = snprintf (envp[envc], len, "L%d=%s", count++, nvar);
assert (wlen == (int) len -1);
}
}
set_env (envc, envp);

View File

@@ -2,7 +2,6 @@
* Copyright (c) 1989 - 1991, Julianne Frances Haugh
* Copyright (c) 1996 - 1997, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2010 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -48,34 +47,21 @@
void motd (void)
{
FILE *fp;
char *motdlist;
const char *motdfile;
char *mb;
char motdlist[BUFSIZ], *motdfile, *mb;
register int c;
motdfile = getdef_str ("MOTD_FILE");
if (NULL == motdfile) {
if ((mb = getdef_str ("MOTD_FILE")) == NULL)
return;
}
motdlist = xstrdup (motdfile);
strncpy (motdlist, mb, sizeof (motdlist));
motdlist[sizeof (motdlist) - 1] = '\0';
for (mb = motdlist; ;mb = NULL) {
motdfile = strtok (mb, ":");
if (NULL == motdfile) {
break;
}
fp = fopen (motdfile, "r");
if (NULL != fp) {
while ((c = getc (fp)) != EOF) {
for (mb = motdlist; (motdfile = strtok (mb, ":")) != NULL; mb = NULL) {
if ((fp = fopen (motdfile, "r")) != NULL) {
while ((c = getc (fp)) != EOF)
putchar (c);
}
fclose (fp);
}
}
fflush (stdout);
free (motdlist);
}

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1999, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -69,7 +69,7 @@ static bool palindrome (unused const char *old, const char *new)
* more than half of the characters are different ones.
*/
static bool similar (/*@notnull@*/const char *old, /*@notnull@*/const char *new)
static bool similar (const char *old, const char *new)
{
int i, j;
@@ -100,7 +100,7 @@ static bool similar (/*@notnull@*/const char *old, /*@notnull@*/const char *new)
* a nice mix of characters.
*/
static bool simple (unused const char *old, const char *new)
static int simple (unused const char *old, const char *new)
{
bool digits = false;
bool uppers = false;
@@ -147,7 +147,7 @@ static bool simple (unused const char *old, const char *new)
return true;
}
static char *str_lower (/*@returned@*/char *string)
static char *str_lower (char *string)
{
char *cp;
@@ -157,10 +157,8 @@ static char *str_lower (/*@returned@*/char *string)
return string;
}
static /*@observer@*//*@null@*/const char *password_check (
/*@notnull@*/const char *old,
/*@notnull@*/const char *new,
/*@notnull@*/const struct passwd *pwdp)
static const char *password_check (const char *old, const char *new,
const struct passwd *pwdp)
{
const char *msg = NULL;
char *oldmono, *newmono, *wrapped;
@@ -221,15 +219,14 @@ static /*@observer@*//*@null@*/const char *password_check (
return msg;
}
static /*@observer@*//*@null@*/const char *obscure_msg (
/*@notnull@*/const char *old,
/*@notnull@*/const char *new,
/*@notnull@*/const struct passwd *pwdp)
/*ARGSUSED*/
static const char *obscure_msg (const char *old, const char *new,
const struct passwd *pwdp)
{
size_t maxlen, oldlen, newlen;
char *new1, *old1;
const char *msg;
const char *result;
char *result;
oldlen = strlen (old);
newlen = strlen (new);
@@ -307,15 +304,15 @@ static /*@observer@*//*@null@*/const char *obscure_msg (
* check passwords.
*/
bool obscure (const char *old, const char *new, const struct passwd *pwdp)
int obscure (const char *old, const char *new, const struct passwd *pwdp)
{
const char *msg = obscure_msg (old, new, pwdp);
if (NULL != msg) {
printf (_("Bad password: %s. "), msg);
return false;
return 0;
}
return true;
return 1;
}
#else /* !USE_PAM */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009 - 2010, Nicolas François
* Copyright (c) 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,7 +39,7 @@
#include <security/pam_appl.h>
#include "prototypes.h"
/*@null@*/ /*@only@*/static const char *non_interactive_password = NULL;
/*@null@*/ /*@only@*/static char *non_interactive_password = NULL;
static int ni_conv (int num_msg,
const struct pam_message **msg,
struct pam_response **resp,

View File

@@ -1,133 +0,0 @@
/*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2001, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id$"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include "prototypes.h"
#include "defines.h"
/*
* remove_tree - delete a directory tree
*
* remove_tree() walks a directory tree and deletes all the files
* and directories.
* At the end, it deletes the root directory itself.
*/
int remove_tree (const char *root, bool remove_root)
{
char *new_name = NULL;
int err = 0;
struct DIRECT *ent;
struct stat sb;
DIR *dir;
/*
* Open the source directory and read each entry. Every file
* entry in the directory is copied with the UID and GID set
* to the provided values. As an added security feature only
* regular files (and directories ...) are copied, and no file
* is made set-ID.
*/
dir = opendir (root);
if (NULL == dir) {
return -1;
}
while ((ent = readdir (dir))) {
size_t new_len = strlen (root) + strlen (ent->d_name) + 2;
/*
* Skip the "." and ".." entries
*/
if (strcmp (ent->d_name, ".") == 0 ||
strcmp (ent->d_name, "..") == 0) {
continue;
}
/*
* Make the filename for the current entry.
*/
free (new_name);
new_name = (char *) malloc (new_len);
if (NULL == new_name) {
err = -1;
break;
}
(void) snprintf (new_name, new_len, "%s/%s", root, ent->d_name);
if (LSTAT (new_name, &sb) == -1) {
continue;
}
if (S_ISDIR (sb.st_mode)) {
/*
* Recursively delete this directory.
*/
if (remove_tree (new_name, true) != 0) {
err = -1;
break;
}
} else {
/*
* Delete the file.
*/
if (unlink (new_name) != 0) {
err = -1;
break;
}
}
}
if (NULL != new_name) {
free (new_name);
}
(void) closedir (dir);
if (remove_root && (0 == err)) {
if (rmdir (root) != 0) {
err = -1;
}
}
return err;
}

View File

@@ -1,124 +0,0 @@
/*
* Copyright (c) 2011 , Julian Pidancet
* Copyright (c) 2011 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id$"
#include <stdio.h>
#include <assert.h>
#include "defines.h"
#include "prototypes.h"
/*@-exitarg@*/
#include "exitcodes.h"
static void change_root (const char* newroot);
/*
* process_root_flag - chroot if given the --root option
*
* This shall be called before accessing the passwd, group, shadow,
* gshadow, useradd's default, login.defs files (non exhaustive list)
* or authenticating the caller.
*
* The audit, syslog, or locale files shall be open before
*/
extern void process_root_flag (const char* short_opt, int argc, char **argv)
{
/*
* Parse the command line options.
*/
int i;
const char *newroot = NULL;
for (i = 0; i < argc; i++) {
if ( (strcmp (argv[i], "--root") == 0)
|| (strcmp (argv[i], short_opt) == 0)) {
if (NULL != newroot) {
fprintf (stderr,
_("%s: multiple --root options\n"),
Prog);
exit (E_BAD_ARG);
}
if (i + 1 == argc) {
fprintf (stderr,
_("%s: option '%s' requires an argument\n"),
Prog, argv[i]);
exit (E_BAD_ARG);
}
newroot = argv[i + 1];
}
}
if (NULL != newroot) {
change_root (newroot);
}
}
static void change_root (const char* newroot)
{
/* Drop privileges */
if ( (setregid (getgid (), getgid ()) != 0)
|| (setreuid (getuid (), getuid ()) != 0)) {
fprintf (stderr, _("%s: failed to drop privileges (%s)\n"),
Prog, strerror (errno));
exit (EXIT_FAILURE);
}
if ('/' != newroot[0]) {
fprintf (stderr,
_("%s: invalid chroot path '%s'\n"),
Prog, newroot);
exit (E_BAD_ARG);
}
if (access (newroot, F_OK) != 0) {
fprintf(stderr,
_("%s: cannot access chroot directory %s: %s\n"),
Prog, newroot, strerror (errno));
exit (E_BAD_ARG);
}
if (chdir (newroot) != 0) {
fprintf(stderr,
_("%s: cannot chdir to chroot directory %s: %s\n"),
Prog, newroot, strerror (errno));
exit (E_BAD_ARG);
}
if (chroot (newroot) != 0) {
fprintf(stderr,
_("%s: unable to chroot to directory %s: %s\n"),
Prog, newroot, strerror (errno));
exit (E_BAD_ARG);
}
}

View File

@@ -23,7 +23,7 @@
static void seedRNG (void);
static /*@observer@*/const char *gensalt (size_t salt_size);
#ifdef USE_SHA_CRYPT
static long shadow_random (long min, long max);
static size_t SHA_salt_size (void);
static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds);
#endif /* USE_SHA_CRYPT */
@@ -81,29 +81,17 @@ static void seedRNG (void)
#define MAGNUM(array,ch) (array)[0]=(array)[2]='$',(array)[1]=(ch),(array)[3]='\0'
#ifdef USE_SHA_CRYPT
/* It is not clear what is the maximum value of random().
* We assume 2^31-1.*/
#define RANDOM_MAX 0x7FFFFFFF
/*
* Return a random number between min and max (both included).
*
* It favors slightly the higher numbers.
* Return the salt size.
* The size of the salt string is between 8 and 16 bytes for the SHA crypt
* methods.
*/
static long shadow_random (long min, long max)
static size_t SHA_salt_size (void)
{
double drand;
long ret;
double rand_size;
seedRNG ();
drand = (double) (max - min + 1) * random () / RANDOM_MAX;
/* On systems were this is not random() range is lower, we favor
* higher numbers of salt. */
ret = (long) (max + 1 - drand);
/* And we catch limits, and use the highest number */
if ((ret < min) || (ret > max)) {
ret = max;
}
return ret;
rand_size = (double) 9.0 * random () / RAND_MAX;
return (size_t) (8 + rand_size);
}
/* Default number of rounds if not explicitly specified. */
@@ -118,12 +106,13 @@ static long shadow_random (long min, long max)
*/
static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds)
{
static char rounds_prefix[18]; /* Max size: rounds=999999999$ */
static char rounds_prefix[18];
long rounds;
if (NULL == prefered_rounds) {
long min_rounds = getdef_long ("SHA_CRYPT_MIN_ROUNDS", -1);
long max_rounds = getdef_long ("SHA_CRYPT_MAX_ROUNDS", -1);
double rand_rounds;
if ((-1 == min_rounds) && (-1 == max_rounds)) {
return "";
@@ -141,7 +130,10 @@ static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds
max_rounds = min_rounds;
}
rounds = shadow_random (min_rounds, max_rounds);
seedRNG ();
rand_rounds = (double) (max_rounds-min_rounds+1.0) * random ();
rand_rounds /= RAND_MAX;
rounds = min_rounds + rand_rounds;
} else if (0 == *prefered_rounds) {
return "";
} else {
@@ -158,8 +150,13 @@ static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds
rounds = ROUNDS_MAX;
}
(void) snprintf (rounds_prefix, sizeof rounds_prefix,
"rounds=%ld$", rounds);
snprintf (rounds_prefix, 18, "rounds=%ld$", rounds);
/* Sanity checks. That should not be necessary. */
rounds_prefix[17] = '\0';
if ('$' != rounds_prefix[16]) {
rounds_prefix[17] = '$';
}
return rounds_prefix;
}
@@ -205,7 +202,7 @@ static /*@observer@*/const char *gensalt (size_t salt_size)
* * For the SHA256 and SHA512 method, this specifies the number of rounds
* (if not NULL).
*/
/*@observer@*/const char *crypt_make_salt (/*@null@*//*@observer@*/const char *meth, /*@null@*/void *arg)
/*@observer@*/const char *crypt_make_salt (/*@null@*/const char *meth, /*@null@*/void *arg)
{
/* Max result size for the SHA methods:
* +3 $5$
@@ -234,11 +231,11 @@ static /*@observer@*/const char *gensalt (size_t salt_size)
} else if (0 == strcmp (method, "SHA256")) {
MAGNUM(result, '5');
strcat(result, SHA_salt_rounds((int *)arg));
salt_len = (size_t) shadow_random (8, 16);
salt_len = SHA_salt_size();
} else if (0 == strcmp (method, "SHA512")) {
MAGNUM(result, '6');
strcat(result, SHA_salt_rounds((int *)arg));
salt_len = (size_t) shadow_random (8, 16);
salt_len = SHA_salt_size();
#endif /* USE_SHA_CRYPT */
} else if (0 != strcmp (method, "DES")) {
fprintf (stderr,

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2010, Nicolas François
* Copyright (c) 2008 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -131,7 +131,7 @@ int setup_uid_gid (const struct passwd *info)
#if defined (HAVE_INITGROUPS) && ! defined (USE_PAM)
if (is_console) {
const char *cp = getdef_str ("CONSOLE_GROUPS");
char *cp = getdef_str ("CONSOLE_GROUPS");
if ((NULL != cp) && (add_groups (cp) != 0)) {
perror ("Warning: add_groups");

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François
* Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -74,7 +74,7 @@ static void read_env_file (const char *filename)
if (NULL == fp) {
return;
}
while (fgets (buf, (int)(sizeof buf), fp) == buf) {
while (fgets (buf, sizeof buf, fp) == buf) {
cp = strrchr (buf, '\n');
if (NULL == cp) {
break;
@@ -200,9 +200,9 @@ static void read_env_file (const char *filename)
void setup_env (struct passwd *info)
{
#ifndef USE_PAM
const char *envf;
char *envf;
#endif
const char *cp;
char *cp;
/*
* Change the current working directory to be the home directory
@@ -228,8 +228,7 @@ void setup_env (struct passwd *info)
exit (EXIT_FAILURE);
}
(void) puts (_("No directory, logging in with HOME=/"));
free (info->pw_dir);
info->pw_dir = xstrdup (temp_pw_dir);
info->pw_dir = temp_pw_dir;
}
/*
@@ -245,8 +244,7 @@ void setup_env (struct passwd *info)
if ((NULL == info->pw_shell) || ('\0' == *info->pw_shell)) {
static char temp_pw_shell[] = SHELL;
free (info->pw_shell);
info->pw_shell = xstrdup (temp_pw_shell);
info->pw_shell = temp_pw_shell;
}
addenv ("SHELL", info->pw_shell);
@@ -267,7 +265,7 @@ void setup_env (struct passwd *info)
if (NULL == cp) {
/* not specified, use a minimal default */
addenv ((info->pw_uid == 0) ? "PATH=/sbin:/bin:/usr/sbin:/usr/bin" : "PATH=/bin:/usr/bin", NULL);
addenv ("PATH=/bin:/usr/bin", NULL);
} else if (strchr (cp, '=')) {
/* specified as name=value (PATH=...) */
addenv (cp, NULL);

View File

@@ -68,8 +68,7 @@ int shell (const char *file, /*@null@*/const char *arg, char *const envp[])
* don't want to tell us what it is themselves.
*/
if (arg == (char *) 0) {
(void) snprintf (arg0, sizeof arg0, "-%s", Basename ((char *) file));
arg0[sizeof arg0 - 1] = '\0';
snprintf (arg0, sizeof arg0, "-%s", Basename ((char *) file));
arg = arg0;
}
@@ -78,7 +77,7 @@ int shell (const char *file, /*@null@*/const char *arg, char *const envp[])
* able to figure out what we are up to without too much
* grief.
*/
(void) execle (file, arg, (char *) 0, envp);
execle (file, arg, (char *) 0, envp);
err = errno;
if (access (file, R_OK|X_OK) == 0) {
@@ -86,7 +85,7 @@ int shell (const char *file, /*@null@*/const char *arg, char *const envp[])
* Assume this is a shell script (with no shebang).
* Interpret it with /bin/sh
*/
(void) execle (SHELL, "sh", "-", file, (char *)0, envp);
execle (SHELL, "sh", "-", file, (char *)0, envp);
err = errno;
}
@@ -95,7 +94,7 @@ int shell (const char *file, /*@null@*/const char *arg, char *const envp[])
* how to execute this stupid shell, so I might as well give
* up in disgust ...
*/
(void) snprintf (arg0, sizeof arg0, _("Cannot execute %s"), file);
snprintf (arg0, sizeof arg0, _("Cannot execute %s"), file);
errno = err;
perror (arg0);
return err;

View File

@@ -36,8 +36,6 @@
#include <config.h>
#include <ctype.h>
#ident "$Id$"
#include "defines.h"
@@ -46,7 +44,6 @@
#ifndef USE_GETDATE
#define USE_GETDATE 1
#endif
#if USE_GETDATE
#include "getdate.h"
/*
@@ -66,8 +63,6 @@
long strtoday (const char *str)
{
time_t t;
bool isnum = true;
const char *s = str;
/*
* get_date() interprets an empty string as the current date,
@@ -78,32 +73,9 @@ long strtoday (const char *str)
return -1;
}
/* If a numerical value is provided, this is already a number of
* days since EPOCH.
*/
if ('-' == *s) {
s++;
}
while (' ' == *s) {
s++;
}
while (isnum && ('\0' != *s)) {
if (!isdigit (*s)) {
isnum = false;
}
s++;
}
if (isnum) {
long retdate;
if (getlong (str, &retdate) == 0) {
return -2;
}
return retdate;
}
t = get_date (str, NULL);
t = get_date (str, (time_t *) 0);
if ((time_t) - 1 == t) {
return -2;
return -1;
}
/* convert seconds to days since 1970-01-01 */
return (long) (t + DAY / 2) / DAY;

View File

@@ -43,7 +43,7 @@
/*
* subsystem - change to subsystem root
*
* A subsystem login is indicated by the presence of a "*" as
* A subsystem login is indicated by the presense of a "*" as
* the first character of the login shell. The given home
* directory will be used as the root of a new filesystem which
* the user is actually logged into.
@@ -66,13 +66,11 @@ void subsystem (const struct passwd *pw)
* must be able to change into it.
*/
if ( (chdir (pw->pw_dir) != 0)
|| (chroot (pw->pw_dir) != 0)) {
(void) printf (_("Can't change root directory to '%s'\n"),
pw->pw_dir);
if (chdir (pw->pw_dir) || chroot (pw->pw_dir)) {
printf (_("Can't change root directory to '%s'\n"),
pw->pw_dir);
SYSLOG ((LOG_WARN, NO_SUBROOT2, pw->pw_dir, pw->pw_name));
closelog ();
exit (EXIT_FAILURE);
}
}

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1992, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2010, Nicolas François
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -47,7 +47,7 @@
*/
void sulog (const char *tty, bool success, const char *oldname, const char *name)
{
const char *sulog_file;
char *sulog_file;
time_t now;
struct tm *tm;
FILE *fp;
@@ -62,10 +62,8 @@ void sulog (const char *tty, bool success, const char *oldname, const char *name
"FAILED su for %s by %s",name,oldname));
}
sulog_file = getdef_str ("SULOG_FILE");
if (NULL == sulog_file) {
if ((sulog_file = getdef_str ("SULOG_FILE")) == (char *) 0)
return;
}
oldgid = getgid ();
oldmask = umask (077);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013 Eric Biederman
* Copyright (c) 2009 , Dan Walsh <dwalsh@redhat.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,19 +26,47 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ifndef _IDMAPPING_H_
#define _IDMAPPING_H_
#ident "$Id$"
struct map_range {
unsigned long upper; /* first ID inside the namespace */
unsigned long lower; /* first ID outside the namespace */
unsigned long count; /* Length of the inside and outside ranges */
};
#include <stdio.h>
#include <sys/wait.h>
#include <fcntl.h>
#include "prototypes.h"
#include "defines.h"
extern struct map_range *get_map_ranges(int ranges, int argc, char **argv);
extern void write_mapping(int proc_dir_fd, int ranges,
struct map_range *mappings, const char *map_file);
int safe_system (const char *command,
const char *argv[],
const char *env[],
int ignore_stderr)
{
int status = -1;
int fd;
pid_t pid;
pid = fork();
if (pid < 0) {
return -1;
}
#endif /* _ID_MAPPING_H_ */
if (pid) { /* Parent */
if (waitpid (pid, &status, 0) > 0) {
return status;
} else {
return -1;
}
}
fd = open ("/dev/null", O_RDWR);
/* Child */
dup2 (fd, 0); // Close Stdin
if (ignore_stderr) {
dup2 (fd, 2); // Close Stderr
}
execve (command, (char *const *) argv, (char *const *) env);
fprintf (stderr, _("Failed to exec '%s'\n"), argv[0]);
exit (EXIT_FAILURE);
}

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1997, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2010, Nicolas François
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -45,10 +45,10 @@ void ttytype (const char *line)
{
FILE *fp;
char buf[BUFSIZ];
const char *typefile;
char *typefile;
char *cp;
char type[1024] = "";
char port[1024];
char type[BUFSIZ];
char port[BUFSIZ];
if (getenv ("TERM") != NULL) {
return;
@@ -76,12 +76,12 @@ void ttytype (const char *line)
*cp = '\0';
}
if ( (sscanf (buf, "%1023s %1023s", type, port) == 2)
&& (strcmp (line, port) == 0)) {
if ((sscanf (buf, "%s %s", type, port) == 2) &&
(strcmp (line, port) == 0)) {
break;
}
}
if ((feof (fp) == 0) && (ferror (fp) == 0) && (type[0] != '\0')) {
if ((feof (fp) == 0) && (ferror (fp) == 0)) {
addenv ("TERM", type);
}

View File

@@ -3,7 +3,7 @@
* Copyright (c) 1991 - 1994, Chip Rosenthal
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -49,28 +49,23 @@
* tz() determines the name of the local timezone by reading the
* contents of the file named by ``fname''.
*/
/*@observer@*/const char *tz (const char *fname)
char *tz (const char *fname)
{
FILE *fp = NULL;
FILE *fp = 0;
static char tzbuf[BUFSIZ];
const char *def_tz = "TZ=CST6CDT";
fp = fopen (fname, "r");
if ( (NULL == fp)
|| (fgets (tzbuf, (int) sizeof (tzbuf), fp) == NULL)) {
def_tz = getdef_str ("ENV_TZ");
if ((NULL == def_tz) || ('/' == def_tz[0])) {
if ((fp = fopen (fname, "r")) == NULL ||
fgets (tzbuf, (int) sizeof (tzbuf), fp) == NULL) {
if (!(def_tz = getdef_str ("ENV_TZ")) || def_tz[0] == '/')
def_tz = "TZ=CST6CDT";
}
strcpy (tzbuf, def_tz);
} else {
} else
tzbuf[strlen (tzbuf) - 1] = '\0';
}
if (NULL != fp) {
if (fp)
(void) fclose (fp);
}
return tzbuf;
}

View File

@@ -38,16 +38,12 @@
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include "defines.h"
#include "prototypes.h"
#ifdef ENABLE_SUBIDS
#include "subordinateio.h"
#endif /* ENABLE_SUBIDS */
#ifdef __linux__
static int check_status (const char *name, const char *sname, uid_t uid);
static int user_busy_processes (const char *name, uid_t uid);
static int check_status (const char *sname, uid_t uid);
static int user_busy_processes (uid_t uid);
#else /* !__linux__ */
static int user_busy_utmp (const char *name);
#endif /* !__linux__ */
@@ -62,7 +58,7 @@ int user_busy (const char *name, uid_t uid)
*/
#ifdef __linux__
/* On Linux, directly parse /proc */
return user_busy_processes (name, uid);
return user_busy_processes (uid);
#else /* !__linux__ */
/* If we cannot rely on /proc, check is there is a record in utmp
* indicating that the user is still logged in */
@@ -95,9 +91,6 @@ static int user_busy_utmp (const char *name)
continue;
}
fprintf (stderr,
_("%s: user %s is currently logged in\n"),
Prog, name);
return 1;
}
@@ -106,7 +99,7 @@ static int user_busy_utmp (const char *name)
#endif /* !__linux__ */
#ifdef __linux__
static int check_status (const char *name, const char *sname, uid_t uid)
static int check_status (const char *sname, uid_t uid)
{
/* 40: /proc/xxxxxxxxxx/task/xxxxxxxxxx/status + \0 */
char status[40];
@@ -129,13 +122,7 @@ static int check_status (const char *name, const char *sname, uid_t uid)
&ruid, &euid, &suid) == 3) {
if ( (ruid == (unsigned long) uid)
|| (euid == (unsigned long) uid)
|| (suid == (unsigned long) uid)
#ifdef ENABLE_SUBIDS
|| have_sub_uids(name, ruid, 1)
|| have_sub_uids(name, euid, 1)
|| have_sub_uids(name, suid, 1)
#endif /* ENABLE_SUBIDS */
) {
|| (suid == (unsigned long) uid)) {
(void) fclose (sfile);
return 1;
}
@@ -150,7 +137,7 @@ static int check_status (const char *name, const char *sname, uid_t uid)
return 0;
}
static int user_busy_processes (const char *name, uid_t uid)
static int user_busy_processes (uid_t uid)
{
DIR *proc;
struct dirent *ent;
@@ -163,10 +150,6 @@ static int user_busy_processes (const char *name, uid_t uid)
struct stat sbroot;
struct stat sbroot_process;
#ifdef ENABLE_SUBIDS
sub_uid_open (O_RDONLY);
#endif /* ENABLE_SUBIDS */
proc = opendir ("/proc");
if (proc == NULL) {
perror ("opendir /proc");
@@ -175,9 +158,6 @@ static int user_busy_processes (const char *name, uid_t uid)
if (stat ("/", &sbroot) != 0) {
perror ("stat (\"/\")");
(void) closedir (proc);
#ifdef ENABLE_SUBIDS
sub_uid_close();
#endif
return 0;
}
@@ -213,14 +193,8 @@ static int user_busy_processes (const char *name, uid_t uid)
continue;
}
if (check_status (name, tmp_d_name, uid) != 0) {
if (check_status (tmp_d_name, uid) != 0) {
(void) closedir (proc);
#ifdef ENABLE_SUBIDS
sub_uid_close();
#endif
fprintf (stderr,
_("%s: user %s is currently used by process %d\n"),
Prog, name, pid);
return 1;
}
@@ -236,14 +210,8 @@ static int user_busy_processes (const char *name, uid_t uid)
if (tid == pid) {
continue;
}
if (check_status (name, task_path+6, uid) != 0) {
if (check_status (task_path+6, uid) != 0) {
(void) closedir (proc);
#ifdef ENABLE_SUBIDS
sub_uid_close();
#endif
fprintf (stderr,
_("%s: user %s is currently used by process %d\n"),
Prog, name, pid);
return 1;
}
}
@@ -254,9 +222,6 @@ static int user_busy_processes (const char *name, uid_t uid)
}
(void) closedir (proc);
#ifdef ENABLE_SUBIDS
sub_uid_close();
#endif /* ENABLE_SUBIDS */
return 0;
}
#endif /* __linux__ */

View File

@@ -42,8 +42,6 @@
#endif
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
@@ -73,7 +71,7 @@ static bool is_my_tty (const char *tty)
}
}
if ('\0' == tmptty[0]) {
if (NULL == tmptty) {
(void) puts (_("Unable to determine your tty name."));
exit (EXIT_FAILURE);
} else if (strncmp (tty, tmptty, sizeof (tmptty)) != 0) {
@@ -131,7 +129,6 @@ static bool is_my_tty (const char *tty)
return ret;
}
#ifndef USE_PAM
/*
* Some systems already have updwtmp() and possibly updwtmpx(). Others
* don't, so we re-implement these functions if necessary.
@@ -163,7 +160,6 @@ static void updwtmpx (const char *filename, const struct utmpx *utx)
}
#endif /* ! HAVE_UPDWTMPX */
#endif /* ! USE_UTMPX */
#endif /* ! USE_PAM */
/*
@@ -204,6 +200,7 @@ static void updwtmpx (const char *filename, const struct utmpx *utx)
strcpy (hostname, host);
#ifdef HAVE_STRUCT_UTMP_UT_HOST
} else if ( (NULL != ut)
&& (NULL != ut->ut_host)
&& ('\0' != ut->ut_host[0])) {
hostname = (char *) xmalloc (sizeof (ut->ut_host) + 1);
strncpy (hostname, ut->ut_host, sizeof (ut->ut_host));
@@ -317,10 +314,7 @@ int setutmp (struct utmp *ut)
}
endutent ();
#ifndef USE_PAM
/* This is done by pam_lastlog */
updwtmp (_WTMP_FILE, ut);
#endif /* ! USE_PAM */
return err;
}
@@ -453,10 +447,7 @@ int setutmpx (struct utmpx *utx)
}
endutxent ();
#ifndef USE_PAM
/* This is done by pam_lastlog */
updwtmpx (_WTMP_FILE "x", utx);
#endif /* ! USE_PAM */
return err;
}

View File

@@ -52,7 +52,7 @@
bool valid (const char *password, const struct passwd *ent)
{
const char *encrypted;
/*@observer@*/const char *salt;
const char *salt;
/*
* Start with blank or empty password entries. Always encrypt
@@ -95,7 +95,6 @@ bool valid (const char *password, const struct passwd *ent)
*/
if ( (NULL != ent->pw_name)
&& (NULL != encrypted)
&& (strcmp (encrypted, ent->pw_passwd) == 0)) {
return true;
} else {

View File

@@ -91,7 +91,7 @@
errno = 0;
status = REENTRANT_NAME(ARG_NAME, result, buffer,
length, &resbuf);
if ((0 == status) && (resbuf == result)) {
if ((0 ==status) && (resbuf == result)) {
/* Build a result structure that can be freed by
* the shadow *_free functions. */
LOOKUP_TYPE *ret_result = DUP_FUNCTION(result);

View File

@@ -44,25 +44,22 @@
#ident "$Id$"
#include <stdio.h>
#include <errno.h>
#include "defines.h"
#include "prototypes.h"
/*@maynotreturn@*/ /*@only@*//*@out@*//*@notnull@*/char *xmalloc (size_t size)
char *xmalloc (size_t size)
{
char *ptr;
ptr = (char *) malloc (size);
if (NULL == ptr) {
(void) fprintf (stderr,
_("%s: failed to allocate memory: %s\n"),
Prog, strerror (errno));
if ((NULL == ptr) && (0 != size)) {
fprintf (stderr, _("malloc(%d) failed\n"), (int) size);
exit (13);
}
return ptr;
}
/*@maynotreturn@*/ /*@only@*//*@notnull@*/char *xstrdup (const char *str)
char *xstrdup (const char *str)
{
return strcpy (xmalloc (strlen (str) + 1), str);
}

1
man/.gitignore vendored
View File

@@ -1,6 +1,5 @@
.xml2po.mo
config.xml
generate_mans.deps
*.[0-9]

View File

@@ -1,73 +1,63 @@
# subdirectories for translated manual pages
if USE_NLS
SUBDIRS = po cs da de es fi fr hu id it ja ko pl pt_BR ru sv tr zh_CN zh_TW
SUBDIRS = po cs de es fi fr hu id it ja ko pl pt_BR ru sv tr zh_CN zh_TW
else
SUBDIRS =
endif
man_MANS = \
man1/chage.1 \
man1/chfn.1 \
man8/chgpasswd.8 \
man8/chpasswd.8 \
man1/chsh.1 \
man1/expiry.1 \
man5/faillog.5 \
man8/faillog.8 \
man3/getspnam.3 \
man1/gpasswd.1 \
man8/groupadd.8 \
man8/groupdel.8 \
man8/groupmems.8 \
man8/groupmod.8 \
man1/groups.1 \
man8/grpck.8 \
man8/grpconv.8 \
man8/grpunconv.8 \
man5/gshadow.5 \
man8/lastlog.8 \
man1/login.1 \
man5/login.defs.5 \
man8/logoutd.8 \
man1/newgrp.1 \
man8/newusers.8 \
man8/nologin.8 \
man1/passwd.1 \
man5/passwd.5 \
man8/pwck.8 \
man8/pwconv.8 \
man8/pwunconv.8 \
man1/sg.1 \
man3/shadow.3 \
man5/shadow.5 \
man1/su.1 \
man5/suauth.5 \
man8/useradd.8 \
man8/userdel.8 \
man8/usermod.8 \
man8/vigr.8 \
man8/vipw.8
chage.1 \
chfn.1 \
chgpasswd.8 \
chpasswd.8 \
chsh.1 \
expiry.1 \
faillog.5 \
faillog.8 \
getspnam.3 \
gpasswd.1 \
groupadd.8 \
groupdel.8 \
groupmems.8 \
groupmod.8 \
groups.1 \
grpck.8 \
grpconv.8 \
grpunconv.8 \
gshadow.5 \
lastlog.8 \
login.1 \
login.defs.5 \
logoutd.8 \
newgrp.1 \
newusers.8 \
nologin.8 \
passwd.1 \
passwd.5 \
pwck.8 \
pwconv.8 \
pwunconv.8 \
sg.1 \
shadow.3 \
shadow.5 \
su.1 \
suauth.5 \
useradd.8 \
userdel.8 \
usermod.8 \
vigr.8 \
vipw.8
man_nopam = \
man5/limits.5 \
man5/login.access.5 \
man5/porttime.5
limits.5 \
login.access.5 \
porttime.5
if !USE_PAM
man_MANS += $(man_nopam)
endif
man_subids = \
man1/newgidmap.1 \
man1/newuidmap.1 \
man5/subgid.5 \
man5/subuid.5
if ENABLE_SUBIDS
man_MANS += $(man_subids)
endif
man_XMANS = \
chage.1.xml \
chfn.1.xml \
@@ -91,9 +81,7 @@ man_XMANS = \
login.access.5.xml \
login.defs.5.xml \
logoutd.8.xml \
newgidmap.1.xml \
newgrp.1.xml \
newuidmap.1.xml \
newusers.8.xml \
nologin.8.xml \
passwd.1.xml \
@@ -106,8 +94,6 @@ man_XMANS = \
sg.1.xml \
su.1.xml \
suauth.5.xml \
subgid.5.xml \
subuid.5.xml \
useradd.8.xml \
userdel.8.xml \
usermod.8.xml \
@@ -163,8 +149,6 @@ login_defs_v = \
SU_WHEEL_ONLY.xml \
SYSLOG_SG_ENAB.xml \
SYSLOG_SU_ENAB.xml \
TCB_AUTH_GROUP.xml \
TCB_SYMLINKS.xml \
TTYGROUP.xml \
TTYTYPE_FILE.xml \
UID_MAX.xml \
@@ -172,9 +156,6 @@ login_defs_v = \
UMASK.xml \
USERDEL_CMD.xml \
USERGROUPS_ENAB.xml \
USE_TCB.xml \
SUB_GID_COUNT.xml \
SUB_UID_COUNT.xml \
SYS_GID_MAX.xml \
SYS_UID_MAX.xml
@@ -182,32 +163,24 @@ EXTRA_DIST = \
$(man_MANS) \
$(man_XMANS) \
$(addprefix login.defs.d/,$(login_defs_v)) \
man1/id.1 \
$(man_nopam) \
id.1 \
id.1.xml \
man8/sulogin.8 \
sulogin.8 \
sulogin.8.xml \
generate_mans.mak \
generate_translations.mak
if USE_PAM
EXTRA_DIST += $(man_nopam)
endif
if !ENABLE_SUBIDS
EXTRA_DIST += $(man_subids)
endif
generate_mans.deps: *.xml
echo "# This file is generated" > $@
awk 'BEGIN{FS="\"";} /^<!ENTITY .* * SYSTEM ".*">$$/{ f=FILENAME; sub(/.xml/,"",f); print "man" substr(f, length (f)) "/" f ": " $$2 }' $(man_XMANS) >> $@
awk 'BEGIN{FS="\"";} /^<!ENTITY .* * SYSTEM ".*">$$/{ f=FILENAME; sub(/.xml/,"",f); print f ": " $$2 }' $(man_XMANS) > $@
if ENABLE_REGENERATE_MAN
@ENABLE_REGENERATE_MAN_TRUE@include generate_mans.deps
include generate_mans.deps
include generate_mans.mak
CLEANFILES = $(man_MANS) man1/id.1 man8/sulogin.8
CLEANFILES = $(man_MANS)
else
$(man_MANS):

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 1990 - 1994, Julianne Frances Haugh
Copyright (c) 2007 - 2011, Nicolas François
Copyright (c) 2007 - 2008, Nicolas François
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -28,38 +28,12 @@
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY USE_TCB SYSTEM "login.defs.d/USE_TCB.xml">
<!-- SHADOW-CONFIG-HERE -->
]>
<refentry id='chage.1'>
<!-- $Id$ -->
<refentryinfo>
<author>
<firstname>Julianne Frances</firstname>
<surname>Haugh</surname>
<contrib>Creation, 1990</contrib>
</author>
<author>
<firstname>Thomas</firstname>
<surname>Kłoczko</surname>
<email>kloczek@pld.org.pl</email>
<contrib>shadow-utils maintainer, 2000 - 2007</contrib>
</author>
<author>
<firstname>Nicolas</firstname>
<surname>François</surname>
<email>nicolas.francois@centraliens.net</email>
<contrib>shadow-utils maintainer, 2007 - now</contrib>
</author>
</refentryinfo>
<refmeta>
<refentrytitle>chage</refentrytitle>
<manvolnum>1</manvolnum>
<refmiscinfo class="sectdesc">User Commands</refmiscinfo>
<refmiscinfo class="source">shadow-utils</refmiscinfo>
<refmiscinfo class="version">&SHADOW_UTILS_VERSION;</refmiscinfo>
</refmeta>
<refnamediv id='name'>
<refname>chage</refname>
@@ -71,8 +45,8 @@
<arg choice='opt'>
<replaceable>options</replaceable>
</arg>
<arg choice='plain'>
<replaceable>LOGIN</replaceable>
<arg choice='opt'>
<replaceable>LOGIN</replaceable>
</arg>
</cmdsynopsis>
</refsynopsisdiv>
@@ -95,7 +69,7 @@
<variablelist remap='IP'>
<varlistentry>
<term>
<option>-d</option>, <option>--lastday</option>&nbsp;<replaceable>LAST_DAY</replaceable>
<option>-d</option>, <option>--lastday</option> <replaceable>LAST_DAY</replaceable>
</term>
<listitem>
<para>
@@ -107,7 +81,7 @@
</varlistentry>
<varlistentry>
<term>
<option>-E</option>, <option>--expiredate</option>&nbsp;<replaceable>EXPIRE_DATE</replaceable>
<option>-E</option>, <option>--expiredate</option> <replaceable>EXPIRE_DATE</replaceable>
</term>
<listitem>
<para>
@@ -133,7 +107,7 @@
</varlistentry>
<varlistentry>
<term>
<option>-I</option>, <option>--inactive</option>&nbsp;<replaceable>INACTIVE</replaceable>
<option>-I</option>, <option>--inactive</option> <replaceable>INACTIVE</replaceable>
</term>
<listitem>
<para>
@@ -162,7 +136,7 @@
</varlistentry>
<varlistentry>
<term>
<option>-m</option>, <option>--mindays</option>&nbsp;<replaceable>MIN_DAYS</replaceable>
<option>-m</option>, <option>--mindays</option> <replaceable>MIN_DAYS</replaceable>
</term>
<listitem>
<para>
@@ -174,7 +148,7 @@
</varlistentry>
<varlistentry>
<term>
<option>-M</option>, <option>--maxdays</option>&nbsp;<replaceable>MAX_DAYS</replaceable>
<option>-M</option>, <option>--maxdays</option> <replaceable>MAX_DAYS</replaceable>
</term>
<listitem>
<para>
@@ -195,19 +169,7 @@
</varlistentry>
<varlistentry>
<term>
<option>-R</option>, <option>--root</option>&nbsp;<replaceable>CHROOT_DIR</replaceable>
</term>
<listitem>
<para>
Apply changes in the <replaceable>CHROOT_DIR</replaceable>
directory and use the configuration files from the
<replaceable>CHROOT_DIR</replaceable> directory.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-W</option>, <option>--warndays</option>&nbsp;<replaceable>WARN_DAYS</replaceable>
<option>-W</option>, <option>--warndays</option> <replaceable>WARN_DAYS</replaceable>
</term>
<listitem>
<para>
@@ -240,18 +202,6 @@
</para>
</refsect1>
<refsect1 id='configuration'>
<title>CONFIGURATION</title>
<para>
The following configuration variables in
<filename>/etc/login.defs</filename> change the behavior of this
tool:
</para>
<variablelist>
&USE_TCB;
</variablelist>
</refsect1>
<refsect1 id='files'>
<title>FILES</title>
<variablelist>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 1990 - 1994, Julianne Frances Haugh
Copyright (c) 2007 - 2011, Nicolas François
Copyright (c) 2007 - 2008, Nicolas François
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -33,35 +33,14 @@
<!ENTITY CHFN_AUTH SYSTEM "login.defs.d/CHFN_AUTH.xml">
<!ENTITY CHFN_RESTRICT SYSTEM "login.defs.d/CHFN_RESTRICT.xml">
<!ENTITY LOGIN_STRING SYSTEM "login.defs.d/LOGIN_STRING.xml">
<!-- SHADOW-CONFIG-HERE -->
]>
<refentry id='chfn.1'>
<!-- $Id$ -->
<refentryinfo>
<author>
<firstname>Julianne Frances</firstname>
<surname>Haugh</surname>
<contrib>Creation, 1990</contrib>
</author>
<author>
<firstname>Thomas</firstname>
<surname>Kłoczko</surname>
<email>kloczek@pld.org.pl</email>
<contrib>shadow-utils maintainer, 2000 - 2007</contrib>
</author>
<author>
<firstname>Nicolas</firstname>
<surname>François</surname>
<email>nicolas.francois@centraliens.net</email>
<contrib>shadow-utils maintainer, 2007 - now</contrib>
</author>
</refentryinfo>
<refmeta>
<refentrytitle>chfn</refentrytitle>
<manvolnum>1</manvolnum>
<refmiscinfo class="sectdesc">User Commands</refmiscinfo>
<refmiscinfo class="source">shadow-utils</refmiscinfo>
<refmiscinfo class="version">&SHADOW_UTILS_VERSION;</refmiscinfo>
</refmeta>
<refnamediv id='name'>
<refname>chfn</refname>
@@ -71,12 +50,12 @@
<refsynopsisdiv id='synopsis'>
<cmdsynopsis>
<command>chfn</command>
<arg choice='opt'>
<replaceable>options</replaceable>
</arg>
<arg choice='opt'>
<replaceable>LOGIN</replaceable>
</arg>
<arg choice='opt'>-f <replaceable>full_name</replaceable></arg>
<arg choice='opt'>-r <replaceable>room_no</replaceable></arg>
<arg choice='opt'>-w <replaceable>work_ph</replaceable></arg>
<arg choice='opt'>-h <replaceable>home_ph</replaceable></arg>
<arg choice='opt'>-o <replaceable>other</replaceable></arg>
<arg choice='opt'><replaceable>user</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
@@ -84,7 +63,7 @@
<title>DESCRIPTION</title>
<para>
The <command>chfn</command> command changes user fullname,
office room number, office phone number, and home phone number information
office number, office extension, and home phone number information
for a user's account. This information is typically printed by
<citerefentry><refentrytitle>finger</refentrytitle><manvolnum>1</manvolnum>
</citerefentry> and similar programs. A normal user may only change
@@ -105,79 +84,6 @@
store accounting information used by other applications.
</para>
</refsect1>
<refsect1 id='options'>
<title>OPTIONS</title>
<para>
The options which apply to the <command>chfn</command> command are:
</para>
<variablelist remap='IP'>
<varlistentry>
<term>
<option>-f</option>, <option>--full-name</option>&nbsp;<replaceable>FULL_NAME</replaceable>
</term>
<listitem>
<para>Change the user's full name.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-h</option>, <option>--home-phone</option>&nbsp;<replaceable>HOME_PHONE</replaceable>
</term>
<listitem>
<para>Change the user's home phone number.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-o</option>, <option>--other</option>&nbsp;<replaceable>OTHER</replaceable>
</term>
<listitem>
<para>
Change the user's other GECOS information. This field is used to
store accounting information used by other applications, and can
be changed only by a superuser.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-r</option>, <option>--room</option>&nbsp;<replaceable>ROOM_NUMBER</replaceable>
</term>
<listitem>
<para>Change the user's room number.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-R</option>, <option>--root</option>&nbsp;<replaceable>CHROOT_DIR</replaceable>
</term>
<listitem>
<para>
Apply changes in the <replaceable>CHROOT_DIR</replaceable>
directory and use the configuration files from the
<replaceable>CHROOT_DIR</replaceable> directory.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-u</option>, <option>--help</option>
</term>
<listitem>
<para>Display help message and exit.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-w</option>, <option>--work-phone</option>&nbsp;<replaceable>WORK_PHONE</replaceable>
</term>
<listitem>
<para>Change the user's office phone number.</para>
</listitem>
</varlistentry>
</variablelist>
<para>
If none of the options are selected, <command>chfn</command>
operates in an interactive fashion, prompting the user with the

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2006 , Tomasz Kłoczko
Copyright (c) 2007 - 2011, Nicolas François
Copyright (c) 2007 - 2009, Nicolas François
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -34,31 +34,14 @@
<!ENTITY MAX_MEMBERS_PER_GROUP SYSTEM "login.defs.d/MAX_MEMBERS_PER_GROUP.xml">
<!ENTITY MD5_CRYPT_ENAB SYSTEM "login.defs.d/MD5_CRYPT_ENAB.xml">
<!ENTITY SHA_CRYPT_MIN_ROUNDS SYSTEM "login.defs.d/SHA_CRYPT_MIN_ROUNDS.xml">
<!-- SHADOW-CONFIG-HERE -->
]>
<refentry id='chgpasswd.8'>
<!-- $Id$ -->
<refentryinfo>
<author>
<firstname>Thomas</firstname>
<surname>Kłoczko</surname>
<email>kloczek@pld.org.pl</email>
<contrib>Creation, 2006</contrib>
</author>
<author>
<firstname>Nicolas</firstname>
<surname>François</surname>
<email>nicolas.francois@centraliens.net</email>
<contrib>shadow-utils maintainer, 2007 - now</contrib>
</author>
</refentryinfo>
<refmeta>
<refentrytitle>chgpasswd</refentrytitle>
<manvolnum>8</manvolnum>
<refmiscinfo class="sectdesc">System Management Commands</refmiscinfo>
<refmiscinfo class="source">shadow-utils</refmiscinfo>
<refmiscinfo class="version">&SHADOW_UTILS_VERSION;</refmiscinfo>
</refmeta>
<refnamediv id='name'>
<refname>chgpasswd</refname>
@@ -91,8 +74,8 @@
</para>
<para>
The default encryption algorithm can be defined for the system with
the <option>ENCRYPT_METHOD</option> variable of <filename>/etc/login.defs</filename>,
and can be overwritten with the <option>-e</option>,
the ENCRYPT_METHOD variable of <filename>/etc/login.defs</filename>,
and can be overwiten with the <option>-e</option>,
<option>-m</option>, or <option>-c</option> options.
</para>
<para>
@@ -142,18 +125,6 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-R</option>, <option>--root</option>&nbsp;<replaceable>CHROOT_DIR</replaceable>
</term>
<listitem>
<para>
Apply changes in the <replaceable>CHROOT_DIR</replaceable>
directory and use the configuration files from the
<replaceable>CHROOT_DIR</replaceable> directory.
</para>
</listitem>
</varlistentry>
<varlistentry condition="sha_crypt">
<term><option>-s</option>, <option>--sha-rounds</option></term>
<listitem>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 1991 , Julianne Frances Haugh
Copyright (c) 2007 - 2011, Nicolas François
Copyright (c) 2007 - 2009, Nicolas François
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -33,36 +33,14 @@
<!ENTITY ENCRYPT_METHOD SYSTEM "login.defs.d/ENCRYPT_METHOD.xml">
<!ENTITY MD5_CRYPT_ENAB SYSTEM "login.defs.d/MD5_CRYPT_ENAB.xml">
<!ENTITY SHA_CRYPT_MIN_ROUNDS SYSTEM "login.defs.d/SHA_CRYPT_MIN_ROUNDS.xml">
<!-- SHADOW-CONFIG-HERE -->
]>
<refentry id='chpasswd.8'>
<!-- $Id$ -->
<refentryinfo>
<author>
<firstname>Julianne Frances</firstname>
<surname>Haugh</surname>
<contrib>Creation, 1991</contrib>
</author>
<author>
<firstname>Thomas</firstname>
<surname>Kłoczko</surname>
<email>kloczek@pld.org.pl</email>
<contrib>shadow-utils maintainer, 2000 - 2007</contrib>
</author>
<author>
<firstname>Nicolas</firstname>
<surname>François</surname>
<email>nicolas.francois@centraliens.net</email>
<contrib>shadow-utils maintainer, 2007 - now</contrib>
</author>
</refentryinfo>
<refmeta>
<refentrytitle>chpasswd</refentrytitle>
<manvolnum>8</manvolnum>
<refmiscinfo class="sectdesc">System Management Commands</refmiscinfo>
<refmiscinfo class="source">shadow-utils</refmiscinfo>
<refmiscinfo class="version">&SHADOW_UTILS_VERSION;</refmiscinfo>
</refmeta>
<refnamediv id='name'>
<refname>chpasswd</refname>
@@ -89,37 +67,38 @@
<emphasis remap='I'>user_name</emphasis>:<emphasis
remap='I'>password</emphasis>
</para>
<refsect2 condition="no_pam">
<para>
By default the passwords must be supplied in clear-text, and are
By default the supplied password must be in clear-text, and is
encrypted by <command>chpasswd</command>.
Also the password age will be updated, if present.
</para>
<para condition="no_pam">
The default encryption algorithm can be defined for the system with
the <option>ENCRYPT_METHOD</option> or
<option>MD5_CRYPT_ENAB</option> variables of
<filename>/etc/login.defs</filename>, and can be overwritten with the
<option>-e</option>, <option>-m</option>, or <option>-c</option>
options.
</para>
<para condition="pam">
By default, passwords are encrypted by PAM, but (even if not
recommended) you can select a different encryption method with the
<option>-e</option>, <option>-m</option>, or <option>-c</option>
options.
</para>
<para>
<phrase condition="pam">Except when PAM is used to encrypt the
passwords,</phrase> <command>chpasswd</command> first updates all the
passwords in memory, and then commits all the changes to disk if no
errors occurred for any user.
</para>
<para condition="pam">
When PAM is used to encrypt the passwords (and update the passwords in
the system database) then if a password cannot be updated
<command>chpasswd</command> continues updating the passwords of the
next users, and will return an error code on exit.
The default encryption algorithm can be defined for the system with
the ENCRYPT_METHOD variable of <filename>/etc/login.defs</filename>,
and can be overwiten with the <option>-e</option>,
<option>-m</option>, or <option>-c</option> options.
</para>
<para>
<command>chpasswd</command> first update the password in memory,
and then commit all the changes to disk if no errors occured for
any users.
</para>
</refsect2>
<refsect2 condition="pam">
<para>
The supplied passwords must be in clear-text.
</para>
<para>
PAM is used to update the password in the system database
according to the PAM chpasswd configuration.
</para>
<para>
When <command>chpasswd</command> fails to update a password, it
continues updating the passwords of the next users, and will
return an error code on exit.
</para>
</refsect2>
<para>
This command is intended to be used in a large system environment
where many accounts are created at a single time.
@@ -132,11 +111,9 @@
The options which apply to the <command>chpasswd</command> command
are:
</para>
<variablelist remap='IP'>
<variablelist remap='IP' condition="no_pam">
<varlistentry>
<term>
<option>-c</option>, <option>--crypt-method</option>&nbsp;<replaceable>METHOD</replaceable>
</term>
<term><option>-c</option>, <option>--crypt-method</option></term>
<listitem>
<para>Use the specified method to encrypt the passwords.</para>
<para condition="no_sha_crypt">
@@ -146,17 +123,6 @@
The available methods are DES, MD5, NONE, and SHA256 or SHA512
if your libc support these methods.
</para>
<para condition="pam">
By default, PAM is used to encrypt the passwords.
</para>
<para condition="no_pam">
By default (if none of the <option>-c</option>,
<option>-m</option>, or <option>-e</option> options are
specified), the encryption method is defined by the
<option>ENCRYPT_METHOD</option> or
<option>MD5_CRYPT_ENAB</option> variables of
<filename>/etc/login.defs</filename>.
</para>
</listitem>
</varlistentry>
<varlistentry>
@@ -174,7 +140,7 @@
</listitem>
</varlistentry>
</variablelist>
<variablelist remap='IP'>
<variablelist remap='IP' condition="no_pam">
<varlistentry>
<term><option>-m</option>, <option>--md5</option></term>
<listitem>
@@ -184,22 +150,8 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-R</option>, <option>--root</option>&nbsp;<replaceable>CHROOT_DIR</replaceable>
</term>
<listitem>
<para>
Apply changes in the <replaceable>CHROOT_DIR</replaceable>
directory and use the configuration files from the
<replaceable>CHROOT_DIR</replaceable> directory.
</para>
</listitem>
</varlistentry>
<varlistentry condition="sha_crypt">
<term>
<option>-s</option>, <option>--sha-rounds</option>&nbsp;<replaceable>ROUNDS</replaceable>
</term>
<term><option>-s</option>, <option>--sha-rounds</option></term>
<listitem>
<para>
Use the specified number of rounds to encrypt the passwords.
@@ -218,8 +170,7 @@
</para>
<para>
By default, the number of rounds is defined by the
<option>SHA_CRYPT_MIN_ROUNDS</option> and
<option>SHA_CRYPT_MAX_ROUNDS</option> variables in
SHA_CRYPT_MIN_ROUNDS and SHA_CRYPT_MAX_ROUNDS variables in
<filename>/etc/login.defs</filename>.
</para>
</listitem>
@@ -233,20 +184,22 @@
Remember to set permissions or umask to prevent readability of
unencrypted files by other users.
</para>
<para condition="no_pam">
You should make sure the passwords and the encryption method respect
the system's password policy.
</para>
</refsect1>
<refsect1 id='configuration'>
<refsect1 id='configuration' condition="no_pam">
<title>CONFIGURATION</title>
<para>
The following configuration variables in
<filename>/etc/login.defs</filename> change the behavior of this
tool:
</para>
<variablelist condition="no_pam">
<variablelist>
&ENCRYPT_METHOD;
&MD5_CRYPT_ENAB;
</variablelist>
<variablelist>
&SHA_CRYPT_MIN_ROUNDS; <!--documents also SHA_CRYPT_MAX_ROUNDS-->
</variablelist>
</refsect1>
@@ -254,19 +207,19 @@
<refsect1 id='files'>
<title>FILES</title>
<variablelist>
<varlistentry>
<varlistentry condition="no_pam">
<term><filename>/etc/passwd</filename></term>
<listitem>
<para>User account information.</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry condition="no_pam">
<term><filename>/etc/shadow</filename></term>
<listitem>
<para>Secure user account information.</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry condition="no_pam">
<term><filename>/etc/login.defs</filename></term>
<listitem>
<para>Shadow password suite configuration.</para>
@@ -290,7 +243,7 @@
<citerefentry>
<refentrytitle>newusers</refentrytitle><manvolnum>8</manvolnum>
</citerefentry>,
<phrase>
<phrase condition="no_pam">
<citerefentry>
<refentrytitle>login.defs</refentrytitle><manvolnum>5</manvolnum>
</citerefentry>,

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 1990 , Julianne Frances Haugh
Copyright (c) 2007 - 2011, Nicolas François
Copyright (c) 2007 - 2008, Nicolas François
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -32,36 +32,14 @@
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY CHSH_AUTH SYSTEM "login.defs.d/CHSH_AUTH.xml">
<!ENTITY LOGIN_STRING SYSTEM "login.defs.d/LOGIN_STRING.xml">
<!-- SHADOW-CONFIG-HERE -->
]>
<refentry id='chsh.1'>
<!-- $Id$ -->
<refentryinfo>
<author>
<firstname>Julianne Frances</firstname>
<surname>Haugh</surname>
<contrib>Creation, 1990</contrib>
</author>
<author>
<firstname>Thomas</firstname>
<surname>Kłoczko</surname>
<email>kloczek@pld.org.pl</email>
<contrib>shadow-utils maintainer, 2000 - 2007</contrib>
</author>
<author>
<firstname>Nicolas</firstname>
<surname>François</surname>
<email>nicolas.francois@centraliens.net</email>
<contrib>shadow-utils maintainer, 2007 - now</contrib>
</author>
</refentryinfo>
<refmeta>
<refentrytitle>chsh</refentrytitle>
<manvolnum>1</manvolnum>
<refmiscinfo class="sectdesc">User Commands</refmiscinfo>
<refmiscinfo class="source">shadow-utils</refmiscinfo>
<refmiscinfo class="version">&SHADOW_UTILS_VERSION;</refmiscinfo>
</refmeta>
<refnamediv id='name'>
<refname>chsh</refname>
@@ -85,7 +63,7 @@
<para>
The <command>chsh</command> command changes the user login shell.
This determines the name of the user's initial login command. A normal
user may only change the login shell for her own account; the
user may only change the login shell for her own account, the
superuser may change the login shell for any account.
</para>
@@ -105,19 +83,7 @@
</varlistentry>
<varlistentry>
<term>
<option>-R</option>, <option>--root</option>&nbsp;<replaceable>CHROOT_DIR</replaceable>
</term>
<listitem>
<para>
Apply changes in the <replaceable>CHROOT_DIR</replaceable>
directory and use the configuration files from the
<replaceable>CHROOT_DIR</replaceable> directory.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-s</option>, <option>--shell</option>&nbsp;<replaceable>SHELL</replaceable>
<option>-s</option>, <option>--shell</option> <replaceable>SHELL</replaceable>
</term>
<listitem>
<para>

View File

@@ -1,2 +1 @@
<!ENTITY GROUP_NAME_MAX_LENGTH '@GROUP_NAME_MAX_LENGTH@'>
<!ENTITY SHADOW_UTILS_VERSION '@VERSION@'>

View File

@@ -2,25 +2,24 @@
mandir = @mandir@/cs
man_MANS = \
man1/expiry.1 \
man5/faillog.5 \
man8/faillog.8 \
man1/gpasswd.1 \
man8/groupadd.8 \
man8/groupdel.8 \
man8/groupmod.8 \
man1/groups.1 \
man8/grpck.8 \
man5/gshadow.5 \
man8/lastlog.8 \
man8/nologin.8 \
man5/passwd.5 \
man5/shadow.5 \
man1/su.1 \
man8/vipw.8
expiry.1 \
faillog.5 \
faillog.8 \
gpasswd.1 \
groupadd.8 \
groupdel.8 \
groupmod.8 \
groups.1 \
grpck.8 \
gshadow.5 \
lastlog.8 \
nologin.8 \
passwd.5 \
shadow.5 \
su.1 \
vipw.8
EXTRA_DIST = $(man_MANS) \
man1/id.1 \
man8/groupmems.8 \
man8/logoutd.8
id.1 \
groupmems.8 \
logoutd.8

Some files were not shown because too many files have changed in this diff Show More