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
10532 changed files with 51744 additions and 516665 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
-52
View File
@@ -1,52 +0,0 @@
dist: bionic
sudo: false
language: c
compiler:
- gcc
- clang
arch:
- amd64
- arm64
- ppc64le
- s390x
before_install:
- sudo apt-get update -qq
- sudo apt-get -y install -qq automake autopoint xsltproc libselinux1-dev gettext expect
- sudo apt-get -y install -qq byacc libtool
script:
- ./autogen.sh --without-selinux --disable-man
- grep ENABLE_ config.status
- make
env:
global:
- secure: "G47VYFrtzqalrVjixTqBG9Qsa8EZRcaqsh1k6fq5JgEyHmMQActpvTUDs9FXf1MEqiY5XX3VDVfBsZgKPHgmHsMzD1bX11xpnpGByB8g7gr8I3u2ZkCREqgi77a5l3LeBh+seWiambe/DYOgvPCNa6pCynLgR9advqtgKhpCruU="
addons:
coverity_scan:
project:
name: "shadow-maint/shadow"
description: "Upstream shadow utils tree"
notification_email: christian.brauner@ubuntu.com,serge@hallyn.com
build_command_prepend: "./autogen.sh --without-selinux --disable-man"
build_command: "make -j4"
branch_pattern: master
script:
- cat /proc/self/uid_map
- cat /proc/self/status
- systemd-detect-virt
- ./autogen.sh --without-selinux --disable-man
- grep ENABLE_ config.status
- make
- sudo make install
- (cd tests; sudo ./run_some; cat testsuite.log)
# vim:et:ts=2:sw=2
+4 -2798
View File
File diff suppressed because it is too large Load Diff
+3 -10
View File
@@ -2,14 +2,7 @@
EXTRA_DIST = NEWS README TODO shadow.spec.in EXTRA_DIST = NEWS README TODO shadow.spec.in
SUBDIRS = libmisc lib AUTOMAKE_OPTIONS = 1.5 dist-bzip2 foreign
if ENABLE_SUBIDS SUBDIRS = po man libmisc lib src \
SUBDIRS += libsubid contrib doc etc
endif
SUBDIRS += src po contrib doc etc
if ENABLE_REGENERATE_MAN
SUBDIRS += man
endif
+73 -274
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
@@ -654,9 +453,9 @@ shadow-4.0.18.2 -> shadow-4.1.0 09-12-2007
- Use MD5_CRYPT_ENAB, ENCRYPT_METHOD, SHA_CRYPT_MIN_ROUNDS, and - Use MD5_CRYPT_ENAB, ENCRYPT_METHOD, SHA_CRYPT_MIN_ROUNDS, and
SHA_CRYPT_MAX_ROUNDS to define the default encryption algorithm for the SHA_CRYPT_MAX_ROUNDS to define the default encryption algorithm for the
passwords. passwords.
- chpasswd, chgpasswd, newusers: New options -c/--crypt-method and - chpaswd, chgpasswd, newusers: New options -c/--crypt-method and
-s/--sha-rounds to supersede the system default encryption algorithm. -s/--sha-rounds to supersede the system default encryption algorithm.
- chpasswd, chgpasswd, newusers: DES is no more the default algorithm. They - chpaswd, chgpasswd, newusers: DES is no more the default algorithm. They
will respect the system default configured in /etc/login.defs will respect the system default configured in /etc/login.defs
*** documentation: *** documentation:
@@ -701,14 +500,14 @@ shadow-4.0.17 -> shadow-4.0.18 01-08-2006
- groupadd, groupmod, useradd, usermod: fixed UID/GID overflow (fixed - groupadd, groupmod, useradd, usermod: fixed UID/GID overflow (fixed
http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=198920) http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=198920)
- passwd, useradd, usermod: fixed inactive/mindays/warndays/maxdays overflow - passwd, useradd, usermod: fixed inactive/mindays/warndays/maxdays overflow
(similar to RH#198920), (simillar to RH#198920),
- groupmems: rewritten for use PAM and getopt_long() and now it is enabled - groupmems: rewrited for use PAM and getopt_long() and now it is enabled
for build and install (patch by George Kraft <gk4@swbell.net>), for build and install (patch by George Kraft <gk4@swbell.net>),
- S/Key: removed assign getpass() to libshadow_getpass() on autoconf level - S/Key: removed assign getpass() to libshadow_getpass() on autoconf level
(patch by Ulrich Mueller <ulm@kph.uni-mainz.de>; http://bugs.gentoo.org/139966), (patch by Ulrich Mueller <ulm@kph.uni-mainz.de>; http://bugs.gentoo.org/139966),
- usermod: back to previous -a option semantics and clarify -a behavior - usermod: back to previous -a option semantics and clarify -a behavior
on documentation level (by Greg Schafer <gschafer@zip.com.au>), on documentation level (by Greg Schafer <gschafer@zip.com.au>),
- chsh, groupmod: rewritten for use getopt_long(). - chsh, groupmod: rewrited for use getopt_long().
- updated translations: ca, cs, da, eu, fr, gl, hu, ko, pl, pt, ru, sv, tr, uk, vi. - updated translations: ca, cs, da, eu, fr, gl, hu, ko, pl, pt, ru, sv, tr, uk, vi.
*** documentation: *** documentation:
- fr and ru man pages are up to date, - fr and ru man pages are up to date,
@@ -743,7 +542,7 @@ shadow-4.0.15 -> shadow-4.0.16 05-06-2006
*** general: *** general:
- userdel: better fix for old CERT VU#312962 (which was fixed in shadow 4.0.8): - userdel: better fix for old CERT VU#312962 (which was fixed in shadow 4.0.8):
fixed forgotten checking of the return value from fchown() before fixed forgoten checking of the return value from fchown() before
proceeding with the fchmod() (based on Owl patch prepared by proceeding with the fchmod() (based on Owl patch prepared by
Rafal Wojtczuk <nergal@owl.openwall.com>), Rafal Wojtczuk <nergal@owl.openwall.com>),
- userdel: use login.defs::MAIL_DIR instead hardcoded /var/mail in created - userdel: use login.defs::MAIL_DIR instead hardcoded /var/mail in created
@@ -755,7 +554,7 @@ shadow-4.0.15 -> shadow-4.0.16 05-06-2006
passwords and libshadow_getpass() is used only because libc getpass() passwords and libshadow_getpass() is used only because libc getpass()
do not handles password prompting with echo enabled, do not handles password prompting with echo enabled,
- move login.defs::MD5_CRYPT_ENAB to non-PAM part, - move login.defs::MD5_CRYPT_ENAB to non-PAM part,
- userdel: rewritten for use getopt_log(), - userdel: rewrited for use getopt_log(),
- install default/template configuration files: - install default/template configuration files:
-- if shadow is configured with use PAM install /etc/pam.d/* files, -- if shadow is configured with use PAM install /etc/pam.d/* files,
-- if shadow do not uses PAM install /etc/{limits,login.acces} files, -- if shadow do not uses PAM install /etc/{limits,login.acces} files,
@@ -793,7 +592,7 @@ shadow-4.0.15 -> shadow-4.0.16 05-06-2006
- updated ru login.defs(5), passwd(1), userdel(8), usermod(8) man pages, - updated ru login.defs(5), passwd(1), userdel(8), usermod(8) man pages,
- pw_auth(3) man page removed (outdated), - pw_auth(3) man page removed (outdated),
- install limits(5), login.access(5) and porttime(5) man pages only when - install limits(5), login.access(5) and porttime(5) man pages only when
shadow is built with PAM support disabled, shadow is builded with PAM support disabled,
- passwd(1): better document how password strength is checked - passwd(1): better document how password strength is checked
(fixed http://bugs.debian.org/115380), (fixed http://bugs.debian.org/115380),
- usermod(8): added missing -a option description - usermod(8): added missing -a option description
@@ -816,7 +615,7 @@ shadow-4.0.14 -> shadow-4.0.15 13-03-2006
- login: default UMASK if not specified in login.defs is 022 (pointed by - login: default UMASK if not specified in login.defs is 022 (pointed by
Peter Vrabec <pvrabec@redhat.com>), Peter Vrabec <pvrabec@redhat.com>),
- chgpasswd: new tool (by Jonas Meurer <mejo@debian.org>), - chgpasswd: new tool (by Jonas Meurer <mejo@debian.org>),
- lastlog: print the usage and exit if an additional argument is provided to - lastlog: print the usage and exit if an additional argument is profided to
lastlog (merge 488_laslog_verify_arguments Debian patch), lastlog (merge 488_laslog_verify_arguments Debian patch),
- login, newgrp, nologin, su: do not link with libselinux (merge - login, newgrp, nologin, su: do not link with libselinux (merge
490_link_selinux_only_when_needed Debian patch), 490_link_selinux_only_when_needed Debian patch),
@@ -830,9 +629,9 @@ shadow-4.0.14 -> shadow-4.0.15 13-03-2006
tries exceeded, tries exceeded,
- always prints the number of tries in the syslog entry. - always prints the number of tries in the syslog entry.
- add special handling for PAM_ABORT - add special handling for PAM_ABORT
- add an entry to faillog, as when USE_PAM is not defined. (#53164) - add an entry to failog, as when USE_PAM is not defined. (#53164)
- changed pam_end to PAM_END. This is certainly was a mistake. PAM_END is - changed pam_end to PAM_END. This is certainly was a mistake. PAM_END is
pam_close_session + pam_end. Here, the session is still not open, we pam_close_seesion + pam_end. Here, the session is still not open, we
don't have to close it. don't have to close it.
- a HAVE_PAM_FAIL_DELAY is missing, - a HAVE_PAM_FAIL_DELAY is missing,
- su: fixed pam session support (patch from Topi Miettinen; fixed #57526, - su: fixed pam session support (patch from Topi Miettinen; fixed #57526,
@@ -840,7 +639,7 @@ shadow-4.0.14 -> shadow-4.0.15 13-03-2006
- userdel: user's group is already removed by update_groups(). - userdel: user's group is already removed by update_groups().
remove_group() is not needed (bug introduced in 4.0.14 on merge FC fixes). remove_group() is not needed (bug introduced in 4.0.14 on merge FC fixes).
Fixed by Nicolas François <nicolas.francois@centraliens.net>, Fixed by Nicolas François <nicolas.francois@centraliens.net>,
- useradd: always remove group and gshadow databases lock, Fixed by Nicolas - useradd: allways remove group and gshadow databases lock, Fixed by Nicolas
François <nicolas.francois@centraliens.net> François <nicolas.francois@centraliens.net>
(http://bugs.debian.org/348250) (http://bugs.debian.org/348250)
- auditing fixes: - auditing fixes:
@@ -848,14 +647,14 @@ shadow-4.0.14 -> shadow-4.0.15 13-03-2006
added audit_logger() prototype), added audit_logger() prototype),
- useradd: fixed excess audit_logger() argument, - useradd: fixed excess audit_logger() argument,
- chage: added missing \n on display password status if password must be - chage: added missing \n on display password status if password must be
changed, chaged,
- useradd: fixed allow non-unique UID (http://bugs.debian.org/351281), - useradd: fixed allow non-unique UID (http://bugs.debian.org/351281),
- various code cleanups for make possible compilation of shadow with -Wall - variouse code cleanups for make possible compilation of shadow with -Wall
-Werror (by Alexander Gattin <xrgtn@yandex.ru>), -Werror (by Alexander Gattin <xrgtn@yandex.ru>),
- su: move exit() outside libmisc/shell.c::shell() for handle shell() errors - su: move exit() outside libmisc/shell.c::shell() for handle shell() errors
on higher level (now is better visable where some programs exit with 126 on higher level (now is better visable where some programs exit with 126
and 127 exit codes); added new shell() parameter (char *const envp[]) and 127 exit codes); added new shell() parameter (char *const envp[])
which allow fix preserving enviroment in su on using -p, (patch by which allow fix preserving enviloment in su on using -p, (patch by
Alexander Gattin <xrgtn@yandex.ru>), Alexander Gattin <xrgtn@yandex.ru>),
- su: added handle -c,--command option for GNU su compliance (merge - su: added handle -c,--command option for GNU su compliance (merge
437_su_-c_option Debian patch), 437_su_-c_option Debian patch),
@@ -903,7 +702,7 @@ shadow-4.0.13 -> shadow-4.0.14 03-01-2006
- userdel: make the -f option force the removal of the user's group (even if it - userdel: make the -f option force the removal of the user's group (even if it
is the primary group of another user) is the primary group of another user)
(merge 453_userdel_-f_removes_group Debian patch), (merge 453_userdel_-f_removes_group Debian patch),
- usermod: rewritten for use getopt_long() (Christian Perrier <bubulle@kheops.frmug.org>), - usermod: rewrited for use getopt_long() (Christian Perrier <bubulle@kheops.frmug.org>),
- grpck: fixed segmentation fault on using -s when /etc/gshadow is empty (fix by - grpck: fixed segmentation fault on using -s when /etc/gshadow is empty (fix by
Tomasz Lemiech <szpajder@staszic.waw.pl>), Tomasz Lemiech <szpajder@staszic.waw.pl>),
- passwd: remove handle -f, -g and -s options. - passwd: remove handle -f, -g and -s options.
@@ -912,7 +711,7 @@ shadow-4.0.13 -> shadow-4.0.14 03-01-2006
Nicolas François <nicolas.francois@centraliens.net>) Nicolas François <nicolas.francois@centraliens.net>)
- su: export $USER and $SHELL as well as $HOME (http://bugs.debian.org/11003 and - su: export $USER and $SHELL as well as $HOME (http://bugs.debian.org/11003 and
http://bugs.debian.org/11189), http://bugs.debian.org/11189),
- su, vipw: rewritten for use getopt_long(), - su, vipw: rewrited for use getopt_long(),
- su: log successful/failed through syslog (http://bugs.debian.org/190215), - su: log successful/failed through syslog (http://bugs.debian.org/190215),
- updated translations: ca, cs, da, eu, fi, fr, it, pl, pt, ru, sv, tl, vi, - updated translations: ca, cs, da, eu, fi, fr, it, pl, pt, ru, sv, tl, vi,
- new translations: gl. - new translations: gl.
@@ -946,7 +745,7 @@ shadow-4.0.12 -> shadow-4.0.13 10-10-2005
*** general: *** general:
- chage: removed duplicated pam_start(), - chage: removed duplicated pam_start(),
- chfn, chsh: finished PAM support using pam_start() and co., - chfn, chsh: finished PAM support usin pam_start() and co.,
- userdel: userdel should not remove the group which is primary for someone else - userdel: userdel should not remove the group which is primary for someone else
(fix by Nicolas François <nicolas.francois@centraliens.net> (fix by Nicolas François <nicolas.francois@centraliens.net>
http://bugs.debian.org/295416), http://bugs.debian.org/295416),
@@ -955,7 +754,7 @@ shadow-4.0.12 -> shadow-4.0.13 10-10-2005
- fixedlib/commonio.c: don't assume selinux is enabled if is_selinux_enabled() - fixedlib/commonio.c: don't assume selinux is enabled if is_selinux_enabled()
returns -1 (merge isSelinuxEnabled FC patch by Jeremy Katz <katzj@redhat.com>), returns -1 (merge isSelinuxEnabled FC patch by Jeremy Katz <katzj@redhat.com>),
- login, su (non-PAM case): fixed setup max address space limits (added missing break - login, su (non-PAM case): fixed setup max address space limits (added missing break
statement in case) spotted by Lasse Collin <lasse.collin@tukaani.org>, statement in case) spoted by Lasse Collin <lasse.collin@tukaani.org>,
- auditing support added. Patch prepared by Peter Vrabec <pvrabec@redhat.com> basing - auditing support added. Patch prepared by Peter Vrabec <pvrabec@redhat.com> basing
on work by Steve Grubb from http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=159215 on work by Steve Grubb from http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=159215
Now auditing support have commands: chage, gpasswd, groupadd, groupdel, groupmod, Now auditing support have commands: chage, gpasswd, groupadd, groupdel, groupmod,
@@ -972,12 +771,12 @@ shadow-4.0.12 -> shadow-4.0.13 10-10-2005
This will permit to adduser Debian script to detect if chage failed because the This will permit to adduser Debian script to detect if chage failed because the
system doesn't have shadowed passwords (fix for http://bugs.debian.org/317012), system doesn't have shadowed passwords (fix for http://bugs.debian.org/317012),
- merge 010_more-i18ned-messages Debian patch which adds i18n support for few - merge 010_more-i18ned-messages Debian patch which adds i18n support for few
more messages (originally patch was prepared by Guillem Jover <guillem@debian.org>), more messages (orginaly patch was prepared by Guillem Jover <guillem@debian.org>),
- lastlog: added handle -b option which allow print only lastlog records older than - lastlog: added handle -b option which allow print only lastlog records older than
specified DAYS (fix by <miles@lubin.us>), specified DAYS (fix by <miles@lubin.us>),
- chpasswd, gpasswd, newusers: fixed libmisc/salt.c for use login.defs::MD5_CRYPT_ENAB - chpasswd, gpasswd, newusers: fixed libmisc/salt.c for use login.defs::MD5_CRYPT_ENAB
only if PAM support is disabled (fix by John Gatewood Ham <zappaman@buraphalinux.org>), only if PAM support is disabled (fix by John Gatewood Ham <zappaman@buraphalinux.org>),
- passwd: rewritten for use getopt_long(), - passwd: rewrited for use getopt_long(),
- newgrp: when newgrp process sits between parent and child shells, it should - newgrp: when newgrp process sits between parent and child shells, it should
propagate STOPs from child to parent and CONTs from parent to child, propagate STOPs from child to parent and CONTs from parent to child,
otherwise e.g. bash's "suspend" command won't work otherwise e.g. bash's "suspend" command won't work
@@ -987,11 +786,11 @@ shadow-4.0.12 -> shadow-4.0.13 10-10-2005
- chsh(1), groupadd(8), newusers(8), pwconv(8), useradd(8), userdel(8), usermod(8): - chsh(1), groupadd(8), newusers(8), pwconv(8), useradd(8), userdel(8), usermod(8):
added missing references to /etc/login.defs and login.defs(5) added missing references to /etc/login.defs and login.defs(5)
(Christian Perrier <bubulle@kheops.frmug.org>), (Christian Perrier <bubulle@kheops.frmug.org>),
- passwd(5): rewritten based on work by Greg Wooledge <greg@wooledge.org> - passwd(5): rewrited based on work by Greg Wooledge <greg@wooledge.org>
http://bugs.debian.org/328113 http://bugs.debian.org/328113
- login(1): added securetty(5) to SEE ALSO section - login(1): added securetty(5) to SEE ALSO section
(fixed Debian bug http://bugs.debian.org/325773), (fixed Debian bug http://bugs.debian.org/325773),
- groupadd(8), useradd(8): fix regular expression describing allowed login/group - groupadd(8), useradd(8): fix regular expression describing alloved login/group
names (pointed by Nicolas François <nicolas.francois@centraliens.net>) names (pointed by Nicolas François <nicolas.francois@centraliens.net>)
(correct is [a-z_][a-z0-9_-]*[$]), (correct is [a-z_][a-z0-9_-]*[$]),
- groupadd(8), useradd(8): documents in CAVEATS section the limitations shadow - groupadd(8), useradd(8): documents in CAVEATS section the limitations shadow
@@ -1001,9 +800,9 @@ shadow-4.0.12 -> shadow-4.0.13 10-10-2005
shadow-4.0.11.1 -> shadow-4.0.12 22-08-2005 shadow-4.0.11.1 -> shadow-4.0.12 22-08-2005
*** general: *** general:
- newgrp, login: remove using login.defs::CLOSE_SESSIONS variable and always - newgrp, login: remove using login.defs::CLOSE_SESSIONS variable and allways
close PAM session, close PAM session,
- fixed configure.in: really enable shadow group support by default (pointed by - fixed configure.in: realy enable shadow group support by default (pointed by
Greg Schafer <gschafer@zip.com.au> and Peter Vrabec <pvrabec@redhat.com>), Greg Schafer <gschafer@zip.com.au> and Peter Vrabec <pvrabec@redhat.com>),
- login.defs: removed handle QMAIL_DIR variable, - login.defs: removed handle QMAIL_DIR variable,
- login: allow regular user to login on read-only root file system (not only for root) - login: allow regular user to login on read-only root file system (not only for root)
@@ -1028,9 +827,9 @@ shadow-4.0.11.1 -> shadow-4.0.12 22-08-2005
period and permit brute-force attacks (fixed http://bugs.debian.org/288827), period and permit brute-force attacks (fixed http://bugs.debian.org/288827),
- uClibc fixes (by Martin Schlemmer <azarah@nosferatu.za.org>): - uClibc fixes (by Martin Schlemmer <azarah@nosferatu.za.org>):
added require ngettext (added [need-ngettext] to AM_GNU_GETTEXT() parameters) added require ngettext (added [need-ngettext] to AM_GNU_GETTEXT() parameters)
and stub prototype for ngettext() in lib/prototypes.h (necessary if shadow and stub prototype for ngettext() in lib/prototypes.h (neccessary if shadow
compiled with disabled NLS support) compiled with disabled NLS support)
- groupadd: rewritten for use getopt_long(), - groupadd: rewrited for use getopt_long(),
- groupadd, groupdel, groupmod, userdel: do OPENLOG() before pam_start(), - groupadd, groupdel, groupmod, userdel: do OPENLOG() before pam_start(),
- groupadd: fixed double OPENLOG(), - groupadd: fixed double OPENLOG(),
- removed lib/{grpack,gspack,pwpack,sppack}.c and prototypes from lib/prototypes.h - removed lib/{grpack,gspack,pwpack,sppack}.c and prototypes from lib/prototypes.h
@@ -1066,7 +865,7 @@ shadow-4.0.10 -> shadow-4.0.11 18-07-2005
- su: ignore SIGINT while authenticating. A ^C could defeat the waiting period and - su: ignore SIGINT while authenticating. A ^C could defeat the waiting period and
permit brute-force attacks. Also ignore SIGQUIT. permit brute-force attacks. Also ignore SIGQUIT.
Fixed: http://bugs.debian.org/52372 and http://bugs.debian.org/288827 Fixed: http://bugs.debian.org/52372 and http://bugs.debian.org/288827
- useradd: rewritten for use getopt_long(), - useradd: rewrited for use getopt_long(),
- newgrp: add fix for handle splitted NIS groups: extends the functionality that, - newgrp: add fix for handle splitted NIS groups: extends the functionality that,
if the requested group is given, all groups of the same GID are tested for if the requested group is given, all groups of the same GID are tested for
membership of the requesting user. membership of the requesting user.
@@ -1097,7 +896,7 @@ shadow-4.0.10 -> shadow-4.0.11 18-07-2005
- updated translations: cs, da, de, es, fi, pl, pt, ro, ru, sk. - updated translations: cs, da, de, es, fi, pl, pt, ro, ru, sk.
*** documentation: *** documentation:
- pwck(8): document -q option (based on Debian patch for fix http://bugs.debian.org/309408) - pwck(8): document -q option (based on Debian patch for fix http://bugs.debian.org/309408)
- pwck(8): rewritten OPTIONS section and better SYNOPSIS, - pwck(8): rewrited OPTIONS section and better SYNOPSIS,
- lastlog(8): document that lastlog is a sparse file, and don't need to be rotated - lastlog(8): document that lastlog is a sparse file, and don't need to be rotated
http://bugs.debian.org/219321 http://bugs.debian.org/219321
- login(8): better explain the respective roles of login, init and getty with regards - login(8): better explain the respective roles of login, init and getty with regards
@@ -1111,12 +910,12 @@ shadow-4.0.9 -> shadow-4.0.10 28-06-2005
*** general: *** general:
- mkpasswd: removed, - mkpasswd: removed,
- userdel: now deletes user groups from /etc/gshadow as well as /etc/group. - userdel: now deletes user groups from /etc/gshdow as well as /etc/group.
Fix by Nicolas François <nicolas.francois@centraliens.net>. Fix by Nicolas François <nicolas.francois@centraliens.net>.
http://bugs.debian.org/99442 http://bugs.debian.org/99442
- usermod: when relocating a user's home directory, don't fail and remove the new - usermod: when relocating a user's home directory, don't fail and remove the new
home directory if we can't remove the old home directory for some home directory if we can't remove the old home directory for some
reason; the results can be spectacularly poor if, for instance, only reason; the results can be spectularly poort if, for instance, only
the rmdir() fails. Patch prepared by Timo Lindfors <lindi-spamtrap@newmail.com>. the rmdir() fails. Patch prepared by Timo Lindfors <lindi-spamtrap@newmail.com>.
http://bugs.debian.org/166369 http://bugs.debian.org/166369
- su: fix syslogs to be less ambiguous. Use old:new format instead of old-new - su: fix syslogs to be less ambiguous. Use old:new format instead of old-new
@@ -1124,7 +923,7 @@ shadow-4.0.9 -> shadow-4.0.10 28-06-2005
http://bugs.debian.org/213592 http://bugs.debian.org/213592
- removed not used now libmisc/setup.c, - removed not used now libmisc/setup.c,
- login: use also UTMPX API instead UTMP on failure (login was affected for this - login: use also UTMPX API instead UTMP on failure (login was affected for this
when shadow was built without PAM support) when shadow was builded without PAM support)
patch by Nicolas François <nicolas.francois@centraliens.net> patch by Nicolas François <nicolas.francois@centraliens.net>
- login: the PAM session needs to be closed as root, thus before change_uid() - login: the PAM session needs to be closed as root, thus before change_uid()
http://bugs.debian.org/53570 http://bugs.debian.org/195048 http://bugs.debian.org/211884 http://bugs.debian.org/53570 http://bugs.debian.org/195048 http://bugs.debian.org/211884
@@ -1135,12 +934,12 @@ shadow-4.0.9 -> shadow-4.0.10 28-06-2005
http://bugs.debian.org/48002 http://bugs.debian.org/48002
- login: fixed username on succesful login (was using the normal username, - login: fixed username on succesful login (was using the normal username,
when it should have used pam_user) http://bugs.debian.org/47819 when it should have used pam_user) http://bugs.debian.org/47819
- remove using SHADOWPWD #define so now shadow is always built with shadow - remove using SHADOWPWD #define so now shadow is allways builded with shadow
password support, passwowd support,
- chage: rewritten for use getopt_long(), - chage: rewrited for use getopt_long(),
- updated translations: ca, cs, da, fi, pl, ru, zh_TW. - updated translations: ca, cs, da, fi, pl, ru, zh_TW.
*** documentation: *** documentation:
- most of the man pages now are generated from XML files so in case submitting any - most of the man pages now are generated from XML files so in case submiting any
chages to this resources please make diff to XML files, chages to this resources please make diff to XML files,
- chfn: give more details about the influence of login.defs on what's allowed to - chfn: give more details about the influence of login.defs on what's allowed to
users. users.
@@ -1148,7 +947,7 @@ shadow-4.0.9 -> shadow-4.0.10 28-06-2005
shadow-4.0.8 -> shadow-4.0.9 23-05-2005 shadow-4.0.8 -> shadow-4.0.9 23-05-2005
*** general: *** general:
- passwd: fixed segfault in non-PAM configuration - passwd: fixed segfault in non-PAM connfiguration
(submited by Greg Schafer <gschafer@zip.com.au>), (submited by Greg Schafer <gschafer@zip.com.au>),
- newgrp: fixed NULL pointer dereference - getlogin() and ttyname() can - newgrp: fixed NULL pointer dereference - getlogin() and ttyname() can
return NULL which is not checked (http://bugs.debian.org/162303), return NULL which is not checked (http://bugs.debian.org/162303),
@@ -1170,15 +969,15 @@ shadow-4.0.7 -> shadow-4.0.8 26-04-2005
- configure.in: add using AC_GNU_SOURCE macro for kill compilation warnings about - configure.in: add using AC_GNU_SOURCE macro for kill compilation warnings about
implicit declaration of function `fseeko', implicit declaration of function `fseeko',
- faillog: changed faillog record display format for allow fit in 80 columns all - faillog: changed faillog record display format for allow fit in 80 columns all
faillog attributes, faillog atributies,
- removed NDBM code (unused), - removed NDBM code (unused),
- fixed use of SU_WHEEL_ONLY in su. Now su really is available for wheel group - fixed use of SU_WHEEL_ONLY in su. Now su realy is avalaible for wheel group
members. Thanks to Mike Frysinger <vapier@gentoo.org> for report: members. Thanks to Mike Frysinger <vapier@gentoo.org> for report:
http://bugs.gentoo.org/show_bug.cgi?id=80345 http://bugs.gentoo.org/show_bug.cgi?id=80345
- drop never finished kerberos and des_rpc support (for kerberos support back firs - drop never finished kerberos and des_rpc support (for kerberos support back firs
must be prepared modularization), must be prepared modularization),
- fixed UTMP path detection (by Kelledin <kelledin@users.sf.net>), - fixed UTMP path detection (by Kelledin <kelledin@users.sf.net>),
- useradd: rewritten group count to dynamic (by John Newbigin - useradd: rewrited group count to dynamic (by John Newbigin
<jnewbigin@ict.swin.edu.au>), <jnewbigin@ict.swin.edu.au>),
- login: fixed create lastlog entry fo users never loged in on non-PAM - login: fixed create lastlog entry fo users never loged in on non-PAM
variant of login (fix by <oracular@ziplip.com>), variant of login (fix by <oracular@ziplip.com>),
@@ -1193,7 +992,7 @@ shadow-4.0.7 -> shadow-4.0.8 26-04-2005
fchmod() is executed. (Actually, we could also pass the final "mode" to fchmod() is executed. (Actually, we could also pass the final "mode" to
the open() call and then save the consequent fchmod().) the open() call and then save the consequent fchmod().)
- SELinux changes: added changes in chage, chfn, chsh, passwd for allow - SELinux changes: added changes in chage, chfn, chsh, passwd for allow
construct more grained user password/account properties on SELinux construct more grained user password/accuunt properties on SELinux
policies level. Patch originally based on RH changes (submited by Chris policies level. Patch originally based on RH changes (submited by Chris
PeBenito <pebenito@gentoo.org>), PeBenito <pebenito@gentoo.org>),
- added SELinux changes: in libmisc/copydir.c (based on Fedora patch), - added SELinux changes: in libmisc/copydir.c (based on Fedora patch),
@@ -1211,7 +1010,7 @@ shadow-4.0.7 -> shadow-4.0.8 26-04-2005
- newgrp(1): fix #251926, #166173, #113191 Debian bugs: explain why editing /etc/group - newgrp(1): fix #251926, #166173, #113191 Debian bugs: explain why editing /etc/group
(without gshadow) doesn't permit to use newgrp, (without gshadow) doesn't permit to use newgrp,
- newgrp(1): newgrp uses /bin/sh (not bash), - newgrp(1): newgrp uses /bin/sh (not bash),
- faillog(8): updated after rewritten faillog command for use getopt_long(), - faillog(8): updated after rewrited faillog command for use getopt_long(),
- login(1): removed fragment about abilities pass enviroment variables in login prompt, - login(1): removed fragment about abilities pass enviroment variables in login prompt,
- gshadow(5): new file (by Nicolas Nicolas François <nicolas.francois@centraliens.net>), - gshadow(5): new file (by Nicolas Nicolas François <nicolas.francois@centraliens.net>),
- usermod(8): fixed #302388 Debian bug: added separated -o option description, - usermod(8): fixed #302388 Debian bug: added separated -o option description,
@@ -1229,24 +1028,24 @@ shadow-4.0.6 -> shadow-4.0.7 26-01-2005
-- use fseeko() instead fseek() and remove casting file offsets to unsigned -- use fseeko() instead fseek() and remove casting file offsets to unsigned
long. long.
- lastlog: - lastlog:
-- rewritten source code using the same style as in chpasswd.c, -- rewrited source code using the same style as in chpasswd.c,
-- open lastlog file after finish parse commandline options -- open lastlog file after finish parse comman line optiomns
(now --help output can be displayed for users without lastlog (now --help otput can be displayd for users without lastlog
file read permission), file read permission),
-- cleanups in lastlog(8) man page using the same style as in -- cleanups in lastlog(8) man page using the same style as in
chpasswd(8). chpasswd(8).
- chpasswd: - chpasswd:
-- switch chpasswd to use getopt_long() and adds a --md5 option -- switch chpasswd to use getopt_long() and adds a --md5 option
(by Ian Gulliver <ian@penguinhosting.net>), (by Ian Gulliver <ian@penguinhosting.net>),
-- rewritten chpasswd(8) man page. -- rewrited chpasswd(8) man page.
shadow-4.0.5 -> shadow-4.0.6 08-11-2004 shadow-4.0.5 -> shadow-4.0.6 08-11-2004
- su: fixed adding of pam_env env variables to enviroment - su: fixed adding of pam_env env variables to enviroment
(Martin Schlemmer <azarah@nosferatu.za.org>), (Martin Schlemmer <azarah@nosferatu.za.org>),
- autoconf: fixed filling MAIL_SPOOL_DIR and MAIL_SPOOL_FILE variables - autoconf: fixed filling MAIL_SPOOL_DIR and MAIL_SPOOL_FILE variables
which was always empty (Gregorio Guidi <g.guidi@sns.it>), which was allways empty (Gregorio Guidi <g.guidi@sns.it>),
- really close security bug in libmisc/pwdcheck.c, - realuy closse security bug in libmisc/pwdcheck.c,
- added missing template/example PAM service config files for chfn, chsh and - added missing template/example PAM service config files for chfn, chsh and
userdel, userdel,
- do not translate variable names from /etc/default/useradd during - do not translate variable names from /etc/default/useradd during
@@ -1257,10 +1056,10 @@ shadow-4.0.4.1 -> shadow-4.0.5 27-10-2004
- change libmisc to private static library, - change libmisc to private static library,
- added SELinux support (basing on patch from Gentoo), - added SELinux support (basing on patch from Gentoo),
- chage: more verbose/human readable -l output. This output is much more - chage: more verbose/human readable -l output. This output is much more
better for send directly via email for each users as message with account beter for send directly via email for each users as message with account
status (for example as message with warning about account/password expiration), status (for example as message with warning about account/password expiration),
- login: fixed handle -f option: now it works correctly without specify "-h - login: fixed handle -f option: now it works correctly without specify "-h
<host>" if open login session locally is required (thanks for help <host>" if open login session localy is required (thanks for help
investigate bug for Krzysztof Kotlenga), investigate bug for Krzysztof Kotlenga),
- userdel: when removing a user with userdel, userdel was always exits with 1 (fixed). - userdel: when removing a user with userdel, userdel was always exits with 1 (fixed).
Based on http://bugs.gentoo.org/show_bug.cgi?id=66687, Based on http://bugs.gentoo.org/show_bug.cgi?id=66687,
@@ -1274,7 +1073,7 @@ shadow-4.0.4.1 -> shadow-4.0.5 27-10-2004
makes httpd Option SymlinkIfOwnerMatch break for default weg pages makes httpd Option SymlinkIfOwnerMatch break for default weg pages
including symlinks placed into /etc/skel/public_html for example. including symlinks placed into /etc/skel/public_html for example.
http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=66819 http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=66819
- su: add pam_open_session() support. If built without PAM support - su: add pam_open_session() support. If builded without PAM support
propagate $DISPLAY and $XAUTHORITY enviroment variables. propagate $DISPLAY and $XAUTHORITY enviroment variables.
Based on http://www.gentoo.org/cgi-bin/viewcvs.cgi/sys-apps/shadow/files/shadow-4.0.4.1-su-pam_open_session.patch?rev=1.1 Based on http://www.gentoo.org/cgi-bin/viewcvs.cgi/sys-apps/shadow/files/shadow-4.0.4.1-su-pam_open_session.patch?rev=1.1
- applied 036_pam_access_with_preauth.patch Debian patch submited by Bjorn - applied 036_pam_access_with_preauth.patch Debian patch submited by Bjorn
@@ -1287,11 +1086,11 @@ shadow-4.0.4.1 -> shadow-4.0.5 27-10-2004
Use constant strings rather than argv[0] for syslog ident in the user Use constant strings rather than argv[0] for syslog ident in the user
management commands, management commands,
shadow-4.0.4.1-owl-tmp.diff: shadow-4.0.4.1-owl-tmp.diff:
Remove using mktemp() if mkstemp() prototype not found (use always mkstemp()), Remove using mktemp() if mkstemp() prototype not found (use allways mkstemp()),
shadow-4.0.4.1-owl-check-reads.diff: shadow-4.0.4.1-owl-check-reads.diff:
Add checking for read errors in commonio and vipw/vigr (not doing so could Add checking for read errors in commonio and vipw/vigr (not doing so could
result in data loss when the records are written back), result in data loss when the records are written back),
- fixed security bug in libmisc/pwdcheck.c which allow unauthorized - fixed securirty bug in libmisc/pwdcheck.c which allow unauthorized
account properties modification. account properties modification.
Affected tools: chfn and chsh. Affected tools: chfn and chsh.
Bug was discovered by Martin Schulze <joey@infodrom.org>. Bug was discovered by Martin Schulze <joey@infodrom.org>.
@@ -1307,12 +1106,12 @@ shadow-4.0.4.1 -> shadow-4.0.5 27-10-2004
shadow-4.0.4 => shadow-4.0.4.1 14-01-2004 shadow-4.0.4 => shadow-4.0.4.1 14-01-2004
- bug fixes in automake files for generate correct tar ball on "make dist": - bug fixes in automake files for generate correct tar ball on "make dist":
added missing "EXTRA_DIST = $(man_MANS)" in man/*/Makefile.am. added mising "EXTRA_DIST = $(man_MANS)" in man/*/Makefile.am.
shadow-4.0.3 => shadow-4.0.4 14-01-2004 shadow-4.0.3 => shadow-4.0.4 14-01-2004
*** general: *** general:
- added missing information about -f options in groupadd usage message - added missing information about -f options in groupadd usage mesage
(document this also in man page), (document this also in man page),
- removed TCFS support (tcfs is dead), - removed TCFS support (tcfs is dead),
- convert all po/*.po files to utf-8, - convert all po/*.po files to utf-8,
@@ -1320,7 +1119,7 @@ shadow-4.0.3 => shadow-4.0.4 14-01-2004
per service flushing method instead HUPing nscd process), per service flushing method instead HUPing nscd process),
- removed old AUTH_METHODS dependent code, - removed old AUTH_METHODS dependent code,
- chage: now all code depend on SHADOWPWD. If shadow will not be configured - chage: now all code depend on SHADOWPWD. If shadow will not be configured
on autoconf level for using shadow password chage is olny stub which on autoconf level for using shadow possword chage is olny stub which
informs "chage not configured for shadow password support." informs "chage not configured for shadow password support."
- dpasswd: removed, - dpasswd: removed,
- login: remove handle login.defs::DIALUPS_CHECK_ENAB code, - login: remove handle login.defs::DIALUPS_CHECK_ENAB code,
@@ -1328,7 +1127,7 @@ shadow-4.0.3 => shadow-4.0.4 14-01-2004
- ALL tools, libraries: remove old SVR4, SVR4_SI86_EUA BSD_QUOTA and ATT_AGE - ALL tools, libraries: remove old SVR4, SVR4_SI86_EUA BSD_QUOTA and ATT_AGE
dependent code, dependent code,
- ALL: ready for gettext 0.11.5, automake 1.7.4, autoconf 2.57, - ALL: ready for gettext 0.11.5, automake 1.7.4, autoconf 2.57,
- logoutd, userd: handle also utmpx if available, - logoutd, userd: handle also utmpx if avalaile,
- newgrp: fix for non-PAM version - newgrp: fix for non-PAM version
Use CLOSE_SESSIONS depending code only when USE_PAM. Use CLOSE_SESSIONS depending code only when USE_PAM.
The problem was reported by Mattias Webjorn Eriksson using Slackware The problem was reported by Mattias Webjorn Eriksson using Slackware
@@ -1356,7 +1155,7 @@ shadow-4.0.3 => shadow-4.0.4 14-01-2004
shadow-4.0.2 => shadow-4.0.3 13-03-2002 shadow-4.0.2 => shadow-4.0.3 13-03-2002
- added various cs, de, fr, id, it, ko man pages found mainly in national - added variouse cs, de, fr, id, it, ko man pages found mainly in national
man pages translations projects (this documents are not synced with man pages translations projects (this documents are not synced with
current en version but you know .. "Documentations is lik sex. When it is current en version but you know .. "Documentations is lik sex. When it is
good it very very good. Whet it is bad it is better than nothing."). Any good it very very good. Whet it is bad it is better than nothing."). Any
@@ -1372,9 +1171,9 @@ shadow-4.0.2 => shadow-4.0.3 13-03-2002
shadow-4.0.1 => shadow-4.0.2 17-02-2002 shadow-4.0.1 => shadow-4.0.2 17-02-2002
- resolve many fuzzy translations also all this which may cause problems on - resolve many fuzzy translations also all this which may cause problems on
displaying long uid/gid, displaing long uid/gid,
- allow use "$" on ending in created by useradd username accounts for allow - allow use "$" on ending in cereated by useradd usermname accounts for allow
create machine accounts for samba (thanks to Jerome Borsboom create machine acounts for samba (thanks to Jerome Borsboom
<borsboom@tch.fgg.eur.nl> for point this problem in 4.0.1), <borsboom@tch.fgg.eur.nl> for point this problem in 4.0.1),
- fix small but ugly bug in configure.in in libpam_mics library detection. - fix small but ugly bug in configure.in in libpam_mics library detection.
@@ -1394,7 +1193,7 @@ shadow-4.0.0 => shadow-4.0.1
as root. If root does read-only, there's no lock needed. Added missing as root. If root does read-only, there's no lock needed. Added missing
"#include <errno.h>" for above (me). "#include <errno.h>" for above (me).
shadow-4.0.0-owl-warnings.diff shadow-4.0.0-owl-warnings.diff
Olny one fix from this patch was applied because other was fixed few days Olny one fix from this patch was aplayd because other was fixed few days
before :) before :)
shadow-4.0.0-owl-check_names.diff shadow-4.0.0-owl-check_names.diff
Merge only prat this patch with checking login name matching; checking Merge only prat this patch with checking login name matching; checking
@@ -1402,7 +1201,7 @@ shadow-4.0.0 => shadow-4.0.1
probably _POSIX_LOGIN_NAME_MAX from <bits/posix1_lim.h>, probably _POSIX_LOGIN_NAME_MAX from <bits/posix1_lim.h>,
shadow-4.0.0-owl-chage-drop-priv.diff shadow-4.0.0-owl-chage-drop-priv.diff
shadow-4.0.0-owl-pam-auth.diff shadow-4.0.0-owl-pam-auth.diff
Merge part with reorder initialize PAM and checking if chage is runed by Merge part with reorder initialize PAM and checkin is chage is runed by
root or not - now chage can be runed from non-root account for checking root or not - now chage can be runed from non-root account for checking
by user own account information (if PAM enabled). by user own account information (if PAM enabled).
- fixes for handle/print correctly 32bit uid/gid (Thorsten Kukuk <kukuk@suse.de>), - fixes for handle/print correctly 32bit uid/gid (Thorsten Kukuk <kukuk@suse.de>),
@@ -1446,30 +1245,30 @@ shadow-20001016 => shadow-4.0.0 06-01-2002
- much better automake support, - much better automake support,
- added pt_BR man pages for gpasswd(1), groupadd(8), groupdel(8), - added pt_BR man pages for gpasswd(1), groupadd(8), groupdel(8),
groupmod(8), shadow(5) (man pages for other nations also are welcome), groupmod(8), shadow(5) (man pages for other nations also are welcome),
- many small fixes and updates nad improvements in man pages, - mamny small fixes and updates nad improvements in man pages,
- applied Debian patch to man pages for shadowconfig, - aplayed Debian patch to man pages for shadowconfig,
- remove limit to 6 chars logged tty name (012_libmisc_sulog.c.diff Debian - remove limit to 6 chars logged tty name (012_libmisc_sulog.c.diff Debian
patch). patch).
shadow-20001012 -> shadow-20001016: shadow-20001012 -> shadow-20001016:
- conditionally disabled body reload_nscd() because not every - conditionaly disabled body reload_nscd() because not every
version of nscd can handle it (this can be enabled by define version of nscd can handle it (this can be enabled by define
ENABLE_NSCD_SIGHUP) (Marek Michałkiewicz <marekm@linux.org.pl>) ENABLE_NSCD_SIGHUP) (Marek Michałkiewicz <marekm@linux.org.pl>)
- fixes on autoconf/automake level for dist target, - fixes on autoconf/automake level for dist target,
- Julianne F. Haugh new contact address. - Julianne F. Haugh new contact adress.
shadow-20000902 => shadow-20001012 shadow-20000902 => shadow-20001012
- removed /redhat directory with obsoleted files (partially rewritten spec - removed /redhat directory with obsoleted files (partialy rewrited spec
file is now in root directory), file is now in root directory),
- applied shadow-19990827-group.patch patch from RH wich prevents adduser - aplayed shadow-19990827-group.patch patch from RH wich prevents adduser
overwrite previously existing groups in adduser, overwrite previously existing groups in adduser,
- added PAM support for chage (bind to "chage" PAM config file) also - added PAM support for chage (bind to "chage" PAM config file) also
added PAM support for all other small tools like chpasswd, groupadd, added PAM support for all other small tools like chpasswd, groupadd,
groupdel, groupmod, newusers, useradd, userdel, usermod (bind to common groupdel, groupmod, newusers, useradd, userdel, usermod (bind to common
"shadow" PAM config file) - this modifications mainly based on "shadow" PAM config file) - this modificaytions mainly based on
modifications prepared by Janek Rękojarski <baggins@pld.org.pl>, modifications prepared by Janek Rękojarski <baggins@pld.org.pl>,
- many small fixes and improvements in automake (mow "make dist" - many small fixes and improvments in automake (mow "make dist"
works correctly), works correctly),
- added cs translation (Jiri Pavlovsky <Jiri.Pavlovsky@ff.cuni.cz>). - added cs translation (Jiri Pavlovsky <Jiri.Pavlovsky@ff.cuni.cz>).
+18 -25
View File
@@ -2,25 +2,30 @@ Shadow SITES
============ ============
Homepage Homepage
http://github.com/shadow-maint/shadow http://pkg-shadow.alioth.debian.org/
Issue tracker FTP site
http://github.com/shadow-maint/shadow/issues ftp://pkg-shadow.alioth.debian.org/pub/pkg-shadow
Releases SVN repository
https://github.com/shadow-maint/shadow/releases anonymous read only access: svn://svn.debian.org/pkg-shadow/upstream
SVN web interface
http://svn.debian.org/wsvn/pkg-shadow/upstream
or
http://svn.debian.org/viewsvn/pkg-shadow/upstream
Mailing lists Mailing lists
for general discuss: pkg-shadow-devel@alioth-lists.debian.net for general discuss: pkg-shadow-devel@lists.alioth.debian.org
commit list: pkg-shadow-commits@alioth-lists.debian.net commit list: pkg-shadow-commits@lists.alioth.debian.org
Mailing lists subscription Mailing lists subscription
http://alioth-lists.debian.net/mailman/listinfo/pkg-shadow-devel http://lists.alioth.debian.org/mailman/listinfo/pkg-shadow-devel
http://alioth-lists.debian.net/mailman/listinfo/pkg-shadow-commits http://lists.alioth.debian.org/mailman/listinfo/pkg-shadow-commits
Mailing lists archives: Mailing lists archives:
http://alioth-lists.debian.net/pipermail/pkg-shadow-devel/ http://lists.alioth.debian.org/pipermail/pkg-shadow-devel/
http://alioth-lists.debian.net/pipermail/pkg-shadow-commits/ http://lists.alioth.debian.org/pipermail/pkg-shadow-commits/
S/Key support: S/Key support:
Shadow can be built with S/Key support using the S/Key package from: Shadow can be built with S/Key support using the S/Key package from:
@@ -32,14 +37,13 @@ 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...
Adam Rudnicki <adam@v-lo.krakow.pl> Adam Rudnicki <adam@v-lo.krakow.pl>
Alan Curry <pacman@tardis.mars.net> Alan Curry <pacman@tardis.mars.net>
Aleksa Sarai <cyphar@cyphar.com>
Alexander O. Yuriev <alex@bach.cis.temple.edu> Alexander O. Yuriev <alex@bach.cis.temple.edu>
Algis Rudys <arudys@rice.edu> Algis Rudys <arudys@rice.edu>
Andreas Jaeger <aj@arthur.rhein-neckar.de> Andreas Jaeger <aj@arthur.rhein-neckar.de>
@@ -51,7 +55,6 @@ Brian R. Gaeke <brg@dgate.org>
Calle Karlsson <ckn@kash.se> Calle Karlsson <ckn@kash.se>
Chip Rosenthal <chip@unicom.com> Chip Rosenthal <chip@unicom.com>
Chris Evans <lady0110@sable.ox.ac.uk> Chris Evans <lady0110@sable.ox.ac.uk>
Chris Lamb <chris@chris-lamb.co.uk>
Cristian Gafton <gafton@sorosis.ro> Cristian Gafton <gafton@sorosis.ro>
Dan Walsh <dwalsh@redhat.com> Dan Walsh <dwalsh@redhat.com>
Darcy Boese <possum@chardonnay.niagara.com> Darcy Boese <possum@chardonnay.niagara.com>
@@ -59,8 +62,6 @@ Dave Hagewood <admin@arrowweb.com>
David A. Holland <dholland@hcs.harvard.edu> David A. Holland <dholland@hcs.harvard.edu>
David Frey <David.Frey@lugs.ch> David Frey <David.Frey@lugs.ch>
Ed Carp <ecarp@netcom.com> Ed Carp <ecarp@netcom.com>
Ed Neville <ed@s5h.net>
Eric W. Biederman" <ebiederm@xmission.com>
Floody <flood@evcom.net> Floody <flood@evcom.net>
Frank Denis <j@4u.net> Frank Denis <j@4u.net>
George Kraft IV <gk4@us.ibm.com> George Kraft IV <gk4@us.ibm.com>
@@ -68,9 +69,7 @@ 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>
Jason Franklin <jason.franklin@quoininc.com>
Jay Soffian <jay@lw.net> Jay Soffian <jay@lw.net>
Jesse Thilo <Jesse.Thilo@pobox.com> Jesse Thilo <Jesse.Thilo@pobox.com>
Joey Hess <joey@kite.ml.org> Joey Hess <joey@kite.ml.org>
@@ -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>
@@ -92,18 +90,15 @@ Martin Bene <mb@sime.com>
Martin Mares <mj@gts.cz> Martin Mares <mj@gts.cz>
Michael Meskes <meskes@topsystem.de> Michael Meskes <meskes@topsystem.de>
Michael Talbot-Wilson <mike@calypso.bns.com.au> Michael Talbot-Wilson <mike@calypso.bns.com.au>
Michael Vetter <jubalh@iodoru.org>
Mike Frysinger <vapier@gentoo.org> Mike Frysinger <vapier@gentoo.org>
Mike Pakovic <mpakovic@users.southeast.net> 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>
@@ -118,7 +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)
Christian Brauner <christian@brauner.io> (2019-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
+1 -3
View File
@@ -1,12 +1,10 @@
#! /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 \
--enable-maintainer-mode \ --enable-maintainer-mode \
--enable-shared \ --disable-shared \
--without-libpam \ --without-libpam \
--with-selinux \ --with-selinux \
"$@" "$@"
+33 -259
View File
@@ -1,29 +1,16 @@
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.69]) AC_INIT
m4_define([libsubid_abi_major], 3) AM_INIT_AUTOMAKE(shadow, 4.1.4.2)
m4_define([libsubid_abi_minor], 0)
m4_define([libsubid_abi_micro], 0)
m4_define([libsubid_abi], [libsubid_abi_major.libsubid_abi_minor.libsubid_abi_micro])
AC_INIT([shadow], [4.9], [pkg-shadow-devel@lists.alioth.debian.org], [],
[https://github.com/shadow-maint/shadow])
AM_INIT_AUTOMAKE([1.11 foreign dist-xz])
AC_CONFIG_MACRO_DIRS([m4])
AM_SILENT_RULES([yes])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
AC_SUBST([LIBSUBID_ABI_MAJOR], [libsubid_abi_major])
AC_SUBST([LIBSUBID_ABI_MINOR], [libsubid_abi_minor])
AC_SUBST([LIBSUBID_ABI_MICRO], [libsubid_abi_micro])
AC_SUBST([LIBSUBID_ABI], [libsubid_abi])
dnl Some hacks... dnl Some hacks...
test "$prefix" = "NONE" && prefix="/usr" test "$prefix" = "NONE" && prefix="/usr"
test "$prefix" = "/usr" && exec_prefix="" test "$prefix" = "/usr" && exec_prefix=""
AC_GNU_SOURCE AC_GNU_SOURCE
AM_DISABLE_SHARED
AM_ENABLE_STATIC AM_ENABLE_STATIC
AM_ENABLE_SHARED
AM_MAINTAINER_MODE AM_MAINTAINER_MODE
@@ -32,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.
@@ -42,21 +30,18 @@ AC_HEADER_STDC
AC_HEADER_SYS_WAIT AC_HEADER_SYS_WAIT
AC_HEADER_STDBOOL AC_HEADER_STDBOOL
AC_CHECK_HEADERS(crypt.h 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/capability.h sys/random.h sys/resource.h \ utime.h ulimit.h sys/resource.h gshadow.h lastlog.h \
gshadow.h lastlog.h locale.h rpc/key_prot.h netdb.h acl/libacl.h \ locale.h rpc/key_prot.h netdb.h)
attr/libattr.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])])
AC_CHECK_FUNCS(arc4random_buf l64a fchmod fchown fsync futimes getgroups \ AC_CHECK_FUNCS(l64a fchmod fchown fsync futimes getgroups gethostname getspnam \
gethostname getentropy getrandom getspnam gettimeofday getusershell \ gettimeofday getusershell getutent initgroups lchown lckpwdf lstat \
getutent initgroups lchown lckpwdf lstat lutimes memcpy memset \ lutimes memcpy memset setgroups sigaction strchr updwtmp updwtmpx innetgr \
setgroups sigaction strchr updwtmp updwtmpx innetgr getpwnam_r \ getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo)
getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo ruserok \
dlopen)
AC_SYS_LARGEFILE AC_SYS_LARGEFILE
dnl Checks for typedefs, structures, and compiler characteristics. dnl Checks for typedefs, structures, and compiler characteristics.
@@ -85,6 +70,12 @@ AC_CHECK_MEMBERS([struct utmp.ut_type,
struct utmp.ut_time, struct utmp.ut_time,
struct utmp.ut_xtime, struct utmp.ut_xtime,
struct utmp.ut_tv],,,[[#include <utmp.h>]]) struct utmp.ut_tv],,,[[#include <utmp.h>]])
dnl There are dependencies:
dnl If UTMPX has to be used, the utmp structure shall have a ut_id field.
if test "$ac_cv_header_utmpx_h" = "yes" &&
test "$ac_cv_member_struct_utmp_ut_id" != "yes"; then
AC_MSG_ERROR(Systems with UTMPX and no ut_id field in the utmp structure are not supported)
fi
AC_CHECK_MEMBERS([struct utmpx.ut_name, AC_CHECK_MEMBERS([struct utmpx.ut_name,
struct utmpx.ut_host, struct utmpx.ut_host,
@@ -121,9 +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_CHECK_FUNC(secure_getenv, [AC_DEFINE(HAS_SECURE_GETENV, AC_FUNC_SETPGRP
1,
[Defined to 1 if you have the declaration of 'secure_getenv'])])
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,
@@ -206,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@:>@])],
@@ -237,7 +224,7 @@ AC_ARG_ENABLE(account-tools-setuid,
*) AC_MSG_ERROR(bad value ${enableval} for --enable-account-tools-setuid) *) AC_MSG_ERROR(bad value ${enableval} for --enable-account-tools-setuid)
;; ;;
esac], esac],
[enable_acct_tools_setuid="no"] [enable_acct_tools_setuid="maybe"]
) )
AC_ARG_ENABLE(utmpx, AC_ARG_ENABLE(utmpx,
@@ -251,61 +238,30 @@ AC_ARG_ENABLE(utmpx,
[enable_utmpx="no"] [enable_utmpx="no"]
) )
AC_ARG_ENABLE(subordinate-ids, AC_ARG_WITH(audit,
[AC_HELP_STRING([--enable-subordinate-ids],
[support subordinate ids @<:@default=yes@:>@])],
[enable_subids="${enableval}"],
[enable_subids="maybe"]
)
AC_ARG_WITH(audit,
[AC_HELP_STRING([--with-audit], [use auditing support @<:@default=yes if found@:>@])], [AC_HELP_STRING([--with-audit], [use auditing support @<:@default=yes if found@:>@])],
[with_audit=$withval], [with_audit=maybe]) [with_audit=$withval], [with_audit=maybe])
AC_ARG_WITH(libpam, AC_ARG_WITH(libpam,
[AC_HELP_STRING([--with-libpam], [use libpam for PAM support @<:@default=yes if found@:>@])], [AC_HELP_STRING([--with-libpam], [use libpam for PAM support @<:@default=yes if found@:>@])],
[with_libpam=$withval], [with_libpam=maybe]) [with_libpam=$withval], [with_libpam=maybe])
AC_ARG_WITH(btrfs,
[AC_HELP_STRING([--with-btrfs], [add BtrFS support @<:@default=yes if found@:>@])],
[with_btrfs=$withval], [with_btrfs=maybe])
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@:>@])],
[with_sha_crypt=$withval], [with_sha_crypt=yes]) [with_sha_crypt=$withval], [with_sha_crypt=yes])
AC_ARG_WITH(bcrypt,
[AC_HELP_STRING([--with-bcrypt], [allow the bcrypt password encryption algorithm @<:@default=no@:>@])],
[with_bcrypt=$withval], [with_bcrypt=no])
AC_ARG_WITH(yescrypt,
[AC_HELP_STRING([--with-yescrypt], [allow the yescrypt password encryption algorithm @<:@default=no@:>@])],
[with_yescrypt=$withval], [with_yescrypt=no])
AC_ARG_WITH(nscd, AC_ARG_WITH(nscd,
[AC_HELP_STRING([--with-nscd], [enable support for nscd @<:@default=yes@:>@])], [AC_HELP_STRING([--with-nscd], [enable support for nscd @<:@default=yes@:>@])],
[with_nscd=$withval], [with_nscd=yes]) [with_nscd=$withval], [with_nscd=yes])
AC_ARG_WITH(sssd,
[AC_HELP_STRING([--with-sssd], [enable support for flushing sssd caches @<:@default=yes@:>@])],
[with_sssd=$withval], [with_sssd=yes])
AC_ARG_WITH(group-name-max-length, AC_ARG_WITH(group-name-max-length,
[AC_HELP_STRING([--with-group-name-max-length], [set max group name length @<:@default=16@:>@])], [AC_HELP_STRING([--with-group-name-max-length], [set max group name length @<:@default=16@:>@])],
[with_group_name_max_length=$withval], [with_group_name_max_length=yes]) [with_group_name_max_length=$withval], [with_group_name_max_length=yes])
AC_ARG_WITH(su,
[AC_HELP_STRING([--with-su], [build and install su program and man page @<:@default=yes@:>@])],
[with_su=$withval], [with_su=yes])
if test "$with_group_name_max_length" = "no" ; then if test "$with_group_name_max_length" = "no" ; then
with_group_name_max_length=0 with_group_name_max_length=0
@@ -321,31 +277,12 @@ if test "$with_sha_crypt" = "yes"; then
AC_DEFINE(USE_SHA_CRYPT, 1, [Define to allow the SHA256 and SHA512 password encryption algorithms]) AC_DEFINE(USE_SHA_CRYPT, 1, [Define to allow the SHA256 and SHA512 password encryption algorithms])
fi fi
AM_CONDITIONAL(USE_BCRYPT, test "x$with_bcrypt" = "xyes")
if test "$with_bcrypt" = "yes"; then
AC_DEFINE(USE_BCRYPT, 1, [Define to allow the bcrypt password encryption algorithm])
fi
AM_CONDITIONAL(USE_YESCRYPT, test "x$with_yescrypt" = "xyes")
if test "$with_yescrypt" = "yes"; then
AC_DEFINE(USE_YESCRYPT, 1, [Define to allow the yescrypt password encryption algorithm])
fi
if test "$with_nscd" = "yes"; then if test "$with_nscd" = "yes"; then
AC_CHECK_FUNC(posix_spawn, AC_CHECK_FUNC(posix_spawn,
[AC_DEFINE(USE_NSCD, 1, [Define to support flushing of nscd caches])], [AC_DEFINE(USE_NSCD, 1, [Define to support flushing of nscd caches])],
[AC_MSG_ERROR([posix_spawn is needed for nscd support])]) [AC_MSG_ERROR([posix_spawn is needed for nscd support])])
fi fi
if test "$with_sssd" = "yes"; then
AC_CHECK_FUNC(posix_spawn,
[AC_DEFINE(USE_SSSD, 1, [Define to support flushing of sssd caches])],
[AC_MSG_ERROR([posix_spawn is needed for sssd support])])
fi
AS_IF([test "$with_su" != "no"], AC_DEFINE(WITH_SU, 1, [Build with su])])
AM_CONDITIONAL([WITH_SU], [test "x$with_su" != "xno"])
dnl Check for some functions in libc first, only if not found check for dnl Check for some functions in libc first, only if not found check for
dnl other libraries. This should prevent linking libnsl if not really dnl other libraries. This should prevent linking libnsl if not really
dnl needed (Linux glibc, Irix), but still link it if needed (Solaris). dnl needed (Linux glibc, Irix), but still link it if needed (Solaris).
@@ -354,17 +291,6 @@ AC_SEARCH_LIBS(inet_ntoa, inet)
AC_SEARCH_LIBS(socket, socket) AC_SEARCH_LIBS(socket, socket)
AC_SEARCH_LIBS(gethostbyname, nsl) AC_SEARCH_LIBS(gethostbyname, nsl)
AC_CHECK_LIB([econf],[econf_readDirs],[LIBECONF="-leconf"],[LIBECONF=""])
if test -n "$LIBECONF"; then
ECONF_CPPFLAGS="-DUSE_ECONF=1"
AC_ARG_ENABLE([vendordir],
AS_HELP_STRING([--enable-vendordir=DIR], [Directory for distribution provided configuration files]),,[])
fi
AC_SUBST(ECONF_CPPFLAGS)
AC_SUBST(LIBECONF)
AC_SUBST([VENDORDIR], [$enable_vendordir])
AM_CONDITIONAL([HAVE_VENDORDIR], [test "x$enable_vendordir" != x])
if test "$enable_shadowgrp" = "yes"; then if test "$enable_shadowgrp" = "yes"; then
AC_DEFINE(SHADOWGRP, 1, [Define to support the shadow group file.]) AC_DEFINE(SHADOWGRP, 1, [Define to support the shadow group file.])
fi fi
@@ -377,96 +303,20 @@ if test "$enable_man" = "yes"; then
AC_PATH_PROG([XSLTPROC], [xsltproc]) AC_PATH_PROG([XSLTPROC], [xsltproc])
if test -z "$XSLTPROC"; then if test -z "$XSLTPROC"; then
enable_man=no enable_man=no
AC_MSG_ERROR([xsltproc is missing.])
fi fi
dnl check for DocBook DTD and stylesheets in the local catalog. dnl check for DocBook DTD and stylesheets in the local catalog.
JH_CHECK_XML_CATALOG([-//OASIS//DTD DocBook XML V4.5//EN], JH_CHECK_XML_CATALOG([-//OASIS//DTD DocBook XML V4.1.2//EN],
[DocBook XML DTD V4.5], [], enable_man=no) [DocBook XML DTD V4.1.2], [], enable_man=no)
JH_CHECK_XML_CATALOG([http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl], JH_CHECK_XML_CATALOG([http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl],
[DocBook XSL Stylesheets >= 1.70.1], [], enable_man=no) [DocBook XSL Stylesheets >= 1.70.1], [], enable_man=no)
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(LIYESCRYPT)
AC_CHECK_LIB(crypt, crypt, [LIYESCRYPT=-lcrypt],
[AC_MSG_ERROR([crypt() not found])])
AC_SUBST(LIBACL)
if test "$with_acl" != "no"; then
AC_CHECK_HEADERS(acl/libacl.h attr/error_context.h, [acl_header="yes"], [acl_header="no"])
if test "$acl_header$with_acl" = "noyes" ; then
AC_MSG_ERROR([acl/libacl.h or attr/error_context.h is missing])
elif test "$acl_header" = "yes" ; then
AC_CHECK_LIB(acl, perm_copy_file,
[AC_CHECK_LIB(acl, perm_copy_fd,
[acl_lib="yes"],
[acl_lib="no"])],
[acl_lib="no"])
if test "$acl_lib$with_acl" = "noyes" ; then
AC_MSG_ERROR([libacl not found])
elif test "$acl_lib" = "no" ; then
with_acl="no"
else
AC_DEFINE(WITH_ACL, 1,
[Build shadow with ACL support])
LIBACL="-lacl"
with_acl="yes"
fi
else
with_acl="no"
fi
fi
AC_SUBST(LIBATTR)
if test "$with_attr" != "no"; then
AC_CHECK_HEADERS(attr/libattr.h attr/error_context.h, [attr_header="yes"], [attr_header="no"])
if test "$attr_header$with_attr" = "noyes" ; then
AC_MSG_ERROR([attr/libattr.h or attr/error_context.h is missing])
elif test "$attr_header" = "yes" ; then
AC_CHECK_LIB(attr, attr_copy_file,
[AC_CHECK_LIB(attr, attr_copy_fd,
[attr_lib="yes"],
[attr_lib="no"])],
[attr_lib="no"])
if test "$attr_lib$with_attr" = "noyes" ; then
AC_MSG_ERROR([libattr not found])
elif test "$attr_lib" = "no" ; then
with_attr="no"
else
AC_DEFINE(WITH_ATTR, 1,
[Build shadow with Extended Attributes support])
LIBATTR="-lattr"
with_attr="yes"
fi
else
with_attr="no"
fi
fi
AC_SUBST(LIBAUDIT) 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"])
@@ -510,80 +360,29 @@ if test "$with_libcrack" = "yes"; then
AC_DEFINE(HAVE_LIBCRACK_PW, 1, [Defined if it includes *Pw functions.])) AC_DEFINE(HAVE_LIBCRACK_PW, 1, [Defined if it includes *Pw functions.]))
fi fi
if test "$with_btrfs" != "no"; then
AC_CHECK_HEADERS([sys/statfs.h linux/magic.h linux/btrfs_tree.h], \
[btrfs_headers="yes"], [btrfs_headers="no"])
if test "$btrfs_headers$with_btrfs" = "noyes" ; then
AC_MSG_ERROR([One of sys/statfs.h linux/magic.h linux/btrfs_tree.h is missing])
fi
if test "$btrfs_headers" = "yes" ; then
AC_DEFINE(WITH_BTRFS, 1, [Build shadow with BtrFS support])
with_btrfs="yes"
fi
fi
AM_CONDITIONAL(WITH_BTRFS, test x$with_btrfs = xyes)
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,
@@ -638,7 +437,7 @@ if test "$with_libpam" = "yes"; then
LIBS=$save_libs LIBS=$save_libs
AC_DEFINE(USE_PAM, 1, [Define to support Pluggable Authentication Modules]) AC_DEFINE(USE_PAM, 1, [Define to support Pluggable Authentication Modules])
AC_DEFINE_UNQUOTED(SHADOW_PAM_CONVERSATION, [$pam_conv_function],[PAM conversation to use]) AC_DEFINE_UNQUOTED(SHADOW_PAM_CONVERSATION, [$pam_conv_function],[PAM converstation to use])
AM_CONDITIONAL(USE_PAM, [true]) AM_CONDITIONAL(USE_PAM, [true])
AC_MSG_CHECKING(use login and su access checking if PAM not used) AC_MSG_CHECKING(use login and su access checking if PAM not used)
@@ -668,19 +467,6 @@ if test "$enable_acct_tools_setuid" != "no"; then
fi fi
AM_CONDITIONAL(ACCT_TOOLS_SETUID, test "x$enable_acct_tools_setuid" = "xyes") AM_CONDITIONAL(ACCT_TOOLS_SETUID, test "x$enable_acct_tools_setuid" = "xyes")
AC_ARG_WITH(fcaps,
[AC_HELP_STRING([--with-fcaps], [use file capabilities instead of suid binaries for newuidmap/newgidmap @<:@default=no@:>@])],
[with_fcaps=$withval], [with_fcaps=no])
AM_CONDITIONAL(FCAPS, test "x$with_fcaps" = "xyes")
if test "x$with_fcaps" = "xyes"; then
AC_CHECK_PROGS(capcmd, "setcap")
if test "x$capcmd" = "x" ; then
AC_MSG_ERROR([setcap command not available])
fi
fi
AC_SUBST(LIBSKEY) AC_SUBST(LIBSKEY)
AC_SUBST(LIBMD) AC_SUBST(LIBMD)
if test "$with_skey" = "yes"; then if test "$with_skey" = "yes"; then
@@ -717,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
@@ -738,7 +523,6 @@ AC_CONFIG_FILES([
man/zh_TW/Makefile man/zh_TW/Makefile
libmisc/Makefile libmisc/Makefile
lib/Makefile lib/Makefile
libsubid/Makefile
src/Makefile src/Makefile
contrib/Makefile contrib/Makefile
etc/Makefile etc/Makefile
@@ -757,18 +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 " BtrFS support: $with_btrfs"
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 " bcrypt passwords encryption: $with_bcrypt"
echo " yescrypt passwords encryption: $with_yescrypt"
echo " nscd support: $with_nscd" echo " nscd support: $with_nscd"
echo " sssd support: $with_sssd"
echo " subordinate IDs support: $enable_subids"
echo " use file caps: $with_fcaps"
echo " install su: $with_su"
echo echo
+1 -1
View File
@@ -20,7 +20,7 @@
** 1/28/95 ** 1/28/95
** shadow-adduser 1.3: ** shadow-adduser 1.3:
** **
** Basically a bug-fix on my additions in 1.2. Thanks to Terry Stewart ** Basically a bug-fix on my additions in 1.2. Thanx to Terry Stewart
** (stew@texas.net) for pointing out one of the many idiotic bugs I introduced. ** (stew@texas.net) for pointing out one of the many idiotic bugs I introduced.
** It was such a stupid bug that I would have never seen it myself. ** It was such a stupid bug that I would have never seen it myself.
** **
+1 -1
View File
@@ -34,7 +34,7 @@
** 1/28/95 ** 1/28/95
** shadow-adduser 1.3: ** shadow-adduser 1.3:
** **
** Basically a bug-fix on my additions in 1.2. Thanks to Terry Stewart ** Basically a bug-fix on my additions in 1.2. Thanx to Terry Stewart
** (stew@texas.net) for pointing out one of the many idiotic bugs I introduced. ** (stew@texas.net) for pointing out one of the many idiotic bugs I introduced.
** It was such a stupid bug that I would have never seen it myself. ** It was such a stupid bug that I would have never seen it myself.
** **
+1 -1
View File
@@ -32,7 +32,7 @@ def_home_dir=/home/users
# default shell # default shell
def_shell=/bin/tcsh def_shell=/bin/tcsh
# Default expiration date (mm/dd/yy) # Defaul expiration date (mm/dd/yy)
def_expire="" def_expire=""
# default dates # default dates
+1 -1
View File
@@ -480,7 +480,7 @@ X.B groupmems
\fB-D\fR | \fB-D\fR |
[\fB-g\fI group_name \fR] [\fB-g\fI group_name \fR]
X.SH DESCRIPTION X.SH DESCRIPTION
The \fBgroupmems\fR utility allows a user to administer their own The \fBgroupmems\fR utility allows a user to administer his/her own
group membership list without the requirement of superuser privileges. group membership list without the requirement of superuser privileges.
The \fBgroupmems\fR utility is for systems that configure its users to The \fBgroupmems\fR utility is for systems that configure its users to
be in their own name sake primary group (i.e., guest / guest). be in their own name sake primary group (i.e., guest / guest).
+1 -1
View File
@@ -2,7 +2,7 @@ Hello Marek,
I have created a diffile against the 980403 release that adds I have created a diffile against the 980403 release that adds
functionality to newusers for automatic handling of users with only functionality to newusers for automatic handling of users with only
anonymous ftp login (using the guestgroup feature in ftpaccess, which anonomous ftp login (using the guestgroup feature in ftpaccess, which
means that the users home directory looks like '/home/user/./'). It also means that the users home directory looks like '/home/user/./'). It also
adds a commandline argument to specify an initial directory structure adds a commandline argument to specify an initial directory structure
for such users, with a tarball normally containing the bin,lib,etc for such users, with a tarball normally containing the bin,lib,etc
+1 -1
View File
@@ -15,7 +15,7 @@ Changes:
- code merged into lmain.c --cristiang - code merged into lmain.c --cristiang
TODO: - support groups in the limits file TODO: - support groups in the limits file
(only usernames are supported at this moment :-( ) (only usernames are supported at this momment :-( )
Setting user limits for shadow login program Setting user limits for shadow login program
-15
View File
@@ -1,15 +0,0 @@
<HEAD>
<title>shadow - Welcome</title>
</head>
<body>
<h2> Welcome!</h2>
<p> This is the shadow tool suite home page. </p>
<p>
You can find releases <a href="https://github.com/shadow-maint/shadow/releases">here</a>.
</p>
<p>
Raise issues, request features, and report bugs <a href="https://github.com/shadow-maint/shadow/issues">here</a>.
</p>
</body>
+2 -1
View File
@@ -4,7 +4,8 @@
sysconf_DATA = login.defs sysconf_DATA = login.defs
defaultdir = $(sysconfdir)/default defaultdir = $(sysconfdir)/default
default_DATA = default_DATA = \
useradd
nonpam_files = \ nonpam_files = \
limits \ limits \
+54 -147
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,19 +27,10 @@ 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
#
# Limit the highest user ID number for which the lastlog entries should
# be updated.
#
# No LASTLOG_UID_MAX means that there is no user ID limit for writing
# lastlog entries.
#
#LASTLOG_UID_MAX
# #
# Enable checking and display of mailbox status upon login. # Enable checking and display of mailbox status upon login.
# #
@@ -59,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
@@ -73,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
@@ -91,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
@@ -167,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
@@ -192,20 +183,14 @@ 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 if HOME_MODE is not set.
# 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 their mind. # must make up her mind.
UMASK 022 UMASK 022
# HOME_MODE is used by useradd(8) and newusers(8) to set the mode for new
# home directories.
# If HOME_MODE is not set, the value of UMASK is used to create the mode.
#HOME_MODE 0700
# #
# Password aging controls: # Password aging controls:
# #
@@ -228,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
@@ -286,16 +263,16 @@ 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".
# #
CHFN_RESTRICT rwh CHFN_RESTRICT rwh
# #
@@ -316,19 +293,16 @@ 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 BCRYPT, BCRYPT-based algorithm will be used for encrypting password
# If set to YESCRYPT, YESCRYPT-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)
# MD5 and DES should not be used for new hashes, see crypt(5) for recommendations.
# Overrides the MD5_CRYPT_ENAB option # Overrides the MD5_CRYPT_ENAB option
# #
# 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
@@ -340,72 +314,35 @@ 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).
# which is orders of magnitude too low for modern hardware. # The values must be inside the 1000-999999999 range.
# The values must be within 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.
# #
#SHA_CRYPT_MIN_ROUNDS 5000 # SHA_CRYPT_MIN_ROUNDS 5000
#SHA_CRYPT_MAX_ROUNDS 5000 # SHA_CRYPT_MAX_ROUNDS 5000
#
# Only works if ENCRYPT_METHOD is set to BCRYPT.
#
# Define the number of BCRYPT rounds.
# With a lot of rounds, it is more difficult to brute-force the password.
# However, more CPU resources will be needed to authenticate users if
# this value is increased.
#
# If not specified, 13 rounds will be attempted.
# 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.
#
#BCRYPT_MIN_ROUNDS 13
#BCRYPT_MAX_ROUNDS 13
#
# Only works if ENCRYPT_METHOD is set to YESCRYPT.
#
# Define the YESCRYPT cost factor.
# With a higher cost factor, it is more difficult to brute-force the password.
# However, more CPU time and more memory will be needed to authenticate users
# if this value is increased.
#
# If not specified, a cost factor of 5 will be used.
# The value must be within the 1-11 range.
#
#YESCRYPT_COST_FACTOR 5
# #
# 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
#
# The pwck(8) utility emits a warning for any system account with a home
# directory that does not exist. Some system accounts intentionally do
# not have a home directory. Such accounts may have this string as
# their home directory in /etc/passwd to avoid a spurious warning.
#
NONEXISTENT /nonexistent
# #
# If this file exists and is readable, login environment will be # If this file exists and is readable, login environment will be
# read from it. Every line should be in the form name=value. # read from it. Every line should be in the form name=value.
@@ -424,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).
# #
@@ -440,40 +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
#
# Allow newuidmap and newgidmap when running under an alternative
# primary group.
#
#GRANT_AUX_GROUP_SUBIDS yes
#
# Prevents an empty password field to be interpreted as "no authentication
# required".
# Set to "yes" to prevent for all accounts
# Set to "superuser" to prevent for UID 0 / root (default)
# Set to "no" to not prevent for any account (dangerous, historical default)
PREVENT_NO_AUTH superuser
#
# Select the HMAC cryptography algorithm.
# Used in pam_timestamp module to calculate the keyed-hash message
# authentication code.
#
# Note: It is recommended to check hmac(3) to see the possible algorithms
# that are available in your system.
#
#HMAC_CRYPTO_ALGO SHA512
+2 -5
View File
@@ -6,7 +6,8 @@ pamd_files = \
chsh \ chsh \
groupmems \ groupmems \
login \ login \
passwd passwd \
su
pamd_acct_tools_files = \ pamd_acct_tools_files = \
chage \ chage \
@@ -28,8 +29,4 @@ pamd_DATA += $(pamd_acct_tools_files)
endif endif
endif endif
if WITH_SU
pamd_files += su
endif
EXTRA_DIST = $(pamd_files) $(pamd_acct_tools_files) EXTRA_DIST = $(pamd_files) $(pamd_acct_tools_files)
+8
View File
@@ -0,0 +1,8 @@
# useradd defaults file
GROUP=1000
HOME=/home
INACTIVE=-1
EXPIRE=
SHELL=/bin/bash
SKEL=/etc/skel
CREATE_MAIL_SPOOL=yes
+1 -19
View File
@@ -5,10 +5,7 @@ DEFS =
noinst_LTLIBRARIES = libshadow.la noinst_LTLIBRARIES = libshadow.la
libshadow_la_CPPFLAGS = $(ECONF_CPPFLAGS) libshadow_la_LDFLAGS = -version-info 0:0:0
if HAVE_VENDORDIR
libshadow_la_CPPFLAGS += -DVENDORDIR=\"$(VENDORDIR)\"
endif
libshadow_la_SOURCES = \ libshadow_la_SOURCES = \
commonio.c \ commonio.c \
@@ -17,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 \
@@ -31,11 +27,8 @@ libshadow_la_SOURCES = \
groupio.h \ groupio.h \
gshadow.c \ gshadow.c \
lockpw.c \ lockpw.c \
nss.c \
nscd.c \ nscd.c \
nscd.h \ nscd.h \
sssd.c \
sssd.h \
pam_defs.h \ pam_defs.h \
port.c \ port.c \
port.h \ port.h \
@@ -45,12 +38,6 @@ libshadow_la_SOURCES = \
pwio.c \ pwio.c \
pwio.h \ pwio.h \
pwmem.c \ pwmem.c \
run_part.h \
run_part.c \
subordinateio.h \
subordinateio.c \
selinux.c \
semanage.c \
sgetgrent.c \ sgetgrent.c \
sgetpwent.c \ sgetpwent.c \
sgetspent.c \ sgetspent.c \
@@ -60,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:
# #
+118 -281
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,17 +45,16 @@
#include <stdio.h> #include <stdio.h>
#include <signal.h> #include <signal.h>
#include "nscd.h" #include "nscd.h"
#include "sssd.h" #ifdef WITH_SELINUX
#ifdef WITH_TCB #include <selinux/selinux.h>
#include <tcb.h> #endif
#endif /* WITH_TCB */
#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,
@@ -133,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;
@@ -141,13 +140,8 @@ static int do_lock_file (const char *file, const char *lock, bool log)
int retval; int retval;
char buf[32]; char buf[32];
fd = open (file, O_CREAT | O_TRUNC | O_WRONLY, 0600); fd = open (file, O_CREAT | O_EXCL | O_WRONLY, 0600);
if (-1 == fd) { if (-1 == fd) {
if (log) {
(void) fprintf (shadow_logfd,
"%s: %s: %s\n",
Prog, file, strerror (errno));
}
return 0; return 0;
} }
@@ -155,21 +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 (shadow_logfd,
"%s: %s file write error: %s\n",
Prog, file, strerror (errno));
}
(void) close (fd);
unlink (file);
return 0;
}
if (fdatasync (fd) == -1) {
if (log) {
(void) fprintf (shadow_logfd,
"%s: %s file sync error: %s\n",
Prog, file, strerror (errno));
}
(void) close (fd); (void) close (fd);
unlink (file); unlink (file);
return 0; return 0;
@@ -178,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 (shadow_logfd,
"%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 (shadow_logfd,
"%s: %s: %s\n",
Prog, lock, strerror (errno));
}
unlink (file); unlink (file);
errno = EINVAL; errno = EINVAL;
return 0; return 0;
@@ -201,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 (shadow_logfd,
"%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 (shadow_logfd,
"%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 (shadow_logfd,
"%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 (shadow_logfd,
"%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 (shadow_logfd,
"%s: %s: lock file already used\n",
Prog, file);
}
} else {
if (log) {
(void) fprintf (shadow_logfd,
"%s: cannot get lock %s: %s\n",
Prog, lock, strerror (errno));
}
} }
unlink (file); unlink (file);
@@ -281,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:
@@ -312,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;
} }
@@ -336,12 +277,8 @@ static int create_backup (const char *backup, FILE * fp)
/* FIXME: unlink the backup file? */ /* FIXME: unlink the backup file? */
return -1; return -1;
} }
if (fsync (fileno (bkfp)) != 0) { if ( (fsync (fileno (bkfp)) != 0)
(void) fclose (bkfp); || (fclose (bkfp) != 0)) {
/* FIXME: unlink the backup file? */
return -1;
}
if (fclose (bkfp) != 0) {
/* FIXME: unlink the backup file? */ /* FIXME: unlink the backup file? */
return -1; return -1;
} }
@@ -378,7 +315,6 @@ static void free_linked_list (struct commonio_db *db)
int commonio_setname (struct commonio_db *db, const char *name) int commonio_setname (struct commonio_db *db, const char *name)
{ {
snprintf (db->filename, sizeof (db->filename), "%s", name); snprintf (db->filename, sizeof (db->filename), "%s", name);
db->setname = true;
return 1; return 1;
} }
@@ -389,79 +325,54 @@ 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 = NULL; char file[1024];
char* lock = NULL; char lock[1024];
size_t lock_file_len;
size_t file_len;
int err = 0;
if (db->locked) { if (db->locked) {
return 1; return 1;
} }
file_len = strlen(db->filename) + 11;/* %lu max size */
lock_file_len = strlen(db->filename) + 6; /* sizeof ".lock" */ snprintf (file, sizeof file, "%s.%lu",
file = (char*)malloc(file_len);
if(file == NULL) {
goto cleanup_ENOMEM;
}
lock = (char*)malloc(lock_file_len);
if(lock == NULL) {
goto cleanup_ENOMEM;
}
snprintf (file, file_len, "%s.%lu",
db->filename, (unsigned long) getpid ()); db->filename, (unsigned long) getpid ());
snprintf (lock, lock_file_len, "%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++;
err = 1; return 1;
} }
cleanup_ENOMEM: return 0;
if(file)
free(file);
if(lock)
free(lock);
return err;
} }
int commonio_lock (struct commonio_db *db) int commonio_lock (struct commonio_db *db)
{ {
int i;
#ifdef HAVE_LCKPWDF #ifdef HAVE_LCKPWDF
/* /*
* Only if the system libc has a real lckpwdf() - the one from * only if the system libc has a real lckpwdf() - the one from
* lockpw.c calls us and would cause infinite recursion! * lockpw.c calls us and would cause infinite recursion!
* It is also not used with the prefix option.
*/ */
if (!db->setname) {
/*
* Call lckpwdf() on the first lock.
* If it succeeds, call *_lock() only once
* (no retries, it should always succeed).
*/
if (0 == lock_count) {
if (lckpwdf () == -1) {
if (geteuid () != 0) {
(void) fprintf (shadow_logfd,
"%s: Permission denied.\n",
Prog);
}
return 0; /* failure */
}
}
if (commonio_lock_nowait (db, true) != 0) { /*
return 1; /* success */ * Call lckpwdf() on the first lock.
* If it succeeds, call *_lock() only once
* (no retries, it should always succeed).
*/
if (0 == lock_count) {
if (lckpwdf () == -1) {
return 0; /* failure */
} }
ulckpwdf ();
return 0; /* failure */
} }
#endif /* !HAVE_LCKPWDF */
if (commonio_lock_nowait (db) != 0) {
return 1; /* success */
}
ulckpwdf ();
return 0; /* failure */
#else
int i;
/* /*
* lckpwdf() not used - do it the old way. * lckpwdf() not used - do it the old way.
@@ -477,17 +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 (shadow_logfd, "%s: Permission denied.\n",
Prog);
return 0; return 0;
} }
} }
return 0; /* failure */ return 0; /* failure */
#endif
} }
static void dec_lock_count (void) static void dec_lock_count (void)
@@ -500,12 +410,11 @@ static void dec_lock_count (void)
if (nscd_need_reload) { if (nscd_need_reload) {
nscd_flush_cache ("passwd"); nscd_flush_cache ("passwd");
nscd_flush_cache ("group"); nscd_flush_cache ("group");
sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP);
nscd_need_reload = false; nscd_need_reload = false;
} }
#ifdef HAVE_LCKPWDF #ifdef HAVE_LCKPWDF
ulckpwdf (); ulckpwdf ();
#endif /* HAVE_LCKPWDF */ #endif
} }
} }
} }
@@ -624,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;
@@ -641,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
@@ -680,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);
@@ -766,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;
@@ -780,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;
@@ -811,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];
@@ -859,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;
@@ -941,11 +805,16 @@ static int write_all (const struct commonio_db *db)
int commonio_close (struct commonio_db *db) int commonio_close (struct commonio_db *db)
/*@requires notnull db->fp@*/
{ {
char buf[1024]; char buf[1024];
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;
@@ -953,10 +822,8 @@ int commonio_close (struct commonio_db *db)
db->isopen = false; db->isopen = false;
if (!db->changed || db->readonly) { if (!db->changed || db->readonly) {
if (NULL != db->fp) { fclose (db->fp);
(void) fclose (db->fp); db->fp = NULL;
db->fp = NULL;
}
goto success; goto success;
} }
@@ -967,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 (db->filename, S_IFREG) != 0) {
errors++;
}
#endif
if (create_backup (buf, db->fp) != 0) { if (create_backup (buf, db->fp) != 0) {
errors++; errors++;
} }
@@ -990,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;
@@ -1002,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 (db->filename, S_IFREG) != 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;
@@ -1032,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++;
} }
@@ -1050,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;
} }
@@ -1092,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);
} }
@@ -1113,8 +983,7 @@ int commonio_update (struct commonio_db *db, const void *eptr)
p = find_entry_by_name (db, db->ops->getname (eptr)); p = find_entry_by_name (db, db->ops->getname (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 (shadow_logfd, _("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);
@@ -1139,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)
{ {
@@ -1218,7 +1055,7 @@ int commonio_remove (struct commonio_db *db, const char *name)
return 0; return 0;
} }
if (next_entry_by_name (db, p->next, name) != NULL) { if (next_entry_by_name (db, p->next, name) != NULL) {
fprintf (shadow_logfd, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), name, db->filename); fprintf (stderr, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), name, db->filename);
return 0; return 0;
} }
+13 -20
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,12 @@
*/ */
/* $Id$ */ /* $Id$ */
#ifndef COMMONIO_H #ifndef _COMMONIO_H
#define COMMONIO_H #define _COMMONIO_H
#ifdef WITH_SELINUX
#include <selinux/selinux.h>
#endif
#include "defines.h" /* bool */ #include "defines.h" /* bool */
@@ -117,19 +121,12 @@ struct commonio_db {
/*@dependent@*/ /*@null@*/FILE *fp; /*@dependent@*/ /*@null@*/FILE *fp;
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
/*@null@*/char *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;
/* /*
@@ -139,29 +136,25 @@ struct commonio_db {
bool isopen:1; bool isopen:1;
bool locked:1; bool locked:1;
bool readonly:1; bool readonly:1;
bool setname:1;
}; };
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
+2 -18
View File
@@ -4,8 +4,6 @@
#ifndef _DEFINES_H_ #ifndef _DEFINES_H_
#define _DEFINES_H_ #define _DEFINES_H_
#include "config.h"
#if HAVE_STDBOOL_H #if HAVE_STDBOOL_H
# include <stdbool.h> # include <stdbool.h>
#else #else
@@ -26,7 +24,7 @@ typedef unsigned char _Bool;
/* Take care of NLS matters. */ /* Take care of NLS matters. */
#ifdef S_SPLINT_S #ifdef S_SPLINT_S
extern char *setlocale(int categories, const char *locale); extern char *setlocale(int categorie, const char *locale);
# define LC_ALL (6) # define LC_ALL (6)
extern char * bindtextdomain (const char * domainname, const char * dirname); extern char * bindtextdomain (const char * domainname, const char * dirname);
extern char * textdomain (const char * domainname); extern char * textdomain (const char * domainname);
@@ -96,14 +94,6 @@ char *strchr (), *strrchr (), *strtok ();
# include <unistd.h> # include <unistd.h>
#endif #endif
/*
* crypt(3), crypt_gensalt(3), and their
* feature test macros may be defined in here.
*/
#if HAVE_CRYPT_H
# include <crypt.h>
#endif
#if TIME_WITH_SYS_TIME #if TIME_WITH_SYS_TIME
# include <sys/time.h> # include <sys/time.h>
# include <time.h> # include <time.h>
@@ -187,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); \
@@ -392,10 +382,4 @@ extern char *strerror ();
# endif # endif
#endif #endif
#ifdef HAVE_SECURE_GETENV
# define shadow_getenv(name) secure_getenv(name)
# else
# define shadow_getenv(name) getenv(name)
#endif
#endif /* _DEFINES_H_ */ #endif /* _DEFINES_H_ */
+12 -17
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,43 +40,38 @@
#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':
method = "MD5"; method = "MD5";
break; break;
case '2':
method = "BCRYPT";
break;
case '5': case '5':
method = "SHA256"; method = "SHA256";
break; break;
case '6': case '6':
method = "SHA512"; method = "SHA512";
break; break;
case 'y':
method = "YESCRYPT";
break;
default: default:
{ {
static char nummethod[4] = "$x$"; static char nummethod[4] = "$x$";
@@ -84,9 +79,9 @@
method = &nummethod[0]; method = &nummethod[0];
} }
} }
(void) fprintf (shadow_logfd, 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);
} }
+42 -186
View File
@@ -40,9 +40,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#ifdef USE_ECONF
#include <libeconf.h>
#endif
#include "getdef.h" #include "getdef.h"
/* /*
* A configuration item definition. * A configuration item definition.
@@ -52,43 +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}, \
{"HMAC_CRYPTO_ALGO", 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},
/*
* Items used in other tools (util-linux, etc.)
*/
#define FOREIGNDEFS \
{"ALWAYS_SET_PATH", NULL}, \
{"ENV_ROOTPATH", NULL}, \
{"LOGIN_KEEP_USERNAME", NULL}, \
{"LOGIN_PLAIN_PROMPT", NULL}, \
{"MOTD_FIRSTONLY", 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},
@@ -104,10 +64,8 @@ static struct itemdef def_table[] = {
{"FAKE_SHELL", NULL}, {"FAKE_SHELL", NULL},
{"GID_MAX", NULL}, {"GID_MAX", NULL},
{"GID_MIN", NULL}, {"GID_MIN", NULL},
{"HOME_MODE", NULL},
{"HUSHLOGIN_FILE", NULL}, {"HUSHLOGIN_FILE", NULL},
{"KILLCHAR", NULL}, {"KILLCHAR", NULL},
{"LASTLOG_UID_MAX", NULL},
{"LOGIN_RETRIES", NULL}, {"LOGIN_RETRIES", NULL},
{"LOGIN_TIMEOUT", NULL}, {"LOGIN_TIMEOUT", NULL},
{"LOG_OK_LOGINS", NULL}, {"LOG_OK_LOGINS", NULL},
@@ -116,7 +74,6 @@ static struct itemdef def_table[] = {
{"MAIL_FILE", NULL}, {"MAIL_FILE", NULL},
{"MAX_MEMBERS_PER_GROUP", NULL}, {"MAX_MEMBERS_PER_GROUP", NULL},
{"MD5_CRYPT_ENAB", NULL}, {"MD5_CRYPT_ENAB", NULL},
{"NONEXISTENT", NULL},
{"PASS_MAX_DAYS", NULL}, {"PASS_MAX_DAYS", NULL},
{"PASS_MIN_DAYS", NULL}, {"PASS_MIN_DAYS", NULL},
{"PASS_WARN_AGE", NULL}, {"PASS_WARN_AGE", NULL},
@@ -124,19 +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
#ifdef USE_BCRYPT
{"BCRYPT_MAX_ROUNDS", NULL},
{"BCRYPT_MIN_ROUNDS", NULL},
#endif
#ifdef USE_YESCRYPT
{"YESCRYPT_COST_FACTOR", NULL},
#endif
{"SUB_GID_COUNT", NULL},
{"SUB_GID_MAX", NULL},
{"SUB_GID_MIN", NULL},
{"SUB_UID_COUNT", NULL},
{"SUB_UID_MAX", NULL},
{"SUB_UID_MIN", NULL},
{"SULOG_FILE", NULL}, {"SULOG_FILE", NULL},
{"SU_NAME", NULL}, {"SU_NAME", NULL},
{"SYS_GID_MAX", NULL}, {"SYS_GID_MAX", NULL},
@@ -152,46 +96,42 @@ 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 #endif
#ifdef WITH_TCB
{"TCB_AUTH_GROUP", NULL},
{"TCB_SYMLINKS", NULL},
{"USE_TCB", NULL},
#endif
{"FORCE_SHADOW", NULL},
{"GRANT_AUX_GROUP_SUBIDS", NULL},
{"PREVENT_NO_AUTH", NULL},
{NULL, NULL} {NULL, NULL}
}; };
#define NUMKNOWNDEFS (sizeof(knowndef_table)/sizeof(knowndef_table[0]))
static struct itemdef knowndef_table[] = {
#ifdef USE_PAM
PAMDEFS
#endif
FOREIGNDEFS
{NULL, NULL}
};
#ifdef USE_ECONF
#ifdef VENDORDIR
static const char* vendordir = VENDORDIR;
#else
static const char* vendordir = NULL;
#endif
static const char* sysconfdir = "/etc";
#else
#ifndef LOGINDEFS #ifndef LOGINDEFS
#define LOGINDEFS "/etc/login.defs" #define LOGINDEFS "/etc/login.defs"
#endif #endif
static const char* def_fname = LOGINDEFS; /* login config defs file */ static char def_fname[] = LOGINDEFS; /* login config defs file */
#endif
static bool def_loaded = false; /* are defs already loaded? */ static bool def_loaded = false; /* are defs already loaded? */
/* local function prototypes */ /* local function prototypes */
@@ -267,7 +207,7 @@ int getdef_num (const char *item, int dflt)
if ( (getlong (d->value, &val) == 0) if ( (getlong (d->value, &val) == 0)
|| (val > INT_MAX) || (val > INT_MAX)
|| (val < INT_MIN)) { || (val < INT_MIN)) {
fprintf (shadow_logfd, fprintf (stderr,
_("configuration error - cannot parse %s value: '%s'"), _("configuration error - cannot parse %s value: '%s'"),
item, d->value); item, d->value);
return dflt; return dflt;
@@ -302,7 +242,7 @@ unsigned int getdef_unum (const char *item, unsigned int dflt)
if ( (getlong (d->value, &val) == 0) if ( (getlong (d->value, &val) == 0)
|| (val < 0) || (val < 0)
|| (val > INT_MAX)) { || (val > INT_MAX)) {
fprintf (shadow_logfd, fprintf (stderr,
_("configuration error - cannot parse %s value: '%s'"), _("configuration error - cannot parse %s value: '%s'"),
item, d->value); item, d->value);
return dflt; return dflt;
@@ -335,7 +275,7 @@ long getdef_long (const char *item, long dflt)
} }
if (getlong (d->value, &val) == 0) { if (getlong (d->value, &val) == 0) {
fprintf (shadow_logfd, fprintf (stderr,
_("configuration error - cannot parse %s value: '%s'"), _("configuration error - cannot parse %s value: '%s'"),
item, d->value); item, d->value);
return dflt; return dflt;
@@ -368,7 +308,7 @@ unsigned long getdef_ulong (const char *item, unsigned long dflt)
if (getulong (d->value, &val) == 0) { if (getulong (d->value, &val) == 0) {
/* FIXME: we should have a getulong */ /* FIXME: we should have a getulong */
fprintf (shadow_logfd, fprintf (stderr,
_("configuration error - cannot parse %s value: '%s'"), _("configuration error - cannot parse %s value: '%s'"),
item, d->value); item, d->value);
return dflt; return dflt;
@@ -406,7 +346,7 @@ int putdef_str (const char *name, const char *value)
cp = strdup (value); cp = strdup (value);
if (NULL == cp) { if (NULL == cp) {
(void) fputs (_("Could not allocate space for config info.\n"), (void) fputs (_("Could not allocate space for config info.\n"),
shadow_logfd); stderr);
SYSLOG ((LOG_ERR, "could not allocate space for config info")); SYSLOG ((LOG_ERR, "could not allocate space for config info"));
return -1; return -1;
} }
@@ -431,6 +371,7 @@ static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name)
{ {
struct itemdef *ptr; struct itemdef *ptr;
/* /*
* Search into the table. * Search into the table.
*/ */
@@ -445,51 +386,13 @@ 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++) { fprintf (stderr,
if (strcmp (ptr->name, name) == 0) {
goto out;
}
}
fprintf (shadow_logfd,
_("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;
} }
/*
* setdef_config_file - set the default configuration file path
*
* must be called prior to any def* calls.
*/
void setdef_config_file (const char* file)
{
#ifdef USE_ECONF
size_t len;
char* cp;
len = strlen(file) + strlen(sysconfdir) + 2;
cp = malloc(len);
if (cp == NULL)
exit (13);
snprintf(cp, len, "%s/%s", file, sysconfdir);
sysconfdir = cp;
#ifdef VENDORDIR
len = strlen(file) + strlen(vendordir) + 2;
cp = malloc(len);
if (cp == NULL)
exit (13);
snprintf(cp, len, "%s/%s", file, vendordir);
vendordir = cp;
#endif
#else
def_fname = file;
#endif
}
/* /*
* def_load - load configuration table * def_load - load configuration table
* *
@@ -498,16 +401,20 @@ void setdef_config_file (const char* file)
static void def_load (void) static void def_load (void)
{ {
#ifdef USE_ECONF
econf_file *defs_file = NULL;
econf_err error;
char **keys;
size_t key_number;
#else
int i; int i;
FILE *fp; FILE *fp;
char buf[1024], *name, *value, *s; char buf[1024], *name, *value, *s;
#endif
/*
* Open the configuration definitions file.
*/
fp = fopen (def_fname, "r");
if (NULL == fp) {
int err = errno;
SYSLOG ((LOG_CRIT, "cannot open login definitions %s [%s]",
def_fname, strerror (err)));
exit (EXIT_FAILURE);
}
/* /*
* Set the initialized flag. * Set the initialized flag.
@@ -515,56 +422,6 @@ static void def_load (void)
*/ */
def_loaded = true; def_loaded = true;
#ifdef USE_ECONF
error = econf_readDirs (&defs_file, vendordir, sysconfdir, "login", "defs", " \t", "#");
if (error) {
if (error == ECONF_NOFILE)
return;
SYSLOG ((LOG_CRIT, "cannot open login definitions [%s]",
econf_errString(error)));
exit (EXIT_FAILURE);
}
if ((error = econf_getKeys(defs_file, NULL, &key_number, &keys))) {
SYSLOG ((LOG_CRIT, "cannot read login definitions [%s]",
econf_errString(error)));
exit (EXIT_FAILURE);
}
for (size_t i = 0; i < key_number; i++) {
char *value;
econf_getStringValue(defs_file, NULL, keys[i], &value);
/*
* Store the value in def_table.
*
* Ignore failures to load the login.defs file.
* The error was already reported to the user and to
* syslog. The tools will just use their default values.
*/
(void)putdef_str (keys[i], value);
}
econf_free (keys);
econf_free (defs_file);
#else
/*
* Open the configuration definitions file.
*/
fp = fopen (def_fname, "r");
if (NULL == fp) {
if (errno == ENOENT)
return;
int err = errno;
SYSLOG ((LOG_CRIT, "cannot open login definitions %s [%s]",
def_fname, strerror (err)));
exit (EXIT_FAILURE);
}
/* /*
* Go through all of the lines in the file. * Go through all of the lines in the file.
*/ */
@@ -614,7 +471,6 @@ static void def_load (void)
} }
(void) fclose (fp); (void) fclose (fp);
#endif
} }
-1
View File
@@ -40,7 +40,6 @@ extern unsigned long getdef_ulong (const char *, unsigned long);
extern unsigned int getdef_unum (const char *, unsigned int); extern unsigned int getdef_unum (const char *, unsigned int);
extern /*@observer@*/ /*@null@*/const char *getdef_str (const char *); extern /*@observer@*/ /*@null@*/const char *getdef_str (const char *);
extern int putdef_str (const char *, const char *); extern int putdef_str (const char *, const char *);
extern void setdef_config_file (const char* file);
/* default UMASK value if not specified in /etc/login.defs */ /* default UMASK value if not specified in /etc/login.defs */
#define GETDEF_DEFAULT_UMASK 022 #define GETDEF_DEFAULT_UMASK 022
+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;
} }
+11 -51
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,17 +113,13 @@ 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 */
false, /* changed */ false, /* changed */
false, /* isopen */ false, /* isopen */
false, /* locked */ false, /* locked */
false, /* readonly */ false /* readonly */
false /* setname */
}; };
int gr_setdbname (const char *filename) int gr_setdbname (const char *filename)
@@ -334,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++);
@@ -356,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;
@@ -365,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;
@@ -404,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) {
@@ -434,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 -59
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;
} }
} }
@@ -87,55 +75,15 @@
return gr; return gr;
} }
void gr_free_members (struct group *grent)
{
if (NULL != grent->gr_mem) {
size_t i;
for (i = 0; NULL != grent->gr_mem[i]; i++) {
free (grent->gr_mem[i]);
}
free (grent->gr_mem);
grent->gr_mem = NULL;
}
}
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));
grent->gr_mem++;
} }
gr_free_members(grent);
free (grent); free (grent);
} }
bool gr_append_member(struct group *grp, char *member)
{
int i;
if (NULL == grp->gr_mem || grp->gr_mem[0] == NULL) {
grp->gr_mem = (char **)malloc(2 * sizeof(char *));
if (!grp->gr_mem) {
return false;
}
grp->gr_mem[0] = strdup(member);
if (!grp->gr_mem[0]) {
return false;
}
grp->gr_mem[1] = NULL;
return true;
}
for (i = 0; grp->gr_mem[i]; i++) ;
grp->gr_mem = realloc(grp->gr_mem, (i + 2) * sizeof(char *));
if (NULL == grp->gr_mem) {
return false;
}
grp->gr_mem[i] = strdup(member);
if (NULL == grp->gr_mem[i]) {
return false;
}
grp->gr_mem[i + 1] = NULL;
return true;
}
+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 (shadow_logfd, _(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 (shadow_logfd, 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 (shadow_logfd, _("%s: nscd exited with status %d\n"),
Prog, code);
(void) fprintf (shadow_logfd, _(MSG_NSCD_FLUSH_CACHE_FAILED), Prog);
return -1; return -1;
} }
-149
View File
@@ -1,149 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <stdbool.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <stdatomic.h>
#include "prototypes.h"
#include "../libsubid/subid.h"
#define NSSWITCH "/etc/nsswitch.conf"
// NSS plugin handling for subids
// If nsswitch has a line like
// subid: sssd
// then sssd will be consulted for subids. Unlike normal NSS dbs,
// only one db is supported at a time. That's open to debate, but
// the subids are a pretty limited resource, and local files seem
// bound to step on any other allocations leading to insecure
// conditions.
static atomic_flag nss_init_started;
static atomic_bool nss_init_completed;
static struct subid_nss_ops *subid_nss;
bool nss_is_initialized() {
return atomic_load(&nss_init_completed);
}
void nss_exit() {
if (nss_is_initialized() && subid_nss) {
dlclose(subid_nss->handle);
free(subid_nss);
subid_nss = NULL;
}
}
// nsswitch_path is an argument only to support testing.
void nss_init(char *nsswitch_path) {
FILE *nssfp = NULL;
char *line = NULL, *p, *token, *saveptr;
size_t len = 0;
if (atomic_flag_test_and_set(&nss_init_started)) {
// Another thread has started nss_init, wait for it to complete
while (!atomic_load(&nss_init_completed))
usleep(100);
return;
}
if (!nsswitch_path)
nsswitch_path = NSSWITCH;
// read nsswitch.conf to check for a line like:
// subid: files
nssfp = fopen(nsswitch_path, "r");
if (!nssfp) {
fprintf(shadow_logfd, "Failed opening %s: %m", nsswitch_path);
atomic_store(&nss_init_completed, true);
return;
}
while ((getline(&line, &len, nssfp)) != -1) {
if (line[0] == '\0' || line[0] == '#')
continue;
if (strlen(line) < 8)
continue;
if (strncasecmp(line, "subid:", 6) != 0)
continue;
p = &line[6];
while ((*p) && isspace(*p))
p++;
if (!*p)
continue;
for (token = strtok_r(p, " \n\t", &saveptr);
token;
token = strtok_r(NULL, " \n\t", &saveptr)) {
char libname[65];
void *h;
if (strcmp(token, "files") == 0) {
subid_nss = NULL;
goto done;
}
if (strlen(token) > 50) {
fprintf(shadow_logfd, "Subid NSS module name too long (longer than 50 characters): %s\n", token);
fprintf(shadow_logfd, "Using files\n");
subid_nss = NULL;
goto done;
}
snprintf(libname, 64, "libsubid_%s.so", token);
h = dlopen(libname, RTLD_LAZY);
if (!h) {
fprintf(shadow_logfd, "Error opening %s: %s\n", libname, dlerror());
fprintf(shadow_logfd, "Using files\n");
subid_nss = NULL;
goto done;
}
subid_nss = malloc(sizeof(*subid_nss));
if (!subid_nss) {
dlclose(h);
goto done;
}
subid_nss->has_range = dlsym(h, "shadow_subid_has_range");
if (!subid_nss->has_range) {
fprintf(shadow_logfd, "%s did not provide @has_range@\n", libname);
dlclose(h);
free(subid_nss);
subid_nss = NULL;
goto done;
}
subid_nss->list_owner_ranges = dlsym(h, "shadow_subid_list_owner_ranges");
if (!subid_nss->list_owner_ranges) {
fprintf(shadow_logfd, "%s did not provide @list_owner_ranges@\n", libname);
dlclose(h);
free(subid_nss);
subid_nss = NULL;
goto done;
}
subid_nss->find_subid_owners = dlsym(h, "shadow_subid_find_subid_owners");
if (!subid_nss->find_subid_owners) {
fprintf(shadow_logfd, "%s did not provide @find_subid_owners@\n", libname);
dlclose(h);
free(subid_nss);
subid_nss = NULL;
goto done;
}
subid_nss->handle = h;
goto done;
}
fprintf(shadow_logfd, "No usable subid NSS module found, using files\n");
// subid_nss has to be null here, but to ease reviews:
free(subid_nss);
subid_nss = NULL;
goto done;
}
done:
atomic_store(&nss_init_completed, true);
free(line);
if (nssfp) {
atexit(nss_exit);
fclose(nssfp);
}
}
struct subid_nss_ops *get_subid_nss_handle() {
nss_init(NULL);
return subid_nss;
}
+32 -150
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,8 +57,7 @@
#include "defines.h" #include "defines.h"
#include "commonio.h" #include "commonio.h"
extern /*@observer@*/ const char *Prog; /* Program name showed in error messages */ extern char *Prog;
extern FILE *shadow_logfd; /* file descripter to which error messages are printed */
/* addgrps.c */ /* addgrps.c */
#if defined (HAVE_SETGROUPS) && ! defined (USE_PAM) #if defined (HAVE_SETGROUPS) && ! defined (USE_PAM)
@@ -73,37 +70,27 @@ extern int expire (const struct passwd *, /*@null@*/const struct spwd *);
/* isexpired.c */ /* isexpired.c */
extern int isexpired (const struct passwd *, /*@null@*/const struct spwd *); extern int isexpired (const struct passwd *, /*@null@*/const struct spwd *);
/* btrfs.c */
#ifdef WITH_BTRFS
extern int btrfs_create_subvolume(const char *path);
extern int btrfs_remove_subvolume(const char *path);
extern int btrfs_is_subvolume(const char *path);
extern int is_btrfs(const char *path);
#endif
/* 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);
@@ -129,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 *);
@@ -160,20 +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 (gid_t *range_start, unsigned long *range_count);
/* find_new_sub_uids.c */
extern int find_new_sub_uids (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);
@@ -186,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);
@@ -207,9 +184,7 @@ extern void __gr_set_changed (void);
/* groupmem.c */ /* groupmem.c */
extern /*@null@*/ /*@only@*/struct group *__gr_dup (const struct group *grent); extern /*@null@*/ /*@only@*/struct group *__gr_dup (const struct group *grent);
extern void gr_free_members (struct group *grent);
extern void gr_free (/*@out@*/ /*@only@*/struct group *grent); extern void gr_free (/*@out@*/ /*@only@*/struct group *grent);
extern bool gr_append_member (struct group *grp, char *member);
/* hushed.c */ /* hushed.c */
extern bool hushed (const char *username); extern bool hushed (const char *username);
@@ -261,74 +236,18 @@ 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);
/* nss.c */ /* pam_pass_non_interractive.c */
#include <libsubid/subid.h>
extern void nss_init(char *nsswitch_path);
extern bool nss_is_initialized();
struct subid_nss_ops {
/*
* nss_has_range: does a user own a given subid range
*
* @owner: username
* @start: first subid in queried range
* @count: number of subids in queried range
* @idtype: subuid or subgid
* @result: true if @owner has been allocated the subid range.
*
* returns success if the module was able to determine an answer (true or false),
* else an error status.
*/
enum subid_status (*has_range)(const char *owner, unsigned long start, unsigned long count, enum subid_type idtype, bool *result);
/*
* nss_list_owner_ranges: list the subid ranges delegated to a user.
*
* @owner - string representing username being queried
* @id_type - subuid or subgid
* @ranges - pointer to an array of struct subid_range, or NULL. The
* returned array must be freed by the caller.
* @count - pointer to an integer into which the number of returned ranges
* is written.
* returns success if the module was able to determine an answer,
* else an error status.
*/
enum subid_status (*list_owner_ranges)(const char *owner, enum subid_type id_type, struct subid_range **ranges, int *count);
/*
* nss_find_subid_owners: find uids who own a given subuid or subgid.
*
* @id - the delegated id (subuid or subgid) being queried
* @id_type - subuid or subgid
* @uids - pointer to an array of uids which will be allocated by
* nss_find_subid_owners()
* @count - number of uids found
*
* returns success if the module was able to determine an answer,
* else an error status.
*/
enum subid_status (*find_subid_owners)(unsigned long id, enum subid_type id_type, uid_t **uids, int *count);
/* The dlsym handle to close */
void *handle;
};
extern struct subid_nss_ops *get_subid_nss_handle();
/* pam_pass_non_interactive.c */
#ifdef USE_PAM #ifdef USE_PAM
extern int do_pam_passwd_non_interactive (const char *pam_service, extern int do_pam_passwd_non_interractive (const char *pam_service,
const char *username, const char *username,
const char* password); const char* password);
#endif /* USE_PAM */ #endif /* USE_PAM */
/* 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 */
@@ -339,21 +258,6 @@ extern void do_pam_passwd (const char *user, bool silent, bool change_expired);
/* port.c */ /* port.c */
extern bool isttytime (const char *, const char *, time_t); extern bool isttytime (const char *, const char *, time_t);
/* prefix_flag.c */
extern const char* process_prefix_flag (const char* short_opt, int argc, char **argv);
extern struct group *prefix_getgrnam(const char *name);
extern struct group *prefix_getgrgid(gid_t gid);
extern struct passwd *prefix_getpwuid(uid_t uid);
extern struct passwd *prefix_getpwnam(const char* name);
extern struct spwd *prefix_getspnam(const char* name);
extern struct group *prefix_getgr_nam_gid(const char *grname);
extern void prefix_setpwent();
extern struct passwd* prefix_getpwent();
extern void prefix_endpwent();
extern void prefix_setgrent();
extern struct group* prefix_getgrent();
extern void prefix_endgrent();
/* pwd2spwd.c */ /* pwd2spwd.c */
#ifndef USE_PAM #ifndef USE_PAM
extern struct spwd *pwd_to_spwd (const struct passwd *); extern struct spwd *pwd_to_spwd (const struct passwd *);
@@ -376,31 +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, mode_t mode);
extern int reset_selinux_file_context (void);
extern int check_selinux_permit (const char *perm_name);
#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);
@@ -446,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,
@@ -472,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 */
@@ -482,19 +367,17 @@ extern int set_filesize_limit (int blocks);
extern int user_busy (const char *name, uid_t uid); extern int user_busy (const char *name, uid_t uid);
/* utmp.c */ /* utmp.c */
#ifndef USE_UTMPX
extern /*@null@*/struct utmp *get_current_utmp (void); extern /*@null@*/struct utmp *get_current_utmp (void);
extern struct utmp *prepare_utmp (const char *name, extern struct utmp *prepare_utmp (const char *name,
const char *line, const char *line,
const char *host, const char *host,
/*@null@*/const struct utmp *ut); /*@null@*/const struct utmp *ut);
extern int setutmp (struct utmp *ut); extern int setutmp (struct utmp *ut);
#else #ifdef USE_UTMPX
extern /*@null@*/struct utmpx *get_current_utmp (void);
extern struct utmpx *prepare_utmpx (const char *name, extern struct utmpx *prepare_utmpx (const char *name,
const char *line, const char *line,
const char *host, const char *host,
/*@null@*/const struct utmpx *ut); /*@null@*/const struct utmp *ut);
extern int setutmpx (struct utmpx *utx); extern int setutmpx (struct utmpx *utx);
#endif /* USE_UTMPX */ #endif /* USE_UTMPX */
@@ -502,10 +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 *);
extern void xfree(void *ap);
/* 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
/* /*
+1 -16
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,17 +94,13 @@ 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 */
false, /* changed */ false, /* changed */
false, /* isopen */ false, /* isopen */
false, /* locked */ false, /* locked */
false, /* readonly */ false /* readonly */
false /* setname */
}; };
int pw_setdbname (const char *filename) int pw_setdbname (const char *filename)
+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);
-102
View File
@@ -1,102 +0,0 @@
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <lib/prototypes.h>
int run_part (char *script_path, char *name, char *action)
{
int pid;
int wait_status;
int pid_status;
char *args[] = { script_path, NULL };
pid=fork();
if (pid==-1){
perror ("Could not fork");
return 1;
}
if (pid==0) {
setenv ("ACTION",action,1);
setenv ("SUBJECT",name,1);
execv (script_path,args);
perror ("execv");
exit(1);
}
pid_status = wait (&wait_status);
if (pid_status == pid) {
return (wait_status);
}
perror ("waitpid");
return (1);
}
int run_parts (char *directory, char *name, char *action)
{
struct dirent **namelist;
int scanlist;
int n;
int execute_result;
scanlist = scandir (directory, &namelist, 0, alphasort);
if (scanlist<0) {
return (0);
}
for (n=0; n<scanlist; n++) {
int path_length;
struct stat sb;
path_length=strlen(directory) + strlen(namelist[n]->d_name) + 2;
char *s = (char*)malloc(path_length);
if (!s) {
printf ("could not allocate memory\n");
for (; n<scanlist; n++) {
free (namelist[n]);
}
free (namelist);
return (1);
}
snprintf (s, path_length, "%s/%s", directory, namelist[n]->d_name);
execute_result = 0;
if (stat (s, &sb) == -1) {
perror ("stat");
free (s);
for (; n<scanlist; n++) {
free (namelist[n]);
}
free (namelist);
return (1);
}
if (S_ISREG (sb.st_mode) || S_ISLNK (sb.st_mode)) {
execute_result = run_part (s, name, action);
}
free (s);
if (execute_result!=0) {
fprintf (shadow_logfd,
"%s: did not exit cleanly.\n",
namelist[n]->d_name);
for (; n<scanlist; n++) {
free (namelist[n]);
}
break;
}
free (namelist[n]);
}
free (namelist);
return (execute_result);
}
-2
View File
@@ -1,2 +0,0 @@
int run_part (char *script_path, char *name, char *action);
int run_parts (char *directory, char *name, char *action);
-226
View File
@@ -1,226 +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 <stdio.h>
#include "defines.h"
#include <selinux/selinux.h>
#include <selinux/label.h>
#include "prototypes.h"
static bool selinux_checked = false;
static bool selinux_enabled;
static /*@null@*/struct selabel_handle *selabel_hnd = NULL;
static void cleanup(void)
{
if (selabel_hnd) {
selabel_close(selabel_hnd);
selabel_hnd = NULL;
}
}
/*
* 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, mode_t mode)
{
if (!selinux_checked) {
selinux_enabled = is_selinux_enabled () > 0;
selinux_checked = true;
}
if (selinux_enabled) {
/* Get the default security context for this file */
/*@null@*/char *fcontext_raw = NULL;
int r;
if (selabel_hnd == NULL) {
selabel_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
if (selabel_hnd == NULL) {
return security_getenforce () != 0;
}
(void) atexit(cleanup);
}
r = selabel_lookup_raw(selabel_hnd, &fcontext_raw, dst_name, mode);
if (r < 0) {
/* No context specified for the searched path */
if (errno == ENOENT) {
return 0;
}
return security_getenforce () != 0;
}
/* Set the security context for the next created file */
r = setfscreatecon_raw (fcontext_raw);
freecon (fcontext_raw);
if (r < 0) {
return security_getenforce () != 0;
}
}
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_raw (NULL) != 0) {
return security_getenforce () != 0;
}
}
return 0;
}
/*
* Log callback for libselinux internal error reporting.
*/
__attribute__((__format__ (printf, 2, 3)))
static int selinux_log_cb (int type, const char *fmt, ...) {
va_list ap;
char *buf;
int r;
#ifdef WITH_AUDIT
static int selinux_audit_fd = -2;
#endif
va_start (ap, fmt);
r = vasprintf (&buf, fmt, ap);
va_end (ap);
if (r < 0) {
return 0;
}
#ifdef WITH_AUDIT
if (-2 == selinux_audit_fd) {
selinux_audit_fd = audit_open ();
if (-1 == selinux_audit_fd) {
/* You get these only when the kernel doesn't have
* audit compiled in. */
if ( (errno != EINVAL)
&& (errno != EPROTONOSUPPORT)
&& (errno != EAFNOSUPPORT)) {
(void) fputs (_("Cannot open audit interface.\n"),
shadow_logfd);
SYSLOG ((LOG_WARN, "Cannot open audit interface."));
}
}
}
if (-1 != selinux_audit_fd) {
if (SELINUX_AVC == type) {
if (audit_log_user_avc_message (selinux_audit_fd,
AUDIT_USER_AVC, buf, NULL, NULL,
NULL, 0) > 0) {
goto skip_syslog;
}
} else if (SELINUX_ERROR == type) {
if (audit_log_user_avc_message (selinux_audit_fd,
AUDIT_USER_SELINUX_ERR, buf, NULL, NULL,
NULL, 0) > 0) {
goto skip_syslog;
}
}
}
#endif
SYSLOG ((LOG_WARN, "libselinux: %s", buf));
skip_syslog:
free (buf);
return 0;
}
/*
* check_selinux_permit - Check whether SELinux grants the given
* operation
*
* Parameter is the SELinux permission name, e.g. rootok
*
* Returns 0 when permission is granted
* or something failed but running in
* permissive mode
*/
int check_selinux_permit (const char *perm_name)
{
char *user_context_raw;
int r;
if (0 == is_selinux_enabled ()) {
return 0;
}
selinux_set_callback (SELINUX_CB_LOG, (union selinux_callback) selinux_log_cb);
if (getprevcon_raw (&user_context_raw) != 0) {
fprintf (shadow_logfd,
_("%s: can not get previous SELinux process context: %s\n"),
Prog, strerror (errno));
SYSLOG ((LOG_WARN,
"can not get previous SELinux process context: %s",
strerror (errno)));
return (security_getenforce () != 0);
}
r = selinux_check_access (user_context_raw, user_context_raw, "passwd", perm_name, NULL);
freecon (user_context_raw);
return r;
}
#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 (shadow_logfd, _("[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 (shadow_logfd,
_("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 (shadow_logfd, _("SELinux policy not managed\n"));
goto fail;
}
ret = semanage_access_check (handle);
if (ret < SEMANAGE_CAN_READ) {
fprintf (shadow_logfd, _("Cannot read SELinux policy store\n"));
goto fail;
}
ret = semanage_connect (handle);
if (ret != 0) {
fprintf (shadow_logfd,
_("Cannot establish SELinux management connection\n"));
goto fail;
}
ret = semanage_begin_transaction (handle);
if (ret != 0) {
fprintf (shadow_logfd, _("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 (shadow_logfd,
_("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 (shadow_logfd,
_("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 (shadow_logfd,
_("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 (shadow_logfd,
_("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 (shadow_logfd,
_("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 (shadow_logfd, _("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 (shadow_logfd,
_("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 (shadow_logfd,
_("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 (shadow_logfd,
_("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 (shadow_logfd, _("Cannot init SELinux management\n"));
ret = 1;
goto done;
}
ret = semanage_seuser_key_create (handle, login_name, &key);
if (ret != 0) {
fprintf (shadow_logfd, _("Cannot create SELinux user key\n"));
ret = 1;
goto done;
}
ret = semanage_seuser_exists (handle, key, &seuser_exists);
if (ret < 0) {
fprintf (shadow_logfd, _("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 (shadow_logfd,
_("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 (shadow_logfd,
_("Cannot add SELinux user mapping\n"));
ret = 1;
goto done;
}
}
ret = semanage_commit (handle);
if (ret < 0) {
fprintf (shadow_logfd, _("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 (shadow_logfd, _("Cannot init SELinux management\n"));
ret = 1;
goto done;
}
ret = semanage_seuser_key_create (handle, login_name, &key);
if (ret != 0) {
fprintf (shadow_logfd, _("Cannot create SELinux user key\n"));
ret = 1;
goto done;
}
ret = semanage_seuser_exists (handle, key, &exists);
if (ret < 0) {
fprintf (shadow_logfd, _("Cannot verify the SELinux user\n"));
ret = 1;
goto done;
}
if (0 == exists) {
fprintf (shadow_logfd,
_("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 (shadow_logfd, _("Cannot verify the SELinux user\n"));
ret = 1;
goto done;
}
if (0 == exists) {
fprintf (shadow_logfd,
_("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 (shadow_logfd,
_("Could not delete login mapping for %s"),
login_name);
ret = 1;
goto done;
}
ret = semanage_commit (handle);
if (ret < 0) {
fprintf (shadow_logfd, _("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 */
+1 -1
View File
@@ -136,7 +136,7 @@ struct group *sgetgrent (const char *buf)
cp++; cp++;
} }
} }
if (i < (NFIELDS - 1) || *grpfields[2] == '\0' || cp != NULL) { if (i < (NFIELDS - 1) || *grpfields[2] == '\0') {
return (struct group *) 0; return (struct group *) 0;
} }
grent.gr_name = grpfields[0]; grent.gr_name = grpfields[0];
-5
View File
@@ -90,11 +90,6 @@ struct passwd *sgetpwent (const char *buf)
} }
} }
/* something at the end, columns over shot */
if( cp != NULL ) {
return( NULL );
}
/* /*
* There must be exactly NFIELDS colon separated fields or * There must be exactly NFIELDS colon separated fields or
* the entry is invalid. Also, the UID and GID must be non-blank. * the entry is invalid. Also, the UID and GID must be non-blank.
+1
View File
@@ -52,6 +52,7 @@ struct spwd *sgetspent (const char *string)
static struct spwd spwd; static struct spwd spwd;
char *fields[FIELDS]; char *fields[FIELDS];
char *cp; char *cp;
char *cpp;
int i; int i;
/* /*
+11 -57
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,17 +189,13 @@ 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 */
false, /* changed */ false, /* changed */
false, /* isopen */ false, /* isopen */
false, /* locked */ false, /* locked */
false, /* readonly */ false /* readonly */
false /* setname */
}; };
int sgr_setdbname (const char *filename) int sgr_setdbname (const char *filename)
@@ -254,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);
+30 -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;
} }
@@ -130,6 +127,7 @@ static struct spwd *my_sgetspent (const char *string)
static struct spwd spwd; static struct spwd spwd;
char *fields[FIELDS]; char *fields[FIELDS];
char *cp; char *cp;
char *cpp;
int i; int i;
/* /*
@@ -174,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];
@@ -214,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;
} }
@@ -268,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;
} }
@@ -290,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;
} }
@@ -312,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;
} }
@@ -335,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;
} }
@@ -388,10 +375,10 @@ struct spwd *getspent (void)
#ifdef USE_NIS #ifdef USE_NIS
int nis_1_user = 0; int nis_1_user = 0;
struct spwd *val; struct spwd *val;
char buf[BUFSIZ];
#endif #endif
if (NULL == shadow) { if (!shadow)
setspent (); setspent ();
}
#ifdef USE_NIS #ifdef USE_NIS
again: again:
@@ -445,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;
@@ -453,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;
} }
@@ -482,8 +469,9 @@ struct spwd *getspnam (const char *name)
struct spwd *sp; struct spwd *sp;
#ifdef USE_NIS #ifdef USE_NIS
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 ();
@@ -493,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);
@@ -517,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
@@ -531,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);
+6 -94
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,18 +93,14 @@ 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 */
false, /* changed */ false, /* changed */
false, /* isopen */ false, /* isopen */
false, /* locked */ false, /* locked */
false, /* readonly */ false /* readonly */
false /* setname */
}; };
int spw_setdbname (const char *filename) int spw_setdbname (const char *filename)
@@ -130,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)
@@ -205,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)
@@ -259,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);
} }
-84
View File
@@ -1,84 +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 (shadow_logfd);
pid = fork ();
if (0 == pid) {
(void) execve (cmd, (char * const *) argv,
(char * const *) envp);
if (ENOENT == errno) {
exit (E_CMD_NOTFOUND);
}
fprintf (shadow_logfd, "%s: cannot execute %s: %s\n",
Prog, cmd, strerror (errno));
exit (E_CMD_NOEXEC);
} else if ((pid_t)-1 == pid) {
fprintf (shadow_logfd, "%s: cannot execute %s: %s\n",
Prog, cmd, strerror (errno));
return -1;
}
do {
wpid = waitpid (pid, status, 0);
if ((pid_t)-1 == wpid && errno == ECHILD)
break;
} while ( ((pid_t)-1 == wpid && errno == EINTR)
|| ((pid_t)-1 != wpid && wpid != pid));
if ((pid_t)-1 == wpid) {
fprintf (shadow_logfd, "%s: waitpid (status: %d): %s\n",
Prog, *status, strerror (errno));
return -1;
}
return 0;
}
-73
View File
@@ -1,73 +0,0 @@
/* Author: Peter Vrabec <pvrabec@redhat.com> */
#include <config.h>
#ifdef USE_SSSD
#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
#include "exitcodes.h"
#include "defines.h"
#include "prototypes.h"
#include "sssd.h"
#define MSG_SSSD_FLUSH_CACHE_FAILED "%s: Failed to flush the sssd cache."
int sssd_flush_cache (int dbflags)
{
int status, code, rv;
const char *cmd = "/usr/sbin/sss_cache";
char *sss_cache_args = NULL;
const char *spawnedArgs[] = {"sss_cache", NULL, NULL};
const char *spawnedEnv[] = {NULL};
int i = 0;
sss_cache_args = malloc(4);
if (sss_cache_args == NULL) {
return -1;
}
sss_cache_args[i++] = '-';
if (dbflags & SSSD_DB_PASSWD) {
sss_cache_args[i++] = 'U';
}
if (dbflags & SSSD_DB_GROUP) {
sss_cache_args[i++] = 'G';
}
sss_cache_args[i++] = '\0';
if (i == 2) {
/* Neither passwd nor group, nothing to do */
free(sss_cache_args);
return 0;
}
spawnedArgs[1] = sss_cache_args;
rv = run_command (cmd, spawnedArgs, spawnedEnv, &status);
free(sss_cache_args);
if (rv != 0) {
/* run_command writes its own more detailed message. */
SYSLOG ((LOG_WARN, MSG_SSSD_FLUSH_CACHE_FAILED, Prog));
return -1;
}
code = WEXITSTATUS (status);
if (!WIFEXITED (status)) {
SYSLOG ((LOG_WARN, "%s: sss_cache did not terminate normally (signal %d)",
Prog, WTERMSIG (status)));
return -1;
} else if (code == E_CMD_NOTFOUND) {
/* sss_cache is not installed, or it is installed but uses an
interpreter that is missing. Probably the former. */
return 0;
} else if (code != 0) {
SYSLOG ((LOG_WARN, "%s: sss_cache exited with status %d", Prog, code));
SYSLOG ((LOG_WARN, MSG_SSSD_FLUSH_CACHE_FAILED, Prog));
return -1;
}
return 0;
}
#else /* USE_SSSD */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* USE_SSSD */
-17
View File
@@ -1,17 +0,0 @@
#ifndef _SSSD_H_
#define _SSSD_H_
#define SSSD_DB_PASSWD 0x001
#define SSSD_DB_GROUP 0x002
/*
* sssd_flush_cache - flush specified service buffer in sssd cache
*/
#ifdef USE_SSSD
extern int sssd_flush_cache (int dbflags);
#else
#define sssd_flush_cache(service) (0)
#endif
#endif
-1052
View File
File diff suppressed because it is too large Load Diff
-48
View File
@@ -1,48 +0,0 @@
/*
* Copyright (c) 2012- Eric W. Biederman
*/
#ifndef _SUBORDINATEIO_H
#define _SUBORDINATEIO_H
#include <config.h>
#ifdef ENABLE_SUBIDS
#include <sys/types.h>
#include "../libsubid/subid.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 local_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 list_owner_ranges(const char *owner, enum subid_type id_type, struct subid_range **ranges);
extern bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, bool reuse);
extern bool release_subid_range(struct subordinate_range *range, enum subid_type id_type);
extern int find_subid_owners(unsigned long id, enum subid_type id_type, uid_t **uids);
extern void free_subordinate_ranges(struct subordinate_range **ranges, int 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 local_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 (shadow_logfd, _("%s: out of memory\n"), Prog); \
(void) fflush (shadow_logfd); \
} 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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%s: Cannot create directory %s: %s\n"),
Prog, dir, strerror (errno));
goto out_free_dir;
}
if (chown (dir, 0, st.st_gid) != 0) {
fprintf (shadow_logfd,
_("%s: Cannot change owner of %s: %s\n"),
Prog, dir, strerror (errno));
goto out_free_dir;
}
if (chmod (dir, 0711) != 0) {
fprintf (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%s: Cannot stat %s: %s\n"),
Prog, tcbdir, strerror (errno));
goto out_free;
}
if (chown (tcbdir, 0, 0) != 0) {
fprintf (shadow_logfd,
_("%s: Cannot change owners of %s: %s\n"),
Prog, tcbdir, strerror (errno));
goto out_free;
}
if (chmod (tcbdir, 0700) != 0) {
fprintf (shadow_logfd,
_("%s: Cannot change mode of %s: %s\n"),
Prog, tcbdir, strerror (errno));
goto out_free;
}
if (lstat (shadow, &filemode) != 0) {
if (errno != ENOENT) {
fprintf (shadow_logfd,
_("%s: Cannot lstat %s: %s\n"),
Prog, shadow, strerror (errno));
goto out_free;
}
fprintf (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%s: Cannot change owner of %s: %s\n"),
Prog, shadow, strerror (errno));
goto out_free;
}
if (chmod (shadow, filemode.st_mode & 07777) != 0) {
fprintf (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%s: Cannot open %s: %s\n"),
Prog, shadow, strerror (errno));
goto out_free;
}
close (fd);
if (chown (shadow, 0, authgid) != 0) {
fprintf (shadow_logfd,
_("%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 (shadow_logfd,
_("%s: Cannot change mode of %s: %s\n"),
Prog, shadow, strerror (errno));
goto out_free;
}
if (chown (dir, 0, authgid) != 0) {
fprintf (shadow_logfd,
_("%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 (shadow_logfd,
_("%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
+6 -17
View File
@@ -1,11 +1,11 @@
EXTRA_DIST = .indent.pro xgetXXbyYY.c EXTRA_DIST = .indent.pro xgetXXbyYY.c
AM_CPPFLAGS = -I$(top_srcdir)/lib $(ECONF_CPPFLAGS) INCLUDES = -I$(top_srcdir)/lib
noinst_LTLIBRARIES = libmisc.la noinst_LIBRARIES = libmisc.a
libmisc_la_SOURCES = \ libmisc_a_SOURCES = \
addgrps.c \ addgrps.c \
age.c \ age.c \
audit_help.c \ audit_help.c \
@@ -23,18 +23,14 @@ libmisc_la_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 \
@@ -44,18 +40,16 @@ libmisc_la_SOURCES = \
myname.c \ myname.c \
obscure.c \ obscure.c \
pam_pass.c \ pam_pass.c \
pam_pass_non_interactive.c \ pam_pass_non_interractive.c \
prefix_flag.c \
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 \
@@ -72,8 +66,3 @@ libmisc_la_SOURCES = \
xgetspnam.c \ xgetspnam.c \
xmalloc.c \ xmalloc.c \
yesno.c yesno.c
if WITH_BTRFS
libmisc_la_SOURCES += btrfs.c
endif
+4 -12
View File
@@ -57,7 +57,6 @@ int add_groups (const char *list)
bool added; bool added;
char *token; char *token;
char buf[1024]; char buf[1024];
int ret;
if (strlen (list) >= sizeof (buf)) { if (strlen (list) >= sizeof (buf)) {
errno = EINVAL; errno = EINVAL;
@@ -72,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 */
@@ -94,7 +89,7 @@ int add_groups (const char *list)
grp = getgrnam (token); /* local, no need for xgetgrnam */ grp = getgrnam (token); /* local, no need for xgetgrnam */
if (NULL == grp) { if (NULL == grp) {
fprintf (shadow_logfd, _("Warning: unknown group %s\n"), fprintf (stderr, _("Warning: unknown group %s\n"),
token); token);
continue; continue;
} }
@@ -106,7 +101,7 @@ int add_groups (const char *list)
} }
if (ngroups >= sysconf (_SC_NGROUPS_MAX)) { if (ngroups >= sysconf (_SC_NGROUPS_MAX)) {
fputs (_("Warning: too many groups\n"), shadow_logfd); fputs (_("Warning: too many groups\n"), stderr);
break; break;
} }
tmp = (gid_t *) realloc (grouplist, (size_t)(ngroups + 1) * sizeof (GETGROUPS_T)); tmp = (gid_t *) realloc (grouplist, (size_t)(ngroups + 1) * sizeof (GETGROUPS_T));
@@ -121,12 +116,9 @@ int add_groups (const char *list)
} }
if (added) { if (added) {
ret = setgroups ((size_t)ngroups, grouplist); return setgroups ((size_t)ngroups, grouplist);
free (grouplist);
return ret;
} }
free (grouplist);
return 0; return 0;
} }
#else /* HAVE_SETGROUPS && !USE_PAM */ #else /* HAVE_SETGROUPS && !USE_PAM */
+3 -3
View File
@@ -59,7 +59,7 @@ void audit_help_open (void)
return; return;
} }
(void) fputs (_("Cannot open audit interface - aborting.\n"), (void) fputs (_("Cannot open audit interface - aborting.\n"),
shadow_logfd); stderr);
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} }
} }
@@ -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;
} }
-110
View File
@@ -1,110 +0,0 @@
#include <linux/btrfs_tree.h>
#include <linux/magic.h>
#include <sys/statfs.h>
#include <stdbool.h>
#include "prototypes.h"
static bool path_exists(const char *p)
{
struct stat sb;
return stat(p, &sb) == 0;
}
static const char *btrfs_cmd(void)
{
const char *btrfs_paths[] = {"/sbin/btrfs",
"/bin/btrfs", "/usr/sbin/btrfs", "/usr/bin/btrfs", NULL};
const char *p;
int i;
for (i = 0, p = btrfs_paths[i]; p; i++, p = btrfs_paths[i])
if (path_exists(p))
return p;
return NULL;
}
static int run_btrfs_subvolume_cmd(const char *subcmd, const char *arg1, const char *arg2)
{
int status = 0;
const char *cmd = btrfs_cmd();
const char *argv[] = {
"btrfs",
"subvolume",
subcmd,
arg1,
arg2,
NULL
};
if (access(cmd, X_OK)) {
return 1;
}
if (run_command(cmd, argv, NULL, &status))
return -1;
return status;
}
int btrfs_create_subvolume(const char *path)
{
return run_btrfs_subvolume_cmd("create", path, NULL);
}
int btrfs_remove_subvolume(const char *path)
{
return run_btrfs_subvolume_cmd("delete", "-C", path);
}
/* Adapted from btrfsprogs */
/*
* This intentionally duplicates btrfs_util_is_subvolume_fd() instead of opening
* a file descriptor and calling it, because fstat() and fstatfs() don't accept
* file descriptors opened with O_PATH on old kernels (before v3.6 and before
* v3.12, respectively), but stat() and statfs() can be called on a path that
* the user doesn't have read or write permissions to.
*
* returns:
* 1 - btrfs subvolume
* 0 - not btrfs subvolume
* -1 - error
*/
int btrfs_is_subvolume(const char *path)
{
struct stat st;
int ret;
ret = is_btrfs(path);
if (ret <= 0)
return ret;
ret = stat(path, &st);
if (ret == -1)
return -1;
if (st.st_ino != BTRFS_FIRST_FREE_OBJECTID || !S_ISDIR(st.st_mode)) {
return 0;
}
return 1;
}
/* Adapted from btrfsprogs */
int is_btrfs(const char *path)
{
struct statfs sfs;
int ret;
ret = statfs(path, &sfs);
if (ret == -1)
return -1;
return sfs.f_type == BTRFS_SUPER_MAGIC;
}
-7
View File
@@ -46,18 +46,11 @@
#include "defines.h" #include "defines.h"
#include "chkname.h" #include "chkname.h"
int allow_bad_names = false;
static bool is_valid_name (const char *name) static bool is_valid_name (const char *name)
{ {
if (allow_bad_names) {
return true;
}
/* /*
* User/group names must match [a-z_][a-z0-9_-]*[$] * User/group names must match [a-z_][a-z0-9_-]*[$]
*/ */
if (('\0' == *name) || if (('\0' == *name) ||
!((('a' <= *name) && ('z' >= *name)) || ('_' == *name))) { !((('a' <= *name) && ('z' >= *name)) || ('_' == *name))) {
return false; return false;
+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;
} }
+2 -3
View File
@@ -62,7 +62,6 @@ void chown_tty (const struct passwd *info)
grent = getgr_nam_gid (getdef_str ("TTYGROUP")); grent = getgr_nam_gid (getdef_str ("TTYGROUP"));
if (NULL != grent) { if (NULL != grent) {
gid = grent->gr_gid; gid = grent->gr_gid;
gr_free (grent);
} else { } else {
gid = info->pw_gid; gid = info->pw_gid;
} }
@@ -73,10 +72,10 @@ 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 (shadow_logfd, fprintf (stderr,
_("Unable to change owner or mode of tty stdin: %s"), _("Unable to change owner or mode of tty stdin: %s"),
strerror (err)); strerror (err));
SYSLOG ((LOG_WARN, SYSLOG ((LOG_WARN,
+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;
+2 -2
View File
@@ -203,7 +203,7 @@ void cleanup_report_del_group_gshadow (void *group_name)
void cleanup_unlock_group (unused void *arg) void cleanup_unlock_group (unused void *arg)
{ {
if (gr_unlock () == 0) { if (gr_unlock () == 0) {
fprintf (shadow_logfd, fprintf (stderr,
_("%s: failed to unlock %s\n"), _("%s: failed to unlock %s\n"),
Prog, gr_dbname ()); Prog, gr_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
@@ -223,7 +223,7 @@ void cleanup_unlock_group (unused void *arg)
void cleanup_unlock_gshadow (unused void *arg) void cleanup_unlock_gshadow (unused void *arg)
{ {
if (sgr_unlock () == 0) { if (sgr_unlock () == 0) {
fprintf (shadow_logfd, fprintf (stderr,
_("%s: failed to unlock %s\n"), _("%s: failed to unlock %s\n"),
Prog, sgr_dbname ()); Prog, sgr_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
+2 -2
View File
@@ -120,7 +120,7 @@ void cleanup_report_add_user_shadow (void *user_name)
void cleanup_unlock_passwd (unused void *arg) void cleanup_unlock_passwd (unused void *arg)
{ {
if (pw_unlock () == 0) { if (pw_unlock () == 0) {
fprintf (shadow_logfd, fprintf (stderr,
_("%s: failed to unlock %s\n"), _("%s: failed to unlock %s\n"),
Prog, pw_dbname ()); Prog, pw_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
@@ -139,7 +139,7 @@ void cleanup_unlock_passwd (unused void *arg)
void cleanup_unlock_shadow (unused void *arg) void cleanup_unlock_shadow (unused void *arg)
{ {
if (spw_unlock () == 0) { if (spw_unlock () == 0) {
fprintf (shadow_logfd, fprintf (stderr,
_("%s: failed to unlock %s\n"), _("%s: failed to unlock %s\n"),
Prog, spw_dbname ()); Prog, spw_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
+5 -9
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[1024], *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,16 +68,13 @@ static bool is_listed (const char *cfgin, const char *tty, bool def)
*/ */
if (*cons != '/') { if (*cons != '/') {
char *pbuf; strcpy (buf, cons);
strncpy (buf, cons, sizeof (buf)); while ((s = strtok (buf, ":")) != NULL) {
buf[sizeof (buf) - 1] = '\0';
pbuf = &buf[0];
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 -316
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 (shadow_logfd, _("%s: "), Prog); /* Get the default security context for this file */
if (vfprintf (shadow_logfd, fmt, ap) != 0) { if (matchpathcon (dst_name, 0, &scontext) < 0) {
(void) fputs (_(": "), shadow_logfd); 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 (shadow_logfd, "%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 (shadow_logfd,
"%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, S_IFDIR) != 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, S_IFLNK) != 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, statp->st_mode & S_IFMT) != 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,45 +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, S_IFREG) != 0) { selinux_file_context (dst);
(void) close (ifd); #endif
return -1;
}
#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 */
) {
if (ofd >= 0) {
(void) close (ofd);
}
(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 (ofd);
(void) close (ifd);
return -1; return -1;
} }
} }
@@ -791,10 +642,9 @@ static int copy_file (const char *src, const char *dst,
#ifdef HAVE_FUTIMES #ifdef HAVE_FUTIMES
if (futimes (ofd, mt) != 0) { if (futimes (ofd, mt) != 0) {
(void) close (ofd);
return -1; return -1;
} }
#endif /* HAVE_FUTIMES */ #endif
if (close (ofd) != 0) { if (close (ofd) != 0) {
return -1; return -1;
@@ -804,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)
+4 -14
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
@@ -171,7 +161,7 @@ void addenv (const char *string, /*@null@*/const char *value)
} }
newenvp = __newenvp; newenvp = __newenvp;
} else { } else {
(void) fputs (_("Environment overflow\n"), shadow_logfd); (void) fputs (_("Environment overflow\n"), stderr);
newenvc--; newenvc--;
free (newenvp[newenvc]); free (newenvp[newenvc]);
} }
@@ -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++) {
+3 -5
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
@@ -98,7 +98,7 @@ void failure (uid_t uid, const char *tty, struct faillog *fl)
fl->fail_cnt++; fl->fail_cnt++;
} }
strncpy (fl->fail_line, tty, sizeof (fl->fail_line) - 1); strncpy (fl->fail_line, tty, sizeof fl->fail_line);
(void) time (&fl->fail_time); (void) time (&fl->fail_time);
/* /*
@@ -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;
/* /*
+1 -1
View File
@@ -69,7 +69,7 @@ extern int failcheck (uid_t uid, struct faillog *fl, bool failed);
extern void failprint (const struct faillog *); extern void failprint (const struct faillog *);
/* /*
* failtmp - update the cumulative failure log * failtmp - update the cummulative failure log
* *
* failtmp updates the (struct utmp) formatted failure log which * failtmp updates the (struct utmp) formatted failure log which
* maintains a record of all login failures. * maintains a record of all login failures.
-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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (prefix_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 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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd, * 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;
} }
-85
View File
@@ -1,85 +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 (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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 */
-85
View File
@@ -1,85 +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 (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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (prefix_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 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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd,
_("%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 (shadow_logfd, * 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
@@ -66,7 +66,7 @@
#endif #endif
/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc), /* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
as well as gratuitously global symbol names, so we can have multiple as well as gratuitiously global symbol names, so we can have multiple
yacc generated parsers in the same program. Note that these are only yacc generated parsers in the same program. Note that these are only
the variables produced by yacc. If other parser generators (bison, the variables produced by yacc. If other parser generators (bison,
byacc, etc) produce additional global names that conflict at link time, byacc, etc) produce additional global names that conflict at link time,
+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 = shadow_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 (shadow_logfd,
_("Environment variable $SOURCE_DATE_EPOCH: strtoull: %s\n"),
strerror(errno));
} else if (endptr == source_date_epoch) {
fprintf (shadow_logfd,
_("Environment variable $SOURCE_DATE_EPOCH: No digits were found: %s\n"),
endptr);
} else if (*endptr != '\0') {
fprintf (shadow_logfd,
_("Environment variable $SOURCE_DATE_EPOCH: Trailing garbage: %s\n"),
endptr);
} else if (epoch > ULONG_MAX) {
fprintf (shadow_logfd,
_("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 (shadow_logfd,
_("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);
} }
-245
View File
@@ -1,245 +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"
#if HAVE_SYS_CAPABILITY_H
#include <sys/prctl.h>
#include <sys/capability.h>
#endif
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(shadow_logfd, "%s: error calculating number of arguments\n", Prog);
return NULL;
}
if (ranges != ((argc + 2) / 3)) {
fprintf(shadow_logfd, "%s: ranges: %u is wrong for argc: %d\n", Prog, ranges, argc);
return NULL;
}
if ((ranges * 3) > argc) {
fprintf(shadow_logfd, "ranges: %u argc: %d\n",
ranges, argc);
fprintf(shadow_logfd,
_( "%s: Not enough arguments to form %u mappings\n"),
Prog, ranges);
return NULL;
}
mappings = calloc(ranges, sizeof(*mappings));
if (!mappings) {
fprintf(shadow_logfd, _( "%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(shadow_logfd, _( "%s: subuid overflow detected.\n"), Prog);
exit(EXIT_FAILURE);
}
if (mapping->upper > UINT_MAX ||
mapping->lower > UINT_MAX ||
mapping->count > UINT_MAX) {
fprintf(shadow_logfd, _( "%s: subuid overflow detected.\n"), Prog);
exit(EXIT_FAILURE);
}
if (mapping->lower + mapping->count > UINT_MAX ||
mapping->upper + mapping->count > UINT_MAX) {
fprintf(shadow_logfd, _( "%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(shadow_logfd, _( "%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)
#if HAVE_SYS_CAPABILITY_H
static inline bool maps_lower_root(int cap, int ranges, struct map_range *mappings)
{
int idx;
struct map_range *mapping;
if (cap != CAP_SETUID)
return false;
mapping = mappings;
for (idx = 0; idx < ranges; idx++, mapping++) {
if (mapping->lower == 0)
return true;
}
return false;
}
#endif
/*
* The ruid refers to the caller's uid and is used to reset the effective uid
* back to the callers real uid.
* This clutch mainly exists for setuid-based new{g,u}idmap binaries that are
* called in contexts where all capabilities other than the necessary
* CAP_SET{G,U}ID capabilities are dropped. Since the kernel will require
* assurance that the caller holds CAP_SYS_ADMIN over the target user namespace
* the only way it can confirm is in this case is if the effective uid is
* equivalent to the uid owning the target user namespace.
* Note, we only support this when a) new{g,u}idmap is not called by root and
* b) if the caller's uid and the uid retrieved via system appropriate means
* (shadow file or other) are identical. Specifically, this does not support
* when the root user calls the new{g,u}idmap binary for an unprivileged user.
* If this is wanted: use file capabilities!
*/
void write_mapping(int proc_dir_fd, int ranges, struct map_range *mappings,
const char *map_file, uid_t ruid)
{
int idx;
struct map_range *mapping;
size_t bufsize;
char *buf, *pos;
int fd;
#if HAVE_SYS_CAPABILITY_H
int cap;
struct __user_cap_header_struct hdr = {_LINUX_CAPABILITY_VERSION_3, 0};
struct __user_cap_data_struct data[2] = {{0}};
if (strcmp(map_file, "uid_map") == 0) {
cap = CAP_SETUID;
} else if (strcmp(map_file, "gid_map") == 0) {
cap = CAP_SETGID;
} else {
fprintf(shadow_logfd, _("%s: Invalid map file %s specified\n"), Prog, map_file);
exit(EXIT_FAILURE);
}
/* Align setuid- and fscaps-based new{g,u}idmap behavior. */
if (geteuid() == 0 && geteuid() != ruid) {
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) {
fprintf(shadow_logfd, _("%s: Could not prctl(PR_SET_KEEPCAPS)\n"), Prog);
exit(EXIT_FAILURE);
}
if (seteuid(ruid) < 0) {
fprintf(shadow_logfd, _("%s: Could not seteuid to %d\n"), Prog, ruid);
exit(EXIT_FAILURE);
}
}
/* Lockdown new{g,u}idmap by dropping all unneeded capabilities. */
memset(data, 0, sizeof(data));
data[0].effective = CAP_TO_MASK(cap);
/*
* When uid 0 from the ancestor userns is supposed to be mapped into
* the child userns we need to retain CAP_SETFCAP.
*/
if (maps_lower_root(cap, ranges, mappings))
data[0].effective |= CAP_TO_MASK(CAP_SETFCAP);
data[0].permitted = data[0].effective;
if (capset(&hdr, data) < 0) {
fprintf(shadow_logfd, _("%s: Could not set caps\n"), Prog);
exit(EXIT_FAILURE);
}
#endif
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(shadow_logfd, _("%s: snprintf failed!\n"), Prog);
exit(EXIT_FAILURE);
}
pos += written;
}
/* Write the mapping to the mapping file */
fd = openat(proc_dir_fd, map_file, O_WRONLY);
if (fd < 0) {
fprintf(shadow_logfd, _("%s: open of %s failed: %s\n"),
Prog, map_file, strerror(errno));
exit(EXIT_FAILURE);
}
if (write(fd, buf, pos - buf) != (pos - buf)) {
fprintf(shadow_logfd, _("%s: write to %s failed: %s\n"),
Prog, map_file, strerror(errno));
exit(EXIT_FAILURE);
}
close(fd);
free(buf);
}
+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;
} }
+71 -185
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,8 +432,9 @@ 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) &
(void) fputs (_("Too many logins.\n"), shadow_logfd); LOGIN_ERROR_LOGIN) {
(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 -14
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);
@@ -241,7 +229,6 @@ bool is_on_list (char *const *list, const char *member)
if ('\0' == *members) { if ('\0' == *members) {
*array = (char *) 0; *array = (char *) 0;
free (members);
return array; return array;
} }
+2 -2
View File
@@ -100,9 +100,9 @@ void dolastlog (
ll_time = newlog.ll_time; ll_time = newlog.ll_time;
(void) time (&ll_time); (void) time (&ll_time);
newlog.ll_time = ll_time; newlog.ll_time = ll_time;
strncpy (newlog.ll_line, line, sizeof (newlog.ll_line) - 1); strncpy (newlog.ll_line, line, sizeof newlog.ll_line);
#if HAVE_LL_HOST #if HAVE_LL_HOST
strncpy (newlog.ll_host, host, sizeof (newlog.ll_host) - 1); strncpy (newlog.ll_host, host, sizeof newlog.ll_host);
#endif #endif
if ( (lseek (fd, offset, SEEK_SET) != offset) if ( (lseek (fd, offset, SEEK_SET) != offset)
|| (write (fd, (const void *) &newlog, sizeof newlog) != (ssize_t) sizeof newlog) || (write (fd, (const void *) &newlog, sizeof newlog) != (ssize_t) sizeof newlog)
+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);
} }
-3
View File
@@ -62,9 +62,6 @@
if ((NULL != pw) && (pw->pw_uid == ruid)) { if ((NULL != pw) && (pw->pw_uid == ruid)) {
return pw; return pw;
} }
if (NULL != pw) {
pw_free (pw);
}
} }
return xgetpwuid (ruid); return xgetpwuid (ruid);
+13 -22
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);
@@ -268,12 +265,6 @@ static /*@observer@*//*@null@*/const char *obscure_msg (
#ifdef USE_SHA_CRYPT #ifdef USE_SHA_CRYPT
|| (strcmp (result, "SHA256") == 0) || (strcmp (result, "SHA256") == 0)
|| (strcmp (result, "SHA512") == 0) || (strcmp (result, "SHA512") == 0)
#endif
#ifdef USE_BCRYPT
|| (strcmp (result, "BCRYPT") == 0)
#endif
#ifdef USE_YESCRYPT
|| (strcmp (result, "YESCRYPT") == 0)
#endif #endif
) { ) {
return NULL; return NULL;
@@ -313,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 */
+4 -4
View File
@@ -59,20 +59,20 @@ void do_pam_passwd (const char *user, bool silent, bool change_expired)
ret = pam_start ("passwd", user, &conv, &pamh); ret = pam_start ("passwd", user, &conv, &pamh);
if (ret != PAM_SUCCESS) { if (ret != PAM_SUCCESS) {
fprintf (shadow_logfd, fprintf (stderr,
_("passwd: pam_start() failed, error %d\n"), ret); _("passwd: pam_start() failed, error %d\n"), ret);
exit (10); /* XXX */ exit (10); /* XXX */
} }
ret = pam_chauthtok (pamh, flags); ret = pam_chauthtok (pamh, flags);
if (ret != PAM_SUCCESS) { if (ret != PAM_SUCCESS) {
fprintf (shadow_logfd, _("passwd: %s\n"), pam_strerror (pamh, ret)); fprintf (stderr, _("passwd: %s\n"), pam_strerror (pamh, ret));
fputs (_("passwd: password unchanged\n"), shadow_logfd); fputs (_("passwd: password unchanged\n"), stderr);
pam_end (pamh, ret); pam_end (pamh, ret);
exit (10); /* XXX */ exit (10); /* XXX */
} }
fputs (_("passwd: password updated successfully\n"), shadow_logfd); fputs (_("passwd: password updated successfully\n"), stderr);
(void) pam_end (pamh, PAM_SUCCESS); (void) pam_end (pamh, PAM_SUCCESS);
} }
#else /* !USE_PAM */ #else /* !USE_PAM */
@@ -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,
@@ -76,7 +76,7 @@ static int ni_conv (int num_msg,
switch (msg[count]->msg_style) { switch (msg[count]->msg_style) {
case PAM_PROMPT_ECHO_ON: case PAM_PROMPT_ECHO_ON:
fprintf (shadow_logfd, fprintf (stderr,
_("%s: PAM modules requesting echoing are not supported.\n"), _("%s: PAM modules requesting echoing are not supported.\n"),
Prog); Prog);
goto failed_conversation; goto failed_conversation;
@@ -88,7 +88,7 @@ static int ni_conv (int num_msg,
break; break;
case PAM_ERROR_MSG: case PAM_ERROR_MSG:
if ( (NULL == msg[count]->msg) if ( (NULL == msg[count]->msg)
|| (fprintf (shadow_logfd, "%s\n", msg[count]->msg) <0)) { || (fprintf (stderr, "%s\n", msg[count]->msg) <0)) {
goto failed_conversation; goto failed_conversation;
} }
responses[count].resp = NULL; responses[count].resp = NULL;
@@ -101,7 +101,7 @@ static int ni_conv (int num_msg,
responses[count].resp = NULL; responses[count].resp = NULL;
break; break;
default: default:
(void) fprintf (shadow_logfd, (void) fprintf (stderr,
_("%s: conversation type %d not supported.\n"), _("%s: conversation type %d not supported.\n"),
Prog, msg[count]->msg_style); Prog, msg[count]->msg_style);
goto failed_conversation; goto failed_conversation;
@@ -134,7 +134,7 @@ failed_conversation:
* *
* Return 0 on success, 1 on failure. * Return 0 on success, 1 on failure.
*/ */
int do_pam_passwd_non_interactive (const char *pam_service, int do_pam_passwd_non_interractive (const char *pam_service,
const char *username, const char *username,
const char* password) const char* password)
{ {
@@ -143,7 +143,7 @@ int do_pam_passwd_non_interactive (const char *pam_service,
ret = pam_start (pam_service, username, &non_interactive_pam_conv, &pamh); ret = pam_start (pam_service, username, &non_interactive_pam_conv, &pamh);
if (ret != PAM_SUCCESS) { if (ret != PAM_SUCCESS) {
fprintf (shadow_logfd, fprintf (stderr,
_("%s: (user %s) pam_start failure %d\n"), _("%s: (user %s) pam_start failure %d\n"),
Prog, username, ret); Prog, username, ret);
return 1; return 1;
@@ -152,7 +152,7 @@ int do_pam_passwd_non_interactive (const char *pam_service,
non_interactive_password = password; non_interactive_password = password;
ret = pam_chauthtok (pamh, 0); ret = pam_chauthtok (pamh, 0);
if (ret != PAM_SUCCESS) { if (ret != PAM_SUCCESS) {
fprintf (shadow_logfd, fprintf (stderr,
_("%s: (user %s) pam_chauthtok() failed, error:\n" _("%s: (user %s) pam_chauthtok() failed, error:\n"
"%s\n"), "%s\n"),
Prog, username, pam_strerror (pamh, ret)); Prog, username, pam_strerror (pamh, ret));
-359
View File
@@ -1,359 +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"
#include "groupio.h"
#include "pwio.h"
#ifdef SHADOWGRP
#include "sgroupio.h"
#endif
#include "shadowio.h"
#ifdef ENABLE_SUBIDS
#include "subordinateio.h"
#endif /* ENABLE_SUBIDS */
#include "getdef.h"
static char *passwd_db_file = NULL;
static char *spw_db_file = NULL;
static char *group_db_file = NULL;
static char *sgroup_db_file = NULL;
static char *suid_db_file = NULL;
static char *sgid_db_file = NULL;
static char *def_conf_file = NULL;
static FILE* fp_pwent = NULL;
static FILE* fp_grent = NULL;
/*
* process_prefix_flag - prefix all paths if given the --prefix 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 const char* process_prefix_flag (const char* short_opt, int argc, char **argv)
{
/*
* Parse the command line options.
*/
int i;
const char *prefix = NULL, *val;
for (i = 0; i < argc; i++) {
val = NULL;
if ( (strcmp (argv[i], "--prefix") == 0)
|| ((strncmp (argv[i], "--prefix=", 9) == 0)
&& (val = argv[i] + 9))
|| (strcmp (argv[i], short_opt) == 0)) {
if (NULL != prefix) {
fprintf (shadow_logfd,
_("%s: multiple --prefix options\n"),
Prog);
exit (E_BAD_ARG);
}
if (val) {
prefix = val;
} else if (i + 1 == argc) {
fprintf (shadow_logfd,
_("%s: option '%s' requires an argument\n"),
Prog, argv[i]);
exit (E_BAD_ARG);
} else {
prefix = argv[++ i];
}
}
}
if (prefix != NULL) {
if ( prefix[0] == '\0' || !strcmp(prefix, "/"))
return ""; /* if prefix is "/" then we ignore the flag option */
/* should we prevent symbolic link from being used as a prefix? */
if ( prefix[0] != '/') {
fprintf (shadow_logfd,
_("%s: prefix must be an absolute path\n"),
Prog);
exit (E_BAD_ARG);
}
size_t len;
len = strlen(prefix) + strlen(PASSWD_FILE) + 2;
passwd_db_file = xmalloc(len);
snprintf(passwd_db_file, len, "%s/%s", prefix, PASSWD_FILE);
pw_setdbname(passwd_db_file);
len = strlen(prefix) + strlen(GROUP_FILE) + 2;
group_db_file = xmalloc(len);
snprintf(group_db_file, len, "%s/%s", prefix, GROUP_FILE);
gr_setdbname(group_db_file);
#ifdef SHADOWGRP
len = strlen(prefix) + strlen(SGROUP_FILE) + 2;
sgroup_db_file = xmalloc(len);
snprintf(sgroup_db_file, len, "%s/%s", prefix, SGROUP_FILE);
sgr_setdbname(sgroup_db_file);
#endif
#ifdef USE_NIS
__setspNIS(0); /* disable NIS for now, at least until it is properly supporting a "prefix" */
#endif
len = strlen(prefix) + strlen(SHADOW_FILE) + 2;
spw_db_file = xmalloc(len);
snprintf(spw_db_file, len, "%s/%s", prefix, SHADOW_FILE);
spw_setdbname(spw_db_file);
#ifdef ENABLE_SUBIDS
len = strlen(prefix) + strlen("/etc/subuid") + 2;
suid_db_file = xmalloc(len);
snprintf(suid_db_file, len, "%s/%s", prefix, "/etc/subuid");
sub_uid_setdbname(suid_db_file);
len = strlen(prefix) + strlen("/etc/subgid") + 2;
sgid_db_file = xmalloc(len);
snprintf(sgid_db_file, len, "%s/%s", prefix, "/etc/subgid");
sub_gid_setdbname(sgid_db_file);
#endif
#ifdef USE_ECONF
setdef_config_file(prefix);
#else
len = strlen(prefix) + strlen("/etc/login.defs") + 2;
def_conf_file = xmalloc(len);
snprintf(def_conf_file, len, "%s/%s", prefix, "/etc/login.defs");
setdef_config_file(def_conf_file);
#endif
}
if (prefix == NULL)
return "";
return prefix;
}
extern struct group *prefix_getgrnam(const char *name)
{
if (group_db_file) {
FILE* fg;
struct group * grp = NULL;
fg = fopen(group_db_file, "rt");
if(!fg)
return NULL;
while((grp = fgetgrent(fg)) != NULL) {
if(!strcmp(name, grp->gr_name))
break;
}
fclose(fg);
return grp;
}
return getgrnam(name);
}
extern struct group *prefix_getgrgid(gid_t gid)
{
if (group_db_file) {
FILE* fg;
struct group * grp = NULL;
fg = fopen(group_db_file, "rt");
if(!fg)
return NULL;
while((grp = fgetgrent(fg)) != NULL) {
if(gid == grp->gr_gid)
break;
}
fclose(fg);
return grp;
}
return getgrgid(gid);
}
extern struct passwd *prefix_getpwuid(uid_t uid)
{
if (passwd_db_file) {
FILE* fg;
struct passwd *pwd = NULL;
fg = fopen(passwd_db_file, "rt");
if(!fg)
return NULL;
while((pwd = fgetpwent(fg)) != NULL) {
if(uid == pwd->pw_uid)
break;
}
fclose(fg);
return pwd;
}
else {
return getpwuid(uid);
}
}
extern struct passwd *prefix_getpwnam(const char* name)
{
if (passwd_db_file) {
FILE* fg;
struct passwd *pwd = NULL;
fg = fopen(passwd_db_file, "rt");
if(!fg)
return NULL;
while((pwd = fgetpwent(fg)) != NULL) {
if(!strcmp(name, pwd->pw_name))
break;
}
fclose(fg);
return pwd;
}
else {
return getpwnam(name);
}
}
extern struct spwd *prefix_getspnam(const char* name)
{
if (spw_db_file) {
FILE* fg;
struct spwd *sp = NULL;
fg = fopen(spw_db_file, "rt");
if(!fg)
return NULL;
while((sp = fgetspent(fg)) != NULL) {
if(!strcmp(name, sp->sp_namp))
break;
}
fclose(fg);
return sp;
}
else {
return getspnam(name);
}
}
extern void prefix_setpwent()
{
if(!passwd_db_file) {
setpwent();
return;
}
if (fp_pwent)
fclose (fp_pwent);
fp_pwent = fopen(passwd_db_file, "rt");
if(!fp_pwent)
return;
}
extern struct passwd* prefix_getpwent()
{
if(!passwd_db_file) {
return getpwent();
}
return fgetpwent(fp_pwent);
}
extern void prefix_endpwent()
{
if(!passwd_db_file) {
endpwent();
return;
}
if (fp_pwent)
fclose(fp_pwent);
fp_pwent = NULL;
}
extern void prefix_setgrent()
{
if(!group_db_file) {
setgrent();
return;
}
if (fp_grent)
fclose (fp_grent);
fp_grent = fopen(group_db_file, "rt");
if(!fp_grent)
return;
}
extern struct group* prefix_getgrent()
{
if(!group_db_file) {
return getgrent();
}
return fgetgrent(fp_grent);
}
extern void prefix_endgrent()
{
if(!group_db_file) {
endgrent();
return;
}
if (fp_grent)
fclose(fp_grent);
fp_grent = NULL;
}
extern struct group *prefix_getgr_nam_gid(const char *grname)
{
long long int gid;
char *endptr;
struct group *g;
if (NULL == grname) {
return NULL;
}
if (group_db_file) {
errno = 0;
gid = strtoll (grname, &endptr, 10);
if ( ('\0' != *grname)
&& ('\0' == *endptr)
&& (ERANGE != errno)
&& (gid == (gid_t)gid)) {
return prefix_getgrgid ((gid_t) gid);
}
g = prefix_getgrnam (grname);
return g ? __gr_dup(g) : NULL;
}
else
return getgr_nam_gid(grname);
}
+2 -1
View File
@@ -40,6 +40,7 @@
#include "prototypes.h" #include "prototypes.h"
#include "defines.h" #include "defines.h"
#include <pwd.h> #include <pwd.h>
extern time_t time (time_t *);
/* /*
* pwd_to_spwd - create entries for new spwd structure * pwd_to_spwd - create entries for new spwd structure
@@ -65,7 +66,7 @@ struct spwd *pwd_to_spwd (const struct passwd *pw)
*/ */
sp.sp_min = 0; sp.sp_min = 0;
sp.sp_max = (10000L * DAY) / SCALE; sp.sp_max = (10000L * DAY) / SCALE;
sp.sp_lstchg = (long) gettime () / SCALE; sp.sp_lstchg = (long) time ((time_t *) 0) / SCALE;
if (0 == sp.sp_lstchg) { if (0 == sp.sp_lstchg) {
/* Better disable aging than requiring a password /* Better disable aging than requiring a password
* change */ * change */
+1 -1
View File
@@ -51,7 +51,7 @@ void passwd_check (const char *user, const char *passwd, unused const char *prog
if (pw_auth (passwd, user, PW_LOGIN, (char *) 0) != 0) { if (pw_auth (passwd, user, PW_LOGIN, (char *) 0) != 0) {
SYSLOG ((LOG_WARN, "incorrect password for `%s'", user)); SYSLOG ((LOG_WARN, "incorrect password for `%s'", user));
(void) sleep (1); (void) sleep (1);
fprintf (shadow_logfd, _("Incorrect password for %s.\n"), user); fprintf (stderr, _("Incorrect password for %s.\n"), user);
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} }
} }
-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;
}

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