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
10429 changed files with 48380 additions and 494381 deletions
-3
View File
@@ -17,8 +17,6 @@ Makefile.in
/ABOUT-NLS /ABOUT-NLS
/aclocal.m4 /aclocal.m4
/autom4te.cache /autom4te.cache
/compile
/config.cache
/config.guess /config.guess
/config.h /config.h
/config.h.in /config.h.in
@@ -46,5 +44,4 @@ Makefile.in
/po/stamp-po /po/stamp-po
/shadow.spec /shadow.spec
/shadow-*.tar.*
/libmisc/getdate.c /libmisc/getdate.c
-20
View File
@@ -1,20 +0,0 @@
sudo: false
language: c
compiler:
- gcc
- clang
addons:
apt:
packages:
- autopoint
- xsltproc
script:
- ./autogen.sh --without-selinux --disable-man
- grep ENABLE_ config.status
- make
# vim:et:ts=2:sw=2
+4 -2678
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -2,5 +2,7 @@
EXTRA_DIST = NEWS README TODO shadow.spec.in EXTRA_DIST = NEWS README TODO shadow.spec.in
AUTOMAKE_OPTIONS = 1.5 dist-bzip2 foreign
SUBDIRS = po man libmisc lib src \ SUBDIRS = po man libmisc lib src \
contrib doc etc contrib doc etc
+2 -203
View File
@@ -1,207 +1,6 @@
$Id$ $Id$
shadow-4.1.5.1 -> shadow-4.2 UNRELEASED shadow-4.1.4.1 -> shadow-4.1.4.2 2009-07-24
*** 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
- general - general
* Improved support for large groups (impacts most user/group management * 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. faillog faster.
- gpasswd - gpasswd
* Fix failures when the gshadow file is not present. * 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). to indicate that the password is shadowed (consistency with grpconv).
* Make sure the group and gshadow files are unlocked on exit. * Make sure the group and gshadow files are unlocked on exit.
- groupadd - groupadd
+2 -7
View File
@@ -37,7 +37,7 @@ S/Key support:
Authors and contributors 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 reports and various comments. This list may be incomplete, I received
a lot of mail... a lot of mail...
@@ -69,7 +69,6 @@ Greg Mortensen <loki@world.std.com>
Guido van Rooij Guido van Rooij
Guy Maor <maor@debian.org> Guy Maor <maor@debian.org>
Hrvoje Dogan <hdogan@bjesomar.srce.hr> Hrvoje Dogan <hdogan@bjesomar.srce.hr>
Jakub Hrozek <jhrozek@redhat.com>
Janos Farkas <chexum@bankinf.banki.hu> Janos Farkas <chexum@bankinf.banki.hu>
Jay Soffian <jay@lw.net> Jay Soffian <jay@lw.net>
Jesse Thilo <Jesse.Thilo@pobox.com> Jesse Thilo <Jesse.Thilo@pobox.com>
@@ -81,7 +80,6 @@ Joshua Cowan <jcowan@hermit.reslife.okstate.edu>
Judd Bourgeois <shagboy@bluesky.net> Judd Bourgeois <shagboy@bluesky.net>
Juergen Heinzl <unicorn@noris.net> Juergen Heinzl <unicorn@noris.net>
Juha Virtanen <jiivee@iki.fi> Juha Virtanen <jiivee@iki.fi>
Julian Pidancet <julian.pidancet@gmail.com>
Julianne Frances Haugh <jockgrrl@ix.netcom.com> Julianne Frances Haugh <jockgrrl@ix.netcom.com>
Leonard N. Zubkoff <lnz@dandelion.com> Leonard N. Zubkoff <lnz@dandelion.com>
Luca Berra <bluca@www.polimi.it> Luca Berra <bluca@www.polimi.it>
@@ -97,12 +95,10 @@ Mike Pakovic <mpakovic@users.southeast.net>
Nicolas François <nicolas.francois@centraliens.net> Nicolas François <nicolas.francois@centraliens.net>
Nikos Mavroyanopoulos <nmav@i-net.paiko.gr> Nikos Mavroyanopoulos <nmav@i-net.paiko.gr>
Pavel Machek <pavel@bug.ucw.cz> Pavel Machek <pavel@bug.ucw.cz>
Peter Vrabec <pvrabec@redhat.com>
Phillip Street Phillip Street
Rafał Maszkowski <rzm@icm.edu.pl> Rafał Maszkowski <rzm@icm.edu.pl>
Rani Chouha <ranibey@smartec.com> Rani Chouha <ranibey@smartec.com>
Sami Kerola <kerolasa@rocketmail.com> Sami Kerola <kerolasa@rocketmail.com>
Scott Garman <scott.a.garman@intel.com>
Sebastian Rick Rijkers <srrijkers@gmail.com> Sebastian Rick Rijkers <srrijkers@gmail.com>
Seraphim Mellos <mellos@ceid.upatras.gr> Seraphim Mellos <mellos@ceid.upatras.gr>
Shane Watts <shane@nexus.mlckew.edu.au> Shane Watts <shane@nexus.mlckew.edu.au>
@@ -117,6 +113,5 @@ Maintainers
=========== ===========
Tomasz Kłoczko <kloczek@pld.org.pl> (2000-2007) Tomasz Kłoczko <kloczek@pld.org.pl> (2000-2007)
Nicolas François <nicolas.francois@centraliens.net> (2007-2014) Nicolas François <nicolas.francois@centraliens.net> (2007-now)
Serge E. Hallyn <serge@hallyn.com> (2014-now)
+1 -14
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 /etc/default/useradd
* GROUP=1000 should accept a group name. * GROUP=1000 should accept a group name.
@@ -115,13 +108,7 @@ ALL:
entry (with a password). entry (with a password).
- Add check to move passwd passwords to shadow if there is a shadow - Add check to move passwd passwords to shadow if there is a shadow
file. file.
- Support an alternative /etc/tcb directory as second parameter.
- add options -g / -G to specify alternative group / gshadow files
- su - su
- add a login.defs configuration parameter to add variables to keep in - add a login.defs configuration parameter to add variables to keep in
the environment with "su -l" (TERM/TERMCOLOR/...) the environment with "su -l" (TERM/TERMCOLOR/...
- vipw
- set ACLs and XATTRs on the temporary file (and backups?)
- vipw + selinux -> use lib/selinux.c
-2
View File
@@ -1,7 +1,5 @@
#! /bin/sh #! /bin/sh
autoreconf -v -f --install || exit 1 autoreconf -v -f --install || exit 1
./configure \ ./configure \
CFLAGS="-O2 -Wall" \ CFLAGS="-O2 -Wall" \
--enable-man \ --enable-man \
+16 -150
View File
@@ -1,9 +1,6 @@
dnl Process this file with autoconf to produce a configure script. dnl Process this file with autoconf to produce a configure script.
AC_PREREQ([2.64]) AC_INIT
AC_INIT([shadow], [4.5], [pkg-shadow-devel@lists.alioth.debian.org], [], AM_INIT_AUTOMAKE(shadow, 4.1.4.2)
[https://github.com/shadow-maint/shadow])
AM_INIT_AUTOMAKE([1.11 foreign dist-xz])
AM_SILENT_RULES([yes])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
dnl Some hacks... dnl Some hacks...
@@ -22,6 +19,7 @@ AC_PROG_CC
AC_ISC_POSIX AC_ISC_POSIX
AC_PROG_LN_S AC_PROG_LN_S
AC_PROG_YACC AC_PROG_YACC
AM_C_PROTOTYPES
AM_PROG_LIBTOOL AM_PROG_LIBTOOL
dnl Checks for libraries. dnl Checks for libraries.
@@ -35,8 +33,7 @@ AC_HEADER_STDBOOL
AC_CHECK_HEADERS(errno.h fcntl.h limits.h unistd.h sys/time.h utmp.h \ 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 \ 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 \ 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 \ locale.h rpc/key_prot.h netdb.h)
attr/error_context.h)
dnl shadow now uses the libc's shadow implementation dnl shadow now uses the libc's shadow implementation
AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])]) AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])])
@@ -44,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 \ AC_CHECK_FUNCS(l64a fchmod fchown fsync futimes getgroups gethostname getspnam \
gettimeofday getusershell getutent initgroups lchown lckpwdf lstat \ gettimeofday getusershell getutent initgroups lchown lckpwdf lstat \
lutimes memcpy memset setgroups sigaction strchr updwtmp updwtmpx innetgr \ lutimes memcpy memset setgroups sigaction strchr updwtmp updwtmpx innetgr \
getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo \ getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo)
ruserok)
AC_SYS_LARGEFILE AC_SYS_LARGEFILE
dnl Checks for typedefs, structures, and compiler characteristics. dnl Checks for typedefs, structures, and compiler characteristics.
@@ -116,6 +112,7 @@ AC_REPLACE_FUNCS(sgetgrent sgetpwent sgetspent)
AC_REPLACE_FUNCS(snprintf strcasecmp strdup strerror strstr) AC_REPLACE_FUNCS(snprintf strcasecmp strdup strerror strstr)
AC_CHECK_FUNC(setpgrp) AC_CHECK_FUNC(setpgrp)
AC_FUNC_SETPGRP
if test "$ac_cv_header_shadow_h" = "yes"; then if test "$ac_cv_header_shadow_h" = "yes"; then
AC_CACHE_CHECK(for working shadow group support, AC_CACHE_CHECK(for working shadow group support,
@@ -198,10 +195,8 @@ AC_DEFINE_UNQUOTED(PASSWD_PROGRAM, "$shadow_cv_passwd_dir/passwd",
dnl XXX - quick hack, should disappear before anyone notices :). dnl XXX - quick hack, should disappear before anyone notices :).
AC_DEFINE(USE_SYSLOG, 1, [Define to use syslog().]) 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(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_DEFINE(RUSEROK, 0, [Define to the ruserok() "success" return value (0 or 1).])
fi
AC_ARG_ENABLE(shadowgrp, AC_ARG_ENABLE(shadowgrp,
[AC_HELP_STRING([--enable-shadowgrp], [enable shadow group support @<:@default=yes@:>@])], [AC_HELP_STRING([--enable-shadowgrp], [enable shadow group support @<:@default=yes@:>@])],
@@ -243,13 +238,6 @@ AC_ARG_ENABLE(utmpx,
[enable_utmpx="no"] [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_ARG_WITH(audit,
[AC_HELP_STRING([--with-audit], [use auditing support @<:@default=yes if found@:>@])], [AC_HELP_STRING([--with-audit], [use auditing support @<:@default=yes if found@:>@])],
[with_audit=$withval], [with_audit=maybe]) [with_audit=$withval], [with_audit=maybe])
@@ -259,20 +247,11 @@ AC_ARG_WITH(libpam,
AC_ARG_WITH(selinux, AC_ARG_WITH(selinux,
[AC_HELP_STRING([--with-selinux], [use SELinux support @<:@default=yes if found@:>@])], [AC_HELP_STRING([--with-selinux], [use SELinux support @<:@default=yes if found@:>@])],
[with_selinux=$withval], [with_selinux=maybe]) [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_ARG_WITH(skey,
[AC_HELP_STRING([--with-skey], [use S/Key support @<:@default=no@:>@])], [AC_HELP_STRING([--with-skey], [use S/Key support @<:@default=no@:>@])],
[with_skey=$withval], [with_skey=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_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]) [with_libcrack=$withval], [with_libcrack=no])
AC_ARG_WITH(sha-crypt, AC_ARG_WITH(sha-crypt,
[AC_HELP_STRING([--with-sha-crypt], [allow the SHA256 and SHA512 password encryption algorithms @<:@default=yes@:>@])], [AC_HELP_STRING([--with-sha-crypt], [allow the SHA256 and SHA512 password encryption algorithms @<:@default=yes@:>@])],
@@ -334,81 +313,10 @@ if test "$enable_man" = "yes"; then
fi fi
AM_CONDITIONAL(ENABLE_REGENERATE_MAN, test "x$enable_man" != "xno") 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_SUBST(LIBCRYPT)
AC_CHECK_LIB(crypt, crypt, [LIBCRYPT=-lcrypt], AC_CHECK_LIB(crypt, crypt, [LIBCRYPT=-lcrypt],
[AC_MSG_ERROR([crypt() not found])]) [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) AC_SUBST(LIBAUDIT)
if test "$with_audit" != "no"; then if test "$with_audit" != "no"; then
AC_CHECK_HEADER(libaudit.h, [audit_header="yes"], [audit_header="no"]) AC_CHECK_HEADER(libaudit.h, [audit_header="yes"], [audit_header="no"])
@@ -453,65 +361,28 @@ if test "$with_libcrack" = "yes"; then
fi fi
AC_SUBST(LIBSELINUX) AC_SUBST(LIBSELINUX)
AC_SUBST(LIBSEMANAGE)
if test "$with_selinux" != "no"; then if test "$with_selinux" != "no"; then
AC_CHECK_HEADERS(selinux/selinux.h, [selinux_header="yes"], [selinux_header="no"]) AC_CHECK_HEADERS(selinux/selinux.h, [selinux_header="yes"], [selinux_header="no"])
if test "$selinux_header$with_selinux" = "noyes" ; then if test "$selinux_header$with_selinux" = "noyes" ; then
AC_MSG_ERROR([selinux/selinux.h is missing]) AC_MSG_ERROR([selinux/selinux.h is missing])
fi elif test "$selinux_header" = "yes" ; then
AC_CHECK_LIB(selinux, is_selinux_enabled,
AC_CHECK_HEADERS(semanage/semanage.h, [semanage_header="yes"], [semanage_header="no"]) [selinux_lib="yes"], [selinux_lib="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"])
if test "$selinux_lib$with_selinux" = "noyes" ; then if test "$selinux_lib$with_selinux" = "noyes" ; then
AC_MSG_ERROR([libselinux not found]) AC_MSG_ERROR([libselinux not found])
fi elif test "$selinux_lib" = "no" ; then
with_selinux="no"
AC_CHECK_LIB(semanage, semanage_connect, [semanage_lib="yes"], [semanage_lib="no"]) else
if test "$semanage_lib$with_selinux" = "noyes" ; then
AC_MSG_ERROR([libsemanage not found])
fi
if test "$selinux_lib$semanage_lib" == "yesyes" ; then
AC_DEFINE(WITH_SELINUX, 1, AC_DEFINE(WITH_SELINUX, 1,
[Build shadow with SELinux support]) [Build shadow with SELinux support])
LIBSELINUX="-lselinux" LIBSELINUX="-lselinux"
LIBSEMANAGE="-lsemanage"
with_selinux="yes" with_selinux="yes"
else
with_selinux="no"
fi fi
else else
with_selinux="no" with_selinux="no"
fi fi
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) AC_SUBST(LIBPAM)
if test "$with_libpam" != "no"; then if test "$with_libpam" != "no"; then
AC_CHECK_LIB(pam, pam_start, AC_CHECK_LIB(pam, pam_start,
@@ -632,9 +503,8 @@ AC_CONFIG_FILES([
doc/Makefile doc/Makefile
man/Makefile man/Makefile
man/config.xml man/config.xml
man/po/Makefile man/po/Makefile.in
man/cs/Makefile man/cs/Makefile
man/da/Makefile
man/de/Makefile man/de/Makefile
man/es/Makefile man/es/Makefile
man/fi/Makefile man/fi/Makefile
@@ -671,12 +541,8 @@ if test "$with_libpam" = "yes"; then
echo " suid account management tools: $enable_acct_tools_setuid" echo " suid account management tools: $enable_acct_tools_setuid"
fi fi
echo " SELinux support: $with_selinux" 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 " shadow group support: $enable_shadowgrp"
echo " S/Key support: $with_skey" echo " S/Key support: $with_skey"
echo " SHA passwords encryption: $with_sha_crypt" echo " SHA passwords encryption: $with_sha_crypt"
echo " nscd support: $with_nscd" echo " nscd support: $with_nscd"
echo " subordinate IDs support: $enable_subids"
echo echo
+50 -64
View File
@@ -6,18 +6,18 @@
# #
# Delay in seconds before being allowed another attempt after a login failure # 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. # Note: When PAM is used, some modules may enfore a minimal delay (e.g.
# pam_unix(8) enforces a 2s delay) # pam_unix enforces a 2s delay)
# #
FAIL_DELAY 3 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 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 LOG_UNKFAIL_ENAB no
@@ -27,7 +27,7 @@ LOG_UNKFAIL_ENAB no
LOG_OK_LOGINS 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 LASTLOG_ENAB yes
@@ -50,13 +50,13 @@ OBSCURE_CHECKS_ENAB yes
PORTTIME_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 QUOTAS_ENAB yes
# #
# Enable "syslog" logging of su(1) activity - in addition to sulog file logging. # Enable "syslog" logging of su activity - in addition to sulog file logging.
# SYSLOG_SG_ENAB does the same for newgrp(1) and sg(1). # SYSLOG_SG_ENAB does the same for newgrp and sg.
# #
SYSLOG_SU_ENAB yes SYSLOG_SU_ENAB yes
SYSLOG_SG_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 # If defined, either full pathname of a file containing device names or
# a ":" delimited list of device names. Root logins will be allowed only # a ":" delimited list of device names. Root logins will be allowed only
# from these devices. # upon these devices.
# #
CONSOLE /etc/securetty CONSOLE /etc/securetty
#CONSOLE console:tty01:tty02:tty03:tty04 #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 #SULOG_FILE /var/log/sulog
@@ -82,33 +82,33 @@ MOTD_FILE /etc/motd
#MOTD_FILE /etc/motd:/usr/lib/news/news-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 #ISSUE_FILE /etc/issue
# #
# If defined, file which maps tty line to TERM environment parameter. # 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 #TTYTYPE_FILE /etc/ttytype
# #
# If defined, login(1) failures will be logged here in a utmp format. # If defined, login failures will be logged here in a utmp format.
# last(1), when invoked as lastb(1), will read /var/log/btmp, so... # last, when invoked as lastb, will read /var/log/btmp, so...
# #
FTMP_FILE /var/log/btmp FTMP_FILE /var/log/btmp
# #
# If defined, name of file whose presence will inhibit non-root # If defined, name of file whose presence which will inhibit non-root
# logins. The content of this file should be a message indicating # logins. The contents of this file should be a message indicating
# why logins are inhibited. # why logins are inhibited.
# #
NOLOGINS_FILE /etc/nologin NOLOGINS_FILE /etc/nologin
# #
# If defined, the command name to display when running "su -". For # If defined, the command name to display when running "su -". For
# example, if this is defined as "su" then ps(1) will display the # example, if this is defined as "su" then a "ps" will display the
# command as "-su". If not defined, then ps(1) 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". # name of the shell actually being run, e.g. something like "-sh".
# #
SU_NAME su SU_NAME su
@@ -158,10 +158,10 @@ ENV_PATH PATH=/bin:/usr/bin
# TTYGROUP Login tty will be assigned this group ownership. # TTYGROUP Login tty will be assigned this group ownership.
# TTYPERM Login tty will be set to this permission. # TTYPERM Login tty will be set to this permission.
# #
# If you have a write(1) program which is "setgid" to a special group # If you have a "write" program which is "setgid" to a special group
# which owns the terminals, define TTYGROUP as the number of such group # which owns the terminals, define TTYGROUP to the group number and
# and TTYPERM as 0620. Otherwise leave TTYGROUP commented out and # TTYPERM to 0620. Otherwise leave TTYGROUP commented out and assign
# set TTYPERM to either 622 or 600. # TTYPERM to either 622 or 600.
# #
TTYGROUP tty TTYGROUP tty
TTYPERM 0600 TTYPERM 0600
@@ -183,13 +183,12 @@ ERASECHAR 0177
KILLCHAR 025 KILLCHAR 025
#ULIMIT 2097152 #ULIMIT 2097152
# Default initial "umask" value used by login(1) on non-PAM enabled systems. # Default initial "umask" value for non-PAM enabled systems.
# Default "umask" value for pam_umask(8) on PAM enabled systems. # UMASK is also used by useradd and newusers to set the mode of new home
# UMASK is also used by useradd(8) and newusers(8) to set the mode for new # directories.
# home directories.
# 022 is the default value, but 027, or even 077, could be considered # 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 # better for privacy. There is no One True Answer here: each sysadmin
# must make up his/her mind. # must make up her mind.
UMASK 022 UMASK 022
# #
@@ -214,43 +213,35 @@ PASS_WARN_AGE 7
SU_WHEEL_ONLY no 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 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_MIN 1000
UID_MAX 60000 UID_MAX 60000
# System accounts # System accounts
SYS_UID_MIN 101 SYS_UID_MIN 101
SYS_UID_MAX 999 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_MIN 1000
GID_MAX 60000 GID_MAX 60000
# System accounts # System accounts
SYS_GID_MIN 101 SYS_GID_MIN 101
SYS_GID_MAX 999 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 LOGIN_RETRIES 5
# #
# Max time in seconds for login(1) # Max time in seconds for login
# #
LOGIN_TIMEOUT 60 LOGIN_TIMEOUT 60
@@ -272,12 +263,12 @@ PASS_ALWAYS_WARN yes
#PASS_MAX_LEN 8 #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 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 # any combination of letters "frwh" (full name, room number, work
# phone, home phone). If not defined, no changes are allowed. # phone, home phone). If not defined, no changes are allowed.
# For backward compatibility, "yes" = "rwh" and "no" = "frwh". # 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 # Note: If you use PAM, it is recommended to use a value consistent with
# the PAM modules configuration. # 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 #MD5_CRYPT_ENAB no
# #
# Only works if compiled with ENCRYPTMETHOD_SELECT defined: # 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 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 SHA512, SHA512-based algorithm will be used for encrypting password
# If set to DES, DES-based algorithm will be used for encrypting password (default) # 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. # Only works if ENCRYPT_METHOD is set to SHA256 or SHA512.
# #
# Define the number of SHA rounds. # Define the number of SHA rounds.
# With a lot of rounds, it is more difficult to brute-force the password. # With a lot of rounds, it is more difficult to brute forcing the password.
# However, more CPU resources will be needed to authenticate users if # But note also that it more CPU resources will be needed to authenticate
# this value is increased. # users.
# #
# If not specified, the libc will choose the default number of rounds (5000). # 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 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. # 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 # 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. # setting). Default is none.
# #
# Use with caution - it is possible for users to gain permanent # 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... # How to do it is left as an exercise for the reader...
# #
#CONSOLE_GROUPS floppy:audio:cdrom #CONSOLE_GROUPS floppy:audio:cdrom
# #
# Should login be allowed if we can't cd to the home directory? # Should login be allowed if we can't cd to the home directory?
# Default is no. # Default in no.
# #
DEFAULT_HOME yes DEFAULT_HOME yes
@@ -370,14 +361,14 @@ ENVIRON_FILE /etc/environment
# (examples: 022 -> 002, 077 -> 007) for non-root users, if the uid is # (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. # 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 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. # 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 # with the same group ID, to avoid limitation of the line length in the
# group file). # group file).
# #
@@ -386,15 +377,10 @@ USERGROUPS_ENAB yes
#MAX_MEMBERS_PER_GROUP 0 #MAX_MEMBERS_PER_GROUP 0
# #
# If useradd(8) should create home directories for users by default (non # If useradd should create home directories for users by default (non
# system users only). # system users only)
# This option is overridden with the -M or -m flags on the useradd(8) # This option is overridden with the -M or -m flags on the useradd command
# command-line. # line.
# #
#CREATE_HOME yes #CREATE_HOME yes
#
# Force use shadow, even if shadow passwd & shadow group files are
# missing.
#
#FORCE_SHADOW yes
-10
View File
@@ -14,7 +14,6 @@ libshadow_la_SOURCES = \
encrypt.c \ encrypt.c \
exitcodes.h \ exitcodes.h \
faillog.h \ faillog.h \
fields.c \
fputsx.c \ fputsx.c \
getdef.c \ getdef.c \
getdef.h \ getdef.h \
@@ -39,10 +38,6 @@ libshadow_la_SOURCES = \
pwio.c \ pwio.c \
pwio.h \ pwio.h \
pwmem.c \ pwmem.c \
subordinateio.h \
subordinateio.c \
selinux.c \
semanage.c \
sgetgrent.c \ sgetgrent.c \
sgetpwent.c \ sgetpwent.c \
sgetspent.c \ sgetspent.c \
@@ -52,13 +47,8 @@ libshadow_la_SOURCES = \
shadowio.c \ shadowio.c \
shadowio.h \ shadowio.h \
shadowmem.c \ shadowmem.c \
spawn.c \
utent.c utent.c
if WITH_TCB
libshadow_la_SOURCES += tcbfuncs.c tcbfuncs.h
endif
# These files are unneeded for some reason, listed in # These files are unneeded for some reason, listed in
# order of appearance: # order of appearance:
# #
+88 -214
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1990 - 1994, Julianne Frances Haugh * Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2001, Marek Michałkiewicz * Copyright (c) 1996 - 2001, Marek Michałkiewicz
* Copyright (c) 2001 - 2006, Tomasz Kłoczko * Copyright (c) 2001 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2011, Nicolas François * Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -45,16 +45,16 @@
#include <stdio.h> #include <stdio.h>
#include <signal.h> #include <signal.h>
#include "nscd.h" #include "nscd.h"
#ifdef WITH_TCB #ifdef WITH_SELINUX
#include <tcb.h> #include <selinux/selinux.h>
#endif /* WITH_TCB */ #endif
#include "prototypes.h" #include "prototypes.h"
#include "commonio.h" #include "commonio.h"
/* local function prototypes */ /* local function prototypes */
static int lrename (const char *, const char *); static int lrename (const char *, const char *);
static int check_link_count (const char *file); 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 ( static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms (
const char *name, const char *name,
const char *mode, 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; int fd;
pid_t pid; 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); fd = open (file, O_CREAT | O_EXCL | O_WRONLY, 0600);
if (-1 == fd) { if (-1 == fd) {
if (log) {
(void) fprintf (stderr,
"%s: %s: %s\n",
Prog, file, strerror (errno));
}
return 0; 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); snprintf (buf, sizeof buf, "%lu", (unsigned long) pid);
len = (ssize_t) strlen (buf) + 1; len = (ssize_t) strlen (buf) + 1;
if (write (fd, buf, (size_t) len) != len) { if (write (fd, buf, (size_t) len) != len) {
if (log) {
(void) fprintf (stderr,
"%s: %s: %s\n",
Prog, file, strerror (errno));
}
(void) close (fd); (void) close (fd);
unlink (file); unlink (file);
return 0; return 0;
@@ -167,22 +157,12 @@ static int do_lock_file (const char *file, const char *lock, bool log)
if (link (file, lock) == 0) { if (link (file, lock) == 0) {
retval = check_link_count (file); retval = check_link_count (file);
if ((0==retval) && log) {
(void) fprintf (stderr,
"%s: %s: lock file already used\n",
Prog, file);
}
unlink (file); unlink (file);
return retval; return retval;
} }
fd = open (lock, O_RDWR); fd = open (lock, O_RDWR);
if (-1 == fd) { if (-1 == fd) {
if (log) {
(void) fprintf (stderr,
"%s: %s: %s\n",
Prog, lock, strerror (errno));
}
unlink (file); unlink (file);
errno = EINVAL; errno = EINVAL;
return 0; 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); len = read (fd, buf, sizeof (buf) - 1);
close (fd); close (fd);
if (len <= 0) { if (len <= 0) {
if (log) {
(void) fprintf (stderr,
"%s: existing lock file %s without a PID\n",
Prog, lock);
}
unlink (file); unlink (file);
errno = EINVAL; errno = EINVAL;
return 0; return 0;
} }
buf[len] = '\0'; buf[len] = '\0';
if (get_pid (buf, &pid) == 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); unlink (file);
errno = EINVAL; errno = EINVAL;
return 0; return 0;
} }
if (kill (pid, 0) == 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); unlink (file);
errno = EEXIST; errno = EEXIST;
return 0; return 0;
} }
if (unlink (lock) != 0) { if (unlink (lock) != 0) {
if (log) {
(void) fprintf (stderr,
"%s: cannot get lock %s: %s\n",
Prog, lock, strerror (errno));
}
unlink (file); unlink (file);
return 0; return 0;
} }
retval = 0; retval = 0;
if (link (file, lock) == 0) { if ((link (file, lock) == 0) && (check_link_count (file) != 0)) {
retval = check_link_count (file); retval = 1;
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));
}
} }
unlink (file); unlink (file);
@@ -270,21 +219,21 @@ static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms (
if (fchown (fileno (fp), sb->st_uid, sb->st_gid) != 0) { if (fchown (fileno (fp), sb->st_uid, sb->st_gid) != 0) {
goto fail; goto fail;
} }
#else /* !HAVE_FCHOWN */ #else
if (chown (name, sb->st_mode) != 0) { if (chown (name, sb->st_mode) != 0) {
goto fail; goto fail;
} }
#endif /* !HAVE_FCHOWN */ #endif
#ifdef HAVE_FCHMOD #ifdef HAVE_FCHMOD
if (fchmod (fileno (fp), sb->st_mode & 0664) != 0) { if (fchmod (fileno (fp), sb->st_mode & 0664) != 0) {
goto fail; goto fail;
} }
#else /* !HAVE_FCHMOD */ #else
if (chmod (name, sb->st_mode & 0664) != 0) { if (chmod (name, sb->st_mode & 0664) != 0) {
goto fail; goto fail;
} }
#endif /* !HAVE_FCHMOD */ #endif
return fp; return fp;
fail: fail:
@@ -301,12 +250,15 @@ static int create_backup (const char *backup, FILE * fp)
struct utimbuf ub; struct utimbuf ub;
FILE *bkfp; FILE *bkfp;
int c; int c;
mode_t mask;
if (fstat (fileno (fp), &sb) != 0) { if (fstat (fileno (fp), &sb) != 0) {
return -1; return -1;
} }
bkfp = fopen_set_perms (backup, "w", &sb); mask = umask (077);
bkfp = fopen (backup, "w");
(void) umask (mask);
if (NULL == bkfp) { if (NULL == bkfp) {
return -1; return -1;
} }
@@ -373,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 file[1024];
char lock[1024]; char lock[1024];
@@ -385,7 +337,7 @@ int commonio_lock_nowait (struct commonio_db *db, bool log)
snprintf (file, sizeof file, "%s.%lu", snprintf (file, sizeof file, "%s.%lu",
db->filename, (unsigned long) getpid ()); db->filename, (unsigned long) getpid ());
snprintf (lock, sizeof lock, "%s.lock", db->filename); 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; db->locked = true;
lock_count++; lock_count++;
return 1; return 1;
@@ -409,22 +361,17 @@ int commonio_lock (struct commonio_db *db)
*/ */
if (0 == lock_count) { if (0 == lock_count) {
if (lckpwdf () == -1) { if (lckpwdf () == -1) {
if (geteuid () != 0) {
(void) fprintf (stderr,
"%s: Permission denied.\n",
Prog);
}
return 0; /* failure */ return 0; /* failure */
} }
} }
if (commonio_lock_nowait (db, true) != 0) { if (commonio_lock_nowait (db) != 0) {
return 1; /* success */ return 1; /* success */
} }
ulckpwdf (); ulckpwdf ();
return 0; /* failure */ return 0; /* failure */
#else /* !HAVE_LCKPWDF */ #else
int i; int i;
/* /*
@@ -441,18 +388,16 @@ int commonio_lock (struct commonio_db *db)
if (i > 0) { if (i > 0) {
sleep (LOCK_SLEEP); /* delay between retries */ 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 */ return 1; /* success */
} }
/* no unnecessary retries on "permission denied" errors */ /* no unnecessary retries on "permission denied" errors */
if (geteuid () != 0) { if (geteuid () != 0) {
(void) fprintf (stderr, "%s: Permission denied.\n",
Prog);
return 0; return 0;
} }
} }
return 0; /* failure */ return 0; /* failure */
#endif /* !HAVE_LCKPWDF */ #endif
} }
static void dec_lock_count (void) static void dec_lock_count (void)
@@ -469,7 +414,7 @@ static void dec_lock_count (void)
} }
#ifdef HAVE_LCKPWDF #ifdef HAVE_LCKPWDF
ulckpwdf (); ulckpwdf ();
#endif /* HAVE_LCKPWDF */ #endif
} }
} }
} }
@@ -588,7 +533,6 @@ int commonio_open (struct commonio_db *db, int mode)
void *eptr = NULL; void *eptr = NULL;
int flags = mode; int flags = mode;
size_t buflen; size_t buflen;
int fd;
int saved_errno; int saved_errno;
mode &= ~O_CREAT; mode &= ~O_CREAT;
@@ -605,31 +549,11 @@ int commonio_open (struct commonio_db *db, int mode)
return 0; return 0;
} }
db->head = NULL; db->head = db->tail = NULL;
db->tail = NULL;
db->cursor = NULL; db->cursor = NULL;
db->changed = false; db->changed = false;
fd = open (db->filename, db->fp = fopen (db->filename, db->readonly ? "r" : "r+");
(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;
/* /*
* If O_CREAT was specified and the file didn't exist, it will be * If O_CREAT was specified and the file didn't exist, it will be
@@ -644,7 +568,16 @@ int commonio_open (struct commonio_db *db, int mode)
} }
/* Do not inherit fd in spawned processes (e.g. nscd) */ /* 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; buflen = BUFLEN;
buf = (char *) malloc (buflen); buf = (char *) malloc (buflen);
@@ -730,6 +663,12 @@ int commonio_open (struct commonio_db *db, int mode)
cleanup_errno: cleanup_errno:
saved_errno = errno; saved_errno = errno;
free_linked_list (db); free_linked_list (db);
#ifdef WITH_SELINUX
if (db->scontext != NULL) {
freecon (db->scontext);
db->scontext = NULL;
}
#endif
fclose (db->fp); fclose (db->fp);
db->fp = NULL; db->fp = NULL;
errno = saved_errno; errno = saved_errno;
@@ -744,26 +683,10 @@ commonio_sort (struct commonio_db *db, int (*cmp) (const void *, const void *))
{ {
struct commonio_entry **entries, *ptr; struct commonio_entry **entries, *ptr;
size_t n = 0, i; size_t n = 0, i;
#if KEEP_NIS_AT_END
struct commonio_entry *nis = NULL;
#endif
for (ptr = db->head; for (ptr = db->head; NULL != ptr; ptr = ptr->next) {
(NULL != ptr)
#if KEEP_NIS_AT_END
&& ((NULL == ptr->line)
|| (('+' != ptr->line[0])
&& ('-' != ptr->line[0])))
#endif
;
ptr = ptr->next) {
n++; n++;
} }
#if KEEP_NIS_AT_END
if (NULL != ptr) {
nis = ptr;
}
#endif
if (n <= 1) { if (n <= 1) {
return 0; return 0;
@@ -775,40 +698,18 @@ commonio_sort (struct commonio_db *db, int (*cmp) (const void *, const void *))
} }
n = 0; n = 0;
for (ptr = db->head; for (ptr = db->head; NULL != ptr; ptr = ptr->next) {
#if KEEP_NIS_AT_END entries[n++] = ptr;
nis != ptr;
#else
NULL != ptr;
#endif
/*@ -nullderef @*/
ptr = ptr->next
/*@ +nullderef @*/
) {
entries[n] = ptr;
n++;
} }
qsort (entries, n, sizeof (struct commonio_entry *), cmp); qsort (entries, n, sizeof (struct commonio_entry *), cmp);
/* Take care of the head and tail separately */
db->head = entries[0]; db->head = entries[0];
n--; db->tail = entries[--n];
#if KEEP_NIS_AT_END
if (NULL == nis)
#endif
{
db->tail = entries[n];
}
db->head->prev = NULL; db->head->prev = NULL;
db->head->next = entries[1]; db->head->next = entries[1];
entries[n]->prev = entries[n - 1]; db->tail->prev = entries[n - 1];
#if KEEP_NIS_AT_END db->tail->next = NULL;
entries[n]->next = nis;
#else
entries[n]->next = NULL;
#endif
/* Now other elements have prev and next entries */
for (i = 1; i < n; i++) { for (i = 1; i < n; i++) {
entries[i]->prev = entries[i - 1]; entries[i]->prev = entries[i - 1];
entries[i]->next = entries[i + 1]; entries[i]->next = entries[i + 1];
@@ -823,8 +724,7 @@ commonio_sort (struct commonio_db *db, int (*cmp) (const void *, const void *))
/* /*
* Sort entries in db according to order in another. * Sort entries in db according to order in another.
*/ */
int commonio_sort_wrt (struct commonio_db *shadow, int commonio_sort_wrt (struct commonio_db *shadow, struct commonio_db *passwd)
const struct commonio_db *passwd)
{ {
struct commonio_entry *head = NULL, *pw_ptr, *spw_ptr; struct commonio_entry *head = NULL, *pw_ptr, *spw_ptr;
const char *name; const char *name;
@@ -911,6 +811,10 @@ int commonio_close (struct commonio_db *db)
int errors = 0; int errors = 0;
struct stat sb; struct stat sb;
#ifdef WITH_SELINUX
/*@null@*/security_context_t old_context = NULL;
#endif
if (!db->isopen) { if (!db->isopen) {
errno = EINVAL; errno = EINVAL;
return 0; return 0;
@@ -918,7 +822,7 @@ int commonio_close (struct commonio_db *db)
db->isopen = false; db->isopen = false;
if (!db->changed || db->readonly) { if (!db->changed || db->readonly) {
(void) fclose (db->fp); fclose (db->fp);
db->fp = NULL; db->fp = NULL;
goto success; goto success;
} }
@@ -930,21 +834,27 @@ int commonio_close (struct commonio_db *db)
memzero (&sb, sizeof sb); memzero (&sb, sizeof sb);
if (NULL != db->fp) { if (NULL != db->fp) {
if (fstat (fileno (db->fp), &sb) != 0) { if (fstat (fileno (db->fp), &sb) != 0) {
(void) fclose (db->fp); fclose (db->fp);
db->fp = NULL; db->fp = NULL;
goto fail; 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. * Create backup file.
*/ */
snprintf (buf, sizeof buf, "%s-", db->filename); 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) { if (create_backup (buf, db->fp) != 0) {
errors++; errors++;
} }
@@ -953,11 +863,6 @@ int commonio_close (struct commonio_db *db)
errors++; errors++;
} }
#ifdef WITH_SELINUX
if (reset_selinux_file_context () != 0) {
errors++;
}
#endif
if (errors != 0) { if (errors != 0) {
db->fp = NULL; db->fp = NULL;
goto fail; goto fail;
@@ -965,20 +870,15 @@ int commonio_close (struct commonio_db *db)
} else { } else {
/* /*
* Default permissions for new [g]shadow files. * Default permissions for new [g]shadow files.
* (passwd and group always exist...)
*/ */
sb.st_mode = db->st_mode; sb.st_mode = 0400;
sb.st_uid = db->st_uid; sb.st_uid = 0;
sb.st_gid = db->st_gid; sb.st_gid = 0;
} }
snprintf (buf, sizeof buf, "%s+", db->filename); 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); db->fp = fopen_set_perms (buf, "w", &sb);
if (NULL == db->fp) { if (NULL == db->fp) {
goto fail; goto fail;
@@ -995,9 +895,9 @@ int commonio_close (struct commonio_db *db)
if (fsync (fileno (db->fp)) != 0) { if (fsync (fileno (db->fp)) != 0) {
errors++; errors++;
} }
#else /* !HAVE_FSYNC */ #else
sync (); sync ();
#endif /* !HAVE_FSYNC */ #endif
if (fclose (db->fp) != 0) { if (fclose (db->fp) != 0) {
errors++; errors++;
} }
@@ -1013,18 +913,25 @@ int commonio_close (struct commonio_db *db)
goto fail; goto fail;
} }
#ifdef WITH_SELINUX
if (reset_selinux_file_context () != 0) {
goto fail;
}
#endif
nscd_need_reload = true; nscd_need_reload = true;
goto success; goto success;
fail: fail:
errors++; errors++;
success: 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); free_linked_list (db);
return errors == 0; return errors == 0;
} }
@@ -1055,7 +962,7 @@ static /*@dependent@*/ /*@null@*/struct commonio_entry *find_entry_by_name (
struct commonio_db *db, struct commonio_db *db,
const char *name) const char *name)
{ {
return next_entry_by_name (db, db->head, name); return next_entry_by_name(db, db->head, name);
} }
@@ -1077,7 +984,6 @@ int commonio_update (struct commonio_db *db, const void *eptr)
if (NULL != p) { if (NULL != p) {
if (next_entry_by_name (db, p->next, db->ops->getname (eptr)) != NULL) { 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); 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; return 0;
} }
db->ops->free (p->eptr); db->ops->free (p->eptr);
@@ -1102,46 +1008,14 @@ int commonio_update (struct commonio_db *db, const void *eptr)
#if KEEP_NIS_AT_END #if KEEP_NIS_AT_END
add_one_entry_nis (db, p); add_one_entry_nis (db, p);
#else /* !KEEP_NIS_AT_END */ #else
add_one_entry (db, p); add_one_entry (db, p);
#endif /* !KEEP_NIS_AT_END */ #endif
db->changed = true; db->changed = true;
return 1; 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) void commonio_del_entry (struct commonio_db *db, const struct commonio_entry *p)
{ {
+8 -18
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1990 - 1994, Julianne Frances Haugh * Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 - 2005, Tomasz Kłoczko * Copyright (c) 2001 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François * Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -31,8 +31,8 @@
*/ */
/* $Id$ */ /* $Id$ */
#ifndef COMMONIO_H #ifndef _COMMONIO_H
#define COMMONIO_H #define _COMMONIO_H
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
#include <selinux/selinux.h> #include <selinux/selinux.h>
@@ -123,17 +123,10 @@ struct commonio_db {
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
/*@null@*/security_context_t scontext; /*@null@*/security_context_t scontext;
#endif #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. * Head, tail, current position in linked list.
*/ */
/*@owned@*/ /*@null@*/struct commonio_entry *head; /*@owned@*/ /*@null@*/struct commonio_entry *head, *tail;
/*@dependent@*/ /*@null@*/struct commonio_entry *tail;
/*@dependent@*/ /*@null@*/struct commonio_entry *cursor; /*@dependent@*/ /*@null@*/struct commonio_entry *cursor;
/* /*
@@ -148,23 +141,20 @@ struct commonio_db {
extern int commonio_setname (struct commonio_db *, const char *); extern int commonio_setname (struct commonio_db *, const char *);
extern bool commonio_present (const struct commonio_db *db); extern bool commonio_present (const struct commonio_db *db);
extern int commonio_lock (struct commonio_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 int commonio_open (struct commonio_db *, int);
extern /*@observer@*/ /*@null@*/const void *commonio_locate (struct commonio_db *, const char *); extern /*@observer@*/ /*@null@*/const void *commonio_locate (struct commonio_db *, const char *);
extern int commonio_update (struct commonio_db *, const void *); 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_remove (struct commonio_db *, const char *);
extern int commonio_rewind (struct commonio_db *); extern int commonio_rewind (struct commonio_db *);
extern /*@observer@*/ /*@null@*/const void *commonio_next (struct commonio_db *); extern /*@observer@*/ /*@null@*/const void *commonio_next (struct commonio_db *);
extern int commonio_close (struct commonio_db *); extern int commonio_close (struct commonio_db *);
extern int commonio_unlock (struct commonio_db *); extern int commonio_unlock (struct commonio_db *);
extern void commonio_del_entry (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, 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, extern int commonio_sort (struct commonio_db *db,
int (*cmp) (const void *, const void *)); int (*cmp) (const void *, const void *));
#endif #endif
+1 -1
View File
@@ -177,7 +177,7 @@ char *strchr (), *strrchr (), *strtok ();
* --Nekral */ * --Nekral */
#define SYSLOG(x) \ #define SYSLOG(x) \
do { \ do { \
char *old_locale = setlocale (LC_ALL, NULL); \ char *old_locale = setlocale(LC_ALL, NULL); \
char *saved_locale = NULL; \ char *saved_locale = NULL; \
if (NULL != old_locale) { \ if (NULL != old_locale) { \
saved_locale = strdup (old_locale); \ saved_locale = strdup (old_locale); \
+12 -11
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1990 - 1993, Julianne Frances Haugh * Copyright (c) 1990 - 1993, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2005 , Tomasz Kłoczko * Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François * Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -40,26 +40,27 @@
#include "prototypes.h" #include "prototypes.h"
#include "defines.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]; static char cipher[128];
char *cp; char *cp;
cp = crypt (clear, salt); cp = crypt (clear, salt);
if (NULL == cp) { if (!cp) {
/* /*
* Single Unix Spec: crypt() may return a null pointer, * Single Unix Spec: crypt() may return a null pointer,
* and set errno to indicate an error. In this case return * and set errno to indicate an error. The caller doesn't
* the NULL so the caller can handle appropriately. * 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. */ * supported, and return a DES encrypted password. */
if ((NULL != salt) && (salt[0] == '$') && (strlen (cp) <= 13)) if ((NULL != salt) && (salt[0] == '$') && (strlen (cp) <= 13))
{ {
/*@observer@*/const char *method; const char *method;
switch (salt[1]) switch (salt[1])
{ {
case '1': case '1':
@@ -78,9 +79,9 @@
method = &nummethod[0]; method = &nummethod[0];
} }
} }
(void) fprintf (stderr, fprintf (stderr,
_("crypt method not supported by libcrypt? (%s)\n"), _("crypt method not supported by libcrypt? (%s)\n"),
method); method);
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} }
+29 -63
View File
@@ -49,32 +49,6 @@ struct itemdef {
/*@null@*/char *value; /* value given, or NULL if no value */ /*@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])) #define NUMDEFS (sizeof(def_table)/sizeof(def_table[0]))
static struct itemdef def_table[] = { static struct itemdef def_table[] = {
{"CHFN_RESTRICT", NULL}, {"CHFN_RESTRICT", NULL},
@@ -107,12 +81,6 @@ static struct itemdef def_table[] = {
{"SHA_CRYPT_MAX_ROUNDS", NULL}, {"SHA_CRYPT_MAX_ROUNDS", NULL},
{"SHA_CRYPT_MIN_ROUNDS", NULL}, {"SHA_CRYPT_MIN_ROUNDS", NULL},
#endif #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}, {"SULOG_FILE", NULL},
{"SU_NAME", NULL}, {"SU_NAME", NULL},
{"SYS_GID_MAX", NULL}, {"SYS_GID_MAX", NULL},
@@ -128,25 +96,33 @@ static struct itemdef def_table[] = {
{"USERDEL_CMD", NULL}, {"USERDEL_CMD", NULL},
{"USERGROUPS_ENAB", NULL}, {"USERGROUPS_ENAB", NULL},
#ifndef USE_PAM #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 #endif
#ifdef USE_SYSLOG #ifdef USE_SYSLOG
{"SYSLOG_SG_ENAB", NULL}, {"SYSLOG_SG_ENAB", NULL},
{"SYSLOG_SU_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 #endif
{NULL, NULL} {NULL, NULL}
}; };
@@ -410,17 +386,10 @@ static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name)
* Item was never found. * Item was never found.
*/ */
for (ptr = knowndef_table; NULL != ptr->name; ptr++) {
if (strcmp (ptr->name, name) == 0) {
goto out;
}
}
fprintf (stderr, fprintf (stderr,
_("configuration error - unknown item '%s' (notify administrator)\n"), _("configuration error - unknown item '%s' (notify administrator)\n"),
name); name);
SYSLOG ((LOG_CRIT, "unknown configuration item `%s'", name)); SYSLOG ((LOG_CRIT, "unknown configuration item `%s'", name));
out:
return (struct itemdef *) NULL; return (struct itemdef *) NULL;
} }
@@ -436,26 +405,23 @@ static void def_load (void)
FILE *fp; FILE *fp;
char buf[1024], *name, *value, *s; 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. * Open the configuration definitions file.
*/ */
fp = fopen (def_fname, "r"); fp = fopen (def_fname, "r");
if (NULL == fp) { if (NULL == fp) {
if (errno == ENOENT)
return;
int err = errno; int err = errno;
SYSLOG ((LOG_CRIT, "cannot open login definitions %s [%s]", SYSLOG ((LOG_CRIT, "cannot open login definitions %s [%s]",
def_fname, strerror (err))); def_fname, strerror (err)));
exit (EXIT_FAILURE); 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. * Go through all of the lines in the file.
*/ */
+6 -3
View File
@@ -44,19 +44,22 @@
*/ */
int getulong (const char *numstr, /*@out@*/unsigned long int *result) int getulong (const char *numstr, /*@out@*/unsigned long int *result)
{ {
unsigned long int val; long long int val;
char *endptr; char *endptr;
errno = 0; errno = 0;
val = strtoul (numstr, &endptr, 0); val = strtoll (numstr, &endptr, 0);
if ( ('\0' == *numstr) if ( ('\0' == *numstr)
|| ('\0' != *endptr) || ('\0' != *endptr)
|| (ERANGE == errno) || (ERANGE == errno)
/*@+ignoresigns@*/
|| (val != (unsigned long int)val)
/*@=ignoresigns@*/
) { ) {
return 0; return 0;
} }
*result = val; *result = (unsigned long int)val;
return 1; return 1;
} }
+10 -49
View File
@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal * Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2005 , Tomasz Kłoczko * Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François * Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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; 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; return (putgrent (gr, file) == -1) ? -1 : 0;
} }
@@ -130,9 +113,6 @@ static /*@owned@*/struct commonio_db group_db = {
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
NULL, /* scontext */ NULL, /* scontext */
#endif #endif
0644, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */ NULL, /* head */
NULL, /* tail */ NULL, /* tail */
NULL, /* cursor */ NULL, /* cursor */
@@ -333,12 +313,13 @@ static /*@null@*/struct commonio_entry *merge_group_entries (
/* Concatenate the 2 lines */ /* Concatenate the 2 lines */
new_line_len = strlen (gr1->line) + strlen (gr2->line) +1; 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) { if (NULL == new_line) {
errno = ENOMEM; errno = ENOMEM;
return NULL; return NULL;
} }
snprintf(new_line, new_line_len + 1, "%s\n%s", gr1->line, gr2->line); snprintf(new_line, new_line_len, "%s\n%s", gr1->line, gr2->line);
new_line[new_line_len] = '\0';
/* Concatenate the 2 list of members */ /* Concatenate the 2 list of members */
for (i=0; NULL != gptr1->gr_mem[i]; i++); for (i=0; NULL != gptr1->gr_mem[i]; i++);
@@ -355,7 +336,7 @@ static /*@null@*/struct commonio_entry *merge_group_entries (
members++; members++;
} }
} }
new_members = (char **)calloc ( (members+1), sizeof(char*) ); new_members = (char **)malloc ( (members+1) * sizeof(char*) );
if (NULL == new_members) { if (NULL == new_members) {
free (new_line); free (new_line);
errno = ENOMEM; errno = ENOMEM;
@@ -364,8 +345,6 @@ static /*@null@*/struct commonio_entry *merge_group_entries (
for (i=0; NULL != gptr1->gr_mem[i]; i++) { for (i=0; NULL != gptr1->gr_mem[i]; i++) {
new_members[i] = gptr1->gr_mem[i]; new_members[i] = gptr1->gr_mem[i];
} }
/* NULL termination enforced by above calloc */
members = i; members = i;
for (i=0; NULL != gptr2->gr_mem[i]; i++) { for (i=0; NULL != gptr2->gr_mem[i]; i++) {
char **pmember = new_members; char **pmember = new_members;
@@ -403,19 +382,15 @@ static int split_groups (unsigned int max_members)
struct commonio_entry *new; struct commonio_entry *new;
struct group *new_gptr; struct group *new_gptr;
unsigned int members = 0; unsigned int members = 0;
unsigned int i;
/* Check if this group must be split */ /* Check if this group must be split */
if (!gr->changed) { if (!gr->changed)
continue; continue;
} if (NULL == gptr)
if (NULL == gptr) {
continue; continue;
}
for (members = 0; NULL != gptr->gr_mem[members]; members++); for (members = 0; NULL != gptr->gr_mem[members]; members++);
if (members <= max_members) { if (members <= max_members)
continue; continue;
}
new = (struct commonio_entry *) malloc (sizeof *new); new = (struct commonio_entry *) malloc (sizeof *new);
if (NULL == new) { if (NULL == new) {
@@ -433,23 +408,9 @@ static int split_groups (unsigned int max_members)
new->changed = true; new->changed = true;
/* Enforce the maximum number of members on gptr */ /* Enforce the maximum number of members on gptr */
for (i = max_members; NULL != gptr->gr_mem[i]; i++) { gptr->gr_mem[max_members] = NULL;
free (gptr->gr_mem[i]);
gptr->gr_mem[i] = NULL;
}
/* Shift all the members */
/* The number of members in new_gptr will be check later */ /* The number of members in new_gptr will be check later */
for (i = 0; NULL != new_gptr->gr_mem[i + max_members]; i++) { new_gptr->gr_mem = &new_gptr->gr_mem[max_members];
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;
}
/* insert the new entry in the list */ /* insert the new entry in the list */
new->prev = gr; new->prev = gr;
+7 -24
View File
@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal * Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2005 , Tomasz Kłoczko * Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2007 - 2013, Nicolas François * Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -48,37 +48,25 @@
if (NULL == gr) { if (NULL == gr) {
return NULL; return NULL;
} }
/* The libc might define other fields. They won't be copied. */ *gr = *grent;
memset (gr, 0, sizeof *gr);
gr->gr_gid = grent->gr_gid;
/*@-mustfreeonly@*/
gr->gr_name = strdup (grent->gr_name); gr->gr_name = strdup (grent->gr_name);
/*@=mustfreeonly@*/
if (NULL == gr->gr_name) { if (NULL == gr->gr_name) {
gr_free(gr);
return NULL; return NULL;
} }
/*@-mustfreeonly@*/
gr->gr_passwd = strdup (grent->gr_passwd); gr->gr_passwd = strdup (grent->gr_passwd);
/*@=mustfreeonly@*/
if (NULL == gr->gr_passwd) { if (NULL == gr->gr_passwd) {
gr_free(gr);
return NULL; return NULL;
} }
for (i = 0; grent->gr_mem[i]; i++); for (i = 0; grent->gr_mem[i]; i++);
/*@-mustfreeonly@*/
gr->gr_mem = (char **) malloc ((i + 1) * sizeof (char *)); gr->gr_mem = (char **) malloc ((i + 1) * sizeof (char *));
/*@=mustfreeonly@*/
if (NULL == gr->gr_mem) { if (NULL == gr->gr_mem) {
gr_free(gr);
return NULL; return NULL;
} }
for (i = 0; grent->gr_mem[i]; i++) { for (i = 0; grent->gr_mem[i]; i++) {
gr->gr_mem[i] = strdup (grent->gr_mem[i]); gr->gr_mem[i] = strdup (grent->gr_mem[i]);
if (NULL == gr->gr_mem[i]) { if (NULL == gr->gr_mem[i]) {
gr_free(gr);
return NULL; return NULL;
} }
} }
@@ -90,16 +78,11 @@
void gr_free (/*@out@*/ /*@only@*/struct group *grent) void gr_free (/*@out@*/ /*@only@*/struct group *grent)
{ {
free (grent->gr_name); free (grent->gr_name);
if (NULL != grent->gr_passwd) { memzero (grent->gr_passwd, strlen (grent->gr_passwd));
memzero (grent->gr_passwd, strlen (grent->gr_passwd)); free (grent->gr_passwd);
free (grent->gr_passwd); while (*(grent->gr_mem)) {
} free (*(grent->gr_mem));
if (NULL != grent->gr_mem) { grent->gr_mem++;
size_t i;
for (i = 0; NULL != grent->gr_mem[i]; i++) {
free (grent->gr_mem[i]);
}
free (grent->gr_mem);
} }
free (grent); free (grent);
} }
+3 -3
View File
@@ -216,13 +216,13 @@ void endsgent (void)
static char *buf = NULL; static char *buf = NULL;
char *cp; char *cp;
struct sgrp *ret;
if (0 == buflen) { if (0 == buflen) {
buf = (char *) malloc (BUFSIZ); buf = (char *) malloc (BUFSIZ);
if (NULL == buf) { if (NULL == buf) {
return NULL; return NULL;
} }
buflen = BUFSIZ;
} }
if (NULL == fp) { if (NULL == fp) {
@@ -230,9 +230,9 @@ void endsgent (void)
} }
#ifdef USE_NIS #ifdef USE_NIS
while (fgetsx (buf, (int) buflen, fp) == buf) while (fgetsx (buf, (int) sizeof buf, fp) == buf)
#else #else
if (fgetsx (buf, (int) buflen, fp) == buf) if (fgetsx (buf, (int) sizeof buf, fp) == buf)
#endif #endif
{ {
while ( ((cp = strrchr (buf, '\n')) == NULL) while ( ((cp = strrchr (buf, '\n')) == NULL)
+1 -1
View File
@@ -43,7 +43,7 @@
struct sgrp { struct sgrp {
char *sg_name; /* group name */ char *sg_name; /* group name */
char *sg_passwd; /* group password */ char *sg_passwd; /* group password */
char **sg_adm; /* group administrator list */ char **sg_adm; /* group administator list */
char **sg_mem; /* group membership list */ char **sg_mem; /* group membership list */
}; };
+34 -26
View File
@@ -3,49 +3,57 @@
#include <config.h> #include <config.h>
#ifdef USE_NSCD #ifdef USE_NSCD
/* because of TEMP_FAILURE_RETRY */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <features.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <spawn.h>
#include <errno.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/types.h> #include <sys/types.h>
#include "exitcodes.h"
#include "defines.h" #include "defines.h"
#include "prototypes.h"
#include "nscd.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 * nscd_flush_cache - flush specified service buffer in nscd cache
*/ */
int nscd_flush_cache (const char *service) int nscd_flush_cache (const char *service)
{ {
int status, code; pid_t pid, termpid;
const char *cmd = "/usr/sbin/nscd"; int err, status;
const char *spawnedArgs[] = {"nscd", "-i", service, NULL}; char *spawnedArgs[] = {"/usr/sbin/nscd", "nscd", "-i", service, NULL};
const char *spawnedEnv[] = {NULL}; char *spawnedEnv[] = {NULL};
if (run_command (cmd, spawnedArgs, spawnedEnv, &status) != 0) { /* spawn process */
/* run_command writes its own more detailed message. */ err = posix_spawn (&pid, spawnedArgs[0], NULL, NULL,
(void) fprintf (stderr, _(MSG_NSCD_FLUSH_CACHE_FAILED), Prog); spawnedArgs, spawnedEnv);
if(0 != err)
{
(void) fputs (_(MSG_NSCD_FLUSH_CACHE_FAILED), stderr);
(void) fprintf (stderr, "posix_spawn() error=%d\n", err);
return -1; return -1;
} }
code = WEXITSTATUS (status); /* Wait for the spawned process to exit */
if (!WIFEXITED (status)) { termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
(void) fprintf (stderr, if (-1 == termpid)
_("%s: nscd did not terminate normally (signal %d)\n"), {
Prog, WTERMSIG (status)); (void) fputs (_(MSG_NSCD_FLUSH_CACHE_FAILED), stderr);
perror("waitpid");
return -1; return -1;
} else if (code == E_CMD_NOTFOUND) { }
/* nscd is not installed, or it is installed but uses an else if (termpid != pid)
interpreter that is missing. Probably the former. */ {
return 0; (void) fputs (_(MSG_NSCD_FLUSH_CACHE_FAILED), stderr);
} else if (code == 1) { (void) fprintf (stderr, "waitpid returned %ld != %ld\n",
/* nscd is installed, but it isn't active. */ (long int) termpid, (long int) pid);
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);
return -1; return -1;
} }
+28 -62
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1990 - 1994, Julianne Frances Haugh * Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko * Copyright (c) 2003 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François * Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -42,8 +42,6 @@
#ifndef _PROTOTYPES_H #ifndef _PROTOTYPES_H
#define _PROTOTYPES_H #define _PROTOTYPES_H
#include <config.h>
#include <sys/stat.h> #include <sys/stat.h>
#ifdef USE_UTMPX #ifdef USE_UTMPX
#include <utmpx.h> #include <utmpx.h>
@@ -59,7 +57,7 @@
#include "defines.h" #include "defines.h"
#include "commonio.h" #include "commonio.h"
extern /*@observer@*/ const char *Prog; extern char *Prog;
/* addgrps.c */ /* addgrps.c */
#if defined (HAVE_SETGROUPS) && ! defined (USE_PAM) #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() renamed to Basename() to avoid libc name space confusion */
/* basename.c */ /* basename.c */
extern /*@observer@*/const char *Basename (const char *str); extern char *Basename (char *str);
/* chowndir.c */ /* chowndir.c */
extern int chown_tree (const char *root, extern int chown_tree (const char *, uid_t, uid_t, gid_t, gid_t);
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
/* chowntty.c */ /* chowntty.c */
extern void chown_tty (const struct passwd *); extern void chown_tty (const struct passwd *);
/* cleanup.c */ /* cleanup.c */
typedef /*@null@*/void (*cleanup_function) (/*@null@*/void *arg); typedef void (*cleanup_function) (/*@null@*/void *arg);
void add_cleanup (/*@notnull@*/cleanup_function pcf, /*@null@*/void *arg); void add_cleanup (cleanup_function pcf, /*@null@*/void *arg);
void del_cleanup (/*@notnull@*/cleanup_function pcf); void del_cleanup (cleanup_function pcf);
void do_cleanups (void); void do_cleanups (void);
/* cleanup_group.c */ /* cleanup_group.c */
struct cleanup_info_mod { struct cleanup_info_mod {
char *audit_msg; char *audit_msg;
char *action; char *action;
/*@observer@*/const char *name; char *name;
}; };
void cleanup_report_add_group (void *group_name); void cleanup_report_add_group (void *group_name);
void cleanup_report_add_group_group (void *group_name); void cleanup_report_add_group_group (void *group_name);
@@ -120,13 +116,15 @@ extern bool console (const char *);
/* copydir.c */ /* copydir.c */
extern int copy_tree (const char *src_root, const char *dst_root, extern int copy_tree (const char *src_root, const char *dst_root,
bool copy_root, long int uid, long int gid);
bool reset_selinux, extern int remove_tree (const char *root);
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid); #ifdef WITH_SELINUX
extern int selinux_file_context (const char *dst_name);
#endif
/* encrypt.c */ /* encrypt.c */
extern /*@exposed@*//*@null@*/char *pw_encrypt (const char *, const char *); extern char *pw_encrypt (const char *, const char *);
/* entry.c */ /* entry.c */
extern void pw_entry (const char *, struct passwd *); extern void pw_entry (const char *, struct passwd *);
@@ -151,22 +149,11 @@ extern int find_new_uid (bool sys_user,
uid_t *uid, uid_t *uid,
/*@null@*/uid_t const *preferred_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 */ /* get_gid.c */
extern int get_gid (const char *gidstr, gid_t *gid); extern int get_gid (const char *gidstr, gid_t *gid);
/* getgr_nam_gid.c */ /* 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 */ /* getlong.c */
extern int getlong (const char *numstr, /*@out@*/long int *result); extern int getlong (const char *numstr, /*@out@*/long int *result);
@@ -179,9 +166,6 @@ extern int getrange (char *range,
unsigned long *min, bool *has_min, unsigned long *min, bool *has_min,
unsigned long *max, bool *has_max); unsigned long *max, bool *has_max);
/* gettime.c */
extern time_t gettime ();
/* get_uid.c */ /* get_uid.c */
extern int get_uid (const char *uidstr, uid_t *uid); extern int get_uid (const char *uidstr, uid_t *uid);
@@ -252,7 +236,7 @@ extern void mailcheck (void);
extern void motd (void); extern void motd (void);
/* myname.c */ /* myname.c */
extern /*@null@*//*@only@*/struct passwd *get_my_pwent (void); extern /*@null@*/struct passwd *get_my_pwent (void);
/* pam_pass_non_interractive.c */ /* pam_pass_non_interractive.c */
#ifdef USE_PAM #ifdef USE_PAM
@@ -263,7 +247,7 @@ extern int do_pam_passwd_non_interractive (const char *pam_service,
/* obscure.c */ /* obscure.c */
#ifndef USE_PAM #ifndef USE_PAM
extern bool obscure (const char *, const char *, const struct passwd *); extern int obscure (const char *, const char *, const struct passwd *);
#endif #endif
/* pam_pass.c */ /* pam_pass.c */
@@ -296,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 /*@null@*/ /*@only@*/struct passwd *__pw_dup (const struct passwd *pwent);
extern void pw_free (/*@out@*/ /*@only@*/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 */ /* rlogin.c */
extern int do_rlogin (const char *remote_host, char *name, size_t namelen, extern int do_rlogin (const char *remote_host, char *name, size_t namelen,
char *term, size_t termlen); char *term, size_t termlen);
/* root_flag.c */
extern void process_root_flag (const char* short_opt, int argc, char **argv);
/* salt.c */ /* salt.c */
extern /*@observer@*/const char *crypt_make_salt (/*@null@*//*@observer@*/const char *meth, /*@null@*/void *arg); extern /*@observer@*/const char *crypt_make_salt (/*@null@*/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
/* setugid.c */ /* setugid.c */
extern int setup_groups (const struct passwd *info); extern int setup_groups (const struct passwd *info);
@@ -365,17 +331,17 @@ extern void spw_free (/*@out@*/ /*@only@*/struct spwd *spent);
/* shell.c */ /* shell.c */
extern int shell (const char *file, /*@null@*/const char *arg, char *const envp[]); extern int shell (const char *file, /*@null@*/const char *arg, char *const envp[]);
/* spawn.c */ /* system.c */
extern int run_command (const char *cmd, const char *argv[], extern int safe_system (const char *command,
/*@null@*/const char *envp[], /*@out@*/int *status); const char *argv[],
const char *env[],
int ignore_stderr);
/* strtoday.c */ /* strtoday.c */
extern long strtoday (const char *); extern long strtoday (const char *);
/* suauth.c */ /* suauth.c */
extern int check_su_auth (const char *actual_id, extern int check_su_auth (const char *actual_id, const char *wanted_id);
const char *wanted_id,
bool su_to_root);
/* sulog.c */ /* sulog.c */
extern void sulog (const char *tty, extern void sulog (const char *tty,
@@ -391,7 +357,7 @@ extern void ttytype (const char *);
/* tz.c */ /* tz.c */
#ifndef USE_PAM #ifndef USE_PAM
extern /*@observer@*/const char *tz (const char *); extern char *tz (const char *);
#endif #endif
/* ulimit.c */ /* ulimit.c */
@@ -419,9 +385,9 @@ extern int setutmpx (struct utmpx *utx);
extern bool valid (const char *, const struct passwd *); extern bool valid (const char *, const struct passwd *);
/* xmalloc.c */ /* 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); @*/; /*@ensures MaxSet(result) == (size - 1); @*/;
extern /*@maynotreturn@*/ /*@only@*//*@notnull@*/char *xstrdup (const char *); extern /*@maynotreturn@*/ /*@only@*/char *xstrdup (const char *);
/* xgetpwnam.c */ /* xgetpwnam.c */
extern /*@null@*/ /*@only@*/struct passwd *xgetpwnam (const char *); extern /*@null@*/ /*@only@*/struct passwd *xgetpwnam (const char *);
+1 -7
View File
@@ -73,7 +73,6 @@ int pw_auth (const char *cipher,
char prompt[1024]; char prompt[1024];
char *clear = NULL; char *clear = NULL;
const char *cp; const char *cp;
const char *encrypted;
int retval; int retval;
#ifdef SKEY #ifdef SKEY
@@ -178,12 +177,7 @@ int pw_auth (const char *cipher,
* the results there as well. * the results there as well.
*/ */
encrypted = pw_encrypt (input, cipher); retval = strcmp (pw_encrypt (input, cipher), cipher);
if (NULL != encrypted) {
retval = strcmp (encrypted, cipher);
} else {
retval = -1;
}
#ifdef SKEY #ifdef SKEY
/* /*
-14
View File
@@ -72,17 +72,6 @@ static int passwd_put (const void *ent, FILE * file)
{ {
const struct passwd *pw = ent; 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; return (putpwent (pw, file) == -1) ? -1 : 0;
} }
@@ -105,9 +94,6 @@ static struct commonio_db passwd_db = {
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
NULL, /* scontext */ NULL, /* scontext */
#endif #endif
0644, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */ NULL, /* head */
NULL, /* tail */ NULL, /* tail */
NULL, /* cursor */ NULL, /* cursor */
+4 -24
View File
@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal * Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2013, Nicolas François * Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -48,43 +48,25 @@
if (NULL == pw) { if (NULL == pw) {
return NULL; return NULL;
} }
/* The libc might define other fields. They won't be copied. */ *pw = *pwent;
memset (pw, 0, sizeof *pw);
pw->pw_uid = pwent->pw_uid;
pw->pw_gid = pwent->pw_gid;
/*@-mustfreeonly@*/
pw->pw_name = strdup (pwent->pw_name); pw->pw_name = strdup (pwent->pw_name);
/*@=mustfreeonly@*/
if (NULL == pw->pw_name) { if (NULL == pw->pw_name) {
pw_free(pw);
return NULL; return NULL;
} }
/*@-mustfreeonly@*/
pw->pw_passwd = strdup (pwent->pw_passwd); pw->pw_passwd = strdup (pwent->pw_passwd);
/*@=mustfreeonly@*/
if (NULL == pw->pw_passwd) { if (NULL == pw->pw_passwd) {
pw_free(pw);
return NULL; return NULL;
} }
/*@-mustfreeonly@*/
pw->pw_gecos = strdup (pwent->pw_gecos); pw->pw_gecos = strdup (pwent->pw_gecos);
/*@=mustfreeonly@*/
if (NULL == pw->pw_gecos) { if (NULL == pw->pw_gecos) {
pw_free(pw);
return NULL; return NULL;
} }
/*@-mustfreeonly@*/
pw->pw_dir = strdup (pwent->pw_dir); pw->pw_dir = strdup (pwent->pw_dir);
/*@=mustfreeonly@*/
if (NULL == pw->pw_dir) { if (NULL == pw->pw_dir) {
pw_free(pw);
return NULL; return NULL;
} }
/*@-mustfreeonly@*/
pw->pw_shell = strdup (pwent->pw_shell); pw->pw_shell = strdup (pwent->pw_shell);
/*@=mustfreeonly@*/
if (NULL == pw->pw_shell) { if (NULL == pw->pw_shell) {
pw_free(pw);
return NULL; return NULL;
} }
@@ -94,10 +76,8 @@
void pw_free (/*@out@*/ /*@only@*/struct passwd *pwent) void pw_free (/*@out@*/ /*@only@*/struct passwd *pwent)
{ {
free (pwent->pw_name); free (pwent->pw_name);
if (pwent->pw_passwd) { memzero (pwent->pw_passwd, strlen (pwent->pw_passwd));
memzero (pwent->pw_passwd, strlen (pwent->pw_passwd)); free (pwent->pw_passwd);
free (pwent->pw_passwd);
}
free (pwent->pw_gecos); free (pwent->pw_gecos);
free (pwent->pw_dir); free (pwent->pw_dir);
free (pwent->pw_shell); free (pwent->pw_shell);
-103
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 */
-378
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 */
+10 -55
View File
@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal * Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2005 , Tomasz Kłoczko * Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2007 - 2013, Nicolas François * Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -40,7 +40,6 @@
#include "prototypes.h" #include "prototypes.h"
#include "defines.h" #include "defines.h"
#include "commonio.h" #include "commonio.h"
#include "getdef.h"
#include "sgroupio.h" #include "sgroupio.h"
/*@null@*/ /*@only@*/struct sgrp *__sgr_dup (const struct sgrp *sgent) /*@null@*/ /*@only@*/struct sgrp *__sgr_dup (const struct sgrp *sgent)
@@ -52,19 +51,13 @@
if (NULL == sg) { if (NULL == sg) {
return NULL; return NULL;
} }
/* Do the same as the other _dup function, even if we know the *sg = *sgent;
* structure. */
memset (sg, 0, sizeof *sg);
/*@-mustfreeonly@*/
sg->sg_name = strdup (sgent->sg_name); sg->sg_name = strdup (sgent->sg_name);
/*@=mustfreeonly@*/
if (NULL == sg->sg_name) { if (NULL == sg->sg_name) {
free (sg); free (sg);
return NULL; return NULL;
} }
/*@-mustfreeonly@*/
sg->sg_passwd = strdup (sgent->sg_passwd); sg->sg_passwd = strdup (sgent->sg_passwd);
/*@=mustfreeonly@*/
if (NULL == sg->sg_passwd) { if (NULL == sg->sg_passwd) {
free (sg->sg_name); free (sg->sg_name);
free (sg); free (sg);
@@ -72,9 +65,7 @@
} }
for (i = 0; NULL != sgent->sg_adm[i]; i++); for (i = 0; NULL != sgent->sg_adm[i]; i++);
/*@-mustfreeonly@*/
sg->sg_adm = (char **) malloc ((i + 1) * sizeof (char *)); sg->sg_adm = (char **) malloc ((i + 1) * sizeof (char *));
/*@=mustfreeonly@*/
if (NULL == sg->sg_adm) { if (NULL == sg->sg_adm) {
free (sg->sg_passwd); free (sg->sg_passwd);
free (sg->sg_name); free (sg->sg_name);
@@ -97,9 +88,7 @@
sg->sg_adm[i] = NULL; sg->sg_adm[i] = NULL;
for (i = 0; NULL != sgent->sg_mem[i]; i++); for (i = 0; NULL != sgent->sg_mem[i]; i++);
/*@-mustfreeonly@*/
sg->sg_mem = (char **) malloc ((i + 1) * sizeof (char *)); sg->sg_mem = (char **) malloc ((i + 1) * sizeof (char *));
/*@=mustfreeonly@*/
if (NULL == sg->sg_mem) { if (NULL == sg->sg_mem) {
for (i = 0; NULL != sg->sg_adm[i]; i++) { for (i = 0; NULL != sg->sg_adm[i]; i++) {
free (sg->sg_adm[i]); free (sg->sg_adm[i]);
@@ -148,20 +137,17 @@ static void gshadow_free (/*@out@*/ /*@only@*/void *ent)
void sgr_free (/*@out@*/ /*@only@*/struct sgrp *sgent) void sgr_free (/*@out@*/ /*@only@*/struct sgrp *sgent)
{ {
size_t i;
free (sgent->sg_name); free (sgent->sg_name);
if (NULL != sgent->sg_passwd) { memzero (sgent->sg_passwd, strlen (sgent->sg_passwd));
memzero (sgent->sg_passwd, strlen (sgent->sg_passwd)); free (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++) { while (NULL != *(sgent->sg_mem)) {
free (sgent->sg_adm[i]); 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); free (sgent);
} }
@@ -181,32 +167,6 @@ static int gshadow_put (const void *ent, FILE * file)
{ {
const struct sgrp *sg = ent; 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; return (putsgent (sg, file) == -1) ? -1 : 0;
} }
@@ -229,9 +189,6 @@ static struct commonio_db gshadow_db = {
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
NULL, /* scontext */ NULL, /* scontext */
#endif #endif
0400, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */ NULL, /* head */
NULL, /* tail */ NULL, /* tail */
NULL, /* cursor */ NULL, /* cursor */
@@ -253,8 +210,6 @@ int sgr_setdbname (const char *filename)
bool sgr_file_present (void) bool sgr_file_present (void)
{ {
if (getdef_bool ("FORCE_SHADOW"))
return true;
return commonio_present (&gshadow_db); return commonio_present (&gshadow_db);
} }
+1 -1
View File
@@ -37,7 +37,7 @@
extern int sgr_close (void); extern int sgr_close (void);
extern bool sgr_file_present (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_lock (void);
extern int sgr_setdbname (const char *filename); extern int sgr_setdbname (const char *filename);
extern /*@observer@*/const char *sgr_dbname (void); extern /*@observer@*/const char *sgr_dbname (void);
+27 -47
View File
@@ -42,10 +42,10 @@
#include "defines.h" #include "defines.h"
#include <stdio.h> #include <stdio.h>
#ifdef USE_NIS #ifdef USE_NIS
static bool nis_used; static int nis_used;
static bool nis_ignore; static int nis_ignore;
static enum { native, start, middle, native2 } nis_state; static enum { native, start, middle, native2 } nis_state;
static bool nis_bound; static int nis_bound;
static char *nis_domain; static char *nis_domain;
static char *nis_key; static char *nis_key;
static int nis_keylen; static int nis_keylen;
@@ -66,12 +66,12 @@ static FILE *shadow;
* __setspNIS - turn on or off NIS searches * __setspNIS - turn on or off NIS searches
*/ */
void __setspNIS (bool flag) void __setspNIS (int flag)
{ {
nis_ignore = !flag; nis_ignore = !flag;
if (nis_ignore) { if (nis_ignore) {
nis_used = false; nis_used = 0;
} }
} }
@@ -81,11 +81,10 @@ void __setspNIS (bool flag)
static int bind_nis (void) static int bind_nis (void)
{ {
if (yp_get_default_domain (&nis_domain)) { if (yp_get_default_domain (&nis_domain))
return -1; return -1;
}
nis_bound = true; nis_bound = 1;
return 0; return 0;
} }
#endif #endif
@@ -96,11 +95,10 @@ static int bind_nis (void)
void setspent (void) void setspent (void)
{ {
if (NULL != shadow) { if (shadow)
rewind (shadow); rewind (shadow);
}else { else
shadow = fopen (SHADOW_FILE, "r"); shadow = fopen (SHADOW_FILE, "r");
}
#ifdef USE_NIS #ifdef USE_NIS
nis_state = native; nis_state = native;
@@ -113,9 +111,8 @@ void setspent (void)
void endspent (void) void endspent (void)
{ {
if (NULL != shadow) { if (shadow)
(void) fclose (shadow); (void) fclose (shadow);
}
shadow = (FILE *) 0; shadow = (FILE *) 0;
} }
@@ -175,9 +172,8 @@ static struct spwd *my_sgetspent (const char *string)
spwd.sp_namp = fields[0]; spwd.sp_namp = fields[0];
#ifdef USE_NIS #ifdef USE_NIS
if (IS_NISCHAR (fields[0][0])) { if (IS_NISCHAR (fields[0][0]))
nis_used = true; nis_used = 1;
}
#endif #endif
spwd.sp_pwdp = fields[1]; spwd.sp_pwdp = fields[1];
@@ -215,9 +211,7 @@ static struct spwd *my_sgetspent (const char *string)
spwd.sp_min = -1; spwd.sp_min = -1;
} else } else
#endif #endif
{
return 0; return 0;
}
} else if (spwd.sp_min < 0) { } else if (spwd.sp_min < 0) {
return 0; return 0;
} }
@@ -269,9 +263,7 @@ static struct spwd *my_sgetspent (const char *string)
spwd.sp_warn = -1; spwd.sp_warn = -1;
} else } else
#endif #endif
{
return 0; return 0;
}
} else if (spwd.sp_warn < 0) { } else if (spwd.sp_warn < 0) {
return 0; return 0;
} }
@@ -291,9 +283,7 @@ static struct spwd *my_sgetspent (const char *string)
spwd.sp_inact = -1; spwd.sp_inact = -1;
} else } else
#endif #endif
{
return 0; return 0;
}
} else if (spwd.sp_inact < 0) { } else if (spwd.sp_inact < 0) {
return 0; return 0;
} }
@@ -313,9 +303,7 @@ static struct spwd *my_sgetspent (const char *string)
spwd.sp_expire = -1; spwd.sp_expire = -1;
} else } else
#endif #endif
{
return 0; return 0;
}
} else if (spwd.sp_expire < 0) { } else if (spwd.sp_expire < 0) {
return 0; return 0;
} }
@@ -336,9 +324,7 @@ static struct spwd *my_sgetspent (const char *string)
spwd.sp_flag = SHADOW_SP_FLAG_UNSET; spwd.sp_flag = SHADOW_SP_FLAG_UNSET;
} else } else
#endif #endif
{
return 0; return 0;
}
} else if (spwd.sp_flag < 0) { } else if (spwd.sp_flag < 0) {
return 0; return 0;
} }
@@ -391,9 +377,8 @@ struct spwd *getspent (void)
struct spwd *val; struct spwd *val;
char buf[BUFSIZ]; char buf[BUFSIZ];
#endif #endif
if (NULL == shadow) { if (!shadow)
setspent (); setspent ();
}
#ifdef USE_NIS #ifdef USE_NIS
again: again:
@@ -447,7 +432,7 @@ struct spwd *getspent (void)
return 0; return 0;
} else { } else {
if (!nis_bound) { if (nis_bound == 0) {
if (bind_nis ()) { if (bind_nis ()) {
nis_state = native2; nis_state = native2;
goto again; goto again;
@@ -455,15 +440,15 @@ struct spwd *getspent (void)
} }
if (nis_state == start) { if (nis_state == start) {
if (yp_first (nis_domain, "shadow.bynam", &nis_key, if (yp_first (nis_domain, "shadow.bynam", &nis_key,
&nis_keylen, &nis_val, &nis_vallen)) { &nis_keylen, &nis_val, &nis_vallen)) {
nis_state = native2; nis_state = native2;
goto again; goto again;
} }
nis_state = middle; nis_state = middle;
} else if (nis_state == middle) { } else if (nis_state == middle) {
if (yp_next (nis_domain, "shadow.bynam", nis_key, if (yp_next (nis_domain, "shadow.bynam", nis_key,
nis_keylen, &nis_key, &nis_keylen, nis_keylen, &nis_key, &nis_keylen,
&nis_val, &nis_vallen)) { &nis_val, &nis_vallen)) {
nis_state = native2; nis_state = native2;
goto again; goto again;
} }
@@ -486,7 +471,7 @@ struct spwd *getspnam (const char *name)
#ifdef USE_NIS #ifdef USE_NIS
char buf[BUFSIZ]; char buf[BUFSIZ];
static char save_name[16]; static char save_name[16];
bool nis_disabled = false; int nis_disabled = 0;
#endif #endif
setspent (); setspent ();
@@ -496,20 +481,18 @@ struct spwd *getspnam (const char *name)
* Search the shadow.byname map for this user. * Search the shadow.byname map for this user.
*/ */
if (!nis_ignore && !nis_bound) { if (!nis_ignore && !nis_bound)
bind_nis (); bind_nis ();
}
if (!nis_ignore && nis_bound) { if (!nis_ignore && nis_bound) {
char *cp; char *cp;
if (yp_match (nis_domain, "shadow.byname", name, 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'); cp = strchr (nis_val, '\n');
if (NULL != cp) { if (NULL != cp)
*cp = '\0'; *cp = '\0';
}
nis_state = middle; nis_state = middle;
sp = my_sgetspent (nis_val); sp = my_sgetspent (nis_val);
@@ -520,9 +503,8 @@ struct spwd *getspnam (const char *name)
} }
endspent (); endspent ();
return sp; return sp;
} else { } else
nis_state = native2; nis_state = native2;
}
} }
#endif #endif
#ifdef USE_NIS #ifdef USE_NIS
@@ -534,19 +516,17 @@ struct spwd *getspnam (const char *name)
*/ */
if (nis_used) { if (nis_used) {
nis_ignore = true; nis_ignore++;
nis_disabled = true; nis_disabled++;
} }
#endif #endif
while ((sp = getspent ()) != (struct spwd *) 0) { while ((sp = getspent ()) != (struct spwd *) 0) {
if (strcmp (name, sp->sp_namp) == 0) { if (strcmp (name, sp->sp_namp) == 0)
break; break;
}
} }
#ifdef USE_NIS #ifdef USE_NIS
if (nis_disabled) { if (nis_disabled)
nis_ignore = false; nis_ignore--;
}
#endif #endif
endspent (); endspent ();
return (sp); return (sp);
+5 -92
View File
@@ -40,12 +40,7 @@
#include <shadow.h> #include <shadow.h>
#include <stdio.h> #include <stdio.h>
#include "commonio.h" #include "commonio.h"
#include "getdef.h"
#include "shadowio.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) static /*@null@*/ /*@only@*/void *shadow_dup (const void *ent)
{ {
@@ -77,12 +72,6 @@ static int shadow_put (const void *ent, FILE * file)
{ {
const struct spwd *sp = ent; 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; return (putspent (sp, file) == -1) ? -1 : 0;
} }
@@ -104,10 +93,7 @@ static struct commonio_db shadow_db = {
NULL, /* fp */ NULL, /* fp */
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
NULL, /* scontext */ NULL, /* scontext */
#endif /* WITH_SELINUX */ #endif
0400, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */ NULL, /* head */
NULL, /* tail */ NULL, /* tail */
NULL, /* cursor */ NULL, /* cursor */
@@ -129,52 +115,17 @@ int spw_setdbname (const char *filename)
bool spw_file_present (void) bool spw_file_present (void)
{ {
if (getdef_bool ("FORCE_SHADOW"))
return true;
return commonio_present (&shadow_db); return commonio_present (&shadow_db);
} }
int spw_lock (void) int spw_lock (void)
{ {
#ifdef WITH_TCB return commonio_lock (&shadow_db);
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 */
} }
int spw_open (int mode) int spw_open (int mode)
{ {
int retval = 0; return commonio_open (&shadow_db, mode);
#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;
} }
/*@observer@*/ /*@null@*/const struct spwd *spw_locate (const char *name) /*@observer@*/ /*@null@*/const struct spwd *spw_locate (const char *name)
@@ -204,45 +155,12 @@ int spw_rewind (void)
int spw_close (void) int spw_close (void)
{ {
int retval = 0; return commonio_close (&shadow_db);
#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;
} }
int spw_unlock (void) int spw_unlock (void)
{ {
#ifdef WITH_TCB return commonio_unlock (&shadow_db);
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 */
} }
struct commonio_entry *__spw_get_head (void) struct commonio_entry *__spw_get_head (void)
@@ -258,10 +176,5 @@ void __spw_del_entry (const struct commonio_entry *ent)
/* Sort with respect to passwd ordering. */ /* Sort with respect to passwd ordering. */
int spw_sort () 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 ()); return commonio_sort_wrt (&shadow_db, __pw_get_db ());
} }
+2 -2
View File
@@ -31,8 +31,8 @@
*/ */
/* $Id$ */ /* $Id$ */
#ifndef SHADOWIO_H #ifndef _SHADOWIO_H
#define SHADOWIO_H #define _SHADOWIO_H
#include "defines.h" #include "defines.h"
+5 -22
View File
@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal * Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2005 , Tomasz Kłoczko * Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2007 - 2013, Nicolas François * Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -49,28 +49,13 @@
if (NULL == sp) { if (NULL == sp) {
return NULL; return NULL;
} }
/* The libc might define other fields. They won't be copied. */ *sp = *spent;
memset (sp, 0, sizeof *sp); sp->sp_namp = strdup (spent->sp_namp);
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@*/
if (NULL == sp->sp_namp) { if (NULL == sp->sp_namp) {
free(sp);
return NULL; return NULL;
} }
/*@-mustfreeonly@*/
sp->sp_pwdp = strdup (spent->sp_pwdp); sp->sp_pwdp = strdup (spent->sp_pwdp);
/*@=mustfreeonly@*/
if (NULL == sp->sp_pwdp) { if (NULL == sp->sp_pwdp) {
free(sp->sp_namp);
free(sp);
return NULL; return NULL;
} }
@@ -80,10 +65,8 @@
void spw_free (/*@out@*/ /*@only@*/struct spwd *spent) void spw_free (/*@out@*/ /*@only@*/struct spwd *spent)
{ {
free (spent->sp_namp); free (spent->sp_namp);
if (NULL != spent->sp_pwdp) { memzero (spent->sp_pwdp, strlen (spent->sp_pwdp));
memzero (spent->sp_pwdp, strlen (spent->sp_pwdp)); free (spent->sp_pwdp);
free (spent->sp_pwdp);
}
free (spent); free (spent);
} }
-82
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;
}
-701
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 */
-41
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
-613
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;
}
-19
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
+19
View File
@@ -88,6 +88,25 @@ struct utmp *getutent (void)
return &utmp_buf; 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 #else
extern int errno; /* warning: ANSI C forbids an empty source file */ extern int errno; /* warning: ANSI C forbids an empty source file */
#endif #endif
+3 -8
View File
@@ -1,7 +1,7 @@
EXTRA_DIST = .indent.pro xgetXXbyYY.c EXTRA_DIST = .indent.pro xgetXXbyYY.c
AM_CPPFLAGS = -I$(top_srcdir)/lib INCLUDES = -I$(top_srcdir)/lib
noinst_LIBRARIES = libmisc.a noinst_LIBRARIES = libmisc.a
@@ -23,18 +23,14 @@ libmisc_a_SOURCES = \
env.c \ env.c \
failure.c \ failure.c \
failure.h \ failure.h \
fields.c \
find_new_gid.c \ find_new_gid.c \
find_new_uid.c \ find_new_uid.c \
find_new_sub_gids.c \
find_new_sub_uids.c \
getdate.h \ getdate.h \
getdate.y \ getdate.y \
getgr_nam_gid.c \ getgr_nam_gid.c \
getrange.c \ getrange.c \
gettime.c \
hushed.c \ hushed.c \
idmapping.h \
idmapping.c \
isexpired.c \ isexpired.c \
limits.c \ limits.c \
list.c log.c \ list.c log.c \
@@ -48,13 +44,12 @@ libmisc_a_SOURCES = \
pwd2spwd.c \ pwd2spwd.c \
pwdcheck.c \ pwdcheck.c \
pwd_init.c \ pwd_init.c \
remove_tree.c \
rlogin.c \ rlogin.c \
root_flag.c \
salt.c \ salt.c \
setugid.c \ setugid.c \
setupenv.c \ setupenv.c \
shell.c \ shell.c \
system.c \
strtoday.c \ strtoday.c \
sub.c \ sub.c \
sulog.c \ sulog.c \
+1 -5
View File
@@ -71,11 +71,7 @@ int add_groups (const char *list)
return -1; return -1;
} }
ngroups = getgroups (i, grouplist); ngroups = getgroups (i, grouplist);
if ( ( (-1 == ngroups) if ((-1 == ngroups) || (i > (size_t)ngroups)) {
&& (EINVAL != errno))
|| (i > (size_t)ngroups)) {
/* Unexpected failure of getgroups or successful
* reception of the groups */
break; break;
} }
/* not enough room, so try allocating a larger buffer */ /* not enough room, so try allocating a larger buffer */
+2 -2
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 * id - uid or gid that the operation is being performed on. This is used
* only when user is NULL. * 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, const char *name, unsigned int id,
shadow_audit_result result) shadow_audit_result result)
{ {
@@ -84,7 +84,7 @@ void audit_logger (int type, unused const char *pgname, const char *op,
return; return;
} else { } else {
audit_log_acct_message (audit_fd, type, NULL, op, name, id, audit_log_acct_message (audit_fd, type, NULL, op, name, id,
NULL, NULL, NULL, (int) result); NULL, NULL, NULL, (int) result);
} }
} }
+2 -2
View File
@@ -42,9 +42,9 @@
#include "defines.h" #include "defines.h"
#include "prototypes.h" #include "prototypes.h"
/*@observer@*/const char *Basename (const char *str) char *Basename (char *str)
{ {
char *cp = strrchr (str, '/'); char *cp = strrchr (str, '/');
return (NULL != cp) ? cp + 1 : str; return cp ? cp + 1 : str;
} }
+24 -89
View File
@@ -2,7 +2,6 @@
* Copyright (c) 1992 - 1993, Julianne Frances Haugh * Copyright (c) 1992 - 1993, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2010 - , Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * chown_dir() walks a directory tree and changes the ownership
* of all files owned by the provided user ID. * 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, int
uid_t old_uid, chown_tree (const char *root, uid_t old_uid, uid_t new_uid, gid_t old_gid,
uid_t new_uid, gid_t new_gid)
gid_t old_gid,
gid_t new_gid)
{ {
char *new_name; char new_name[1024];
size_t new_name_len;
int rc = 0; int rc = 0;
struct DIRECT *ent; struct DIRECT *ent;
struct stat sb; struct stat sb;
DIR *dir; 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 * 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) { if (access (root, F_OK) != 0)
free (new_name);
return -1; return -1;
}
/* /*
* Open the directory and read each entry. Every entry is tested * 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 * 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 * recursively. If not, it is checked to see if it is owned by
* shall be changed. * old user ID.
*/ */
dir = opendir (root); if (!(dir = opendir (root)))
if (NULL == dir) {
free (new_name);
return -1; return -1;
}
while ((ent = readdir (dir))) { 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 * Skip the "." and ".." entries
*/ */
if ( (strcmp (ent->d_name, ".") == 0) if (strcmp (ent->d_name, ".") == 0 ||
|| (strcmp (ent->d_name, "..") == 0)) { strcmp (ent->d_name, "..") == 0)
continue; continue;
}
/* /*
* Make the filename for both the source and the * Make the filename for both the source and the
* destination files. * destination files.
*/ */
ent_name_len = strlen (root) + strlen (ent->d_name) + 2; if (strlen (root) + strlen (ent->d_name) + 2 > sizeof new_name)
if (ent_name_len > new_name_len) { break;
/*@only@*/char *tmp = realloc (new_name, ent_name_len);
if (NULL == tmp) {
rc = -1;
break;
}
new_name = tmp;
new_name_len = ent_name_len;
}
(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! */ /* Don't follow symbolic links! */
if (LSTAT (new_name, &sb) == -1) { if (LSTAT (new_name, &sb) == -1)
continue; continue;
}
if (S_ISDIR (sb.st_mode) && !S_ISLNK (sb.st_mode)) { if (S_ISDIR (sb.st_mode) && !S_ISLNK (sb.st_mode)) {
@@ -146,56 +112,25 @@ int chown_tree (const char *root,
} }
#ifndef HAVE_LCHOWN #ifndef HAVE_LCHOWN
/* don't use chown (follows symbolic links!) */ /* don't use chown (follows symbolic links!) */
if (S_ISLNK (sb.st_mode)) { if (S_ISLNK (sb.st_mode))
continue; continue;
}
#endif #endif
/* if (sb.st_uid == old_uid)
* By default, the IDs are not changed (-1). LCHOWN (new_name, new_uid,
* sb.st_gid == old_gid ? new_gid : sb.st_gid);
* 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;
}
}
} }
free (new_name);
(void) closedir (dir); (void) closedir (dir);
/* /*
* Now do the root of the tree * Now do the root of the tree
*/ */
if ((0 == rc) && (stat (root, &sb) == 0)) { if (stat (root, &sb) == 0) {
uid_t tmpuid = (uid_t) -1; if (sb.st_uid == old_uid) {
gid_t tmpgid = (gid_t) -1; LCHOWN (root, new_uid,
if (((uid_t) -1 == old_uid) || (sb.st_uid == old_uid)) { sb.st_gid == old_gid ? new_gid : sb.st_gid);
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 (root, tmpuid, tmpgid);
}
} else {
rc = -1;
} }
return rc; return rc;
} }
+1 -1
View File
@@ -72,7 +72,7 @@ void chown_tty (const struct passwd *info)
*/ */
if ( (fchown (STDIN_FILENO, info->pw_uid, gid) != 0) 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; int err = errno;
fprintf (stderr, fprintf (stderr,
+5 -21
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008 - 2011, Nicolas François * Copyright (c) 2008 , Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -38,12 +38,8 @@
* The cleanup_functions stack. * The cleanup_functions stack.
*/ */
#define CLEANUP_FUNCTIONS 10 #define CLEANUP_FUNCTIONS 10
typedef /*@null@*/void * parg_t;
static cleanup_function cleanup_functions[CLEANUP_FUNCTIONS]; static cleanup_function cleanup_functions[CLEANUP_FUNCTIONS];
static parg_t cleanup_function_args[CLEANUP_FUNCTIONS]; static void * cleanup_function_args[CLEANUP_FUNCTIONS];
static pid_t cleanup_pid = 0;
/* /*
* - Cleanup functions shall not fail. * - 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. * 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: * It is intended to be used as:
* atexit (do_cleanups); * atexit (do_cleanups);
*/ */
@@ -70,10 +63,6 @@ void do_cleanups (void)
/* Make sure there were no overflow */ /* Make sure there were no overflow */
assert (NULL == cleanup_functions[CLEANUP_FUNCTIONS-1]); assert (NULL == cleanup_functions[CLEANUP_FUNCTIONS-1]);
if (getpid () != cleanup_pid) {
return;
}
i = CLEANUP_FUNCTIONS; i = CLEANUP_FUNCTIONS;
do { do {
i--; i--;
@@ -86,17 +75,13 @@ void do_cleanups (void)
/* /*
* add_cleanup - Add a cleanup_function to the cleanup_functions stack. * 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; unsigned int i;
assert (NULL != pcf); assert (NULL != pcf);
assert (NULL == cleanup_functions[CLEANUP_FUNCTIONS-2]); assert (NULL == cleanup_functions[CLEANUP_FUNCTIONS-2]);
if (0 == cleanup_pid) {
cleanup_pid = getpid ();
}
/* Add the cleanup_function at the end of the stack */ /* Add the cleanup_function at the end of the stack */
for (i=0; NULL != cleanup_functions[i]; i++); for (i=0; NULL != cleanup_functions[i]; i++);
cleanup_functions[i] = pcf; 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. * 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; unsigned int i;
assert (NULL != pcf); assert (NULL != pcf);
@@ -124,8 +109,7 @@ void del_cleanup (/*@notnull@*/cleanup_function pcf)
/* Move the rest of the cleanup functions */ /* Move the rest of the cleanup functions */
for (; i<CLEANUP_FUNCTIONS; i++) { for (; i<CLEANUP_FUNCTIONS; i++) {
/* Make sure the cleanup function was specified only once */ /* Make sure the cleanup function was specified only once */
assert ( (i == (CLEANUP_FUNCTIONS -1)) assert (cleanup_functions[i+1] != pcf);
|| (cleanup_functions[i+1] != pcf));
if (i == (CLEANUP_FUNCTIONS -1)) { if (i == (CLEANUP_FUNCTIONS -1)) {
cleanup_functions[i] = NULL; cleanup_functions[i] = NULL;
+4 -7
View File
@@ -3,7 +3,7 @@
* Copyright (c) 1991 , Chip Rosenthal * Copyright (c) 1991 , Chip Rosenthal
* Copyright (c) 1996 - 1998, Marek Michałkiewicz * Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François * Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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) static bool is_listed (const char *cfgin, const char *tty, bool def)
{ {
FILE *fp; FILE *fp;
char buf[200], *s; char buf[200], *cons, *s;
const char *cons;
/* /*
* If the CONSOLE configuration definition isn't given, * 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 != '/') { if (*cons != '/') {
char *pbuf;
strcpy (buf, cons); strcpy (buf, cons);
pbuf = &buf[0]; while ((s = strtok (buf, ":")) != NULL) {
while ((s = strtok (pbuf, ":")) != NULL) {
if (strcmp (s, tty) == 0) { if (strcmp (s, tty) == 0) {
return true; return true;
} }
pbuf = NULL; cons = NULL;
} }
return false; return false;
} }
+221 -310
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1991 - 1994, Julianne Frances Haugh * Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2001, Marek Michałkiewicz * Copyright (c) 1996 - 2001, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko * Copyright (c) 2003 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François * Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -44,19 +44,7 @@
#include "defines.h" #include "defines.h"
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
#include <selinux/selinux.h> #include <selinux/selinux.h>
#endif /* WITH_SELINUX */ #endif
#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 */
static /*@null@*/const char *src_orig; static /*@null@*/const char *src_orig;
static /*@null@*/const char *dst_orig; static /*@null@*/const char *dst_orig;
@@ -70,73 +58,66 @@ struct link_name {
static /*@exposed@*/struct link_name *links; static /*@exposed@*/struct link_name *links;
static int copy_entry (const char *src, const char *dst, static int copy_entry (const char *src, const char *dst,
bool reset_selinux, long int uid, long int gid);
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static int copy_dir (const char *src, const char *dst, static int copy_dir (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[], const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid, long int uid, long int gid);
gid_t old_gid, gid_t new_gid);
#ifdef S_IFLNK #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, static int copy_symlink (const char *src, const char *dst,
unused bool reset_selinux,
const struct stat *statp, const struct timeval mt[], const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid, long int uid, long int gid);
gid_t old_gid, gid_t new_gid); #endif
#endif /* S_IFLNK */ static int copy_hardlink (const char *src, const char *dst,
static int copy_hardlink (const char *dst,
unused bool reset_selinux,
struct link_name *lp); struct link_name *lp);
static int copy_special (const char *src, const char *dst, static int copy_special (const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[], const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid, long int uid, long int gid);
gid_t old_gid, gid_t new_gid);
static int copy_file (const char *src, const char *dst, static int copy_file (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[], const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid, long int uid, long int gid);
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);
#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 if (!selinux_checked) {
* or extended attributes */ selinux_enabled = is_selinux_enabled () > 0;
if (ENOTSUP == errno) { selinux_checked = true;
errno = 0;
return;
} }
va_start (ap, fmt); if (selinux_enabled) {
(void) fprintf (stderr, _("%s: "), Prog); /* Get the default security context for this file */
if (vfprintf (stderr, fmt, ap) != 0) { if (matchpathcon (dst_name, 0, &scontext) < 0) {
(void) fputs (_(": "), stderr); 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)); return 0;
va_end (ap);
} }
#endif
static struct error_context ctx = {
error_acl
};
#endif /* WITH_ACL || WITH_ATTR */
/* /*
* remove_link - delete a link from the linked list * 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; lp->ln_count = sb->st_nlink;
len = name_len - src_len + dst_len + 1; len = name_len - src_len + dst_len + 1;
lp->ln_name = (char *) xmalloc (len); 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; lp->ln_next = links;
links = lp; 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 * copy_tree() walks a directory tree and copies ordinary files
* as it goes. * 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, int copy_tree (const char *src_root, const char *dst_root,
bool copy_root, bool reset_selinux, long int uid, long int gid)
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{ {
int err = 0; int err = 0;
bool set_orig = false; bool set_orig = false;
struct DIRECT *ent; struct DIRECT *ent;
DIR *dir; 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 * Make certain both directories exist. This routine is called
* after the home directory is created, or recursively after the * 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 * Build the filename for both the source and
* the destination files. * the destination files.
*/ */
(void) snprintf (src_name, src_len, "%s/%s", snprintf (src_name, src_len, "%s/%s",
src_root, ent->d_name); src_root, ent->d_name);
(void) snprintf (dst_name, dst_len, "%s/%s", snprintf (dst_name, dst_len, "%s/%s",
dst_root, ent->d_name); dst_root, ent->d_name);
err = copy_entry (src_name, dst_name, err = copy_entry (src_name, dst_name, uid, gid);
reset_selinux,
old_uid, new_uid,
old_gid, new_gid);
} }
if (NULL != src_name) { if (NULL != src_name) {
free (src_name); free (src_name);
@@ -332,25 +276,16 @@ int copy_tree (const char *src_root, const char *dst_root,
if (set_orig) { if (set_orig) {
src_orig = NULL; src_orig = NULL;
dst_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 #ifdef WITH_SELINUX
/* Reset SELinux to create files with default contexts. /* Reset SELinux to create files with default contexts */
* Note that the context is only reset on exit of copy_tree (it is setfscreatecon (NULL);
* assumed that the program would quit without needing a restored #endif
* context if copy_tree failed previously), and that copy_tree can
* be called recursively (hence the context is set on the /* FIXME: with the call to remove_link, we could also check that
* sub-functions of copy_entry). * no links remain in links.
*/ * assert (NULL == links); */
if (reset_selinux_file_context () != 0) {
err = -1;
}
#endif /* WITH_SELINUX */
return err; 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 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. * 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, static int copy_entry (const char *src, const char *dst,
bool reset_selinux, long int uid, long int gid)
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{ {
int err = 0; int err = 0;
struct stat sb; struct stat sb;
@@ -390,30 +319,29 @@ static int copy_entry (const char *src, const char *dst,
#ifdef HAVE_STRUCT_STAT_ST_ATIM #ifdef HAVE_STRUCT_STAT_ST_ATIM
mt[0].tv_sec = sb.st_atim.tv_sec; mt[0].tv_sec = sb.st_atim.tv_sec;
mt[0].tv_usec = sb.st_atim.tv_nsec / 1000; mt[0].tv_usec = sb.st_atim.tv_nsec / 1000;
#else /* !HAVE_STRUCT_STAT_ST_ATIM */ #else
mt[0].tv_sec = sb.st_atime; 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; mt[0].tv_usec = sb.st_atimensec / 1000;
# else /* !HAVE_STRUCT_STAT_ST_ATIMENSEC */ #else
mt[0].tv_usec = 0; mt[0].tv_usec = 0;
# endif /* !HAVE_STRUCT_STAT_ST_ATIMENSEC */ #endif
#endif /* !HAVE_STRUCT_STAT_ST_ATIM */ #endif
#ifdef HAVE_STRUCT_STAT_ST_MTIM #ifdef HAVE_STRUCT_STAT_ST_MTIM
mt[1].tv_sec = sb.st_mtim.tv_sec; mt[1].tv_sec = sb.st_mtim.tv_sec;
mt[1].tv_usec = sb.st_mtim.tv_nsec / 1000; mt[1].tv_usec = sb.st_mtim.tv_nsec / 1000;
#else /* !HAVE_STRUCT_STAT_ST_MTIM */ #else
mt[1].tv_sec = sb.st_mtime; 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; mt[1].tv_usec = sb.st_mtimensec / 1000;
# else /* !HAVE_STRUCT_STAT_ST_MTIMENSEC */ #else
mt[1].tv_usec = 0; mt[1].tv_usec = 0;
# endif /* !HAVE_STRUCT_STAT_ST_MTIMENSEC */ #endif
#endif /* !HAVE_STRUCT_STAT_ST_MTIM */ #endif
if (S_ISDIR (sb.st_mode)) { if (S_ISDIR (sb.st_mode)) {
err = copy_dir (src, dst, reset_selinux, &sb, mt, err = copy_dir (src, dst, &sb, mt, uid, gid);
old_uid, new_uid, old_gid, new_gid);
} }
#ifdef S_IFLNK #ifdef S_IFLNK
@@ -422,17 +350,16 @@ static int copy_entry (const char *src, const char *dst,
*/ */
else if (S_ISLNK (sb.st_mode)) { else if (S_ISLNK (sb.st_mode)) {
err = copy_symlink (src, dst, reset_selinux, &sb, mt, err = copy_symlink (src, dst, &sb, mt, uid, gid);
old_uid, new_uid, old_gid, new_gid);
} }
#endif /* S_IFLNK */ #endif
/* /*
* See if this is a previously copied link * See if this is a previously copied link
*/ */
else if ((lp = check_link (src, &sb)) != NULL) { 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)) { else if (!S_ISREG (sb.st_mode)) {
err = copy_special (src, dst, reset_selinux, &sb, mt, err = copy_special (dst, &sb, mt, uid, gid);
old_uid, new_uid, old_gid, new_gid);
} }
/* /*
@@ -452,8 +378,7 @@ static int copy_entry (const char *src, const char *dst,
*/ */
else { else {
err = copy_file (src, dst, reset_selinux, &sb, mt, err = copy_file (src, dst, &sb, mt, uid, gid);
old_uid, new_uid, old_gid, new_gid);
} }
} }
@@ -465,16 +390,14 @@ static int copy_entry (const char *src, const char *dst,
* *
* Copy a directory (recursively) from src to dst. * Copy a directory (recursively) from src to dst.
* *
* statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set * statp, mt, uid, gid are used to set the access and modification and the
* the access and modification and the access rights. * access rights.
* *
* Return 0 on success, -1 on error. * Return 0 on success, -1 on error.
*/ */
static int copy_dir (const char *src, const char *dst, static int copy_dir (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[], const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid, long int uid, long int gid)
gid_t old_gid, gid_t new_gid)
{ {
int err = 0; int err = 0;
@@ -484,33 +407,14 @@ static int copy_dir (const char *src, const char *dst,
*/ */
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
if (set_selinux_file_context (dst) != 0) { selinux_file_context (dst);
return -1; #endif
}
#endif /* WITH_SELINUX */
if ( (mkdir (dst, statp->st_mode) != 0) if ( (mkdir (dst, statp->st_mode) != 0)
|| (chown_if_needed (dst, statp, || (chown (dst,
old_uid, new_uid, old_gid, new_gid) != 0) (uid == - 1) ? statp->st_uid : (uid_t) uid,
#ifdef WITH_ACL (gid == - 1) ? statp->st_gid : (gid_t) gid) != 0)
|| ( (perm_copy_file (src, dst, &ctx) != 0)
&& (errno != 0))
#else /* !WITH_ACL */
|| (chmod (dst, statp->st_mode) != 0) || (chmod (dst, statp->st_mode) != 0)
#endif /* !WITH_ACL */ || (copy_tree (src, dst, uid, gid) != 0)
#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)
|| (utimes (dst, mt) != 0)) { || (utimes (dst, mt) != 0)) {
err = -1; err = -1;
} }
@@ -525,11 +429,11 @@ static int copy_dir (const char *src, const char *dst,
* return NULL on error. * return NULL on error.
* The return string shall be freed by the caller. * 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; size_t size = 1024;
while (true) { while (1) {
ssize_t nchars; ssize_t nchars;
char *buffer = (char *) malloc (size); char *buffer = (char *) malloc (size);
if (NULL == buffer) { if (NULL == buffer) {
@@ -539,11 +443,10 @@ static /*@null@*/char *readlink_malloc (const char *filename)
nchars = readlink (filename, buffer, size); nchars = readlink (filename, buffer, size);
if (nchars < 0) { if (nchars < 0) {
free(buffer);
return NULL; 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 */ /* readlink does not nul-terminate */
buffer[nchars] = '\0'; buffer[nchars] = '\0';
return buffer; return buffer;
@@ -560,16 +463,14 @@ static /*@null@*/char *readlink_malloc (const char *filename)
* *
* Copy a symlink from src to dst. * Copy a symlink from src to dst.
* *
* statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set * statp, mt, uid, gid are used to set the access and modification and the
* the access and modification and the access rights. * access rights.
* *
* Return 0 on success, -1 on error. * Return 0 on success, -1 on error.
*/ */
static int copy_symlink (const char *src, const char *dst, static int copy_symlink (const char *src, const char *dst,
unused bool reset_selinux,
const struct stat *statp, const struct timeval mt[], const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid, long int uid, long int gid)
gid_t old_gid, gid_t new_gid)
{ {
char *oldlink; 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, /* 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 * create a link to the corresponding entry in the dst_orig
* directory. * directory.
* FIXME: This may change a relative link to an absolute link
*/ */
if (strncmp (oldlink, src_orig, strlen (src_orig)) == 0) { if (strncmp (oldlink, src_orig, strlen (src_orig)) == 0) {
size_t len = strlen (dst_orig) + strlen (oldlink) - strlen (src_orig) + 1; size_t len = strlen (dst_orig) + strlen (oldlink) - strlen (src_orig) + 1;
char *dummy = (char *) xmalloc (len); char *dummy = (char *) malloc (len);
(void) snprintf (dummy, len, "%s%s", snprintf (dummy, len, "%s%s",
dst_orig, dst_orig,
oldlink + strlen (src_orig)); oldlink + strlen (src_orig));
free (oldlink); free (oldlink);
oldlink = dummy; oldlink = dummy;
} }
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
if (set_selinux_file_context (dst) != 0) { selinux_file_context (dst);
free (oldlink); #endif
return -1;
}
#endif /* WITH_SELINUX */
if ( (symlink (oldlink, dst) != 0) if ( (symlink (oldlink, dst) != 0)
|| (lchown_if_needed (dst, statp, || (lchown (dst,
old_uid, new_uid, old_gid, new_gid) != 0)) { (uid == -1) ? statp->st_uid : (uid_t) uid,
/* FIXME: there are no modes on symlinks, right? (gid == -1) ? statp->st_gid : (gid_t) gid) != 0)) {
* 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.
*/
free (oldlink); free (oldlink);
return -1; return -1;
} }
@@ -631,12 +524,12 @@ static int copy_symlink (const char *src, const char *dst,
* it returns ENOSYS on many system * it returns ENOSYS on many system
* - not implemented * - not implemented
*/ */
(void) lutimes (dst, mt); lutimes (dst, mt);
#endif /* HAVE_LUTIMES */ #endif
return 0; return 0;
} }
#endif /* S_IFLNK */ #endif
/* /*
* copy_hardlink - copy a hardlink * 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. * Return 0 on success, -1 on error.
*/ */
static int copy_hardlink (const char *dst, static int copy_hardlink (const char *src, const char *dst,
unused bool reset_selinux,
struct link_name *lp) struct link_name *lp)
{ {
/* FIXME: selinux, ACL, Extended Attributes needed? */ /* TODO: selinux needed? */
if (link (lp->ln_name, dst) != 0) { if (link (lp->ln_name, dst) != 0) {
return -1; 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, /* 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--; lp->ln_count--;
if (lp->ln_count <= 0) { if (lp->ln_count <= 0) {
remove_link (lp); remove_link (lp);
@@ -670,46 +568,26 @@ static int copy_hardlink (const char *dst,
* *
* Copy a special file from src to dst. * Copy a special file from src to dst.
* *
* statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set * statp, mt, uid, gid are used to set the access and modification and the
* the access and modification and the access rights. * access rights.
* *
* Return 0 on success, -1 on error. * Return 0 on success, -1 on error.
*/ */
static int copy_special (const char *src, const char *dst, static int copy_special (const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[], const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid, long int uid, long int gid)
gid_t old_gid, gid_t new_gid)
{ {
int err = 0; int err = 0;
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
if (set_selinux_file_context (dst) != 0) { selinux_file_context (dst);
return -1; #endif
}
#endif /* WITH_SELINUX */
if ( (mknod (dst, statp->st_mode & ~07777, statp->st_rdev) != 0) if ( (mknod (dst, statp->st_mode & ~07777, statp->st_rdev) != 0)
|| (chown_if_needed (dst, statp, || (chown (dst,
old_uid, new_uid, old_gid, new_gid) != 0) (uid == -1) ? statp->st_uid : (uid_t) uid,
#ifdef WITH_ACL (gid == -1) ? statp->st_gid : (gid_t) gid) != 0)
|| ( (perm_copy_file (src, dst, &ctx) != 0)
&& (errno != 0))
#else /* !WITH_ACL */
|| (chmod (dst, statp->st_mode & 07777) != 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)) { || (utimes (dst, mt) != 0)) {
err = -1; err = -1;
} }
@@ -722,16 +600,14 @@ static int copy_special (const char *src, const char *dst,
* *
* Copy a file from src to dst. * Copy a file from src to dst.
* *
* statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set * statp, mt, uid, gid are used to set the access and modification and the
* the access and modification and the access rights. * access rights.
* *
* Return 0 on success, -1 on error. * Return 0 on success, -1 on error.
*/ */
static int copy_file (const char *src, const char *dst, static int copy_file (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[], const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid, long int uid, long int gid)
gid_t old_gid, gid_t new_gid)
{ {
int err = 0; int err = 0;
int ifd; int ifd;
@@ -744,40 +620,20 @@ static int copy_file (const char *src, const char *dst,
return -1; return -1;
} }
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
if (set_selinux_file_context (dst) != 0) { selinux_file_context (dst);
return -1; #endif
}
#endif /* WITH_SELINUX */
ofd = open (dst, O_WRONLY | O_CREAT | O_TRUNC, statp->st_mode & 07777); ofd = open (dst, O_WRONLY | O_CREAT | O_TRUNC, statp->st_mode & 07777);
if ( (ofd < 0) if ( (ofd < 0)
|| (fchown_if_needed (ofd, statp, || (fchown (ofd,
old_uid, new_uid, old_gid, new_gid) != 0) (uid == -1) ? statp->st_uid : (uid_t) uid,
#ifdef WITH_ACL (gid == -1) ? statp->st_gid : (gid_t) gid) != 0)
|| ( (perm_copy_fd (src, ifd, dst, ofd, &ctx) != 0) || (fchmod (ofd, statp->st_mode & 07777) != 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 */
) {
(void) close (ifd); (void) close (ifd);
return -1; return -1;
} }
while ((cnt = read (ifd, buf, sizeof buf)) > 0) { while ((cnt = read (ifd, buf, sizeof buf)) > 0) {
if (write (ofd, buf, (size_t)cnt) != cnt) { if (write (ofd, buf, (size_t)cnt) != cnt) {
(void) close (ifd);
return -1; return -1;
} }
} }
@@ -788,7 +644,7 @@ static int copy_file (const char *src, const char *dst,
if (futimes (ofd, mt) != 0) { if (futimes (ofd, mt) != 0) {
return -1; return -1;
} }
#endif /* HAVE_FUTIMES */ #endif
if (close (ofd) != 0) { if (close (ofd) != 0) {
return -1; return -1;
@@ -798,42 +654,97 @@ static int copy_file (const char *src, const char *dst,
if (utimes(dst, mt) != 0) { if (utimes(dst, mt) != 0) {
return -1; return -1;
} }
#endif /* !HAVE_FUTIMES */ #endif
return err; return err;
} }
#define def_chown_if_needed(chown_function, type_dst) \ /*
static int chown_function ## _if_needed (type_dst dst, \ * remove_tree - delete a directory tree
const struct stat *statp, \ *
uid_t old_uid, uid_t new_uid, \ * remove_tree() walks a directory tree and deletes all the files
gid_t old_gid, gid_t new_gid) \ * and directories.
{ \ * At the end, it deletes the root directory itself.
uid_t tmpuid = (uid_t) -1; \ */
gid_t tmpgid = (gid_t) -1; \
\ int remove_tree (const char *root)
/* Use new_uid if old_uid is set to -1 or if the file was \ {
* owned by the user. */ \ char *new_name = NULL;
if (((uid_t) -1 == old_uid) || (statp->st_uid == old_uid)) { \ int err = 0;
tmpuid = new_uid; \ struct DIRECT *ent;
} \ struct stat sb;
/* Otherwise, or if new_uid was set to -1, we keep the same \ DIR *dir;
* owner. */ \
if ((uid_t) -1 == tmpuid) { \ /*
tmpuid = statp->st_uid; \ * 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
if (((gid_t) -1 == old_gid) || (statp->st_gid == old_gid)) { \ * regular files (and directories ...) are copied, and no file
tmpgid = new_gid; \ * is made set-ID.
} \ */
if ((gid_t) -1 == tmpgid) { \ dir = opendir (root);
tmpgid = statp->st_gid; \ if (NULL == dir) {
} \ return -1;
\ }
return chown_function (dst, tmpuid, tmpgid); \
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)
+3 -13
View File
@@ -115,9 +115,6 @@ void addenv (const char *string, /*@null@*/const char *value)
n = (size_t) (cp - newstring); n = (size_t) (cp - newstring);
/*
* If this environment variable is already set, change its value.
*/
for (i = 0; i < newenvc; i++) { for (i = 0; i < newenvc; i++) {
if ( (strncmp (newstring, newenvp[i], n) == 0) if ( (strncmp (newstring, newenvp[i], n) == 0)
&& (('=' == newenvp[i][n]) || ('\0' == newenvp[i][n]))) { && (('=' == newenvp[i][n]) || ('\0' == newenvp[i][n]))) {
@@ -131,15 +128,8 @@ void addenv (const char *string, /*@null@*/const char *value)
return; return;
} }
/*
* Otherwise, save the new environment variable
*/
newenvp[newenvc++] = newstring; newenvp[newenvc++] = newstring;
/*
* And extend the environment if needed.
*/
/* /*
* Check whether newenvc is a multiple of NEWENVP_STEP. * Check whether newenvc is a multiple of NEWENVP_STEP.
* If so we have to resize the vector. * If so we have to resize the vector.
@@ -153,14 +143,14 @@ void addenv (const char *string, /*@null@*/const char *value)
size_t newsize; size_t newsize;
/* /*
* If the resize operation succeeds we can * If the resize operation succeds we can
* happily go on, else print a message. * happily go on, else print a message.
*/ */
newsize = (newenvc + NEWENVP_STEP) * sizeof (char *); newsize = (newenvc + NEWENVP_STEP) * sizeof (char *);
__newenvp = (char **) realloc (newenvp, newsize); __newenvp = (char **) realloc (newenvp, newsize);
if (NULL != __newenvp) { if (__newenvp) {
/* /*
* If this is our current environment, update * If this is our current environment, update
* environ so that it doesn't point to some * environ so that it doesn't point to some
@@ -261,7 +251,7 @@ void sanitize_env (void)
if (strncmp (*cur, *bad, strlen (*bad)) != 0) { if (strncmp (*cur, *bad, strlen (*bad)) != 0) {
continue; continue;
} }
if (strchr (*cur, '/') == NULL) { if (strchr (*cur, '/') != NULL) {
continue; /* OK */ continue; /* OK */
} }
for (move = cur; NULL != *move; move++) { for (move = cur; NULL != *move; move++) {
+2 -4
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh * Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz * Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2002 - 2005, Tomasz Kłoczko * Copyright (c) 2002 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2010, Nicolas François * Copyright (c) 2008 , Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -273,14 +273,12 @@ void failprint (const struct faillog *fail)
lasttime++; lasttime++;
} }
#endif #endif
/*@-formatconst@*/
(void) printf (ngettext ("%d failure since last login.\n" (void) printf (ngettext ("%d failure since last login.\n"
"Last was %s on %s.\n", "Last was %s on %s.\n",
"%d failures since last login.\n" "%d failures since last login.\n"
"Last was %s on %s.\n", "Last was %s on %s.\n",
(unsigned long) fail->fail_cnt), (unsigned long) fail->fail_cnt),
fail->fail_cnt, lasttime, fail->fail_line); fail->fail_cnt, lasttime, fail->fail_line);
/*@=formatconst@*/
} }
/* /*
@@ -298,7 +296,7 @@ void failtmp (const char *username,
#endif /* !USE_UTMPX */ #endif /* !USE_UTMPX */
) )
{ {
const char *ftmp; char *ftmp;
int fd; int fd;
/* /*
-4
View File
@@ -54,10 +54,6 @@ int valid_field (const char *field, const char *illegal)
const char *cp; const char *cp;
int err = 0; int err = 0;
if (NULL == field) {
return -1;
}
/* For each character of field, search if it appears in the list /* For each character of field, search if it appears in the list
* of illegal characters. */ * of illegal characters. */
for (cp = field; '\0' != *cp; cp++) { for (cp = field; '\0' != *cp; cp++) {
+108 -422
View File
@@ -1,7 +1,6 @@
/* /*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh * Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 2008 - 2011, Nicolas François * Copyright (c) 2008 - 2009, Nicolas François
* Copyright (c) 2014, Red Hat, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -33,123 +32,11 @@
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h>
#include "prototypes.h" #include "prototypes.h"
#include "groupio.h" #include "groupio.h"
#include "getdef.h" #include "getdef.h"
/*
* get_ranges - Get the minimum and maximum ID ranges for the search
*
* This function will return the minimum and maximum ranges for IDs
*
* 0: The function completed successfully
* EINVAL: The provided ranges are impossible (such as maximum < minimum)
*
* preferred_min: The special-case minimum value for a specifically-
* requested ID, which may be lower than the standard min_id
*/
static int get_ranges (bool sys_group, gid_t *min_id, gid_t *max_id,
gid_t *preferred_min)
{
gid_t gid_def_max = 0;
if (sys_group) {
/* System groups */
/* A requested ID is allowed to be below the autoselect range */
*preferred_min = (gid_t) 1;
/* Get the minimum ID range from login.defs or default to 101 */
*min_id = (gid_t) getdef_ulong ("SYS_GID_MIN", 101UL);
/*
* If SYS_GID_MAX is unspecified, we should assume it to be one
* less than the GID_MIN (which is reserved for non-system accounts)
*/
gid_def_max = (gid_t) getdef_ulong ("GID_MIN", 1000UL) - 1;
*max_id = (gid_t) getdef_ulong ("SYS_GID_MAX",
(unsigned long) gid_def_max);
/* Check that the ranges make sense */
if (*max_id < *min_id) {
(void) fprintf (stderr,
_("%s: Invalid configuration: SYS_GID_MIN (%lu), "
"GID_MIN (%lu), SYS_GID_MAX (%lu)\n"),
Prog, (unsigned long) *min_id,
getdef_ulong ("GID_MIN", 1000UL),
(unsigned long) *max_id);
return EINVAL;
}
} else {
/* Non-system groups */
/* Get the values from login.defs or use reasonable defaults */
*min_id = (gid_t) getdef_ulong ("GID_MIN", 1000UL);
*max_id = (gid_t) getdef_ulong ("GID_MAX", 60000UL);
/*
* The preferred minimum should match the standard ID minimum
* for non-system groups.
*/
*preferred_min = *min_id;
/* Check that the ranges make sense */
if (*max_id < *min_id) {
(void) fprintf (stderr,
_("%s: Invalid configuration: GID_MIN (%lu), "
"GID_MAX (%lu)\n"),
Prog, (unsigned long) *min_id,
(unsigned long) *max_id);
return EINVAL;
}
}
return 0;
}
/*
* check_gid - See if the requested GID is available
*
* On success, return 0
* If the ID is in use, return EEXIST
* If the ID is outside the range, return ERANGE
* In other cases, return errno from getgrgid()
*/
static int check_gid (const gid_t gid,
const gid_t gid_min,
const gid_t gid_max,
bool *used_gids)
{
/* First test that the preferred ID is in the range */
if (gid < gid_min || gid > gid_max) {
return ERANGE;
}
/*
* Check whether we already detected this GID
* using the gr_next() loop
*/
if (used_gids != NULL && used_gids[gid]) {
return EEXIST;
}
/* Check if the GID exists according to NSS */
errno = 0;
if (getgrgid (gid) != NULL) {
return EEXIST;
} else {
/* getgrgid() was NULL
* we have to ignore errors as temporary
* failures of remote user identity services
* would completely block user/group creation
*/
}
/* If we've made it here, the GID must be available */
return 0;
}
/* /*
* find_new_gid - Find a new unused GID. * find_new_gid - Find a new unused GID.
* *
@@ -161,338 +48,137 @@ static int check_gid (const gid_t gid,
* Return 0 on success, -1 if no unused GIDs are available. * Return 0 on success, -1 if no unused GIDs are available.
*/ */
int find_new_gid (bool sys_group, int find_new_gid (bool sys_group,
gid_t *gid, gid_t *gid,
/*@null@*/gid_t const *preferred_gid) /*@null@*/gid_t const *preferred_gid)
{ {
bool *used_gids;
const struct group *grp; const struct group *grp;
gid_t gid_min, gid_max, preferred_min; gid_t gid_min, gid_max, group_id, id;
gid_t group_id, id; bool *used_gids;
gid_t lowest_found, highest_found;
int result;
int nospam = 0;
assert(gid != NULL); assert (gid != NULL);
/* if (!sys_group) {
* First, figure out what ID range is appropriate for gid_min = (gid_t) getdef_ulong ("GID_MIN", 1000UL);
* automatic assignment gid_max = (gid_t) getdef_ulong ("GID_MAX", 60000UL);
*/ } else {
result = get_ranges (sys_group, &gid_min, &gid_max, &preferred_min); gid_min = (gid_t) getdef_ulong ("SYS_GID_MIN", 101UL);
if (result == EINVAL) { gid_max = (gid_t) getdef_ulong ("GID_MIN", 1000UL) - 1;
return -1; gid_max = (gid_t) getdef_ulong ("SYS_GID_MAX", (unsigned long) gid_max);
}
used_gids = alloca (sizeof (bool) * (gid_max +1));
memset (used_gids, false, sizeof (bool) * (gid_max + 1));
if ( (NULL != preferred_gid)
&& (*preferred_gid >= gid_min)
&& (*preferred_gid <= gid_max)
/* Check if the user exists according to NSS */
&& (getgrgid (*preferred_gid) == NULL)
/* Check also the local database in case of uncommitted
* changes */
&& (gr_locate_gid (*preferred_gid) == NULL)) {
*gid = *preferred_gid;
return 0;
} }
/* Check if the preferred GID is available */
if (preferred_gid) {
result = check_gid (*preferred_gid, preferred_min, gid_max, NULL);
if (result == 0) {
/*
* Make sure the GID isn't queued for use already
*/
if (gr_locate_gid (*preferred_gid) == NULL) {
*gid = *preferred_gid;
return 0;
}
/*
* gr_locate_gid() found the GID in an as-yet uncommitted
* entry. We'll proceed below and auto-set a GID.
*/
} else if (result == EEXIST || result == ERANGE) {
/*
* Continue on below. At this time, we won't
* treat these two cases differently.
*/
} else {
/*
* An unexpected error occurred. We should report
* this and fail the group creation.
* This differs from the automatic creation
* behavior below, since if a specific GID was
* requested and generated an error, the user is
* more likely to want to stop and address the
* issue.
*/
fprintf (stderr,
_("%s: Encountered error attempting to use "
"preferred GID: %s\n"),
Prog, strerror (result));
return -1;
}
}
/* /*
* Search the entire group file, * Search the entire group file,
* looking for the next unused value. * looking for the largest unused value.
*
* We first check the local database with gr_rewind/gr_next to find
* all local values that are in use.
*
* We then compare the next free value to all databases (local and
* remote) and iterate until we find a free one. If there are free
* values beyond the lowest (system groups) or highest (non-system
* groups), we will prefer those and avoid potentially reclaiming a
* deleted group (which can be a security issue, since it may grant
* access to files belonging to that former group).
*
* If there are no GIDs available at the end of the search, we will
* have no choice but to iterate through the range looking for gaps.
* *
* We check the list of groups according to NSS (setgrent/getgrent),
* but we also check the local database (gr_rewind/gr_next) in case
* some groups were created but the changes were not committed yet.
*/ */
/* Create an array to hold all of the discovered GIDs */
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;
}
memset (used_gids, false, sizeof (bool) * (gid_max + 1));
/* First look for the lowest and highest value in the local database */
(void) gr_rewind ();
highest_found = gid_min;
lowest_found = gid_max;
while ((grp = gr_next ()) != NULL) {
/*
* Does this entry have a lower GID than the lowest we've found
* so far?
*/
if ((grp->gr_gid <= lowest_found) && (grp->gr_gid >= gid_min)) {
lowest_found = grp->gr_gid - 1;
}
/*
* Does this entry have a higher GID than the highest we've found
* so far?
*/
if ((grp->gr_gid >= highest_found) && (grp->gr_gid <= gid_max)) {
highest_found = grp->gr_gid + 1;
}
/* create index of used GIDs */
if (grp->gr_gid >= gid_min
&& grp->gr_gid <= gid_max) {
used_gids[grp->gr_gid] = true;
}
}
if (sys_group) { if (sys_group) {
/* /* setgrent / getgrent / endgrent can be very slow with
* For system groups, we want to start from the * LDAP configurations (and many accounts).
* top of the range and work downwards. * Since there is a limited amount of IDs to be tested
* for system accounts, we just check the existence
* of IDs with getgrgid.
*/ */
group_id = gid_max;
/* for (id = gid_max; id >= gid_min; id--) {
* At the conclusion of the gr_next() search, we will either if (getgrgid (id) != NULL) {
* have a presumed-free GID or we will be at GID_MIN - 1. group_id = id - 1;
*/ used_gids[id] = true;
if (lowest_found < gid_min) {
/*
* In this case, a GID is in use at GID_MIN.
*
* We will reset the search to GID_MAX and proceed down
* through all the GIDs (skipping those we detected with
* used_gids) for a free one. It is a known issue that
* this may result in reusing a previously-deleted GID,
* so administrators should be instructed to use this
* auto-detection with care (and prefer to assign GIDs
* explicitly).
*/
lowest_found = gid_max;
}
/* Search through all of the IDs in the range */
for (id = lowest_found; id >= gid_min; id--) {
result = check_gid (id, gid_min, gid_max, used_gids);
if (result == 0) {
/* This GID is available. Return it. */
*gid = id;
free (used_gids);
return 0;
} else if (result == EEXIST) {
/* This GID is in use, we'll continue to the next */
} else {
/*
* An unexpected error occurred.
*
* Only report it the first time to avoid spamming
* the logs
*
*/
if (!nospam) {
fprintf (stderr,
_("%s: Can't get unique system GID (%s). "
"Suppressing additional messages.\n"),
Prog, strerror (result));
SYSLOG ((LOG_ERR,
"Error checking available GIDs: %s",
strerror (result)));
nospam = 1;
}
/*
* We will continue anyway. Hopefully a later GID
* will work properly.
*/
} }
} }
/* gr_rewind ();
* If we get all the way through the loop, try again from GID_MAX, while ((grp = gr_next ()) != NULL) {
* unless that was where we previously started. (NOTE: the worst-case if ((grp->gr_gid <= group_id) && (grp->gr_gid >= gid_min)) {
* scenario here is that we will run through (GID_MAX - GID_MIN - 1) group_id = grp->gr_gid - 1;
* cycles *again* if we fall into this case with lowest_found as }
* GID_MAX - 1, all groups in the range in use and maintained by /* create index of used GIDs */
* network services such as LDAP.) if (grp->gr_gid <= gid_max) {
*/ used_gids[grp->gr_gid] = true;
if (lowest_found != gid_max) {
for (id = gid_max; id >= gid_min; id--) {
result = check_gid (id, gid_min, gid_max, used_gids);
if (result == 0) {
/* This GID is available. Return it. */
*gid = id;
free (used_gids);
return 0;
} else if (result == EEXIST) {
/* This GID is in use, we'll continue to the next */
} else {
/*
* An unexpected error occurred.
*
* Only report it the first time to avoid spamming
* the logs
*
*/
if (!nospam) {
fprintf (stderr,
_("%s: Can't get unique system GID (%s). "
"Suppressing additional messages.\n"),
Prog, strerror (result));
SYSLOG ((LOG_ERR,
"Error checking available GIDs: %s",
strerror (result)));
nospam = 1;
}
/*
* We will continue anyway. Hopefully a later GID
* will work properly.
*/
}
} }
} }
} else { /* !sys_group */ } else {
/* group_id = gid_min;
* For non-system groups, we want to start from the setgrent ();
* bottom of the range and work upwards. while ((grp = getgrent ()) != NULL) {
*/ if ((grp->gr_gid >= group_id) && (grp->gr_gid <= gid_max)) {
group_id = grp->gr_gid + 1;
/* }
* At the conclusion of the gr_next() search, we will either /* create index of used GIDs */
* have a presumed-free GID or we will be at GID_MAX + 1. if (grp->gr_gid <= gid_max) {
*/ used_gids[grp->gr_gid] = true;
if (highest_found > gid_max) {
/*
* In this case, a GID is in use at GID_MAX.
*
* We will reset the search to GID_MIN and proceed up
* through all the GIDs (skipping those we detected with
* used_gids) for a free one. It is a known issue that
* this may result in reusing a previously-deleted GID,
* so administrators should be instructed to use this
* auto-detection with care (and prefer to assign GIDs
* explicitly).
*/
highest_found = gid_min;
}
/* Search through all of the IDs in the range */
for (id = highest_found; id <= gid_max; id++) {
result = check_gid (id, gid_min, gid_max, used_gids);
if (result == 0) {
/* This GID is available. Return it. */
*gid = id;
free (used_gids);
return 0;
} else if (result == EEXIST) {
/* This GID is in use, we'll continue to the next */
} else {
/*
* An unexpected error occurred.
*
* Only report it the first time to avoid spamming
* the logs
*
*/
if (!nospam) {
fprintf (stderr,
_("%s: Can't get unique GID (%s). "
"Suppressing additional messages.\n"),
Prog, strerror (result));
SYSLOG ((LOG_ERR,
"Error checking available GIDs: %s",
strerror (result)));
nospam = 1;
}
/*
* We will continue anyway. Hopefully a later GID
* will work properly.
*/
} }
} }
endgrent ();
/* gr_rewind ();
* If we get all the way through the loop, try again from GID_MIN, while ((grp = gr_next ()) != NULL) {
* unless that was where we previously started. (NOTE: the worst-case if ((grp->gr_gid >= group_id) && (grp->gr_gid <= gid_max)) {
* scenario here is that we will run through (GID_MAX - GID_MIN - 1) group_id = grp->gr_gid + 1;
* cycles *again* if we fall into this case with highest_found as }
* GID_MIN + 1, all groups in the range in use and maintained by /* create index of used GIDs */
* network services such as LDAP.) if (grp->gr_gid <= gid_max) {
*/ used_gids[grp->gr_gid] = true;
if (highest_found != gid_min) {
for (id = gid_min; id <= gid_max; id++) {
result = check_gid (id, gid_min, gid_max, used_gids);
if (result == 0) {
/* This GID is available. Return it. */
*gid = id;
free (used_gids);
return 0;
} else if (result == EEXIST) {
/* This GID is in use, we'll continue to the next */
} else {
/*
* An unexpected error occurred.
*
* Only report it the first time to avoid spamming
* the logs
*
*/
if (!nospam) {
fprintf (stderr,
_("%s: Can't get unique GID (%s). "
"Suppressing additional messages.\n"),
Prog, strerror (result));
SYSLOG ((LOG_ERR,
"Error checking available GIDs: %s",
strerror (result)));
nospam = 1;
}
/*
* We will continue anyway. Hopefully a later GID
* will work properly.
*/
}
} }
} }
} }
/* The code reached here and found no available IDs in the range */ /*
fprintf (stderr, * If a group with GID equal to GID_MAX exists, the above algorithm
_("%s: Can't get unique GID (no more available GIDs)\n"), * will give us GID_MAX+1 even if not unique. Search for the first
Prog); * free GID starting with GID_MIN.
SYSLOG ((LOG_WARN, "no more available GIDs on the system")); */
free (used_gids); if (sys_group) {
return -1; 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 ) {
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"));
return -1;
}
}
} else {
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) {
fprintf (stderr,
_("%s: Can't get unique GID (no more available GIDs)\n"),
Prog);
SYSLOG ((LOG_WARN, "no more available GID on the system"));
return -1;
}
}
}
*gid = group_id;
return 0;
} }
-86
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 */
-86
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 */
+110 -424
View File
@@ -1,7 +1,6 @@
/* /*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh * Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 2008 - 2011, Nicolas François * Copyright (c) 2008 - 2009, Nicolas François
* Copyright (c) 2014, Red Hat, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -33,123 +32,11 @@
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h>
#include "prototypes.h" #include "prototypes.h"
#include "pwio.h" #include "pwio.h"
#include "getdef.h" #include "getdef.h"
/*
* get_ranges - Get the minimum and maximum ID ranges for the search
*
* This function will return the minimum and maximum ranges for IDs
*
* 0: The function completed successfully
* EINVAL: The provided ranges are impossible (such as maximum < minimum)
*
* preferred_min: The special-case minimum value for a specifically-
* requested ID, which may be lower than the standard min_id
*/
static int get_ranges (bool sys_user, uid_t *min_id, uid_t *max_id,
uid_t *preferred_min)
{
uid_t uid_def_max = 0;
if (sys_user) {
/* System users */
/* A requested ID is allowed to be below the autoselect range */
*preferred_min = (uid_t) 1;
/* Get the minimum ID range from login.defs or default to 101 */
*min_id = (uid_t) getdef_ulong ("SYS_UID_MIN", 101UL);
/*
* If SYS_UID_MAX is unspecified, we should assume it to be one
* less than the UID_MIN (which is reserved for non-system accounts)
*/
uid_def_max = (uid_t) getdef_ulong ("UID_MIN", 1000UL) - 1;
*max_id = (uid_t) getdef_ulong ("SYS_UID_MAX",
(unsigned long) uid_def_max);
/* Check that the ranges make sense */
if (*max_id < *min_id) {
(void) fprintf (stderr,
_("%s: Invalid configuration: SYS_UID_MIN (%lu), "
"UID_MIN (%lu), SYS_UID_MAX (%lu)\n"),
Prog, (unsigned long) *min_id,
getdef_ulong ("UID_MIN", 1000UL),
(unsigned long) *max_id);
return EINVAL;
}
} else {
/* Non-system users */
/* Get the values from login.defs or use reasonable defaults */
*min_id = (uid_t) getdef_ulong ("UID_MIN", 1000UL);
*max_id = (uid_t) getdef_ulong ("UID_MAX", 60000UL);
/*
* The preferred minimum should match the standard ID minimum
* for non-system users.
*/
*preferred_min = *min_id;
/* Check that the ranges make sense */
if (*max_id < *min_id) {
(void) fprintf (stderr,
_("%s: Invalid configuration: UID_MIN (%lu), "
"UID_MAX (%lu)\n"),
Prog, (unsigned long) *min_id,
(unsigned long) *max_id);
return EINVAL;
}
}
return 0;
}
/*
* check_uid - See if the requested UID is available
*
* On success, return 0
* If the ID is in use, return EEXIST
* If the ID is outside the range, return ERANGE
* In other cases, return errno from getpwuid()
*/
static int check_uid(const uid_t uid,
const uid_t uid_min,
const uid_t uid_max,
bool *used_uids)
{
/* First test that the preferred ID is in the range */
if (uid < uid_min || uid > uid_max) {
return ERANGE;
}
/*
* Check whether we already detected this UID
* using the pw_next() loop
*/
if (used_uids != NULL && used_uids[uid]) {
return EEXIST;
}
/* Check if the UID exists according to NSS */
errno = 0;
if (getpwuid(uid) != NULL) {
return EEXIST;
} else {
/* getpwuid() was NULL
* we have to ignore errors as temporary
* failures of remote user identity services
* would completely block user/group creation
*/
}
/* If we've made it here, the UID must be available */
return 0;
}
/* /*
* find_new_uid - Find a new unused UID. * find_new_uid - Find a new unused UID.
* *
@@ -160,339 +47,138 @@ static int check_uid(const uid_t uid,
* *
* Return 0 on success, -1 if no unused UIDs are available. * Return 0 on success, -1 if no unused UIDs are available.
*/ */
int find_new_uid(bool sys_user, int find_new_uid (bool sys_user,
uid_t *uid, uid_t *uid,
/*@null@*/uid_t const *preferred_uid) /*@null@*/uid_t const *preferred_uid)
{ {
bool *used_uids;
const struct passwd *pwd; const struct passwd *pwd;
uid_t uid_min, uid_max, preferred_min; uid_t uid_min, uid_max, user_id, id;
uid_t user_id, id; bool *used_uids;
uid_t lowest_found, highest_found;
int result;
int nospam = 0;
assert (uid != NULL); assert (uid != NULL);
/* if (!sys_user) {
* First, figure out what ID range is appropriate for uid_min = (uid_t) getdef_ulong ("UID_MIN", 1000UL);
* automatic assignment uid_max = (uid_t) getdef_ulong ("UID_MAX", 60000UL);
*/ } else {
result = get_ranges (sys_user, &uid_min, &uid_max, &preferred_min); uid_min = (uid_t) getdef_ulong ("SYS_UID_MIN", 101UL);
if (result == EINVAL) { uid_max = (uid_t) getdef_ulong ("UID_MIN", 1000UL) - 1;
return -1; uid_max = (uid_t) getdef_ulong ("SYS_UID_MAX", (unsigned long) uid_max);
}
/* Check if the preferred UID is available */
if (preferred_uid) {
result = check_uid (*preferred_uid, preferred_min, uid_max, NULL);
if (result == 0) {
/*
* Make sure the UID isn't queued for use already
*/
if (pw_locate_uid (*preferred_uid) == NULL) {
*uid = *preferred_uid;
return 0;
}
/*
* pw_locate_uid() found the UID in an as-yet uncommitted
* entry. We'll proceed below and auto-set an UID.
*/
} else if (result == EEXIST || result == ERANGE) {
/*
* Continue on below. At this time, we won't
* treat these two cases differently.
*/
} else {
/*
* An unexpected error occurred. We should report
* this and fail the user creation.
* This differs from the automatic creation
* behavior below, since if a specific UID was
* requested and generated an error, the user is
* more likely to want to stop and address the
* issue.
*/
fprintf (stderr,
_("%s: Encountered error attempting to use "
"preferred UID: %s\n"),
Prog, strerror (result));
return -1;
}
}
/*
* Search the entire passwd file,
* looking for the next unused value.
*
* We first check the local database with pw_rewind/pw_next to find
* all local values that are in use.
*
* We then compare the next free value to all databases (local and
* remote) and iterate until we find a free one. If there are free
* values beyond the lowest (system users) or highest (non-system
* users), we will prefer those and avoid potentially reclaiming a
* deleted user (which can be a security issue, since it may grant
* access to files belonging to that former user).
*
* If there are no UIDs available at the end of the search, we will
* have no choice but to iterate through the range looking for gaps.
*
*/
/* Create an array to hold all of the discovered UIDs */
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)); memset (used_uids, false, sizeof (bool) * (uid_max + 1));
/* First look for the lowest and highest value in the local database */ if ( (NULL != preferred_uid)
(void) pw_rewind (); && (*preferred_uid >= uid_min)
highest_found = uid_min; && (*preferred_uid <= uid_max)
lowest_found = uid_max; /* Check if the user exists according to NSS */
while ((pwd = pw_next ()) != NULL) { && (getpwuid (*preferred_uid) == NULL)
/* /* Check also the local database in case of uncommitted
* Does this entry have a lower UID than the lowest we've found * changes */
* so far? && (pw_locate_uid (*preferred_uid) == NULL)) {
*/ *uid = *preferred_uid;
if ((pwd->pw_uid <= lowest_found) && (pwd->pw_uid >= uid_min)) { return 0;
lowest_found = pwd->pw_uid - 1;
}
/*
* Does this entry have a higher UID than the highest we've found
* so far?
*/
if ((pwd->pw_uid >= highest_found) && (pwd->pw_uid <= uid_max)) {
highest_found = pwd->pw_uid + 1;
}
/* create index of used UIDs */
if (pwd->pw_uid >= uid_min
&& pwd->pw_uid <= uid_max) {
used_uids[pwd->pw_uid] = true;
}
} }
/*
* Search the entire password file,
* looking for the largest unused value.
*
* We check the list of users according to NSS (setpwent/getpwent),
* but we also check the local database (pw_rewind/pw_next) in case
* some users were created but the changes were not committed yet.
*/
if (sys_user) { if (sys_user) {
/* /* setpwent / getpwent / endpwent can be very slow with
* For system users, we want to start from the * LDAP configurations (and many accounts).
* top of the range and work downwards. * Since there is a limited amount of IDs to be tested
* for system accounts, we just check the existence
* of IDs with getpwuid.
*/ */
user_id = uid_max;
/* for (id = uid_max; id >= uid_min; id--) {
* At the conclusion of the pw_next() search, we will either if (getpwuid (id) != NULL) {
* have a presumed-free UID or we will be at UID_MIN - 1. user_id = id - 1;
*/ used_uids[id] = true;
if (lowest_found < uid_min) {
/*
* In this case, an UID is in use at UID_MIN.
*
* We will reset the search to UID_MAX and proceed down
* through all the UIDs (skipping those we detected with
* used_uids) for a free one. It is a known issue that
* this may result in reusing a previously-deleted UID,
* so administrators should be instructed to use this
* auto-detection with care (and prefer to assign UIDs
* explicitly).
*/
lowest_found = uid_max;
}
/* Search through all of the IDs in the range */
for (id = lowest_found; id >= uid_min; id--) {
result = check_uid (id, uid_min, uid_max, used_uids);
if (result == 0) {
/* This UID is available. Return it. */
*uid = id;
free (used_uids);
return 0;
} else if (result == EEXIST) {
/* This UID is in use, we'll continue to the next */
} else {
/*
* An unexpected error occurred.
*
* Only report it the first time to avoid spamming
* the logs
*
*/
if (!nospam) {
fprintf (stderr,
_("%s: Can't get unique system UID (%s). "
"Suppressing additional messages.\n"),
Prog, strerror (result));
SYSLOG ((LOG_ERR,
"Error checking available UIDs: %s",
strerror (result)));
nospam = 1;
}
/*
* We will continue anyway. Hopefully a later UID
* will work properly.
*/
} }
} }
/* pw_rewind ();
* If we get all the way through the loop, try again from UID_MAX, while ((pwd = pw_next ()) != NULL) {
* unless that was where we previously started. (NOTE: the worst-case if ((pwd->pw_uid <= user_id) && (pwd->pw_uid >= uid_min)) {
* scenario here is that we will run through (UID_MAX - UID_MIN - 1) user_id = pwd->pw_uid - 1;
* cycles *again* if we fall into this case with lowest_found as }
* UID_MAX - 1, all users in the range in use and maintained by /* create index of used UIDs */
* network services such as LDAP.) if (pwd->pw_uid <= uid_max) {
*/ used_uids[pwd->pw_uid] = true;
if (lowest_found != uid_max) {
for (id = uid_max; id >= uid_min; id--) {
result = check_uid (id, uid_min, uid_max, used_uids);
if (result == 0) {
/* This UID is available. Return it. */
*uid = id;
free (used_uids);
return 0;
} else if (result == EEXIST) {
/* This UID is in use, we'll continue to the next */
} else {
/*
* An unexpected error occurred.
*
* Only report it the first time to avoid spamming
* the logs
*
*/
if (!nospam) {
fprintf (stderr,
_("%s: Can't get unique system UID (%s). "
"Suppressing additional messages.\n"),
Prog, strerror (result));
SYSLOG((LOG_ERR,
"Error checking available UIDs: %s",
strerror (result)));
nospam = 1;
}
/*
* We will continue anyway. Hopefully a later UID
* will work properly.
*/
}
} }
} }
} else { /* !sys_user */ } else {
/* user_id = uid_min;
* For non-system users, we want to start from the setpwent ();
* bottom of the range and work upwards. while ((pwd = getpwent ()) != NULL) {
*/ if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) {
user_id = pwd->pw_uid + 1;
/* }
* At the conclusion of the pw_next() search, we will either /* create index of used UIDs */
* have a presumed-free UID or we will be at UID_MAX + 1. if (pwd->pw_uid <= uid_max) {
*/ used_uids[pwd->pw_uid] = true;
if (highest_found > uid_max) {
/*
* In this case, a UID is in use at UID_MAX.
*
* We will reset the search to UID_MIN and proceed up
* through all the UIDs (skipping those we detected with
* used_uids) for a free one. It is a known issue that
* this may result in reusing a previously-deleted UID,
* so administrators should be instructed to use this
* auto-detection with care (and prefer to assign UIDs
* explicitly).
*/
highest_found = uid_min;
}
/* Search through all of the IDs in the range */
for (id = highest_found; id <= uid_max; id++) {
result = check_uid (id, uid_min, uid_max, used_uids);
if (result == 0) {
/* This UID is available. Return it. */
*uid = id;
free (used_uids);
return 0;
} else if (result == EEXIST) {
/* This UID is in use, we'll continue to the next */
} else {
/*
* An unexpected error occurred.
*
* Only report it the first time to avoid spamming
* the logs
*
*/
if (!nospam) {
fprintf (stderr,
_("%s: Can't get unique UID (%s). "
"Suppressing additional messages.\n"),
Prog, strerror (result));
SYSLOG ((LOG_ERR,
"Error checking available UIDs: %s",
strerror (result)));
nospam = 1;
}
/*
* We will continue anyway. Hopefully a later UID
* will work properly.
*/
} }
} }
endpwent ();
/* pw_rewind ();
* If we get all the way through the loop, try again from UID_MIN, while ((pwd = pw_next ()) != NULL) {
* unless that was where we previously started. (NOTE: the worst-case if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) {
* scenario here is that we will run through (UID_MAX - UID_MIN - 1) user_id = pwd->pw_uid + 1;
* cycles *again* if we fall into this case with highest_found as }
* UID_MIN + 1, all users in the range in use and maintained by /* create index of used UIDs */
* network services such as LDAP.) if (pwd->pw_uid <= uid_max) {
*/ used_uids[pwd->pw_uid] = true;
if (highest_found != uid_min) {
for (id = uid_min; id <= uid_max; id++) {
result = check_uid (id, uid_min, uid_max, used_uids);
if (result == 0) {
/* This UID is available. Return it. */
*uid = id;
free (used_uids);
return 0;
} else if (result == EEXIST) {
/* This UID is in use, we'll continue to the next */
} else {
/*
* An unexpected error occurred.
*
* Only report it the first time to avoid spamming
* the logs
*
*/
if (!nospam) {
fprintf (stderr,
_("%s: Can't get unique UID (%s). "
"Suppressing additional messages.\n"),
Prog, strerror (result));
SYSLOG ((LOG_ERR,
"Error checking available UIDs: %s",
strerror (result)));
nospam = 1;
}
/*
* We will continue anyway. Hopefully a later UID
* will work properly.
*/
}
} }
} }
} }
/* The code reached here and found no available IDs in the range */ /*
fprintf (stderr, * If a user with UID equal to UID_MAX exists, the above algorithm
_("%s: Can't get unique UID (no more available UIDs)\n"), * will give us UID_MAX+1 even if not unique. Search for the first
Prog); * free UID starting with UID_MIN.
SYSLOG ((LOG_WARN, "no more available UIDs on the system")); */
free (used_uids); if (sys_user) {
return -1; if (user_id == uid_min - 1) {
for (user_id = uid_max; user_id >= uid_min; user_id--) {
if (false == used_uids[user_id]) {
break;
}
}
if (user_id < uid_min ) {
fprintf (stderr,
_("%s: Can't get unique system UID (no more available UIDs)\n"),
Prog);
SYSLOG ((LOG_WARN,
"no more available UID on the system"));
return -1;
}
}
} else {
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) {
fprintf (stderr,
_("%s: Can't get unique UID (no more available UIDs)\n"),
Prog);
SYSLOG ((LOG_WARN, "no more available UID on the system"));
return -1;
}
}
}
*uid = user_id;
return 0;
} }
+1 -1
View File
@@ -35,5 +35,5 @@
#include <config.h> #include <config.h>
#include "defines.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 #endif
+1 -1
View File
@@ -44,7 +44,7 @@
* The string may be a valid GID or a valid groupname. * The string may be a valid GID or a valid groupname.
* If the group does not exist on the system, NULL is returned. * 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; long long int gid;
char *endptr; char *endptr;
-89
View File
@@ -1,89 +0,0 @@
/*
* Copyright (c) 2017, Chris Lamb
* 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 <errno.h>
#include <limits.h>
#include <stdio.h>
#include "defines.h"
#include "prototypes.h"
/*
* gettime() returns the time as the number of seconds since the Epoch
*
* Like time(), gettime() returns the time as the number of seconds since the
* Epoch, 1970-01-01 00:00:00 +0000 (UTC), except that if the SOURCE_DATE_EPOCH
* environment variable is exported it will use that instead.
*/
/*@observer@*/time_t gettime ()
{
char *endptr;
char *source_date_epoch;
time_t fallback;
unsigned long long epoch;
fallback = time (NULL);
source_date_epoch = getenv ("SOURCE_DATE_EPOCH");
if (!source_date_epoch)
return fallback;
errno = 0;
epoch = strtoull (source_date_epoch, &endptr, 10);
if ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0))
|| (errno != 0 && epoch == 0)) {
fprintf (stderr,
_("Environment variable $SOURCE_DATE_EPOCH: strtoull: %s\n"),
strerror(errno));
} else if (endptr == source_date_epoch) {
fprintf (stderr,
_("Environment variable $SOURCE_DATE_EPOCH: No digits were found: %s\n"),
endptr);
} else if (*endptr != '\0') {
fprintf (stderr,
_("Environment variable $SOURCE_DATE_EPOCH: Trailing garbage: %s\n"),
endptr);
} else if (epoch > ULONG_MAX) {
fprintf (stderr,
_("Environment variable $SOURCE_DATE_EPOCH: value must be smaller than or equal to %lu but was found to be: %llu\n"),
ULONG_MAX, epoch);
} else if (epoch > fallback) {
fprintf (stderr,
_("Environment variable $SOURCE_DATE_EPOCH: value must be smaller than or equal to the current time (%lu) but was found to be: %llu\n"),
fallback, epoch);
} else {
/* Valid */
return (time_t)epoch;
}
return fallback;
}
+3 -3
View File
@@ -3,7 +3,7 @@
* Copyright (c) 1991 - 1993, Chip Rosenthal * Copyright (c) 1991 - 1993, Chip Rosenthal
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2010, Nicolas François * Copyright (c) 2008 - 2009, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -50,7 +50,7 @@
bool hushed (const char *username) bool hushed (const char *username)
{ {
struct passwd *pw; struct passwd *pw;
const char *hushfile; char *hushfile;
char buf[BUFSIZ]; char buf[BUFSIZ];
bool found; bool found;
FILE *fp; FILE *fp;
@@ -76,7 +76,7 @@ bool hushed (const char *username)
*/ */
if (hushfile[0] != '/') { 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); return (access (buf, F_OK) == 0);
} }
-164
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);
}
+1 -1
View File
@@ -107,7 +107,7 @@ int isexpired (const struct passwd *pw, /*@null@*/const struct spwd *sp)
if ( (-1 == sp->sp_lstchg) if ( (-1 == sp->sp_lstchg)
|| (-1 == sp->sp_max) || (-1 == sp->sp_max)
|| (sp->sp_max >= ((10000L * DAY) / SCALE))) { || (sp->sp_max >= (10000L * DAY / SCALE))) {
return 0; return 0;
} }
+70 -184
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh * Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1999, Marek Michałkiewicz * Copyright (c) 1996 - 1999, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko * Copyright (c) 2003 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François * Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -33,7 +33,6 @@
/* /*
* Separated from setup.c. --marekm * Separated from setup.c. --marekm
* Resource limits thanks to Cristian Gafton. * Resource limits thanks to Cristian Gafton.
* Enhancements of resource limit code by Thomas Orgis <thomas@orgis.org>
*/ */
#include <config.h> #include <config.h>
@@ -45,7 +44,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <stdio.h> #include <stdio.h>
#include <ctype.h>
#include "prototypes.h" #include "prototypes.h"
#include "defines.h" #include "defines.h"
#include <pwd.h> #include <pwd.h>
@@ -66,46 +64,22 @@
* value - string value to be read * value - string value to be read
* multiplier - value*multiplier is the actual limit * multiplier - value*multiplier is the actual limit
*/ */
static int setrlimit_value (unsigned int resource, static int
const char *value, setrlimit_value (unsigned int resource, const char *value,
unsigned int multiplier) unsigned int multiplier)
{ {
struct rlimit rlim; struct rlimit rlim;
rlim_t limit; long limit;
/* The "-" is special, not belonging to a strange negative limit. if (getlong (value, &limit) == 0) {
* It is infinity, in a controlled way. return 0;
*/
if ('-' == value[0]) {
limit = RLIM_INFINITY;
} }
else { limit *= multiplier;
/* We cannot use getlong here because it fails when there if (limit != (rlim_t) limit) {
* is more to the value than just this number! return 0;
* 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;
}
} }
rlim.rlim_cur = (rlim_t) limit;
rlim.rlim_cur = limit; rlim.rlim_max = (rlim_t) limit;
rlim.rlim_max = limit;
if (setrlimit (resource, &rlim) != 0) { if (setrlimit (resource, &rlim) != 0) {
return LOGIN_ERROR_RLIMIT; return LOGIN_ERROR_RLIMIT;
} }
@@ -164,12 +138,11 @@ static int check_logins (const char *name, const char *maxlogins)
count = 0; count = 0;
#ifdef USE_UTMPX #ifdef USE_UTMPX
setutxent (); setutxent ();
while ((ut = getutxent ())) while ((ut = getutxent ())) {
#else /* !USE_UTMPX */ #else /* !USE_UTMPX */
setutent (); setutent ();
while ((ut = getutent ())) while ((ut = getutent ())) {
#endif /* !USE_UTMPX */ #endif /* !USE_UTMPX */
{
if (USER_PROCESS != ut->ut_type) { if (USER_PROCESS != ut->ut_type) {
continue; 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. * includes the user who is currently trying to log in.
*/ */
if (count > limit) { if (count > limit) {
SYSLOG ((LOG_WARN, SYSLOG ((LOG_WARN, "Too many logins (max %d) for %s\n",
"Too many logins (max %lu) for %s\n", limit, name));
limit, name));
return LOGIN_ERROR_LOGIN; return LOGIN_ERROR_LOGIN;
} }
return 0; 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) * [Cc]: c = RLIMIT_CORE max core file size (KB)
* [Dd]: d = RLIMIT_DATA max data size (KB) * [Dd]: d = RLIMIT_DATA max data size (KB)
* [Ff]: f = RLIMIT_FSIZE max file 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) * [Mm]: m = RLIMIT_MEMLOCK max locked-in-memory address space (KB)
* [Nn]: n = RLIMIT_NOFILE max number of open files * [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) * [Rr]: r = RLIMIT_RSS max resident set size (KB)
* [Ss]: s = RLIMIT_STACK max stack size (KB) * [Ss]: s = RLIMIT_STACK max stack size (KB)
* [Tt]: t = RLIMIT_CPU max CPU time (MIN) * [Tt]: t = RLIMIT_CPU max CPU time (MIN)
* [Uu]: u = RLIMIT_NPROC max number of processes * [Uu]: u = RLIMIT_NPROC max number of processes
* * [Kk]: k = file creation masK (umask)
* NOTE: Remember to extend the "no-limits" string below when adding a new * [Ll]: l = max number of logins for this user
* limit... * [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: * Return value:
* 0 = okay, of course * 0 = okay, of course
@@ -244,24 +213,6 @@ static int do_user_limits (const char *buf, const char *name)
bool reported = false; bool reported = false;
pp = buf; 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) { while ('\0' != *pp) {
switch (*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); retval |= setrlimit_value (RLIMIT_AS, pp, 1024);
break; break;
#endif #endif
#ifdef RLIMIT_CORE #ifdef RLIMIT_CPU
case 'c': case 't':
case 'C': case 'T':
/* RLIMIT_CORE - max core file size (KB) */ /* RLIMIT_CPU - max CPU time (MIN) */
retval |= setrlimit_value (RLIMIT_CORE, pp, 1024); retval |= setrlimit_value (RLIMIT_CPU, pp, 60);
break; break;
#endif #endif
#ifdef RLIMIT_DATA #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); retval |= setrlimit_value (RLIMIT_FSIZE, pp, 1024);
break; break;
#endif #endif
#ifdef RLIMIT_NICE #ifdef RLIMIT_NPROC
case 'i': case 'u':
case 'I': case 'U':
/* RLIMIT_NICE - max scheduling priority (0..39) */ /* RLIMIT_NPROC - max number of processes */
retval |= setrlimit_value (RLIMIT_NICE, pp, 1); retval |= setrlimit_value (RLIMIT_NPROC, pp, 1);
break; break;
#endif #endif
case 'k': #ifdef RLIMIT_CORE
case 'K': case 'c':
retval |= set_umask (pp); case 'C':
break; /* RLIMIT_CORE - max core file size (KB) */
case 'l': retval |= setrlimit_value (RLIMIT_CORE, pp, 1024);
case 'L':
/* LIMIT the number of concurrent logins */
retval |= check_logins (name, pp);
break; break;
#endif
#ifdef RLIMIT_MEMLOCK #ifdef RLIMIT_MEMLOCK
case 'm': case 'm':
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); retval |= setrlimit_value (RLIMIT_NOFILE, pp, 1);
break; break;
#endif #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 #ifdef RLIMIT_RSS
case 'r': case 'r':
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); retval |= setrlimit_value (RLIMIT_STACK, pp, 1024);
break; break;
#endif #endif
#ifdef RLIMIT_CPU #ifdef RLIMIT_NICE
case 't': case 'i':
case 'T': case 'I':
/* RLIMIT_CPU - max CPU time (MIN) */ /* RLIMIT_NICE - max scheduling priority (0..39) */
retval |= setrlimit_value (RLIMIT_CPU, pp, 60); retval |= setrlimit_value (RLIMIT_NICE, pp, 1);
break; break;
#endif #endif
#ifdef RLIMIT_NPROC #ifdef RLIMIT_RTPRIO
case 'u': case 'o':
case 'U': case 'O':
/* RLIMIT_NPROC - max number of processes */ /* RLIMIT_RTPRIO - max real time priority (0..MAX_RT_PRIO) */
retval |= setrlimit_value (RLIMIT_NPROC, pp, 1); retval |= setrlimit_value (RLIMIT_RTPRIO, pp, 1);
break; break;
#endif #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: default:
/* Only report invalid strings once */ /* 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) { if (!reported) {
SYSLOG ((LOG_WARN, SYSLOG ((LOG_WARN,
"Invalid limit string: '%s'", "Invalid limit string: '%s'",
@@ -378,51 +323,13 @@ static int do_user_limits (const char *buf, const char *name)
retval |= LOGIN_ERROR_RLIMIT; 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; 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) static int setup_user_limits (const char *uname)
{ {
/* TODO: allow and use @group syntax --cristiang */
FILE *fil; FILE *fil;
char buf[1024]; char buf[1024];
char name[1024]; char name[1024];
@@ -444,10 +351,8 @@ static int setup_user_limits (const char *uname)
} }
/* The limits file have the following format: /* The limits file have the following format:
* - '#' (comment) chars only as first chars on a line; * - '#' (comment) chars only as first chars on a line;
* - username must start on first column (or *, or @group) * - username must start on first column
* * A better (smarter) checking should be done --cristiang */
* FIXME: A better (smarter) checking should be done
*/
while (fgets (buf, 1024, fil) != NULL) { while (fgets (buf, 1024, fil) != NULL) {
if (('#' == buf[0]) || ('\n' == buf[0])) { if (('#' == buf[0]) || ('\n' == buf[0])) {
continue; continue;
@@ -459,35 +364,15 @@ static int setup_user_limits (const char *uname)
* username L2 D2048 R4096 * username L2 D2048 R4096
* where spaces={' ',\t}. Also, we reject invalid limits. * where spaces={' ',\t}. Also, we reject invalid limits.
* Imposing a limit should be done with care, so a wrong * Imposing a limit should be done with care, so a wrong
* entry means no care anyway :-). * entry means no care anyway :-). A '-' as a limits
* * strings means no limits --cristiang */
* A '-' as a limits strings means no limits if (sscanf (buf, "%s%[ACDFMNRSTULPIOacdfmnrstulpio0-9 \t-]",
* name, tempbuf) == 2) {
* 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) {
if (strcmp (name, uname) == 0) { if (strcmp (name, uname) == 0) {
strcpy (limits, tempbuf); strcpy (limits, tempbuf);
break; break;
} else if (strcmp (name, "*") == 0) { } else if (strcmp (name, "*") == 0) {
strcpy (deflimits, tempbuf); 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) static void setup_usergroups (const struct passwd *info)
{ {
const struct group *grp; const struct group *grp;
mode_t tmpmask;
/* /*
* if not root, and UID == GID, and username is the same as primary * 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); grp = getgrgid (info->pw_gid);
if ( (NULL != grp) if ( (NULL != grp)
&& (strcmp (info->pw_name, grp->gr_name) == 0)) { && (strcmp (info->pw_name, grp->gr_name) == 0)) {
mode_t tmpmask;
tmpmask = umask (0777); tmpmask = umask (0777);
tmpmask = (tmpmask & ~070) | ((tmpmask >> 3) & 070); tmpmask = (tmpmask & ~070) | ((tmpmask >> 3) & 070);
(void) umask (tmpmask); (void) umask (tmpmask);
@@ -547,7 +432,8 @@ void setup_limits (const struct passwd *info)
if (getdef_bool ("QUOTAS_ENAB")) { if (getdef_bool ("QUOTAS_ENAB")) {
#ifdef LIMITS #ifdef LIMITS
if (info->pw_uid != 0) { 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) fputs (_("Too many logins.\n"), stderr);
(void) sleep (2); /* XXX: Should be FAIL_DELAY */ (void) sleep (2); /* XXX: Should be FAIL_DELAY */
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
+1 -13
View File
@@ -141,12 +141,6 @@
return tmp; 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) /*@only@*/ /*@out@*/char **dup_list (char *const *list)
{ {
int i; int i;
@@ -169,12 +163,6 @@
return tmp; 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) bool is_on_list (char *const *list, const char *member)
{ {
assert (NULL != member); assert (NULL != member);
@@ -199,7 +187,7 @@ bool is_on_list (char *const *list, const char *member)
char *members; char *members;
char **array; char **array;
int i; int i;
char *cp; const char *cp;
char *cp2; char *cp2;
assert (NULL != comma); assert (NULL != comma);
+9 -8
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1993, Julianne Frances Haugh * Copyright (c) 1989 - 1993, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2011, Nicolas François * Copyright (c) 2008 - 2009, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 #define MAX_ENV 32
char *envp[MAX_ENV]; char *envp[MAX_ENV];
int envc;
char *cp; char *cp;
int i; int i;
FILE *fp; FILE *fp;
@@ -87,9 +88,9 @@ void login_prompt (const char *prompt, char *name, int namesize)
*/ */
if (NULL != prompt) { if (NULL != prompt) {
const char *fname = getdef_str ("ISSUE_FILE"); cp = getdef_str ("ISSUE_FILE");
if (NULL != fname) { if (NULL != cp) {
fp = fopen (fname, "r"); fp = fopen (cp, "r");
if (NULL != fp) { if (NULL != fp) {
while ((i = getc (fp)) != EOF) { while ((i = getc (fp)) != EOF) {
(void) putc (i, stdout); (void) putc (i, stdout);
@@ -98,7 +99,7 @@ void login_prompt (const char *prompt, char *name, int namesize)
(void) fclose (fp); (void) fclose (fp);
} }
} }
(void) gethostname (buf, sizeof buf); gethostname (buf, sizeof buf);
printf (prompt, buf); printf (prompt, buf);
(void) fflush (stdout); (void) fflush (stdout);
} }
@@ -147,7 +148,6 @@ void login_prompt (const char *prompt, char *name, int namesize)
if ('\0' != *cp) { /* process new variables */ if ('\0' != *cp) { /* process new variables */
char *nvar; char *nvar;
int count = 1; int count = 1;
int envc;
for (envc = 0; envc < MAX_ENV; envc++) { for (envc = 0; envc < MAX_ENV; envc++) {
nvar = strtok ((0 != envc) ? (char *) 0 : cp, " \t,"); 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; envp[envc] = nvar;
} else { } else {
size_t len = strlen (nvar) + 32; size_t len = strlen (nvar) + 32;
int wlen;
envp[envc] = xmalloc (len); envp[envc] = xmalloc (len);
(void) snprintf (envp[envc], len, wlen = snprintf (envp[envc], len, "L%d=%s", count++, nvar);
"L%d=%s", count++, nvar); assert (wlen == (int) len -1);
} }
} }
set_env (envc, envp); set_env (envc, envp);
+7 -21
View File
@@ -2,7 +2,6 @@
* Copyright (c) 1989 - 1991, Julianne Frances Haugh * Copyright (c) 1989 - 1991, Julianne Frances Haugh
* Copyright (c) 1996 - 1997, Marek Michałkiewicz * Copyright (c) 1996 - 1997, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2010 , Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -48,34 +47,21 @@
void motd (void) void motd (void)
{ {
FILE *fp; FILE *fp;
char *motdlist; char motdlist[BUFSIZ], *motdfile, *mb;
const char *motdfile;
char *mb;
register int c; register int c;
motdfile = getdef_str ("MOTD_FILE"); if ((mb = getdef_str ("MOTD_FILE")) == NULL)
if (NULL == motdfile) {
return; return;
}
motdlist = xstrdup (motdfile); strncpy (motdlist, mb, sizeof (motdlist));
motdlist[sizeof (motdlist) - 1] = '\0';
for (mb = motdlist; ;mb = NULL) { for (mb = motdlist; (motdfile = strtok (mb, ":")) != NULL; mb = NULL) {
motdfile = strtok (mb, ":"); if ((fp = fopen (motdfile, "r")) != NULL) {
if (NULL == motdfile) { while ((c = getc (fp)) != EOF)
break;
}
fp = fopen (motdfile, "r");
if (NULL != fp) {
while ((c = getc (fp)) != EOF) {
putchar (c); putchar (c);
}
fclose (fp); fclose (fp);
} }
} }
fflush (stdout); fflush (stdout);
free (motdlist);
} }
+13 -16
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh * Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1999, Marek Michałkiewicz * Copyright (c) 1996 - 1999, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François * Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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. * 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; int i, j;
@@ -100,7 +100,7 @@ static bool similar (/*@notnull@*/const char *old, /*@notnull@*/const char *new)
* a nice mix of characters. * 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 digits = false;
bool uppers = false; bool uppers = false;
@@ -147,7 +147,7 @@ static bool simple (unused const char *old, const char *new)
return true; return true;
} }
static char *str_lower (/*@returned@*/char *string) static char *str_lower (char *string)
{ {
char *cp; char *cp;
@@ -157,10 +157,8 @@ static char *str_lower (/*@returned@*/char *string)
return string; return string;
} }
static /*@observer@*//*@null@*/const char *password_check ( static const char *password_check (const char *old, const char *new,
/*@notnull@*/const char *old, const struct passwd *pwdp)
/*@notnull@*/const char *new,
/*@notnull@*/const struct passwd *pwdp)
{ {
const char *msg = NULL; const char *msg = NULL;
char *oldmono, *newmono, *wrapped; char *oldmono, *newmono, *wrapped;
@@ -221,15 +219,14 @@ static /*@observer@*//*@null@*/const char *password_check (
return msg; return msg;
} }
static /*@observer@*//*@null@*/const char *obscure_msg ( /*ARGSUSED*/
/*@notnull@*/const char *old, static const char *obscure_msg (const char *old, const char *new,
/*@notnull@*/const char *new, const struct passwd *pwdp)
/*@notnull@*/const struct passwd *pwdp)
{ {
size_t maxlen, oldlen, newlen; size_t maxlen, oldlen, newlen;
char *new1, *old1; char *new1, *old1;
const char *msg; const char *msg;
const char *result; char *result;
oldlen = strlen (old); oldlen = strlen (old);
newlen = strlen (new); newlen = strlen (new);
@@ -307,15 +304,15 @@ static /*@observer@*//*@null@*/const char *obscure_msg (
* check passwords. * 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); const char *msg = obscure_msg (old, new, pwdp);
if (NULL != msg) { if (NULL != msg) {
printf (_("Bad password: %s. "), msg); printf (_("Bad password: %s. "), msg);
return false; return 0;
} }
return true; return 1;
} }
#else /* !USE_PAM */ #else /* !USE_PAM */
+2 -2
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009 - 2010, Nicolas François * Copyright (c) 2009, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -39,7 +39,7 @@
#include <security/pam_appl.h> #include <security/pam_appl.h>
#include "prototypes.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, static int ni_conv (int num_msg,
const struct pam_message **msg, const struct pam_message **msg,
struct pam_response **resp, struct pam_response **resp,
-133
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;
}
-124
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);
}
}
+24 -27
View File
@@ -23,7 +23,7 @@
static void seedRNG (void); static void seedRNG (void);
static /*@observer@*/const char *gensalt (size_t salt_size); static /*@observer@*/const char *gensalt (size_t salt_size);
#ifdef USE_SHA_CRYPT #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); static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds);
#endif /* USE_SHA_CRYPT */ #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' #define MAGNUM(array,ch) (array)[0]=(array)[2]='$',(array)[1]=(ch),(array)[3]='\0'
#ifdef USE_SHA_CRYPT #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). * Return the salt size.
* * The size of the salt string is between 8 and 16 bytes for the SHA crypt
* It favors slightly the higher numbers. * methods.
*/ */
static long shadow_random (long min, long max) static size_t SHA_salt_size (void)
{ {
double drand; double rand_size;
long ret;
seedRNG (); seedRNG ();
drand = (double) (max - min + 1) * random () / RANDOM_MAX; rand_size = (double) 9.0 * random () / RAND_MAX;
/* On systems were this is not random() range is lower, we favor return (size_t) (8 + rand_size);
* 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;
} }
/* Default number of rounds if not explicitly specified. */ /* 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 /*@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; long rounds;
if (NULL == prefered_rounds) { if (NULL == prefered_rounds) {
long min_rounds = getdef_long ("SHA_CRYPT_MIN_ROUNDS", -1); long min_rounds = getdef_long ("SHA_CRYPT_MIN_ROUNDS", -1);
long max_rounds = getdef_long ("SHA_CRYPT_MAX_ROUNDS", -1); long max_rounds = getdef_long ("SHA_CRYPT_MAX_ROUNDS", -1);
double rand_rounds;
if ((-1 == min_rounds) && (-1 == max_rounds)) { if ((-1 == min_rounds) && (-1 == max_rounds)) {
return ""; return "";
@@ -141,7 +130,10 @@ static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds
max_rounds = min_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) { } else if (0 == *prefered_rounds) {
return ""; return "";
} else { } else {
@@ -158,8 +150,13 @@ static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds
rounds = ROUNDS_MAX; rounds = ROUNDS_MAX;
} }
(void) snprintf (rounds_prefix, sizeof rounds_prefix, snprintf (rounds_prefix, 18, "rounds=%ld$", rounds);
"rounds=%ld$", rounds);
/* Sanity checks. That should not be necessary. */
rounds_prefix[17] = '\0';
if ('$' != rounds_prefix[16]) {
rounds_prefix[17] = '$';
}
return rounds_prefix; 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 * * For the SHA256 and SHA512 method, this specifies the number of rounds
* (if not NULL). * (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: /* Max result size for the SHA methods:
* +3 $5$ * +3 $5$
@@ -234,11 +231,11 @@ static /*@observer@*/const char *gensalt (size_t salt_size)
} else if (0 == strcmp (method, "SHA256")) { } else if (0 == strcmp (method, "SHA256")) {
MAGNUM(result, '5'); MAGNUM(result, '5');
strcat(result, SHA_salt_rounds((int *)arg)); 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")) { } else if (0 == strcmp (method, "SHA512")) {
MAGNUM(result, '6'); MAGNUM(result, '6');
strcat(result, SHA_salt_rounds((int *)arg)); strcat(result, SHA_salt_rounds((int *)arg));
salt_len = (size_t) shadow_random (8, 16); salt_len = SHA_salt_size();
#endif /* USE_SHA_CRYPT */ #endif /* USE_SHA_CRYPT */
} else if (0 != strcmp (method, "DES")) { } else if (0 != strcmp (method, "DES")) {
fprintf (stderr, fprintf (stderr,
+2 -2
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh * Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz * Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2010, Nicolas François * Copyright (c) 2008 - 2009, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 defined (HAVE_INITGROUPS) && ! defined (USE_PAM)
if (is_console) { if (is_console) {
const char *cp = getdef_str ("CONSOLE_GROUPS"); char *cp = getdef_str ("CONSOLE_GROUPS");
if ((NULL != cp) && (add_groups (cp) != 0)) { if ((NULL != cp) && (add_groups (cp) != 0)) {
perror ("Warning: add_groups"); perror ("Warning: add_groups");
+7 -9
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh * Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 - 2006, Tomasz Kłoczko * Copyright (c) 2001 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François * Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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) { if (NULL == fp) {
return; return;
} }
while (fgets (buf, (int)(sizeof buf), fp) == buf) { while (fgets (buf, sizeof buf, fp) == buf) {
cp = strrchr (buf, '\n'); cp = strrchr (buf, '\n');
if (NULL == cp) { if (NULL == cp) {
break; break;
@@ -200,9 +200,9 @@ static void read_env_file (const char *filename)
void setup_env (struct passwd *info) void setup_env (struct passwd *info)
{ {
#ifndef USE_PAM #ifndef USE_PAM
const char *envf; char *envf;
#endif #endif
const char *cp; char *cp;
/* /*
* Change the current working directory to be the home directory * Change the current working directory to be the home directory
@@ -228,8 +228,7 @@ void setup_env (struct passwd *info)
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} }
(void) puts (_("No directory, logging in with HOME=/")); (void) puts (_("No directory, logging in with HOME=/"));
free (info->pw_dir); info->pw_dir = temp_pw_dir;
info->pw_dir = xstrdup (temp_pw_dir);
} }
/* /*
@@ -245,8 +244,7 @@ void setup_env (struct passwd *info)
if ((NULL == info->pw_shell) || ('\0' == *info->pw_shell)) { if ((NULL == info->pw_shell) || ('\0' == *info->pw_shell)) {
static char temp_pw_shell[] = SHELL; static char temp_pw_shell[] = SHELL;
free (info->pw_shell); info->pw_shell = temp_pw_shell;
info->pw_shell = xstrdup (temp_pw_shell);
} }
addenv ("SHELL", info->pw_shell); addenv ("SHELL", info->pw_shell);
@@ -267,7 +265,7 @@ void setup_env (struct passwd *info)
if (NULL == cp) { if (NULL == cp) {
/* not specified, use a minimal default */ /* 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, '=')) { } else if (strchr (cp, '=')) {
/* specified as name=value (PATH=...) */ /* specified as name=value (PATH=...) */
addenv (cp, NULL); addenv (cp, NULL);
+4 -5
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. * don't want to tell us what it is themselves.
*/ */
if (arg == (char *) 0) { if (arg == (char *) 0) {
(void) snprintf (arg0, sizeof arg0, "-%s", Basename ((char *) file)); snprintf (arg0, sizeof arg0, "-%s", Basename ((char *) file));
arg0[sizeof arg0 - 1] = '\0';
arg = arg0; 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 * able to figure out what we are up to without too much
* grief. * grief.
*/ */
(void) execle (file, arg, (char *) 0, envp); execle (file, arg, (char *) 0, envp);
err = errno; err = errno;
if (access (file, R_OK|X_OK) == 0) { 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). * Assume this is a shell script (with no shebang).
* Interpret it with /bin/sh * Interpret it with /bin/sh
*/ */
(void) execle (SHELL, "sh", "-", file, (char *)0, envp); execle (SHELL, "sh", "-", file, (char *)0, envp);
err = errno; 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 * how to execute this stupid shell, so I might as well give
* up in disgust ... * up in disgust ...
*/ */
(void) snprintf (arg0, sizeof arg0, _("Cannot execute %s"), file); snprintf (arg0, sizeof arg0, _("Cannot execute %s"), file);
errno = err; errno = err;
perror (arg0); perror (arg0);
return err; return err;
+2 -30
View File
@@ -36,8 +36,6 @@
#include <config.h> #include <config.h>
#include <ctype.h>
#ident "$Id$" #ident "$Id$"
#include "defines.h" #include "defines.h"
@@ -46,7 +44,6 @@
#ifndef USE_GETDATE #ifndef USE_GETDATE
#define USE_GETDATE 1 #define USE_GETDATE 1
#endif #endif
#if USE_GETDATE #if USE_GETDATE
#include "getdate.h" #include "getdate.h"
/* /*
@@ -66,8 +63,6 @@
long strtoday (const char *str) long strtoday (const char *str)
{ {
time_t t; time_t t;
bool isnum = true;
const char *s = str;
/* /*
* get_date() interprets an empty string as the current date, * get_date() interprets an empty string as the current date,
@@ -78,32 +73,9 @@ long strtoday (const char *str)
return -1; return -1;
} }
/* If a numerical value is provided, this is already a number of t = get_date (str, (time_t *) 0);
* 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);
if ((time_t) - 1 == t) { if ((time_t) - 1 == t) {
return -2; return -1;
} }
/* convert seconds to days since 1970-01-01 */ /* convert seconds to days since 1970-01-01 */
return (long) (t + DAY / 2) / DAY; return (long) (t + DAY / 2) / DAY;
+4 -6
View File
@@ -43,7 +43,7 @@
/* /*
* subsystem - change to subsystem root * 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 * the first character of the login shell. The given home
* directory will be used as the root of a new filesystem which * directory will be used as the root of a new filesystem which
* the user is actually logged into. * the user is actually logged into.
@@ -66,13 +66,11 @@ void subsystem (const struct passwd *pw)
* must be able to change into it. * must be able to change into it.
*/ */
if ( (chdir (pw->pw_dir) != 0) if (chdir (pw->pw_dir) || chroot (pw->pw_dir)) {
|| (chroot (pw->pw_dir) != 0)) { printf (_("Can't change root directory to '%s'\n"),
(void) printf (_("Can't change root directory to '%s'\n"), pw->pw_dir);
pw->pw_dir);
SYSLOG ((LOG_WARN, NO_SUBROOT2, pw->pw_dir, pw->pw_name)); SYSLOG ((LOG_WARN, NO_SUBROOT2, pw->pw_dir, pw->pw_name));
closelog (); closelog ();
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} }
} }
+3 -5
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1992, Julianne Frances Haugh * Copyright (c) 1989 - 1992, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 - 2005, Tomasz Kłoczko * Copyright (c) 2001 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2010, Nicolas François * Copyright (c) 2008 , Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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) void sulog (const char *tty, bool success, const char *oldname, const char *name)
{ {
const char *sulog_file; char *sulog_file;
time_t now; time_t now;
struct tm *tm; struct tm *tm;
FILE *fp; 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)); "FAILED su for %s by %s",name,oldname));
} }
sulog_file = getdef_str ("SULOG_FILE"); if ((sulog_file = getdef_str ("SULOG_FILE")) == (char *) 0)
if (NULL == sulog_file) {
return; return;
}
oldgid = getgid (); oldgid = getgid ();
oldmask = umask (077); oldmask = umask (077);
+40 -12
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013 Eric Biederman * Copyright (c) 2009 , Dan Walsh <dwalsh@redhat.com>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <config.h>
#ifndef _IDMAPPING_H_ #ident "$Id$"
#define _IDMAPPING_H_
struct map_range { #include <stdio.h>
unsigned long upper; /* first ID inside the namespace */ #include <sys/wait.h>
unsigned long lower; /* first ID outside the namespace */ #include <fcntl.h>
unsigned long count; /* Length of the inside and outside ranges */ #include "prototypes.h"
}; #include "defines.h"
extern struct map_range *get_map_ranges(int ranges, int argc, char **argv); int safe_system (const char *command,
extern void write_mapping(int proc_dir_fd, int ranges, const char *argv[],
struct map_range *mappings, const char *map_file); 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);
}
+7 -7
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh * Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1997, Marek Michałkiewicz * Copyright (c) 1996 - 1997, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2010, Nicolas François * Copyright (c) 2008 , Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -45,10 +45,10 @@ void ttytype (const char *line)
{ {
FILE *fp; FILE *fp;
char buf[BUFSIZ]; char buf[BUFSIZ];
const char *typefile; char *typefile;
char *cp; char *cp;
char type[1024] = ""; char type[BUFSIZ];
char port[1024]; char port[BUFSIZ];
if (getenv ("TERM") != NULL) { if (getenv ("TERM") != NULL) {
return; return;
@@ -76,12 +76,12 @@ void ttytype (const char *line)
*cp = '\0'; *cp = '\0';
} }
if ( (sscanf (buf, "%1023s %1023s", type, port) == 2) if ((sscanf (buf, "%s %s", type, port) == 2) &&
&& (strcmp (line, port) == 0)) { (strcmp (line, port) == 0)) {
break; break;
} }
} }
if ((feof (fp) == 0) && (ferror (fp) == 0) && (type[0] != '\0')) { if ((feof (fp) == 0) && (ferror (fp) == 0)) {
addenv ("TERM", type); addenv ("TERM", type);
} }
+8 -13
View File
@@ -3,7 +3,7 @@
* Copyright (c) 1991 - 1994, Chip Rosenthal * Copyright (c) 1991 - 1994, Chip Rosenthal
* Copyright (c) 1996 - 1998, Marek Michałkiewicz * Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François * Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * tz() determines the name of the local timezone by reading the
* contents of the file named by ``fname''. * 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]; static char tzbuf[BUFSIZ];
const char *def_tz = "TZ=CST6CDT"; const char *def_tz = "TZ=CST6CDT";
fp = fopen (fname, "r"); if ((fp = fopen (fname, "r")) == NULL ||
if ( (NULL == fp) fgets (tzbuf, (int) sizeof (tzbuf), fp) == NULL) {
|| (fgets (tzbuf, (int) sizeof (tzbuf), fp) == NULL)) { if (!(def_tz = getdef_str ("ENV_TZ")) || def_tz[0] == '/')
def_tz = getdef_str ("ENV_TZ");
if ((NULL == def_tz) || ('/' == def_tz[0])) {
def_tz = "TZ=CST6CDT"; def_tz = "TZ=CST6CDT";
}
strcpy (tzbuf, def_tz); strcpy (tzbuf, def_tz);
} else { } else
tzbuf[strlen (tzbuf) - 1] = '\0'; tzbuf[strlen (tzbuf) - 1] = '\0';
}
if (NULL != fp) { if (fp)
(void) fclose (fp); (void) fclose (fp);
}
return tzbuf; return tzbuf;
} }
+8 -46
View File
@@ -38,16 +38,12 @@
#include <stdio.h> #include <stdio.h>
#include <sys/types.h> #include <sys/types.h>
#include <dirent.h> #include <dirent.h>
#include <fcntl.h>
#include "defines.h" #include "defines.h"
#include "prototypes.h" #include "prototypes.h"
#ifdef ENABLE_SUBIDS
#include "subordinateio.h"
#endif /* ENABLE_SUBIDS */
#ifdef __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);
static int user_busy_processes (const char *name, uid_t uid); static int user_busy_processes (uid_t uid);
#else /* !__linux__ */ #else /* !__linux__ */
static int user_busy_utmp (const char *name); static int user_busy_utmp (const char *name);
#endif /* !__linux__ */ #endif /* !__linux__ */
@@ -62,7 +58,7 @@ int user_busy (const char *name, uid_t uid)
*/ */
#ifdef __linux__ #ifdef __linux__
/* On Linux, directly parse /proc */ /* On Linux, directly parse /proc */
return user_busy_processes (name, uid); return user_busy_processes (uid);
#else /* !__linux__ */ #else /* !__linux__ */
/* If we cannot rely on /proc, check is there is a record in utmp /* If we cannot rely on /proc, check is there is a record in utmp
* indicating that the user is still logged in */ * indicating that the user is still logged in */
@@ -95,9 +91,6 @@ static int user_busy_utmp (const char *name)
continue; continue;
} }
fprintf (stderr,
_("%s: user %s is currently logged in\n"),
Prog, name);
return 1; return 1;
} }
@@ -106,7 +99,7 @@ static int user_busy_utmp (const char *name)
#endif /* !__linux__ */ #endif /* !__linux__ */
#ifdef __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 */ /* 40: /proc/xxxxxxxxxx/task/xxxxxxxxxx/status + \0 */
char status[40]; char status[40];
@@ -129,13 +122,7 @@ static int check_status (const char *name, const char *sname, uid_t uid)
&ruid, &euid, &suid) == 3) { &ruid, &euid, &suid) == 3) {
if ( (ruid == (unsigned long) uid) if ( (ruid == (unsigned long) uid)
|| (euid == (unsigned long) uid) || (euid == (unsigned long) uid)
|| (suid == (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 */
) {
(void) fclose (sfile); (void) fclose (sfile);
return 1; return 1;
} }
@@ -150,7 +137,7 @@ static int check_status (const char *name, const char *sname, uid_t uid)
return 0; return 0;
} }
static int user_busy_processes (const char *name, uid_t uid) static int user_busy_processes (uid_t uid)
{ {
DIR *proc; DIR *proc;
struct dirent *ent; struct dirent *ent;
@@ -163,24 +150,14 @@ static int user_busy_processes (const char *name, uid_t uid)
struct stat sbroot; struct stat sbroot;
struct stat sbroot_process; struct stat sbroot_process;
#ifdef ENABLE_SUBIDS
sub_uid_open (O_RDONLY);
#endif /* ENABLE_SUBIDS */
proc = opendir ("/proc"); proc = opendir ("/proc");
if (proc == NULL) { if (proc == NULL) {
perror ("opendir /proc"); perror ("opendir /proc");
#ifdef ENABLE_SUBIDS
sub_uid_close();
#endif
return 0; return 0;
} }
if (stat ("/", &sbroot) != 0) { if (stat ("/", &sbroot) != 0) {
perror ("stat (\"/\")"); perror ("stat (\"/\")");
(void) closedir (proc); (void) closedir (proc);
#ifdef ENABLE_SUBIDS
sub_uid_close();
#endif
return 0; return 0;
} }
@@ -216,14 +193,8 @@ static int user_busy_processes (const char *name, uid_t uid)
continue; continue;
} }
if (check_status (name, tmp_d_name, uid) != 0) { if (check_status (tmp_d_name, uid) != 0) {
(void) closedir (proc); (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; return 1;
} }
@@ -239,14 +210,8 @@ static int user_busy_processes (const char *name, uid_t uid)
if (tid == pid) { if (tid == pid) {
continue; continue;
} }
if (check_status (name, task_path+6, uid) != 0) { if (check_status (task_path+6, uid) != 0) {
(void) closedir (proc); (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; return 1;
} }
} }
@@ -257,9 +222,6 @@ static int user_busy_processes (const char *name, uid_t uid)
} }
(void) closedir (proc); (void) closedir (proc);
#ifdef ENABLE_SUBIDS
sub_uid_close();
#endif /* ENABLE_SUBIDS */
return 0; return 0;
} }
#endif /* __linux__ */ #endif /* __linux__ */
+2 -11
View File
@@ -42,8 +42,6 @@
#endif #endif
#include <assert.h> #include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h> #include <netdb.h>
#include <stdio.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.")); (void) puts (_("Unable to determine your tty name."));
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} else if (strncmp (tty, tmptty, sizeof (tmptty)) != 0) { } else if (strncmp (tty, tmptty, sizeof (tmptty)) != 0) {
@@ -131,7 +129,6 @@ static bool is_my_tty (const char *tty)
return ret; return ret;
} }
#ifndef USE_PAM
/* /*
* Some systems already have updwtmp() and possibly updwtmpx(). Others * Some systems already have updwtmp() and possibly updwtmpx(). Others
* don't, so we re-implement these functions if necessary. * 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 /* ! HAVE_UPDWTMPX */
#endif /* ! USE_UTMPX */ #endif /* ! USE_UTMPX */
#endif /* ! USE_PAM */
/* /*
@@ -204,6 +200,7 @@ static void updwtmpx (const char *filename, const struct utmpx *utx)
strcpy (hostname, host); strcpy (hostname, host);
#ifdef HAVE_STRUCT_UTMP_UT_HOST #ifdef HAVE_STRUCT_UTMP_UT_HOST
} else if ( (NULL != ut) } else if ( (NULL != ut)
&& (NULL != ut->ut_host)
&& ('\0' != ut->ut_host[0])) { && ('\0' != ut->ut_host[0])) {
hostname = (char *) xmalloc (sizeof (ut->ut_host) + 1); hostname = (char *) xmalloc (sizeof (ut->ut_host) + 1);
strncpy (hostname, ut->ut_host, sizeof (ut->ut_host)); strncpy (hostname, ut->ut_host, sizeof (ut->ut_host));
@@ -317,10 +314,7 @@ int setutmp (struct utmp *ut)
} }
endutent (); endutent ();
#ifndef USE_PAM
/* This is done by pam_lastlog */
updwtmp (_WTMP_FILE, ut); updwtmp (_WTMP_FILE, ut);
#endif /* ! USE_PAM */
return err; return err;
} }
@@ -453,10 +447,7 @@ int setutmpx (struct utmpx *utx)
} }
endutxent (); endutxent ();
#ifndef USE_PAM
/* This is done by pam_lastlog */
updwtmpx (_WTMP_FILE "x", utx); updwtmpx (_WTMP_FILE "x", utx);
#endif /* ! USE_PAM */
return err; return err;
} }
+1 -2
View File
@@ -52,7 +52,7 @@
bool valid (const char *password, const struct passwd *ent) bool valid (const char *password, const struct passwd *ent)
{ {
const char *encrypted; const char *encrypted;
/*@observer@*/const char *salt; const char *salt;
/* /*
* Start with blank or empty password entries. Always encrypt * 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) if ( (NULL != ent->pw_name)
&& (NULL != encrypted)
&& (strcmp (encrypted, ent->pw_passwd) == 0)) { && (strcmp (encrypted, ent->pw_passwd) == 0)) {
return true; return true;
} else { } else {
+1 -1
View File
@@ -91,7 +91,7 @@
errno = 0; errno = 0;
status = REENTRANT_NAME(ARG_NAME, result, buffer, status = REENTRANT_NAME(ARG_NAME, result, buffer,
length, &resbuf); length, &resbuf);
if ((0 == status) && (resbuf == result)) { if ((0 ==status) && (resbuf == result)) {
/* Build a result structure that can be freed by /* Build a result structure that can be freed by
* the shadow *_free functions. */ * the shadow *_free functions. */
LOOKUP_TYPE *ret_result = DUP_FUNCTION(result); LOOKUP_TYPE *ret_result = DUP_FUNCTION(result);
+4 -7
View File
@@ -44,25 +44,22 @@
#ident "$Id$" #ident "$Id$"
#include <stdio.h> #include <stdio.h>
#include <errno.h>
#include "defines.h" #include "defines.h"
#include "prototypes.h" #include "prototypes.h"
/*@maynotreturn@*/ /*@only@*//*@out@*//*@notnull@*/char *xmalloc (size_t size) char *xmalloc (size_t size)
{ {
char *ptr; char *ptr;
ptr = (char *) malloc (size); ptr = (char *) malloc (size);
if (NULL == ptr) { if ((NULL == ptr) && (0 != size)) {
(void) fprintf (stderr, fprintf (stderr, _("malloc(%d) failed\n"), (int) size);
_("%s: failed to allocate memory: %s\n"),
Prog, strerror (errno));
exit (13); exit (13);
} }
return ptr; return ptr;
} }
/*@maynotreturn@*/ /*@only@*//*@notnull@*/char *xstrdup (const char *str) char *xstrdup (const char *str)
{ {
return strcpy (xmalloc (strlen (str) + 1), str); return strcpy (xmalloc (strlen (str) + 1), str);
} }
-1
View File
@@ -1,6 +1,5 @@
.xml2po.mo .xml2po.mo
config.xml config.xml
generate_mans.deps
*.[0-9] *.[0-9]
+52 -78
View File
@@ -1,73 +1,63 @@
# subdirectories for translated manual pages # subdirectories for translated manual pages
if USE_NLS 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 else
SUBDIRS = SUBDIRS =
endif endif
man_MANS = \ man_MANS = \
man1/chage.1 \ chage.1 \
man1/chfn.1 \ chfn.1 \
man8/chgpasswd.8 \ chgpasswd.8 \
man8/chpasswd.8 \ chpasswd.8 \
man1/chsh.1 \ chsh.1 \
man1/expiry.1 \ expiry.1 \
man5/faillog.5 \ faillog.5 \
man8/faillog.8 \ faillog.8 \
man3/getspnam.3 \ getspnam.3 \
man1/gpasswd.1 \ gpasswd.1 \
man8/groupadd.8 \ groupadd.8 \
man8/groupdel.8 \ groupdel.8 \
man8/groupmems.8 \ groupmems.8 \
man8/groupmod.8 \ groupmod.8 \
man1/groups.1 \ groups.1 \
man8/grpck.8 \ grpck.8 \
man8/grpconv.8 \ grpconv.8 \
man8/grpunconv.8 \ grpunconv.8 \
man5/gshadow.5 \ gshadow.5 \
man8/lastlog.8 \ lastlog.8 \
man1/login.1 \ login.1 \
man5/login.defs.5 \ login.defs.5 \
man8/logoutd.8 \ logoutd.8 \
man1/newgrp.1 \ newgrp.1 \
man8/newusers.8 \ newusers.8 \
man8/nologin.8 \ nologin.8 \
man1/passwd.1 \ passwd.1 \
man5/passwd.5 \ passwd.5 \
man8/pwck.8 \ pwck.8 \
man8/pwconv.8 \ pwconv.8 \
man8/pwunconv.8 \ pwunconv.8 \
man1/sg.1 \ sg.1 \
man3/shadow.3 \ shadow.3 \
man5/shadow.5 \ shadow.5 \
man1/su.1 \ su.1 \
man5/suauth.5 \ suauth.5 \
man8/useradd.8 \ useradd.8 \
man8/userdel.8 \ userdel.8 \
man8/usermod.8 \ usermod.8 \
man8/vigr.8 \ vigr.8 \
man8/vipw.8 vipw.8
man_nopam = \ man_nopam = \
man5/limits.5 \ limits.5 \
man5/login.access.5 \ login.access.5 \
man5/porttime.5 porttime.5
if !USE_PAM if !USE_PAM
man_MANS += $(man_nopam) man_MANS += $(man_nopam)
endif 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 = \ man_XMANS = \
chage.1.xml \ chage.1.xml \
chfn.1.xml \ chfn.1.xml \
@@ -91,9 +81,7 @@ man_XMANS = \
login.access.5.xml \ login.access.5.xml \
login.defs.5.xml \ login.defs.5.xml \
logoutd.8.xml \ logoutd.8.xml \
newgidmap.1.xml \
newgrp.1.xml \ newgrp.1.xml \
newuidmap.1.xml \
newusers.8.xml \ newusers.8.xml \
nologin.8.xml \ nologin.8.xml \
passwd.1.xml \ passwd.1.xml \
@@ -106,8 +94,6 @@ man_XMANS = \
sg.1.xml \ sg.1.xml \
su.1.xml \ su.1.xml \
suauth.5.xml \ suauth.5.xml \
subgid.5.xml \
subuid.5.xml \
useradd.8.xml \ useradd.8.xml \
userdel.8.xml \ userdel.8.xml \
usermod.8.xml \ usermod.8.xml \
@@ -163,8 +149,6 @@ login_defs_v = \
SU_WHEEL_ONLY.xml \ SU_WHEEL_ONLY.xml \
SYSLOG_SG_ENAB.xml \ SYSLOG_SG_ENAB.xml \
SYSLOG_SU_ENAB.xml \ SYSLOG_SU_ENAB.xml \
TCB_AUTH_GROUP.xml \
TCB_SYMLINKS.xml \
TTYGROUP.xml \ TTYGROUP.xml \
TTYTYPE_FILE.xml \ TTYTYPE_FILE.xml \
UID_MAX.xml \ UID_MAX.xml \
@@ -172,9 +156,6 @@ login_defs_v = \
UMASK.xml \ UMASK.xml \
USERDEL_CMD.xml \ USERDEL_CMD.xml \
USERGROUPS_ENAB.xml \ USERGROUPS_ENAB.xml \
USE_TCB.xml \
SUB_GID_COUNT.xml \
SUB_UID_COUNT.xml \
SYS_GID_MAX.xml \ SYS_GID_MAX.xml \
SYS_UID_MAX.xml SYS_UID_MAX.xml
@@ -182,32 +163,24 @@ EXTRA_DIST = \
$(man_MANS) \ $(man_MANS) \
$(man_XMANS) \ $(man_XMANS) \
$(addprefix login.defs.d/,$(login_defs_v)) \ $(addprefix login.defs.d/,$(login_defs_v)) \
man1/id.1 \ $(man_nopam) \
id.1 \
id.1.xml \ id.1.xml \
man8/sulogin.8 \ sulogin.8 \
sulogin.8.xml \ sulogin.8.xml \
generate_mans.mak \ generate_mans.mak \
generate_translations.mak generate_translations.mak
if USE_PAM
EXTRA_DIST += $(man_nopam)
endif
if !ENABLE_SUBIDS
EXTRA_DIST += $(man_subids)
endif
generate_mans.deps: *.xml generate_mans.deps: *.xml
echo "# This file is generated" > $@ awk 'BEGIN{FS="\"";} /^<!ENTITY .* * SYSTEM ".*">$$/{ f=FILENAME; sub(/.xml/,"",f); print f ": " $$2 }' $(man_XMANS) > $@
awk 'BEGIN{FS="\"";} /^<!ENTITY .* * SYSTEM ".*">$$/{ f=FILENAME; sub(/.xml/,"",f); print "man" substr(f, length (f)) "/" f ": " $$2 }' $(man_XMANS) >> $@
if ENABLE_REGENERATE_MAN if ENABLE_REGENERATE_MAN
@ENABLE_REGENERATE_MAN_TRUE@include generate_mans.deps include generate_mans.deps
include generate_mans.mak include generate_mans.mak
CLEANFILES = $(man_MANS) man1/id.1 man8/sulogin.8 CLEANFILES = $(man_MANS)
else else
$(man_MANS): $(man_MANS):
@@ -215,4 +188,5 @@ $(man_MANS):
@echo "Error: you need to run configure with '--enable-man'" @echo "Error: you need to run configure with '--enable-man'"
@echo " in order to regenerate man pages." @echo " in order to regenerate man pages."
@echo "" @echo ""
@false
endif endif
+9 -59
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
Copyright (c) 1990 - 1994, Julianne Frances Haugh Copyright (c) 1990 - 1994, Julianne Frances Haugh
Copyright (c) 2007 - 2011, Nicolas François Copyright (c) 2007 - 2008, Nicolas François
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without 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 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 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'> <refentry id='chage.1'>
<!-- $Id$ --> <!-- $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> <refmeta>
<refentrytitle>chage</refentrytitle> <refentrytitle>chage</refentrytitle>
<manvolnum>1</manvolnum> <manvolnum>1</manvolnum>
<refmiscinfo class="sectdesc">User Commands</refmiscinfo> <refmiscinfo class="sectdesc">User Commands</refmiscinfo>
<refmiscinfo class="source">shadow-utils</refmiscinfo>
<refmiscinfo class="version">&SHADOW_UTILS_VERSION;</refmiscinfo>
</refmeta> </refmeta>
<refnamediv id='name'> <refnamediv id='name'>
<refname>chage</refname> <refname>chage</refname>
@@ -71,8 +45,8 @@
<arg choice='opt'> <arg choice='opt'>
<replaceable>options</replaceable> <replaceable>options</replaceable>
</arg> </arg>
<arg choice='plain'> <arg choice='opt'>
<replaceable>LOGIN</replaceable> <replaceable>LOGIN</replaceable>
</arg> </arg>
</cmdsynopsis> </cmdsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
@@ -95,7 +69,7 @@
<variablelist remap='IP'> <variablelist remap='IP'>
<varlistentry> <varlistentry>
<term> <term>
<option>-d</option>, <option>--lastday</option>&nbsp;<replaceable>LAST_DAY</replaceable> <option>-d</option>, <option>--lastday</option> <replaceable>LAST_DAY</replaceable>
</term> </term>
<listitem> <listitem>
<para> <para>
@@ -107,7 +81,7 @@
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<option>-E</option>, <option>--expiredate</option>&nbsp;<replaceable>EXPIRE_DATE</replaceable> <option>-E</option>, <option>--expiredate</option> <replaceable>EXPIRE_DATE</replaceable>
</term> </term>
<listitem> <listitem>
<para> <para>
@@ -133,7 +107,7 @@
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<option>-I</option>, <option>--inactive</option>&nbsp;<replaceable>INACTIVE</replaceable> <option>-I</option>, <option>--inactive</option> <replaceable>INACTIVE</replaceable>
</term> </term>
<listitem> <listitem>
<para> <para>
@@ -162,7 +136,7 @@
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<option>-m</option>, <option>--mindays</option>&nbsp;<replaceable>MIN_DAYS</replaceable> <option>-m</option>, <option>--mindays</option> <replaceable>MIN_DAYS</replaceable>
</term> </term>
<listitem> <listitem>
<para> <para>
@@ -174,7 +148,7 @@
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<option>-M</option>, <option>--maxdays</option>&nbsp;<replaceable>MAX_DAYS</replaceable> <option>-M</option>, <option>--maxdays</option> <replaceable>MAX_DAYS</replaceable>
</term> </term>
<listitem> <listitem>
<para> <para>
@@ -195,19 +169,7 @@
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<option>-R</option>, <option>--root</option>&nbsp;<replaceable>CHROOT_DIR</replaceable> <option>-W</option>, <option>--warndays</option> <replaceable>WARN_DAYS</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>
</term> </term>
<listitem> <listitem>
<para> <para>
@@ -240,18 +202,6 @@
</para> </para>
</refsect1> </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'> <refsect1 id='files'>
<title>FILES</title> <title>FILES</title>
<variablelist> <variablelist>
+9 -103
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
Copyright (c) 1990 - 1994, Julianne Frances Haugh Copyright (c) 1990 - 1994, Julianne Frances Haugh
Copyright (c) 2007 - 2011, Nicolas François Copyright (c) 2007 - 2008, Nicolas François
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without 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_AUTH SYSTEM "login.defs.d/CHFN_AUTH.xml">
<!ENTITY CHFN_RESTRICT SYSTEM "login.defs.d/CHFN_RESTRICT.xml"> <!ENTITY CHFN_RESTRICT SYSTEM "login.defs.d/CHFN_RESTRICT.xml">
<!ENTITY LOGIN_STRING SYSTEM "login.defs.d/LOGIN_STRING.xml"> <!ENTITY LOGIN_STRING SYSTEM "login.defs.d/LOGIN_STRING.xml">
<!-- SHADOW-CONFIG-HERE -->
]> ]>
<refentry id='chfn.1'> <refentry id='chfn.1'>
<!-- $Id$ --> <!-- $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> <refmeta>
<refentrytitle>chfn</refentrytitle> <refentrytitle>chfn</refentrytitle>
<manvolnum>1</manvolnum> <manvolnum>1</manvolnum>
<refmiscinfo class="sectdesc">User Commands</refmiscinfo> <refmiscinfo class="sectdesc">User Commands</refmiscinfo>
<refmiscinfo class="source">shadow-utils</refmiscinfo>
<refmiscinfo class="version">&SHADOW_UTILS_VERSION;</refmiscinfo>
</refmeta> </refmeta>
<refnamediv id='name'> <refnamediv id='name'>
<refname>chfn</refname> <refname>chfn</refname>
@@ -71,12 +50,12 @@
<refsynopsisdiv id='synopsis'> <refsynopsisdiv id='synopsis'>
<cmdsynopsis> <cmdsynopsis>
<command>chfn</command> <command>chfn</command>
<arg choice='opt'> <arg choice='opt'>-f <replaceable>full_name</replaceable></arg>
<replaceable>options</replaceable> <arg choice='opt'>-r <replaceable>room_no</replaceable></arg>
</arg> <arg choice='opt'>-w <replaceable>work_ph</replaceable></arg>
<arg choice='opt'> <arg choice='opt'>-h <replaceable>home_ph</replaceable></arg>
<replaceable>LOGIN</replaceable> <arg choice='opt'>-o <replaceable>other</replaceable></arg>
</arg> <arg choice='opt'><replaceable>user</replaceable></arg>
</cmdsynopsis> </cmdsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
@@ -84,7 +63,7 @@
<title>DESCRIPTION</title> <title>DESCRIPTION</title>
<para> <para>
The <command>chfn</command> command changes user fullname, 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 for a user's account. This information is typically printed by
<citerefentry><refentrytitle>finger</refentrytitle><manvolnum>1</manvolnum> <citerefentry><refentrytitle>finger</refentrytitle><manvolnum>1</manvolnum>
</citerefentry> and similar programs. A normal user may only change </citerefentry> and similar programs. A normal user may only change
@@ -105,79 +84,6 @@
store accounting information used by other applications. store accounting information used by other applications.
</para> </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> <para>
If none of the options are selected, <command>chfn</command> If none of the options are selected, <command>chfn</command>
operates in an interactive fashion, prompting the user with the operates in an interactive fashion, prompting the user with the
+3 -32
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
Copyright (c) 2006 , Tomasz Kłoczko Copyright (c) 2006 , Tomasz Kłoczko
Copyright (c) 2007 - 2011, Nicolas François Copyright (c) 2007 - 2009, Nicolas François
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without 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 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 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"> <!ENTITY SHA_CRYPT_MIN_ROUNDS SYSTEM "login.defs.d/SHA_CRYPT_MIN_ROUNDS.xml">
<!-- SHADOW-CONFIG-HERE -->
]> ]>
<refentry id='chgpasswd.8'> <refentry id='chgpasswd.8'>
<!-- $Id$ --> <!-- $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> <refmeta>
<refentrytitle>chgpasswd</refentrytitle> <refentrytitle>chgpasswd</refentrytitle>
<manvolnum>8</manvolnum> <manvolnum>8</manvolnum>
<refmiscinfo class="sectdesc">System Management Commands</refmiscinfo> <refmiscinfo class="sectdesc">System Management Commands</refmiscinfo>
<refmiscinfo class="source">shadow-utils</refmiscinfo>
<refmiscinfo class="version">&SHADOW_UTILS_VERSION;</refmiscinfo>
</refmeta> </refmeta>
<refnamediv id='name'> <refnamediv id='name'>
<refname>chgpasswd</refname> <refname>chgpasswd</refname>
@@ -91,8 +74,8 @@
</para> </para>
<para> <para>
The default encryption algorithm can be defined for the system with The default encryption algorithm can be defined for the system with
the <option>ENCRYPT_METHOD</option> variable of <filename>/etc/login.defs</filename>, the ENCRYPT_METHOD variable of <filename>/etc/login.defs</filename>,
and can be overwritten with the <option>-e</option>, and can be overwiten with the <option>-e</option>,
<option>-m</option>, or <option>-c</option> options. <option>-m</option>, or <option>-c</option> options.
</para> </para>
<para> <para>
@@ -142,18 +125,6 @@
</para> </para>
</listitem> </listitem>
</varlistentry> </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"> <varlistentry condition="sha_crypt">
<term><option>-s</option>, <option>--sha-rounds</option></term> <term><option>-s</option>, <option>--sha-rounds</option></term>
<listitem> <listitem>
+42 -89
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
Copyright (c) 1991 , Julianne Frances Haugh Copyright (c) 1991 , Julianne Frances Haugh
Copyright (c) 2007 - 2011, Nicolas François Copyright (c) 2007 - 2009, Nicolas François
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without 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 ENCRYPT_METHOD SYSTEM "login.defs.d/ENCRYPT_METHOD.xml">
<!ENTITY MD5_CRYPT_ENAB SYSTEM "login.defs.d/MD5_CRYPT_ENAB.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"> <!ENTITY SHA_CRYPT_MIN_ROUNDS SYSTEM "login.defs.d/SHA_CRYPT_MIN_ROUNDS.xml">
<!-- SHADOW-CONFIG-HERE -->
]> ]>
<refentry id='chpasswd.8'> <refentry id='chpasswd.8'>
<!-- $Id$ --> <!-- $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> <refmeta>
<refentrytitle>chpasswd</refentrytitle> <refentrytitle>chpasswd</refentrytitle>
<manvolnum>8</manvolnum> <manvolnum>8</manvolnum>
<refmiscinfo class="sectdesc">System Management Commands</refmiscinfo> <refmiscinfo class="sectdesc">System Management Commands</refmiscinfo>
<refmiscinfo class="source">shadow-utils</refmiscinfo>
<refmiscinfo class="version">&SHADOW_UTILS_VERSION;</refmiscinfo>
</refmeta> </refmeta>
<refnamediv id='name'> <refnamediv id='name'>
<refname>chpasswd</refname> <refname>chpasswd</refname>
@@ -89,37 +67,38 @@
<emphasis remap='I'>user_name</emphasis>:<emphasis <emphasis remap='I'>user_name</emphasis>:<emphasis
remap='I'>password</emphasis> remap='I'>password</emphasis>
</para> </para>
<refsect2 condition="no_pam">
<para> <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>. encrypted by <command>chpasswd</command>.
Also the password age will be updated, if present. Also the password age will be updated, if present.
</para> </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> <para>
<phrase condition="pam">Except when PAM is used to encrypt the The default encryption algorithm can be defined for the system with
passwords,</phrase> <command>chpasswd</command> first updates all the the ENCRYPT_METHOD variable of <filename>/etc/login.defs</filename>,
passwords in memory, and then commits all the changes to disk if no and can be overwiten with the <option>-e</option>,
errors occurred for any user. <option>-m</option>, or <option>-c</option> options.
</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.
</para> </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> <para>
This command is intended to be used in a large system environment This command is intended to be used in a large system environment
where many accounts are created at a single time. where many accounts are created at a single time.
@@ -132,11 +111,9 @@
The options which apply to the <command>chpasswd</command> command The options which apply to the <command>chpasswd</command> command
are: are:
</para> </para>
<variablelist remap='IP'> <variablelist remap='IP' condition="no_pam">
<varlistentry> <varlistentry>
<term> <term><option>-c</option>, <option>--crypt-method</option></term>
<option>-c</option>, <option>--crypt-method</option>&nbsp;<replaceable>METHOD</replaceable>
</term>
<listitem> <listitem>
<para>Use the specified method to encrypt the passwords.</para> <para>Use the specified method to encrypt the passwords.</para>
<para condition="no_sha_crypt"> <para condition="no_sha_crypt">
@@ -146,17 +123,6 @@
The available methods are DES, MD5, NONE, and SHA256 or SHA512 The available methods are DES, MD5, NONE, and SHA256 or SHA512
if your libc support these methods. if your libc support these methods.
</para> </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> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
@@ -174,7 +140,7 @@
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>
<variablelist remap='IP'> <variablelist remap='IP' condition="no_pam">
<varlistentry> <varlistentry>
<term><option>-m</option>, <option>--md5</option></term> <term><option>-m</option>, <option>--md5</option></term>
<listitem> <listitem>
@@ -184,22 +150,8 @@
</para> </para>
</listitem> </listitem>
</varlistentry> </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"> <varlistentry condition="sha_crypt">
<term> <term><option>-s</option>, <option>--sha-rounds</option></term>
<option>-s</option>, <option>--sha-rounds</option>&nbsp;<replaceable>ROUNDS</replaceable>
</term>
<listitem> <listitem>
<para> <para>
Use the specified number of rounds to encrypt the passwords. Use the specified number of rounds to encrypt the passwords.
@@ -218,8 +170,7 @@
</para> </para>
<para> <para>
By default, the number of rounds is defined by the By default, the number of rounds is defined by the
<option>SHA_CRYPT_MIN_ROUNDS</option> and SHA_CRYPT_MIN_ROUNDS and SHA_CRYPT_MAX_ROUNDS variables in
<option>SHA_CRYPT_MAX_ROUNDS</option> variables in
<filename>/etc/login.defs</filename>. <filename>/etc/login.defs</filename>.
</para> </para>
</listitem> </listitem>
@@ -233,20 +184,22 @@
Remember to set permissions or umask to prevent readability of Remember to set permissions or umask to prevent readability of
unencrypted files by other users. unencrypted files by other users.
</para> </para>
<para condition="no_pam">
You should make sure the passwords and the encryption method respect
the system's password policy.
</para>
</refsect1> </refsect1>
<refsect1 id='configuration'> <refsect1 id='configuration' condition="no_pam">
<title>CONFIGURATION</title> <title>CONFIGURATION</title>
<para> <para>
The following configuration variables in The following configuration variables in
<filename>/etc/login.defs</filename> change the behavior of this <filename>/etc/login.defs</filename> change the behavior of this
tool: tool:
</para> </para>
<variablelist condition="no_pam"> <variablelist>
&ENCRYPT_METHOD; &ENCRYPT_METHOD;
&MD5_CRYPT_ENAB; &MD5_CRYPT_ENAB;
</variablelist>
<variablelist>
&SHA_CRYPT_MIN_ROUNDS; <!--documents also SHA_CRYPT_MAX_ROUNDS--> &SHA_CRYPT_MIN_ROUNDS; <!--documents also SHA_CRYPT_MAX_ROUNDS-->
</variablelist> </variablelist>
</refsect1> </refsect1>
@@ -254,19 +207,19 @@
<refsect1 id='files'> <refsect1 id='files'>
<title>FILES</title> <title>FILES</title>
<variablelist> <variablelist>
<varlistentry> <varlistentry condition="no_pam">
<term><filename>/etc/passwd</filename></term> <term><filename>/etc/passwd</filename></term>
<listitem> <listitem>
<para>User account information.</para> <para>User account information.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry condition="no_pam">
<term><filename>/etc/shadow</filename></term> <term><filename>/etc/shadow</filename></term>
<listitem> <listitem>
<para>Secure user account information.</para> <para>Secure user account information.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry condition="no_pam">
<term><filename>/etc/login.defs</filename></term> <term><filename>/etc/login.defs</filename></term>
<listitem> <listitem>
<para>Shadow password suite configuration.</para> <para>Shadow password suite configuration.</para>
@@ -290,7 +243,7 @@
<citerefentry> <citerefentry>
<refentrytitle>newusers</refentrytitle><manvolnum>8</manvolnum> <refentrytitle>newusers</refentrytitle><manvolnum>8</manvolnum>
</citerefentry>, </citerefentry>,
<phrase> <phrase condition="no_pam">
<citerefentry> <citerefentry>
<refentrytitle>login.defs</refentrytitle><manvolnum>5</manvolnum> <refentrytitle>login.defs</refentrytitle><manvolnum>5</manvolnum>
</citerefentry>, </citerefentry>,
+3 -37
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
Copyright (c) 1990 , Julianne Frances Haugh Copyright (c) 1990 , Julianne Frances Haugh
Copyright (c) 2007 - 2011, Nicolas François Copyright (c) 2007 - 2008, Nicolas François
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without 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" [ "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY CHSH_AUTH SYSTEM "login.defs.d/CHSH_AUTH.xml"> <!ENTITY CHSH_AUTH SYSTEM "login.defs.d/CHSH_AUTH.xml">
<!ENTITY LOGIN_STRING SYSTEM "login.defs.d/LOGIN_STRING.xml"> <!ENTITY LOGIN_STRING SYSTEM "login.defs.d/LOGIN_STRING.xml">
<!-- SHADOW-CONFIG-HERE -->
]> ]>
<refentry id='chsh.1'> <refentry id='chsh.1'>
<!-- $Id$ --> <!-- $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> <refmeta>
<refentrytitle>chsh</refentrytitle> <refentrytitle>chsh</refentrytitle>
<manvolnum>1</manvolnum> <manvolnum>1</manvolnum>
<refmiscinfo class="sectdesc">User Commands</refmiscinfo> <refmiscinfo class="sectdesc">User Commands</refmiscinfo>
<refmiscinfo class="source">shadow-utils</refmiscinfo>
<refmiscinfo class="version">&SHADOW_UTILS_VERSION;</refmiscinfo>
</refmeta> </refmeta>
<refnamediv id='name'> <refnamediv id='name'>
<refname>chsh</refname> <refname>chsh</refname>
@@ -85,7 +63,7 @@
<para> <para>
The <command>chsh</command> command changes the user login shell. The <command>chsh</command> command changes the user login shell.
This determines the name of the user's initial login command. A normal 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. superuser may change the login shell for any account.
</para> </para>
@@ -105,19 +83,7 @@
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<option>-R</option>, <option>--root</option>&nbsp;<replaceable>CHROOT_DIR</replaceable> <option>-s</option>, <option>--shell</option> <replaceable>SHELL</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>
</term> </term>
<listitem> <listitem>
<para> <para>
-1
View File
@@ -1,2 +1 @@
<!ENTITY GROUP_NAME_MAX_LENGTH '@GROUP_NAME_MAX_LENGTH@'> <!ENTITY GROUP_NAME_MAX_LENGTH '@GROUP_NAME_MAX_LENGTH@'>
<!ENTITY SHADOW_UTILS_VERSION '@VERSION@'>
+19 -20
View File
@@ -2,25 +2,24 @@
mandir = @mandir@/cs mandir = @mandir@/cs
man_MANS = \ man_MANS = \
man1/expiry.1 \ expiry.1 \
man5/faillog.5 \ faillog.5 \
man8/faillog.8 \ faillog.8 \
man1/gpasswd.1 \ gpasswd.1 \
man8/groupadd.8 \ groupadd.8 \
man8/groupdel.8 \ groupdel.8 \
man8/groupmod.8 \ groupmod.8 \
man1/groups.1 \ groups.1 \
man8/grpck.8 \ grpck.8 \
man5/gshadow.5 \ gshadow.5 \
man8/lastlog.8 \ lastlog.8 \
man8/nologin.8 \ nologin.8 \
man5/passwd.5 \ passwd.5 \
man5/shadow.5 \ shadow.5 \
man1/su.1 \ su.1 \
man8/vipw.8 vipw.8
EXTRA_DIST = $(man_MANS) \ EXTRA_DIST = $(man_MANS) \
man1/id.1 \ id.1 \
man8/groupmems.8 \ groupmems.8 \
man8/logoutd.8 logoutd.8

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