Compare commits

..

1 Commits

Author SHA1 Message Date
nekral-guest
b8a41d9480 Tag release 4.1.2 2008-05-25 12:58:59 +00:00
303 changed files with 47352 additions and 94901 deletions

47
.gitignore vendored
View File

@@ -1,47 +0,0 @@
*~
lib*.a
*.o
*.lo
*.la
*.gmo
.deps
.libs
*.patch
*.rej
*.orig
Makefile
Makefile.in
/ABOUT-NLS
/aclocal.m4
/autom4te.cache
/config.guess
/config.h
/config.h.in
/config.log
/config.rpath
/config.status
/config.sub
/configure
/depcomp
/install-sh
/libtool
/ltmain.sh
/m4
/missing
/stamp-h1
/ylwrap
/po/*.header
/po/*.sed
/po/*.sin
/po/Makefile.in.in
/po/Makevars.template
/po/POTFILES
/po/Rules-quot
/po/stamp-po
/shadow.spec
/libmisc/getdate.c

4071
ChangeLog

File diff suppressed because it is too large Load Diff

244
NEWS
View File

@@ -1,249 +1,5 @@
$Id$
shadow-4.1.4.1 -> shadow-4.1.4.2 2009-07-24
- general
* Improved support for large groups (impacts most user/group management
tools).
- addition of system users or groups
* Speed improvement. This should be noticeable in case of LDAP configured
systems. This should impact useradd, groupadd, and newusers
* Since system accounts are allocated from SYS_?ID_MIN to SYS_?ID_MAX in
reverse order, accounts are packed close to SYS_?ID_MAX if SYS_?ID_MIN
is already used but there are still dome gaps.
- login
* Add support for shells being a shell script without a shebang.
- su
* Preserve the DISPLAY and XAUTHORITY environment variables. This was
only the case in the non PAM enabled versions.
* Add support for shells being a shell script without a shebang.
*** translation
* The Finnish translation of passwd(1) was outdated and is no more
distributed.
shadow-4.1.4 -> shadow-4.1.4.1 2009-05-22
- login
* Fix failures with empty usernames on non PAM versions.
* Fix CONSOLE (securetty) support on non PAM versions.
- newgrp
* Return the exit status of the child.
- userdel
* On Linux, do not check if an user is logged in with utmp, but check if
the user is running some processes.
* If not on Linux, continue to search for an utmp record, but make sure
the process recorded in the utmp entry is still running.
* Report failures to remove the user's mailbox
* When USERGROUPS_ENAB is enabled, remove the user's group when the
user was the only member.
* Do not fail when -r is used and the home directory does not exist.
- usermod
* Check if the user is busy when the user's UID, name or home directory
is changed.
shadow-4.1.3.1 -> shadow-4.1.4 2009-05-10
- packaging
* Enable --enable-account-tools-setuid by default for PAM builds.
* Add configure option --enable-utmpx, disabled by default to mimic
the previous behavior on Linux (where utmp and utmpx are identical).
* Fix build failure on non-PAM systems when --without-pam is not
specified.
- chpasswd
* Change the passwords using PAM. This permits to define the password
policy in a central place. The -c/--crypt-method, -e/--encrypted,
-m/--md5 and -s/--sha-rounds options are no more supported on PAM
enabled systems.
- grpck
* Warn if a group has an entry in group and gshadow, and the password
field in group is not 'x'.
- login
* Do not trust the current utmp entry's ut_line to set PAM_TTY. This could
lead to DOS attacks.
* (PAM) Even if the user was already authenticated (-f flag), ask the
user to update his authentication token if needed.
- lastlog
* Fix regression causing empty reports.
- newusers
* Change the passwords using PAM. This permits to define the password
policy in a central place. The -c/--crypt-method and -s/--sha-rounds
options are no more supported on PAM enabled systems.
- pwck
* Warn if an user has an entry in passwd and shadow, and the password
field in passwd is not 'x'.
*** translation
- Updated Czech translation
- Updated French translation
- Updated German translation
- Updated Japanese translation
- Updated Korean translation
- Updated Portuguese translation
- Updated Russian translation
shadow-4.1.3 -> shadow-4.1.3.1 2009-04-15
*** security:
- Due to bad parsing of octal permissions, the permissions on tty (login)
but also UMASK were set wrongly (and weirdly). Only shadow-4.1.3 was
affected.
*** general
- login
* Fix regression when no user is specified on the command line.
- userdel
* Fixed SE Linux support
- vipw
* SE Linux: Set the default context to the context of the file being
edited. This ensures that the backup file inherit from the file's
context.
*** translation
- Updated Norwegian Bokmål translation
shadow-4.1.2.2 -> shadow-4.1.3 2009-04-12
*** general:
- packaging
* Fixed support for OpenPAM.
* Fixed support for uclibc.
* Added configure --enable-account-tools-setuid (default) /
--disable-account-tools-setuid options. This permits to disable the
PAM authentication of the caller for chage, chgpasswd, chpasswd,
groupadd, groupdel, groupmod, newusers, useradd, userdel, and usermod.
This authentication is not necessary when these tools are not
installed setuid root.
* Added configure --with-group-name-max-length (default) /
--without-group-name-max-length options. This permits to configure the maximum length allowed for group names:
<no option> -> default of 16 (like today)
--with-group-name-max-length -> default of 16
--without-group-name-max-length -> no max length
--with-group-name-max-length=n > max is set to n
No sanity checking is performed on n so people could do
something neat like --with-group-name-max-length=MAX_INT
- addition of users or groups
* Speed improvement in case UID_MAX/SYS_UID_MAX/GID_MAX/SYS_GID_MAX is
used for an user/group. This should be noticeable in case of LDAP
configured systems. This should impact useradd, groupadd, and newusers
- error handling improvement
* Make sure errors and incomplete changes are reported to syslog and
audit in case of unexpected failures.
* Report system inconsistencies to syslog and audit.
* Only report success to syslog and audit if the changes are really
performed in the system databases.
This is still not complete.
- /etc/login.defs
* New CREATE_HOME variable to tell useradd to create a home directory by
default.
- Translations
* New Kazakh translation.
* Spanish manpages are no more distributed. They are outdated. Please
contact pkg-shadow-devel@lists.alioth.debian.org if you wish to
provide updates.
- faillog
* Accept users specified as a numerical UID, or ranges of users (-user,
user-, user1-user2).
* -l, -m, and -r now apply not only to existing users, but to all the
specified UIDs.
* Options can be specified in any order.
- gpasswd
* Added support for long options --add (-a), --delete (-d),
--remove-password (-r), --restrict (-R), --administrators (-A), and
--members (-M).
* Added support for usernames with arbitrary length.
* audit logging improvements.
* error handling improvement (see above).
* Log permission denied to syslog and audit.
- groupadd
* audit logging improvements.
* error handling improvement (see above).
* Speedup (see "addition of users or groups" above).
* do not create groups with GID set to (gid_t)-1.
* Allocate system group GIDs in reverse order. This could be useful
later to increase the static IDs range.
- groupdel
* audit logging improvements.
* error handling improvement (see above).
- groupmems
* Check if user exist before they are added to groups.
* Avoid segfault in case the specified group does not exist in /etc/group.
* Everybody is allowed to list the users of a group.
* /etc/group is open readonly when one just wants to list the users of a
group.
* Added syslog support.
* Use the groupmems PAM service name instead of groupmod.
* Fix segmentation faults when adding or removing users from a group.
* Added support for shadow groups.
* Added support long options --add (-a), --delete (-d), --purge (-p),
--list (-l), --group (-g).
- groupmod
* audit logging improvements.
* error handling improvement (see above).
* do not create groups with GID set to (gid_t)-1.
- grpck
* warn for groups with GID set to (gid_t)-1.
- login
* Restore the echoctl, echoke, onclr flags to the terminal termio flags.
Reset echoprt, noflsh, tostop. This behavior seems to have change by
mistake in earlier releases (4.0.8, for no obvious reason).
- newusers
* Implement the -r, --system option.
* Speedup (see "addition of users or groups" above).
* do not create users with UID set to (gid_t)-1.
* do not create groups with GID set to (gid_t)-1.
* Allocate system account UIDs/GIDs in reverse order. This could be useful
later to increase the static IDs range.
- passwd
* For compatibility with other passwd version, the --lock an --unlock
options do not lock or unlock the user account anymore. They only
lock or unlock the user's password.
- pwck
* warn for users with UID set to (uid_t)-1.
- su
* Preserve COLORTERM in addition to TERM when su is called with the -l
option.
- useradd
* audit logging improvements.
* Speedup (see "addition of users or groups" above).
* See CREATE_HOME above.
* New -M/--no-create-home option to disable CREATE_HOME.
* do not create users with UID set to (gid_t)-1.
* Added -Z option to map SELinux user for user's login.
* Allocate system user UIDs in reverse order. This could be useful
later to increase the static IDs range.
- userdel
* audit logging improvements.
* Do not fail if the removed user is not in the shadow database.
* When the user's group shall be removed, do not fail if this group is
not in the gshadow file.
* Delete the SELinux user mapping for user's login.
- usermod
* Allow adding LDAP users (or any user not present in the local passwd
file) to local groups
* do not create users with UID set to (gid_t)-1.
* Added -Z option to map SELinux user for user's login.
shadow-4.1.2.1 -> shadow-4.1.2.2 23-11-2008
*** security
- Fix a race condition in login that could lead to gaining ownership or
changing mode of arbitrary files.
- Fix a possible login DOS, which could be caused by injecting forged
entries in utmp.
shadow-4.1.2 -> shadow-4.1.2.1 26-06-2008
*** security
- Fix an "audit log injection" vulnerability in login.
This vulnerability makes it easier for attackers to hide activities by
modifying portions of log events, e.g. by appending an addr= statement
to the login name.
shadow-4.1.1 -> shadow-4.1.2 25-05-2008
*** security:

17
README
View File

@@ -1,19 +1,14 @@
Shadow SITES
============
Homepage
http://pkg-shadow.alioth.debian.org/
FTP site
ftp://pkg-shadow.alioth.debian.org/pub/pkg-shadow
SVN repository
anonymous read only access: svn://svn.debian.org/pkg-shadow/upstream
anonymous read only access: svn://svn.debian.org/pkg-shadow/
SVN web interface
http://svn.debian.org/wsvn/pkg-shadow/upstream
or
http://svn.debian.org/viewsvn/pkg-shadow/upstream
http://svn.debian.org/wsvn/pkg-shadow
Mailing lists
for general discuss: pkg-shadow-devel@lists.alioth.debian.org
@@ -56,7 +51,6 @@ Calle Karlsson <ckn@kash.se>
Chip Rosenthal <chip@unicom.com>
Chris Evans <lady0110@sable.ox.ac.uk>
Cristian Gafton <gafton@sorosis.ro>
Dan Walsh <dwalsh@redhat.com>
Darcy Boese <possum@chardonnay.niagara.com>
Dave Hagewood <admin@arrowweb.com>
David A. Holland <dholland@hcs.harvard.edu>
@@ -83,14 +77,12 @@ Juha Virtanen <jiivee@iki.fi>
Julianne Frances Haugh <jockgrrl@ix.netcom.com>
Leonard N. Zubkoff <lnz@dandelion.com>
Luca Berra <bluca@www.polimi.it>
Lukáš Kuklínek <lkukline@redhat.com>
Lutz Schwalowsky <schwalow@mineralogie.uni-hamburg.de>
Marc Ewing <marc@redhat.com>
Martin Bene <mb@sime.com>
Martin Mares <mj@gts.cz>
Michael Meskes <meskes@topsystem.de>
Michael Talbot-Wilson <mike@calypso.bns.com.au>
Mike Frysinger <vapier@gentoo.org>
Mike Pakovic <mpakovic@users.southeast.net>
Nicolas François <nicolas.francois@centraliens.net>
Nikos Mavroyanopoulos <nmav@i-net.paiko.gr>
@@ -99,8 +91,6 @@ Phillip Street
Rafał Maszkowski <rzm@icm.edu.pl>
Rani Chouha <ranibey@smartec.com>
Sami Kerola <kerolasa@rocketmail.com>
Sebastian Rick Rijkers <srrijkers@gmail.com>
Seraphim Mellos <mellos@ceid.upatras.gr>
Shane Watts <shane@nexus.mlckew.edu.au>
Steve M. Robbins <steve@nyongwa.montreal.qc.ca>
Thorsten Kukuk <kukuk@suse.de>
@@ -112,6 +102,5 @@ Werner Fink <werner@suse.de>
Maintainers
===========
Tomasz Kłoczko <kloczek@pld.org.pl> (2000-2007)
Nicolas François <nicolas.francois@centraliens.net> (2007-now)
Tomasz Kłoczko <kloczek@pld.org.pl> (2000-2006)

110
TODO
View File

@@ -1,38 +1,11 @@
/etc/default/useradd
* GROUP=1000 should accept a group name.
passwd -l should lock the password, not the account.
Check when RLOGIN is enabled if ruserok() exists
vipw: Test SHADOWGRP support before using gshadow features.
Move selinux_file_context out of libmisc/copydir.c
PAM: add support for customization of the PAM support (i.e. support the
Debian PAM configuration)
Review hardcoded root account?
review all call to strto
libmisc/cleanup_user.c
cleanup needed (cleanup_report_add_user* not used)
libxcrypt support
* http://wiki.linuxfromscratch.org/patches/browser/trunk/shadow/shadow-4.0.18.1-owl_blowfish-1.patch
implement getlong, getulong.
avoid atoi, atol, atoul, strtol, strtoul, ...
manpages: comment the RLOGIN parts
Replace build_list (in lib/gshadow.c) and list (in lib/sgetgrent.c) by
comma_to_list()
Revert the modified files if all files could not be changed.
* or warn and indicate which files were modified and which were not.
* check the order the files are modified.
report nscd_flush_cache failures?
call nscd from the programs or from lib (commonio?)
PAM: check if a non-interactive conversation function could be used to set
the password in chpasswd and newusers
PAM: check if a non-interactive conversation function could be used to
WITH_SELINUX
- review all tools to check that the strategies are consistent
@@ -40,20 +13,33 @@ WITH_SELINUX
chage, chfn, chsh: same change needed as in passwd.
- probably need moving check_selinux_access to a separate file.
man useradd
document default behavior for GROUP
remove "The default group number is 1 or whatever is..."
useradd manpage
- add -k option
- mention that -o require -u
testsuite
- newgrp
- test with unknown user's GID
newusers
- add logging to SYSLOG & AUDIT
- use CREATE_HOME
- Add a -Z option (see useradd / usermod)
faillog
- accept numerical user and range of users
Document when/where option appeared, document whether an option is standard
or not.
depends rules for the manpages
Check all the expiry semantics
Add options --crypt-method and --sha-rounds to gpasswd
ALL:
- move base passwd/shadow/group/gshadow operation to module for allow write
different backend modules for db, NIS, LDAP and others. Default backend it
@@ -63,52 +49,38 @@ ALL:
passwd have old piece of code with handling -r option and it will be good
finish this and propagate on other shadow tools for allow operate on other
user databases by well known tools.
- Protect against signals. Register do_cleanups in a signal handler.
- login.defs
- generate depending on configuration
- useradd:
- add handle create user mail spool in maildir format.
- Add support for -k in -D mode
- Add support for -K in -D mode
- Add option to create or not the mail spool (and set the default in -D
mode)
- Change -l to reset the entry if an entry was already there
- set the mask in mkdir?
- add handle -n switch in groups and id command for allow query is
group/user with specified id/gid exist - this will be very usable
on automation in packages for query/check is group/user exist in system
or not,
- groupmems:
- need some work on add PAM and i18n support.
- userdel:
- add backup option for the removal of user resources,
- add lookop and remove per user group.
- user_busy: check that the user is not running any processes.
- missing "deleting group" FAILED
- home dir removed, but userdel may fail and may leave the user
=> warning needed
- usermod
- add an option equivalent to useradd's -l (only when uid is changed)
- the mode of new home directories should be set according to the
original mode. Does copy_tree does this?
- user renamed, order is not kept in /etc/group (see
47_usermod-l_no_shadow_file). This is a problem when the first user is
considered as the admin.
- see mail "user ID change" on April, 15
+ fix call to chown (combination of -m and -u/-g)
+ add tests
- passwd:
- check combination of options (e.g. -u/-l)
- when -u refuse to unlock because it would create an empty password, it
should not display "Password changed."
exit instead?
- newgrp: check the USE_PAM section.
- pwck
- Add check to move passwd passwords to shadow if there is a shadow
entry (with a password).
- Add check to move passwd passwords to shadow if there is a shadow
file.
- groupmems: check reason for isgroup
- su
- add a login.defs configuration parameter to add variables to keep in
the environment with "su -l" (TERM/TERMCOLOR/...
- newusers: doc for pw_gid not clear. Differentiate
pw_gid specified and exist
pw_gid specified but does not exist
* name
* number
pw_gid not specified.
- newusers: document what happens when no uid is specified.
- newusers: add option --system?
-Documentation:
* document when options were added.

View File

@@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT
AM_INIT_AUTOMAKE(shadow, 4.1.4.2)
AM_INIT_AUTOMAKE(shadow, 4.1.2)
AC_CONFIG_HEADERS([config.h])
dnl Some hacks...
@@ -28,7 +28,6 @@ dnl Checks for header files.
AC_HEADER_DIRENT
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_HEADER_STDBOOL
AC_CHECK_HEADERS(errno.h fcntl.h limits.h unistd.h sys/time.h utmp.h \
utmpx.h termios.h termio.h sgtty.h sys/ioctl.h syslog.h paths.h \
@@ -38,10 +37,10 @@ AC_CHECK_HEADERS(errno.h fcntl.h limits.h unistd.h sys/time.h utmp.h \
dnl shadow now uses the libc's shadow implementation
AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])])
AC_CHECK_FUNCS(l64a fchmod fchown fsync futimes getgroups gethostname getspnam \
AC_CHECK_FUNCS(l64a fchmod fchown fsync getgroups gethostname getspnam \
gettimeofday getusershell getutent initgroups lchown lckpwdf lstat \
lutimes memcpy memset setgroups sigaction strchr updwtmp updwtmpx innetgr \
getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo)
memcpy memset setgroups sigaction strchr updwtmp updwtmpx innetgr \
getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r)
AC_SYS_LARGEFILE
dnl Checks for typedefs, structures, and compiler characteristics.
@@ -52,38 +51,40 @@ AC_TYPE_PID_T
AC_TYPE_MODE_T
AC_HEADER_STAT
AC_CHECK_MEMBERS([struct stat.st_rdev])
AC_CHECK_MEMBERS([struct stat.st_atim])
AC_CHECK_MEMBERS([struct stat.st_atimensec])
AC_CHECK_MEMBERS([struct stat.st_mtim])
AC_CHECK_MEMBERS([struct stat.st_mtimensec])
AC_HEADER_TIME
AC_STRUCT_TM
AC_CHECK_MEMBERS([struct utmp.ut_type,
struct utmp.ut_id,
struct utmp.ut_name,
struct utmp.ut_user,
struct utmp.ut_host,
struct utmp.ut_syslen,
struct utmp.ut_addr,
struct utmp.ut_addr_v6,
struct utmp.ut_time,
struct utmp.ut_xtime,
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
if test "$ac_cv_header_utmp_h" = "yes"; then
AC_CACHE_CHECK(for ut_host in struct utmp,
ac_cv_struct_utmp_ut_host,
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([#include <utmp.h>],
[struct utmp ut; char *cp = ut.ut_host;]
)],
[ac_cv_struct_utmp_ut_host=yes],
[ac_cv_struct_utmp_ut_host=no]
)
)
AC_CHECK_MEMBERS([struct utmpx.ut_name,
struct utmpx.ut_host,
struct utmpx.ut_syslen,
struct utmpx.ut_addr,
struct utmpx.ut_addr_v6,
struct utmpx.ut_time,
struct utmpx.ut_xtime],,,[[#include <utmpx.h>]])
if test "$ac_cv_struct_utmp_ut_host" = "yes"; then
AC_DEFINE(UT_HOST, 1, [Define if you have ut_host in struct utmp.])
fi
AC_CACHE_CHECK(for ut_user in struct utmp,
ac_cv_struct_utmp_ut_user,
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <utmp.h>],
[struct utmp ut; char *cp = ut.ut_user;]
)],
[ac_cv_struct_utmp_ut_user=yes],
[ac_cv_struct_utmp_ut_user=no]
)
)
if test "$ac_cv_struct_utmp_ut_user" = "no"; then
AC_DEFINE(ut_user, ut_name,
[Define to ut_name if struct utmp has ut_name (not ut_user).])
fi
fi
if test "$ac_cv_header_lastlog_h" = "yes"; then
AC_CACHE_CHECK(for ll_host in struct lastlog,
@@ -211,31 +212,8 @@ AC_ARG_ENABLE(shadowgrp,
AC_ARG_ENABLE(man,
[AC_HELP_STRING([--enable-man],
[regenerate roff man pages from Docbook @<:@default=no@:>@])],
[enable_man="${enableval}"],
[enable_man="no"]
)
AC_ARG_ENABLE(account-tools-setuid,
[AC_HELP_STRING([--enable-account-tools-setuid],
[Install the user and group management tools setuid and authenticate the callers. This requires --with-pam.])],
[case "${enableval}" in
yes) enable_acct_tools_setuid="yes" ;;
no) enable_acct_tools_setuid="no" ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-account-tools-setuid)
;;
esac],
[enable_acct_tools_setuid="maybe"]
)
AC_ARG_ENABLE(utmpx,
[AC_HELP_STRING([--enable-utmpx],
[enable loggin in utmpx / wtmpx @<:@default=no@:>@])],
[case "${enableval}" in
yes) enable_utmpx="yes" ;;
no) enable_utmpx="no" ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-utmpx) ;;
esac],
[enable_utmpx="no"]
[enable_man=yes],
[enable_man=no]
)
AC_ARG_WITH(audit,
@@ -256,31 +234,10 @@ AC_ARG_WITH(libcrack,
AC_ARG_WITH(sha-crypt,
[AC_HELP_STRING([--with-sha-crypt], [allow the SHA256 and SHA512 password encryption algorithms @<:@default=yes@:>@])],
[with_sha_crypt=$withval], [with_sha_crypt=yes])
AC_ARG_WITH(nscd,
[AC_HELP_STRING([--with-nscd], [enable support for nscd @<:@default=yes@:>@])],
[with_nscd=$withval], [with_nscd=yes])
AC_ARG_WITH(group-name-max-length,
[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])
if test "$with_group_name_max_length" = "no" ; then
with_group_name_max_length=0
elif test "$with_group_name_max_length" = "yes" ; then
with_group_name_max_length=16
fi
AC_DEFINE_UNQUOTED(GROUP_NAME_MAX_LENGTH, $with_group_name_max_length, [max group name length])
AC_SUBST(GROUP_NAME_MAX_LENGTH)
GROUP_NAME_MAX_LENGTH="$with_group_name_max_length"
AM_CONDITIONAL(USE_SHA_CRYPT, test "x$with_sha_crypt" = "xyes")
if test "$with_sha_crypt" = "yes"; then
AC_DEFINE(USE_SHA_CRYPT, 1, [Define to allow the SHA256 and SHA512 password encryption algorithms])
fi
if test "$with_nscd" = "yes"; then
AC_CHECK_FUNC(posix_spawn,
[AC_DEFINE(USE_NSCD, 1, [Define to support flushing of nscd caches])],
[AC_MSG_ERROR([posix_spawn is needed for nscd support])])
AC_DEFINE(USE_SHA_CRYPT, 1, [Define to allow the SHA256 and SHA512 password encryption algorithms])
fi
dnl Check for some functions in libc first, only if not found check for
@@ -311,7 +268,7 @@ if test "$enable_man" = "yes"; then
JH_CHECK_XML_CATALOG([http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl],
[DocBook XSL Stylesheets >= 1.70.1], [], enable_man=no)
fi
AM_CONDITIONAL(ENABLE_REGENERATE_MAN, test "x$enable_man" != "xno")
AM_CONDITIONAL(ENABLE_REGENERATE_MAN, test x$enable_man != xno)
AC_SUBST(LIBCRYPT)
AC_CHECK_LIB(crypt, crypt, [LIBCRYPT=-lcrypt],
@@ -323,15 +280,6 @@ if test "$with_audit" != "no"; then
if test "$audit_header$with_audit" = "noyes" ; then
AC_MSG_ERROR([libaudit.h is missing])
elif test "$audit_header" = "yes"; then
AC_CHECK_DECL(AUDIT_ADD_USER,,[audit_header="no"],[#include <libaudit.h>])
AC_CHECK_DECL(AUDIT_DEL_USER,,[audit_header="no"],[#include <libaudit.h>])
AC_CHECK_DECL(AUDIT_ADD_GROUP,,[audit_header="no"],[#include <libaudit.h>])
AC_CHECK_DECL(AUDIT_DEL_GROUP,,[audit_header="no"],[#include <libaudit.h>])
if test "$audit_header$with_audit" = "noyes" ; then
AC_MSG_ERROR([AUDIT_ADD_USER AUDIT_DEL_USER AUDIT_ADD_GROUP or AUDIT_DEL_GROUP missing from libaudit.h])
fi
fi
if test "$audit_header" = "yes"; then
AC_CHECK_LIB(audit, audit_log_acct_message,
[audit_lib="yes"], [audit_lib="no"])
if test "$audit_lib$with_audit" = "noyes" ; then
@@ -391,55 +339,23 @@ if test "$with_libpam" != "no"; then
AC_MSG_ERROR(libpam not found)
fi
LIBPAM="-lpam"
pam_conv_function="no"
AC_CHECK_LIB(pam, openpam_ttyconv,
[pam_conv_function="openpam_ttyconv"],
AC_CHECK_LIB(pam_misc, misc_conv,
[pam_conv_function="misc_conv"; LIBPAM="$LIBPAM -lpam_misc"])
)
if test "$pam_conv_function$with_libpam" = "noyes" ; then
AC_MSG_ERROR(PAM conversation function not found)
AC_CHECK_LIB(pam_misc, main,
[pam_misc_lib="yes"], [pam_misc_lib="no"])
if test "$pam_misc_lib$with_libpam" = "noyes" ; then
AC_MSG_ERROR(libpam_misc not found)
fi
pam_headers_found=no
AC_CHECK_HEADERS( [security/openpam.h security/pam_misc.h],
[ pam_headers_found=yes ; break ], [],
[ #include <security/pam_appl.h> ] )
if test "$pam_headers_found$with_libpam" = "noyes" ; then
AC_MSG_ERROR(PAM headers not found)
fi
if test "$pam_lib$pam_headers_found" = "yesyes" -a "$pam_conv_function" != "no" ; then
if test "$pam_lib$pam_misc_lib" = "yesyes" ; then
with_libpam="yes"
else
with_libpam="no"
unset LIBPAM
fi
fi
dnl Now with_libpam is either yes or no
if test "$with_libpam" = "yes"; then
AC_CHECK_DECLS([PAM_ESTABLISH_CRED,
PAM_DELETE_CRED,
PAM_NEW_AUTHTOK_REQD,
PAM_DATA_SILENT],
[], [], [#include <security/pam_appl.h>])
save_libs=$LIBS
LIBS="$LIBS $LIBPAM"
# We do not use AC_CHECK_FUNCS to avoid duplicated definition with
# Linux PAM.
AC_CHECK_FUNC(pam_fail_delay, [AC_DEFINE(HAS_PAM_FAIL_DELAY, 1, [Define to 1 if you have the declaration of 'pam_fail_delay'])])
LIBS=$save_libs
AC_DEFINE(USE_PAM, 1, [Define to support Pluggable Authentication Modules])
AC_DEFINE_UNQUOTED(SHADOW_PAM_CONVERSATION, [$pam_conv_function],[PAM converstation to use])
AM_CONDITIONAL(USE_PAM, [true])
LIBPAM="-lpam -lpam_misc"
AC_MSG_CHECKING(use login and su access checking if PAM not used)
AC_MSG_RESULT(no)
else
@@ -449,24 +365,6 @@ else
AC_MSG_RESULT(yes)
fi
if test "$enable_acct_tools_setuid" != "no"; then
if test "$with_libpam" != "yes"; then
if test "$enable_acct_tools_setuid" = "yes"; then
AC_MSG_ERROR(PAM support is required for --enable-account-tools-setuid)
else
enable_acct_tools_setuid="no"
fi
else
enable_acct_tools_setuid="yes"
fi
if test "$enable_acct_tools_setuid" = "yes"; then
AC_DEFINE(ACCT_TOOLS_SETUID,
1,
[Define if account management tools should be installed setuid and authenticate the callers])
fi
fi
AM_CONDITIONAL(ACCT_TOOLS_SETUID, test "x$enable_acct_tools_setuid" = "xyes")
AC_SUBST(LIBSKEY)
AC_SUBST(LIBMD)
if test "$with_skey" = "yes"; then
@@ -482,17 +380,6 @@ if test "$with_skey" = "yes"; then
],[AC_DEFINE(SKEY_BSD_STYLE, 1, [Define to support newer BSD S/Key API])])
fi
if test "$enable_utmpx" = "yes"; then
if test "$ac_cv_header_utmpx_h" != "yes"; then
AC_MSG_ERROR([The utmpx.h header file is required for utmpx support.])
fi
AC_DEFINE(USE_UTMPX,
1,
[Define if utmpx should be used])
fi
AC_DEFINE_UNQUOTED(SHELL, ["$SHELL"], [The default shell.])
AM_GNU_GETTEXT_VERSION(0.16)
AM_GNU_GETTEXT([external], [need-ngettext])
AM_CONDITIONAL(USE_NLS, test "x$USE_NLS" = "xyes")
@@ -502,7 +389,6 @@ AC_CONFIG_FILES([
po/Makefile.in
doc/Makefile
man/Makefile
man/config.xml
man/po/Makefile.in
man/cs/Makefile
man/de/Makefile
@@ -537,12 +423,8 @@ echo
echo " auditing support: $with_audit"
echo " CrackLib support: $with_libcrack"
echo " PAM support: $with_libpam"
if test "$with_libpam" = "yes"; then
echo " suid account management tools: $enable_acct_tools_setuid"
fi
echo " SELinux support: $with_selinux"
echo " shadow group support: $enable_shadowgrp"
echo " S/Key support: $with_skey"
echo " SHA passwords encryption: $with_sha_crypt"
echo " nscd support: $with_nscd"
echo

View File

@@ -230,7 +230,7 @@ void main()
fflush(stdin);
} else
if (dir[strlen(dir)-1]=='/')
sprintf(dir+strlen(dir),"%s",uname);
sprintf(dir,"%s%s",dir,uname);
printf("\nShell [%s]: ",DEFAULT_SHELL);
fflush(stdout);

View File

@@ -296,7 +296,7 @@ main (void)
sprintf (dir, "%s/%s", DEFAULT_HOME, usrname);
}
else if (dir[strlen (dir) - 1] == '/')
sprintf (dir+strlen(dir), "%s", usrname);
sprintf (dir, "%s%s", dir, usrname);
}
else
{

View File

@@ -31,6 +31,8 @@ New ideas to add to this list are welcome, too. --marekm
- new option for /etc/suauth: don't load user's environment (force "su -")
suggested by Ulisses Alonso Camaro
- find out why recent releases won't compile on Solaris
- newusers UID/GID selection algorithm should be the same as useradd
(and use UID_MIN, UID_MAX from login.defs)
- newusers should be able to copy /etc/skel to the new home directory
(like useradd)
- add directories where other packages can add hooks for package-specific

View File

@@ -6,8 +6,6 @@
#
# Delay in seconds before being allowed another attempt after a login failure
# Note: When PAM is used, some modules may enfore a minimal delay (e.g.
# pam_unix enforces a 2s delay)
#
FAIL_DELAY 3
@@ -171,6 +169,7 @@ TTYPERM 0600
#
# ERASECHAR Terminal ERASE character ('\010' = backspace).
# KILLCHAR Terminal KILL character ('\025' = CTRL/U).
# UMASK Default "umask" value.
# ULIMIT Default "ulimit" value.
#
# The ERASECHAR and KILLCHAR are used only on System V machines.
@@ -181,15 +180,8 @@ TTYPERM 0600
#
ERASECHAR 0177
KILLCHAR 025
#ULIMIT 2097152
# Default initial "umask" value for non-PAM enabled systems.
# UMASK is also used by useradd and newusers to set the mode of new home
# directories.
# 022 is the default value, but 027, or even 077, could be considered
# better for privacy. There is no One True Answer here: each sysadmin
# must make up her mind.
UMASK 022
#ULIMIT 2097152
#
# Password aging controls:
@@ -223,7 +215,7 @@ CRACKLIB_DICTPATH /var/cache/cracklib/cracklib_dict
UID_MIN 1000
UID_MAX 60000
# System accounts
SYS_UID_MIN 101
SYS_UID_MIN 100
SYS_UID_MAX 999
#
@@ -232,7 +224,7 @@ SYS_UID_MAX 999
GID_MIN 1000
GID_MAX 60000
# System accounts
SYS_GID_MIN 101
SYS_GID_MIN 100
SYS_GID_MAX 999
#
@@ -375,12 +367,3 @@ USERGROUPS_ENAB yes
# 0 is the default value and disables this feature.
#
#MAX_MEMBERS_PER_GROUP 0
#
# If useradd should create home directories for users by default (non
# system users only)
# This option is overridden with the -M or -m flags on the useradd command
# line.
#
#CREATE_HOME yes

View File

@@ -2,21 +2,19 @@
# and also cooperate to make a distribution for `make dist'
pamd_files = \
chfn \
chsh \
groupmems \
login \
passwd \
su
pamd_acct_tools_files = \
chage \
chfn \
chgpasswd \
chpasswd \
chsh \
groupadd \
groupdel \
groupmems \
groupmod \
login \
newusers \
passwd \
su \
useradd \
userdel \
usermod
@@ -24,9 +22,6 @@ pamd_acct_tools_files = \
if USE_PAM
pamddir = $(sysconfdir)/pam.d
pamd_DATA = $(pamd_files)
if ACCT_TOOLS_SETUID
pamd_DATA += $(pamd_acct_tools_files)
endif
endif
EXTRA_DIST = $(pamd_files) $(pamd_acct_tools_files)
EXTRA_DIST = $(pamd_files)

View File

@@ -17,11 +17,6 @@ libshadow_la_SOURCES = \
fputsx.c \
getdef.c \
getdef.h \
get_gid.c \
getlong.c \
get_pid.c \
get_uid.c \
getulong.c \
groupio.c \
groupmem.c \
groupio.h \
@@ -40,7 +35,6 @@ libshadow_la_SOURCES = \
pwmem.c \
sgetgrent.c \
sgetpwent.c \
sgetspent.c \
sgroupio.c \
sgroupio.h\
shadow.c \

File diff suppressed because it is too large Load Diff

View File

@@ -37,18 +37,14 @@
#ifdef WITH_SELINUX
#include <selinux/selinux.h>
#endif
#include "defines.h" /* bool */
/*
* Linked list entry.
*/
struct commonio_entry {
/*@null@*/char *line;
/*@null@*/void *eptr; /* struct passwd, struct spwd, ... */
/*@dependent@*/ /*@null@*/struct commonio_entry *prev;
/*@owned@*/ /*@null@*/struct commonio_entry *next;
bool changed:1;
char *line;
void *eptr; /* struct passwd, struct spwd, ... */
struct commonio_entry *prev, *next;
unsigned int changed:1;
};
/*
@@ -59,12 +55,12 @@ struct commonio_ops {
* Make a copy of the object (for example, struct passwd)
* and all strings pointed by it, in malloced memory.
*/
/*@null@*/ /*@only@*/void *(*dup) (const void *);
void *(*dup) (const void *);
/*
* free() the object including any strings pointed by it.
*/
void (*free) (/*@out@*/ /*@only@*/void *);
void (*free) (void *);
/*
* Return the name of the object (for example, pw_name
@@ -88,7 +84,7 @@ struct commonio_ops {
* fgets and fputs (can be replaced by versions that
* understand line continuation conventions).
*/
/*@null@*/char *(*fgets) (/*@returned@*/ /*@out@*/char *s, int n, FILE *stream);
char *(*fgets) (char *, int, FILE *);
int (*fputs) (const char *, FILE *);
/*
@@ -97,8 +93,8 @@ struct commonio_ops {
* is open or before it is closed.
* They return 0 on failure and 1 on success.
*/
/*@null@*/int (*open_hook) (void);
/*@null@*/int (*close_hook) (void);
int (*open_hook) (void);
int (*close_hook) (void);
};
/*
@@ -113,41 +109,40 @@ struct commonio_db {
/*
* Operations from above.
*/
/*@observer@*/const struct commonio_ops *ops;
struct commonio_ops *ops;
/*
* Currently open file stream.
*/
/*@dependent@*/ /*@null@*/FILE *fp;
FILE *fp;
#ifdef WITH_SELINUX
/*@null@*/security_context_t scontext;
security_context_t scontext;
#endif
/*
* Head, tail, current position in linked list.
*/
/*@owned@*/ /*@null@*/struct commonio_entry *head, *tail;
/*@dependent@*/ /*@null@*/struct commonio_entry *cursor;
struct commonio_entry *head, *tail, *cursor;
/*
* Various flags.
*/
bool changed:1;
bool isopen:1;
bool locked:1;
bool readonly:1;
unsigned int changed:1;
unsigned int isopen:1;
unsigned int locked:1;
unsigned int readonly:1;
};
extern int commonio_setname (struct commonio_db *, const char *);
extern bool commonio_present (const struct commonio_db *db);
extern int commonio_present (const struct commonio_db *);
extern int commonio_lock (struct commonio_db *);
extern int commonio_lock_nowait (struct commonio_db *);
extern int commonio_open (struct commonio_db *, int);
extern /*@observer@*/ /*@null@*/const void *commonio_locate (struct commonio_db *, const char *);
extern const void *commonio_locate (struct commonio_db *, const char *);
extern int commonio_update (struct commonio_db *, const void *);
extern int commonio_remove (struct commonio_db *, const char *);
extern int commonio_rewind (struct commonio_db *);
extern /*@observer@*/ /*@null@*/const void *commonio_next (struct commonio_db *);
extern const void *commonio_next (struct commonio_db *);
extern int commonio_close (struct commonio_db *);
extern int commonio_unlock (struct commonio_db *);
extern void commonio_del_entry (struct commonio_db *,

View File

@@ -4,60 +4,29 @@
#ifndef _DEFINES_H_
#define _DEFINES_H_
#if HAVE_STDBOOL_H
# include <stdbool.h>
#else
# if ! HAVE__BOOL
# ifdef __cplusplus
typedef bool _Bool;
# else
typedef unsigned char _Bool;
# endif
# endif
# define bool _Bool
# define false (0)
# define true (1)
# define __bool_true_false_are_defined 1
#endif
#define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))
/* Take care of NLS matters. */
#ifdef S_SPLINT_S
extern char *setlocale(int categorie, const char *locale);
# define LC_ALL (6)
extern char * bindtextdomain (const char * domainname, const char * dirname);
extern char * textdomain (const char * domainname);
# define _(Text) Text
# define ngettext(Msgid1, Msgid2, N) \
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
#else
#ifdef HAVE_LOCALE_H
#if HAVE_LOCALE_H
# include <locale.h>
#else
# undef setlocale
# define setlocale(category, locale) (NULL)
# ifndef LC_ALL
# define LC_ALL 6
# endif
#endif
#define gettext_noop(String) (String)
/* #define gettext_def(String) "#define String" */
#ifdef ENABLE_NLS
#if ENABLE_NLS
# include <libintl.h>
# define _(Text) gettext (Text)
#else
# undef bindtextdomain
# define bindtextdomain(Domain, Directory) (NULL)
# define bindtextdomain(Domain, Directory) /* empty */
# undef textdomain
# define textdomain(Domain) (NULL)
# define textdomain(Domain) /* empty */
# define _(Text) Text
# define ngettext(Msgid1, Msgid2, N) \
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
#endif
#endif
#if STDC_HEADERS
# include <stdlib.h>
@@ -167,7 +136,7 @@ char *strchr (), *strrchr (), *strtok ();
/* cleaner than lots of #ifdefs everywhere - use this as follows:
SYSLOG((LOG_CRIT, "user %s cracked root", user)); */
#ifdef ENABLE_NLS
#if ENABLE_NLS
/* Temporarily set LC_TIME to "C" to avoid strange dates in syslog.
This is a workaround for a more general syslog(d) design problem -
syslogd should log the current system time for each event, and not
@@ -177,20 +146,17 @@ char *strchr (), *strrchr (), *strtok ();
* --Nekral */
#define SYSLOG(x) \
do { \
char *old_locale = setlocale(LC_ALL, NULL); \
char *saved_locale = NULL; \
if (NULL != old_locale) { \
saved_locale = strdup (old_locale); \
} \
if (NULL != saved_locale) { \
(void) setlocale (LC_ALL, "C"); \
} \
char *saved_locale = setlocale(LC_ALL, NULL); \
if (saved_locale) \
saved_locale = strdup(saved_locale); \
if (saved_locale) \
setlocale(LC_ALL, "C"); \
syslog x ; \
if (NULL != saved_locale) { \
(void) setlocale (LC_ALL, saved_locale); \
free (saved_locale); \
if (saved_locale) { \
setlocale(LC_ALL, saved_locale); \
free(saved_locale); \
} \
} while (false)
} while (0)
#else /* !ENABLE_NLS */
#define SYSLOG(x) syslog x
#endif /* !ENABLE_NLS */
@@ -337,8 +303,6 @@ extern char *strerror ();
#define SHADOW_PASSWD_STRING "x"
#endif
#define SHADOW_SP_FLAG_UNSET ((unsigned long int)-1)
#ifdef WITH_AUDIT
#ifdef __u8 /* in case we use pam < 0.80 */
#undef __u8
@@ -357,29 +321,4 @@ extern char *strerror ();
# define unused
#endif
/* ! Arguments evaluated twice ! */
#ifndef MIN
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(x,y) (((x) > (y)) ? (x) : (y))
#endif
/* Maximum length of usernames */
#ifdef HAVE_UTMPX_H
# include <utmpx.h>
# define USER_NAME_MAX_LENGTH (sizeof (((struct utmpx *)NULL)->ut_user))
#else
# include <utmp.h>
# ifdef HAVE_STRUCT_UTMP_UT_USER
# define USER_NAME_MAX_LENGTH (sizeof (((struct utmp *)NULL)->ut_user))
# else
# ifdef HAVE_STRUCT_UTMP_UT_NAME
# define USER_NAME_MAX_LENGTH (sizeof (((struct utmp *)NULL)->ut_name))
# else
# define USER_NAME_MAX_LENGTH 32
# endif
# endif
#endif
#endif /* _DEFINES_H_ */

View File

@@ -53,12 +53,12 @@ char *pw_encrypt (const char *clear, const char *salt)
* expect us to return NULL, so...
*/
perror ("crypt");
exit (EXIT_FAILURE);
exit (1);
}
/* The GNU crypt does not return NULL if the algorithm is not
* supported, and return a DES encrypted password. */
if ((NULL != salt) && (salt[0] == '$') && (strlen (cp) <= 13))
if (salt && salt[0] == '$' && strlen (cp) <= 13)
{
const char *method;
switch (salt[1])
@@ -82,15 +82,12 @@ char *pw_encrypt (const char *clear, const char *salt)
fprintf (stderr,
_("crypt method not supported by libcrypt? (%s)\n"),
method);
exit (EXIT_FAILURE);
exit (1);
}
if (strlen (cp) != 13) {
if (strlen (cp) != 13)
return cp; /* nonstandard crypt() in libc, better bail out */
}
strcpy (cipher, cp);
return cipher;
}

View File

@@ -32,12 +32,7 @@
/*
* Exit codes used by shadow programs
*/
#define E_SUCCESS EXIT_SUCCESS /* success */
/*
* FIXME: other values should differ from EXIT_FAILURE (and EXIT_SUCCESS).
*
* FIXME: reserve EXIT_FAILURE for internal failures.
*/
#define E_SUCCESS 0 /* success */
#define E_NOPERM 1 /* permission denied */
#define E_USAGE 2 /* invalid command syntax */
#define E_BAD_ARG 3 /* invalid argument to option */

View File

@@ -39,29 +39,23 @@
#ident "$Id$"
/*@null@*/char *fgetsx (/*@returned@*/ /*@out@*/char *buf, int cnt, FILE * f)
char *fgetsx (char *buf, int cnt, FILE * f)
{
char *cp = buf;
char *ep;
while (cnt > 0) {
if (fgets (cp, cnt, f) != cp) {
if (cp == buf) {
if (fgets (cp, cnt, f) == 0) {
if (cp == buf)
return 0;
} else {
else
break;
}
}
ep = strrchr (cp, '\\');
if ((NULL != ep) && (*(ep + 1) == '\n')) {
cnt -= ep - cp;
if (cnt > 0) {
cp = ep;
*cp = '\0';
}
} else {
if ((ep = strrchr (cp, '\\')) && *(ep + 1) == '\n') {
if ((cnt -= ep - cp) > 0)
*(cp = ep) = '\0';
} else
break;
}
}
return buf;
}
@@ -70,10 +64,9 @@ int fputsx (const char *s, FILE * stream)
{
int i;
for (i = 0; '\0' != *s; i++, s++) {
if (putc (*s, stream) == EOF) {
for (i = 0; *s; i++, s++) {
if (putc (*s, stream) == EOF)
return EOF;
}
#if 0 /* The standard getgr*() can't handle that. --marekm */
if (i > (BUFSIZ / 2)) {
@@ -87,4 +80,3 @@ int fputsx (const char *s, FILE * stream)
}
return 0;
}

View File

@@ -1,54 +0,0 @@
/*
* Copyright (c) 2009 , 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 "prototypes.h"
#include "defines.h"
int get_gid (const char *gidstr, gid_t *gid)
{
long long int val;
char *endptr;
errno = 0;
val = strtoll (gidstr, &endptr, 10);
if ( ('\0' == *gidstr)
|| ('\0' != *endptr)
|| (ERANGE == errno)
|| (/*@+longintegral@*/val != (gid_t)val)/*@=longintegral@*/) {
return 0;
}
*gid = (gid_t)val;
return 1;
}

View File

@@ -1,54 +0,0 @@
/*
* Copyright (c) 2009 , 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 "prototypes.h"
#include "defines.h"
int get_pid (const char *pidstr, pid_t *pid)
{
long long int val;
char *endptr;
errno = 0;
val = strtoll (pidstr, &endptr, 10);
if ( ('\0' == *pidstr)
|| ('\0' != *endptr)
|| (ERANGE == errno)
|| (/*@+longintegral@*/val != (pid_t)val)/*@=longintegral@*/) {
return 0;
}
*pid = (pid_t)val;
return 1;
}

View File

@@ -1,54 +0,0 @@
/*
* Copyright (c) 2009 , 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 "prototypes.h"
#include "defines.h"
int get_uid (const char *uidstr, uid_t *uid)
{
long long int val;
char *endptr;
errno = 0;
val = strtoll (uidstr, &endptr, 10);
if ( ('\0' == *uidstr)
|| ('\0' != *endptr)
|| (ERANGE == errno)
|| (/*@+longintegral@*/val != (uid_t)val)/*@=longintegral@*/) {
return 0;
}
*uid = (uid_t)val;
return 1;
}

View File

@@ -39,14 +39,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include "getdef.h"
/*
* A configuration item definition.
*/
struct itemdef {
/*@null@*/const char *name; /* name of the item */
/*@null@*/char *value; /* value given, or NULL if no value */
const char *name; /* name of the item */
char *value; /* value given, or NULL if no value */
};
#define NUMDEFS (sizeof(def_table)/sizeof(def_table[0]))
@@ -132,10 +131,10 @@ static struct itemdef def_table[] = {
#endif
static char def_fname[] = LOGINDEFS; /* login config defs file */
static bool def_loaded = false; /* are defs already loaded? */
static int def_loaded = 0; /* are defs already loaded? */
/* local function prototypes */
static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *);
static struct itemdef *def_find (const char *);
static void def_load (void);
@@ -146,16 +145,14 @@ static void def_load (void);
* defined. First time invoked, will load definitions from the file.
*/
/*@observer@*/ /*@null@*/const char *getdef_str (const char *item)
char *getdef_str (const char *item)
{
struct itemdef *d;
if (!def_loaded) {
if (!def_loaded)
def_load ();
}
d = def_find (item);
return ((NULL == d)? (const char *) NULL : d->value);
return ((d = def_find (item)) == NULL ? (char *) NULL : d->value);
}
@@ -165,18 +162,15 @@ static void def_load (void);
* Return TRUE if specified item is defined as "yes", else FALSE.
*/
bool getdef_bool (const char *item)
int getdef_bool (const char *item)
{
struct itemdef *d;
if (!def_loaded) {
if (!def_loaded)
def_load ();
}
d = def_find (item);
if ((NULL == d) || (NULL == d->value)) {
return false;
}
if ((d = def_find (item)) == NULL || d->value == NULL)
return 0;
return (strcasecmp (d->value, "yes") == 0);
}
@@ -193,27 +187,14 @@ bool getdef_bool (const char *item)
int getdef_num (const char *item, int dflt)
{
struct itemdef *d;
long val;
if (!def_loaded) {
if (!def_loaded)
def_load ();
}
d = def_find (item);
if ((NULL == d) || (NULL == d->value)) {
if ((d = def_find (item)) == NULL || d->value == NULL)
return dflt;
}
if ( (getlong (d->value, &val) == 0)
|| (val > INT_MAX)
|| (val < INT_MIN)) {
fprintf (stderr,
_("configuration error - cannot parse %s value: '%s'"),
item, d->value);
return dflt;
}
return (int) val;
return (int) strtol (d->value, (char **) NULL, 0);
}
@@ -228,27 +209,14 @@ int getdef_num (const char *item, int dflt)
unsigned int getdef_unum (const char *item, unsigned int dflt)
{
struct itemdef *d;
long val;
if (!def_loaded) {
if (!def_loaded)
def_load ();
}
d = def_find (item);
if ((NULL == d) || (NULL == d->value)) {
if ((d = def_find (item)) == NULL || d->value == NULL)
return dflt;
}
if ( (getlong (d->value, &val) == 0)
|| (val < 0)
|| (val > INT_MAX)) {
fprintf (stderr,
_("configuration error - cannot parse %s value: '%s'"),
item, d->value);
return dflt;
}
return (unsigned int) val;
return (unsigned int) strtoul (d->value, (char **) NULL, 0);
}
@@ -263,59 +231,16 @@ unsigned int getdef_unum (const char *item, unsigned int dflt)
long getdef_long (const char *item, long dflt)
{
struct itemdef *d;
long val;
if (!def_loaded) {
if (!def_loaded)
def_load ();
}
d = def_find (item);
if ((NULL == d) || (NULL == d->value)) {
if ((d = def_find (item)) == NULL || d->value == NULL)
return dflt;
}
if (getlong (d->value, &val) == 0) {
fprintf (stderr,
_("configuration error - cannot parse %s value: '%s'"),
item, d->value);
return dflt;
}
return val;
return strtol (d->value, (char **) NULL, 0);
}
/*
* getdef_ulong - get unsigned long numerical value from table of definitions
*
* Returns numeric value of specified item, else the "dflt" value if
* the item is not defined. Octal (leading "0") and hex (leading "0x")
* values are handled.
*/
unsigned long getdef_ulong (const char *item, unsigned long dflt)
{
struct itemdef *d;
unsigned long val;
if (!def_loaded) {
def_load ();
}
d = def_find (item);
if ((NULL == d) || (NULL == d->value)) {
return dflt;
}
if (getulong (d->value, &val) == 0) {
/* FIXME: we should have a getulong */
fprintf (stderr,
_("configuration error - cannot parse %s value: '%s'"),
item, d->value);
return dflt;
}
return val;
}
/*
* putdef_str - override the value read from /etc/login.defs
@@ -327,33 +252,28 @@ int putdef_str (const char *name, const char *value)
struct itemdef *d;
char *cp;
if (!def_loaded) {
if (!def_loaded)
def_load ();
}
/*
* Locate the slot to save the value. If this parameter
* is unknown then "def_find" will print an err message.
*/
d = def_find (name);
if (NULL == d) {
if ((d = def_find (name)) == NULL)
return -1;
}
/*
* Save off the value.
*/
cp = strdup (value);
if (NULL == cp) {
(void) fputs (_("Could not allocate space for config info.\n"),
stderr);
if ((cp = strdup (value)) == NULL) {
fputs (_("Could not allocate space for config info.\n"),
stderr);
SYSLOG ((LOG_ERR, "could not allocate space for config info"));
return -1;
}
if (NULL != d->value) {
if (d->value)
free (d->value);
}
d->value = cp;
return 0;
@@ -367,8 +287,9 @@ int putdef_str (const char *name, const char *value)
* specified configuration option.
*/
static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name)
static struct itemdef *def_find (const char *name)
{
int n;
struct itemdef *ptr;
@@ -376,10 +297,9 @@ static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name)
* Search into the table.
*/
for (ptr = def_table; NULL != ptr->name; ptr++) {
if (strcmp (ptr->name, name) == 0) {
for (ptr = def_table; ptr->name; ptr++) {
if (!(n = strcmp (ptr->name, name)))
return ptr;
}
}
/*
@@ -387,8 +307,9 @@ static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name)
*/
fprintf (stderr,
_("configuration error - unknown item '%s' (notify administrator)\n"),
name);
_
("configuration error - unknown item '%s' (notify administrator)\n"),
name);
SYSLOG ((LOG_CRIT, "unknown configuration item `%s'", name));
return (struct itemdef *) NULL;
}
@@ -408,35 +329,31 @@ static void def_load (void)
/*
* 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);
if ((fp = fopen (def_fname, "r")) == NULL) {
SYSLOG ((LOG_CRIT, "cannot open login definitions %s [%m]",
def_fname));
exit (1);
}
/*
* Set the initialized flag.
* (do it early to prevent recursion in putdef_str())
*/
def_loaded = true;
++def_loaded;
/*
* Go through all of the lines in the file.
*/
while (fgets (buf, (int) sizeof (buf), fp) != NULL) {
while (fgets (buf, sizeof (buf), fp) != NULL) {
/*
* Trim trailing whitespace.
*/
for (i = (int) strlen (buf) - 1; i >= 0; --i) {
if (!isspace (buf[i])) {
for (i = strlen (buf) - 1; i >= 0; --i) {
if (!isspace (buf[i]))
break;
}
}
i++;
buf[i] = '\0';
buf[++i] = '\0';
/*
* Break the line into two fields.
@@ -455,19 +372,14 @@ static void def_load (void)
/*
* 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 (name, value);
putdef_str (name, value);
}
if (ferror (fp) != 0) {
int err = errno;
SYSLOG ((LOG_CRIT, "cannot read login definitions %s [%s]",
def_fname, strerror (err)));
exit (EXIT_FAILURE);
if (ferror (fp)) {
SYSLOG ((LOG_CRIT, "cannot read login definitions %s [%m]",
def_fname));
exit (1);
}
(void) fclose (fp);
@@ -484,22 +396,18 @@ int main (int argc, char **argv)
def_load ();
for (i = 0; i < NUMDEFS; ++i) {
d = def_find (def_table[i].name);
if (NULL == d) {
if ((d = def_find (def_table[i].name)) == NULL)
printf ("error - lookup '%s' failed\n",
def_table[i].name);
} else {
def_table[i].name);
else
printf ("%4d %-24s %s\n", i + 1, d->name, d->value);
}
}
for (i = 1; i < argc; i++) {
cp = getdef_str (argv[1]);
if (NULL != cp) {
if ((cp = getdef_str (argv[1])) != NULL)
printf ("%s `%s'\n", argv[1], cp);
} else {
else
printf ("%s not found\n", argv[1]);
}
}
exit (EXIT_SUCCESS);
exit (0);
}
#endif

View File

@@ -2,7 +2,6 @@
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2002 - 2006, Tomasz Kłoczko
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,12 +32,11 @@
#define _GETDEF_H
/* getdef.c */
extern bool getdef_bool (const char *);
extern int getdef_bool (const char *);
extern long getdef_long (const char *, long);
extern int getdef_num (const char *, int);
extern unsigned long getdef_ulong (const char *, unsigned long);
extern unsigned int getdef_unum (const char *, unsigned int);
extern /*@observer@*/ /*@null@*/const char *getdef_str (const char *);
extern char *getdef_str (const char *);
extern int putdef_str (const char *, const char *);
/* default UMASK value if not specified in /etc/login.defs */

View File

@@ -1,65 +0,0 @@
/*
* Copyright (c) 2007 - 2009, 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: getlong.c 2763 2009-04-23 09:57:03Z nekral-guest $"
#include <stdlib.h>
#include <errno.h>
#include "prototypes.h"
/*
* getulong - extract an unsigned long integer provided by the numstr string in *result
*
* It supports decimal, hexadecimal or octal representations.
*
* Returns 0 on failure, 1 on success.
*/
int getulong (const char *numstr, /*@out@*/unsigned long int *result)
{
long long int val;
char *endptr;
errno = 0;
val = strtoll (numstr, &endptr, 0);
if ( ('\0' == *numstr)
|| ('\0' != *endptr)
|| (ERANGE == errno)
/*@+ignoresigns@*/
|| (val != (unsigned long int)val)
/*@=ignoresigns@*/
) {
return 0;
}
*result = (unsigned long int)val;
return 1;
}

View File

@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,7 +35,6 @@
#ident "$Id$"
#include <assert.h>
#include <stdio.h>
#include "prototypes.h"
@@ -44,24 +43,29 @@
#include "getdef.h"
#include "groupio.h"
static /*@null@*/struct commonio_entry *merge_group_entries (
/*@null@*/ /*@returned@*/struct commonio_entry *gr1,
/*@null@*/struct commonio_entry *gr2);
static struct commonio_entry *merge_group_entries (struct commonio_entry *gr1,
struct commonio_entry *gr2);
static int split_groups (unsigned int max_members);
static int group_open_hook (void);
static /*@null@*/ /*@only@*/void *group_dup (const void *ent)
static void *group_dup (const void *ent)
{
const struct group *gr = ent;
return __gr_dup (gr);
}
static void group_free (/*@out@*/ /*@only@*/void *ent)
static void group_free (void *ent)
{
struct group *gr = ent;
gr_free (gr);
free (gr->gr_name);
free (gr->gr_passwd);
while (*(gr->gr_mem)) {
free (*(gr->gr_mem));
gr->gr_mem++;
}
free (gr);
}
static const char *group_getname (const void *ent)
@@ -87,9 +91,8 @@ static int group_close_hook (void)
{
unsigned int max_members = getdef_unum("MAX_MEMBERS_PER_GROUP", 0);
if (0 == max_members) {
if (0 == max_members)
return 1;
}
return split_groups (max_members);
}
@@ -106,7 +109,7 @@ static struct commonio_ops group_ops = {
group_close_hook
};
static /*@owned@*/struct commonio_db group_db = {
static struct commonio_db group_db = {
GROUP_FILE, /* filename */
&group_ops, /* ops */
NULL, /* fp */
@@ -116,22 +119,17 @@ static /*@owned@*/struct commonio_db group_db = {
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
false, /* changed */
false, /* isopen */
false, /* locked */
false /* readonly */
0, /* changed */
0, /* isopen */
0, /* locked */
0 /* readonly */
};
int gr_setdbname (const char *filename)
int gr_name (const char *filename)
{
return commonio_setname (&group_db, filename);
}
/*@observer@*/const char *gr_dbname (void)
{
return group_db.filename;
}
int gr_lock (void)
{
return commonio_lock (&group_db);
@@ -142,12 +140,12 @@ int gr_open (int mode)
return commonio_open (&group_db, mode);
}
/*@observer@*/ /*@null@*/const struct group *gr_locate (const char *name)
const struct group *gr_locate (const char *name)
{
return commonio_locate (&group_db, name);
}
/*@observer@*/ /*@null@*/const struct group *gr_locate_gid (gid_t gid)
const struct group *gr_locate_gid (gid_t gid)
{
const struct group *grp;
@@ -174,7 +172,7 @@ int gr_rewind (void)
return commonio_rewind (&group_db);
}
/*@observer@*/ /*@null@*/const struct group *gr_next (void)
const struct group *gr_next (void)
{
return commonio_next (&group_db);
}
@@ -191,15 +189,15 @@ int gr_unlock (void)
void __gr_set_changed (void)
{
group_db.changed = true;
group_db.changed = 1;
}
/*@dependent@*/ /*@null@*/struct commonio_entry *__gr_get_head (void)
struct commonio_entry *__gr_get_head (void)
{
return group_db.head;
}
/*@observer@*/const struct commonio_db *__gr_get_db (void)
struct commonio_db *__gr_get_db (void)
{
return &group_db;
}
@@ -213,23 +211,20 @@ static int gr_cmp (const void *p1, const void *p2)
{
gid_t u1, u2;
if ((*(struct commonio_entry **) p1)->eptr == NULL) {
if ((*(struct commonio_entry **) p1)->eptr == NULL)
return 1;
}
if ((*(struct commonio_entry **) p2)->eptr == NULL) {
if ((*(struct commonio_entry **) p2)->eptr == NULL)
return -1;
}
u1 = ((struct group *) (*(struct commonio_entry **) p1)->eptr)->gr_gid;
u2 = ((struct group *) (*(struct commonio_entry **) p2)->eptr)->gr_gid;
if (u1 < u2) {
if (u1 < u2)
return -1;
} else if (u1 > u2) {
else if (u1 > u2)
return 1;
} else {
else
return 0;
}
}
/* Sort entries by GID */
@@ -243,12 +238,11 @@ static int group_open_hook (void)
unsigned int max_members = getdef_unum("MAX_MEMBERS_PER_GROUP", 0);
struct commonio_entry *gr1, *gr2;
if (0 == max_members) {
if (0 == max_members)
return 1;
}
for (gr1 = group_db.head; NULL != gr1; gr1 = gr1->next) {
for (gr2 = gr1->next; NULL != gr2; gr2 = gr2->next) {
for (gr1 = group_db.head; gr1; gr1 = gr1->next) {
for (gr2 = gr1->next; gr2; gr2 = gr2->next) {
struct group *g1 = (struct group *)gr1->eptr;
struct group *g2 = (struct group *)gr2->eptr;
if (NULL != g1 &&
@@ -263,15 +257,11 @@ static int group_open_hook (void)
if (NULL == gr1)
return 0;
/* Unlink gr2 */
if (NULL != gr2->next) {
if (NULL != gr2->next)
gr2->next->prev = gr2->prev;
}
/* gr2 does not start with head */
assert (NULL != gr2->prev);
gr2->prev->next = gr2->next;
}
}
assert (NULL != gr1);
}
return 1;
@@ -289,16 +279,15 @@ static int group_open_hook (void)
* the modified first entry on success, or NULL on failure (with errno
* set).
*/
static /*@null@*/struct commonio_entry *merge_group_entries (
/*@null@*/ /*@returned@*/struct commonio_entry *gr1,
/*@null@*/struct commonio_entry *gr2)
static struct commonio_entry *merge_group_entries (struct commonio_entry *gr1,
struct commonio_entry *gr2)
{
struct group *gptr1;
struct group *gptr2;
char **new_members;
size_t members = 0;
int members = 0;
char *new_line;
size_t new_line_len, i;
int new_line_len, i;
if (NULL == gr2 || NULL == gr1) {
errno = EINVAL;
return NULL;
@@ -327,36 +316,30 @@ static /*@null@*/struct commonio_entry *merge_group_entries (
for (i=0; NULL != gptr2->gr_mem[i]; i++) {
char **pmember = gptr1->gr_mem;
while (NULL != *pmember) {
if (0 == strcmp(*pmember, gptr2->gr_mem[i])) {
if (0 == strcmp(*pmember, gptr2->gr_mem[i]))
break;
}
pmember++;
}
if (NULL == *pmember) {
if (NULL == *pmember)
members++;
}
}
new_members = (char **)malloc ( (members+1) * sizeof(char*) );
if (NULL == new_members) {
free (new_line);
errno = ENOMEM;
return NULL;
}
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];
}
members = i;
for (i=0; NULL != gptr2->gr_mem[i]; i++) {
char **pmember = new_members;
while (NULL != *pmember) {
if (0 == strcmp(*pmember, gptr2->gr_mem[i])) {
if (0 == strcmp(*pmember, gptr2->gr_mem[i]))
break;
}
pmember++;
}
if (NULL == *pmember) {
new_members[members] = gptr2->gr_mem[i];
members++;
new_members[members++] = gptr2->gr_mem[i];
new_members[members] = NULL;
}
}
@@ -377,7 +360,7 @@ static int split_groups (unsigned int max_members)
{
struct commonio_entry *gr;
for (gr = group_db.head; NULL != gr; gr = gr->next) {
for (gr = group_db.head; gr; gr = gr->next) {
struct group *gptr = (struct group *)gr->eptr;
struct commonio_entry *new;
struct group *new_gptr;
@@ -399,13 +382,12 @@ static int split_groups (unsigned int max_members)
}
new->eptr = group_dup(gr->eptr);
if (NULL == new->eptr) {
free (new);
errno = ENOMEM;
return 0;
}
new_gptr = (struct group *)new->eptr;
new->line = NULL;
new->changed = true;
new->changed = 1;
/* Enforce the maximum number of members on gptr */
gptr->gr_mem[max_members] = NULL;

View File

@@ -31,25 +31,17 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* $Id$ */
#ifndef _GROUPIO_H
#define _GROUPIO_H
#include <sys/types.h>
#include <grp.h>
extern int gr_close (void);
extern /*@observer@*/ /*@null@*/const struct group *gr_locate (const char *name);
extern /*@observer@*/ /*@null@*/const struct group *gr_locate_gid (gid_t gid);
extern const struct group *gr_locate (const char *);
extern const struct group *gr_locate_gid (gid_t gid);
extern int gr_lock (void);
extern int gr_setdbname (const char *filename);
extern /*@observer@*/const char *gr_dbname (void);
extern /*@observer@*/ /*@null@*/const struct group *gr_next (void);
extern int gr_open (int mode);
extern int gr_remove (const char *name);
extern int gr_name (const char *);
extern const struct group *gr_next (void);
extern int gr_open (int);
extern int gr_remove (const char *);
extern int gr_rewind (void);
extern int gr_unlock (void);
extern int gr_update (const struct group *gr);
extern int gr_update (const struct group *);
extern int gr_sort (void);
#endif

View File

@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François
* Copyright (c) 2007 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,51 +39,29 @@
#include "defines.h"
#include "groupio.h"
/*@null@*/ /*@only@*/struct group *__gr_dup (const struct group *grent)
struct group *__gr_dup (const struct group *grent)
{
struct group *gr;
int i;
gr = (struct group *) malloc (sizeof *gr);
if (NULL == gr) {
if (!(gr = (struct group *) malloc (sizeof *gr)))
return NULL;
}
*gr = *grent;
gr->gr_name = strdup (grent->gr_name);
if (NULL == gr->gr_name) {
if (!(gr->gr_name = strdup (grent->gr_name)))
return NULL;
}
gr->gr_passwd = strdup (grent->gr_passwd);
if (NULL == gr->gr_passwd) {
if (!(gr->gr_passwd = strdup (grent->gr_passwd)))
return NULL;
}
for (i = 0; grent->gr_mem[i]; i++);
gr->gr_mem = (char **) malloc ((i + 1) * sizeof (char *));
if (NULL == gr->gr_mem) {
if (!gr->gr_mem)
return NULL;
}
for (i = 0; grent->gr_mem[i]; i++) {
gr->gr_mem[i] = strdup (grent->gr_mem[i]);
if (NULL == gr->gr_mem[i]) {
if (!gr->gr_mem[i])
return NULL;
}
}
gr->gr_mem[i] = NULL;
return gr;
}
void gr_free (/*@out@*/ /*@only@*/struct group *grent)
{
free (grent->gr_name);
memzero (grent->gr_passwd, strlen (grent->gr_passwd));
free (grent->gr_passwd);
while (*(grent->gr_mem)) {
free (*(grent->gr_mem));
grent->gr_mem++;
}
free (grent);
}

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2008 - 2009, Nicolas François
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,20 +40,21 @@
#include <stdio.h>
#include "prototypes.h"
#include "defines.h"
static /*@null@*/FILE *shadow;
static /*@null@*//*@only@*/char **members = NULL;
static FILE *shadow;
static char sgrbuf[BUFSIZ * 4];
static char **members = NULL;
static size_t nmembers = 0;
static /*@null@*//*@only@*/char **admins = NULL;
static char **admins = NULL;
static size_t nadmins = 0;
static struct sgrp sgroup;
#define FIELDS 4
#ifdef USE_NIS
static bool nis_used;
static bool nis_ignore;
static int nis_used;
static int nis_ignore;
static enum { native, start, middle, native2 } nis_state;
static bool nis_bound;
static int nis_bound;
static char *nis_domain;
static char *nis_key;
static int nis_keylen;
@@ -64,6 +65,19 @@ static int nis_vallen;
#endif
#ifdef USE_NIS
/*
* __setsgNIS - turn on or off NIS searches
*/
void __setsgNIS (int flag)
{
nis_ignore = !flag;
if (nis_ignore)
nis_used = 0;
}
/*
* bind_nis - bind to NIS server
*/
@@ -73,35 +87,29 @@ static int bind_nis (void)
if (yp_get_default_domain (&nis_domain))
return -1;
nis_bound = true;
nis_bound = 1;
return 0;
}
#endif
static /*@null@*/char **build_list (char *s, char **list[], size_t * nlist)
static char **build_list (char *s, char **list[], size_t * nlist)
{
char **ptr = *list;
size_t nelem = *nlist, size;
while (s != NULL && *s != '\0') {
size = (nelem + 1) * sizeof (ptr);
ptr = realloc (*list, size);
if (NULL != ptr) {
ptr[nelem] = s;
nelem++;
if ((ptr = realloc (*list, size)) != NULL) {
ptr[nelem++] = s;
*list = ptr;
*nlist = nelem;
s = strchr (s, ',');
if (NULL != s) {
*s = '\0';
s++;
}
if ((s = strchr (s, ',')))
*s++ = '\0';
}
}
size = (nelem + 1) * sizeof (ptr);
ptr = realloc (*list, size);
if (NULL != ptr) {
ptr[nelem] = NULL;
if ((ptr = realloc (*list, size)) != NULL) {
ptr[nelem] = '\0';
*list = ptr;
}
return ptr;
@@ -112,60 +120,41 @@ void setsgent (void)
#ifdef USE_NIS
nis_state = native;
#endif
if (NULL != shadow) {
if (shadow)
rewind (shadow);
} else {
else
shadow = fopen (SGROUP_FILE, "r");
}
}
void endsgent (void)
{
if (NULL != shadow) {
if (shadow)
(void) fclose (shadow);
}
shadow = (FILE *) 0;
}
/*@observer@*//*@null@*/struct sgrp *sgetsgent (const char *string)
struct sgrp *sgetsgent (const char *string)
{
static char *sgrbuf = NULL;
static size_t sgrbuflen = 0;
char *fields[FIELDS];
char *cp;
int i;
size_t len = strlen (string) + 1;
if (len > sgrbuflen) {
char *buf = (char *) realloc (sgrbuf, sizeof (char) * len);
if (NULL == buf) {
return NULL;
}
sgrbuf = buf;
sgrbuflen = len;
}
strncpy (sgrbuf, string, (int) sizeof sgrbuf - 1);
sgrbuf[sizeof sgrbuf - 1] = '\0';
strncpy (sgrbuf, string, len);
sgrbuf[len-1] = '\0';
cp = strrchr (sgrbuf, '\n');
if (NULL != cp) {
if ((cp = strrchr (sgrbuf, '\n')))
*cp = '\0';
}
/*
* There should be exactly 4 colon separated fields. Find
* all 4 of them and save the starting addresses in fields[].
*/
for (cp = sgrbuf, i = 0; (i < FIELDS) && (NULL != cp); i++) {
for (cp = sgrbuf, i = 0; i < FIELDS && cp; i++) {
fields[i] = cp;
cp = strchr (cp, ':');
if (NULL != cp) {
if ((cp = strchr (cp, ':')))
*cp++ = '\0';
}
}
/*
@@ -173,26 +162,24 @@ void endsgent (void)
* the line is invalid.
*/
if ((NULL != cp) || (i != FIELDS)) {
if (cp || i != FIELDS)
#ifdef USE_NIS
if (!IS_NISCHAR (fields[0][0])) {
if (!IS_NISCHAR (fields[0][0]))
return 0;
} else {
nis_used = true;
}
else
nis_used = 1;
#else
return 0;
#endif
}
sgroup.sg_name = fields[0];
sgroup.sg_passwd = fields[1];
if (0 != nadmins) {
if (nadmins) {
nadmins = 0;
free (admins);
admins = NULL;
}
if (0 != nmembers) {
if (nmembers) {
nmembers = 0;
free (members);
members = NULL;
@@ -210,76 +197,44 @@ void endsgent (void)
* converts it to a (struct sgrp). NULL is returned on EOF.
*/
/*@observer@*//*@null@*/struct sgrp *fgetsgent (/*@null@*/FILE * fp)
struct sgrp *fgetsgent (FILE * fp)
{
static size_t buflen = 0;
static char *buf = NULL;
char buf[sizeof sgrbuf];
char *cp;
struct sgrp *ret;
if (0 == buflen) {
buf = (char *) malloc (BUFSIZ);
if (NULL == buf) {
return NULL;
}
}
if (NULL == fp) {
return NULL;
}
if (!fp)
return (0);
#ifdef USE_NIS
while (fgetsx (buf, (int) sizeof buf, fp) == buf)
while (fgetsx (buf, sizeof buf, fp) != (char *) 0)
#else
if (fgetsx (buf, (int) sizeof buf, fp) == buf)
if (fgetsx (buf, sizeof buf, fp) != (char *) 0)
#endif
{
while ( ((cp = strrchr (buf, '\n')) == NULL)
&& (feof (fp) == 0)) {
size_t len;
cp = (char *) realloc (buf, buflen*2);
if (NULL == cp) {
return NULL;
}
buf = cp;
buflen *= 2;
len = strlen (buf);
if (fgetsx (&buf[len],
(int) (buflen - len),
fp) != &buf[len]) {
return NULL;
}
}
cp = strrchr (buf, '\n');
if (NULL != cp) {
if ((cp = strchr (buf, '\n')))
*cp = '\0';
}
#ifdef USE_NIS
if (nis_ignore && IS_NISCHAR (buf[0])) {
if (nis_ignore && IS_NISCHAR (buf[0]))
continue;
}
#endif
return (sgetsgent (buf));
}
return NULL;
return 0;
}
/*
* getsgent - get a single shadow group entry
*/
/*@observer@*//*@null@*/struct sgrp *getsgent (void)
struct sgrp *getsgent (void)
{
#ifdef USE_NIS
bool nis_1_group = false;
int nis_1_group = 0;
struct sgrp *val;
char buf[BUFSIZ];
#endif
if (NULL == shadow) {
if (!shadow)
setsgent ();
}
#ifdef USE_NIS
again:
@@ -294,10 +249,8 @@ void endsgent (void)
* NULL right away if there is none.
*/
val = fgetsgent (shadow);
if (NULL == val) {
if (!(val = fgetsgent (shadow)))
return 0;
}
/*
* If this entry began with a NIS escape character, we have
@@ -306,11 +259,10 @@ void endsgent (void)
*/
if (IS_NISCHAR (val->sg_name[0])) {
if ('\0' != val->sg_name[1]) {
nis_1_group = true;
} else {
if (val->sg_name[1])
nis_1_group = 1;
else
nis_state = start;
}
}
/*
@@ -318,18 +270,16 @@ void endsgent (void)
* use a NIS map, it must be a regular local group.
*/
if (!nis_1_group && (nis_state != start)) {
if (nis_1_group == 0 && nis_state != start)
return val;
}
/*
* If this is an escape to use an NIS map, switch over to
* that bunch of code.
*/
if (nis_state == start) {
if (nis_state == start)
goto again;
}
/*
* NEEDSWORK. Here we substitute pieces-parts of this entry.
@@ -337,7 +287,7 @@ void endsgent (void)
return 0;
} else {
if (!nis_bound) {
if (nis_bound == 0) {
if (bind_nis ()) {
nis_state = native2;
goto again;
@@ -369,11 +319,12 @@ void endsgent (void)
* getsgnam - get a shadow group entry by name
*/
/*@observer@*//*@null@*/struct sgrp *getsgnam (const char *name)
struct sgrp *getsgnam (const char *name)
{
struct sgrp *sgrp;
#ifdef USE_NIS
char buf[BUFSIZ];
static char save_name[16];
int nis_disabled = 0;
#endif
@@ -388,9 +339,8 @@ void endsgent (void)
* Search the gshadow.byname map for this group.
*/
if (!nis_bound) {
if (!nis_bound)
bind_nis ();
}
if (nis_bound) {
char *cp;
@@ -398,14 +348,11 @@ void endsgent (void)
if (yp_match (nis_domain, "gshadow.byname", name,
strlen (name), &nis_val,
&nis_vallen) == 0) {
cp = strchr (nis_val, '\n');
if (NULL != cp) {
if (cp = strchr (nis_val, '\n'))
*cp = '\0';
}
nis_state = middle;
sgrp = sgetsgent (nis_val);
if (NULL != sgrp) {
if (sgrp = sgetsgent (nis_val)) {
strcpy (save_name, sgrp->sg_name);
nis_key = save_name;
nis_keylen = strlen (save_name);
@@ -418,19 +365,20 @@ void endsgent (void)
#endif
#ifdef USE_NIS
if (nis_used) {
nis_ignore = true;
nis_disabled = true;
nis_ignore++;
nis_disabled++;
}
#endif
while ((sgrp = getsgent ()) != (struct sgrp *) 0) {
if (strcmp (name, sgrp->sg_name) == 0) {
if (strcmp (name, sgrp->sg_name) == 0)
break;
}
}
#ifdef USE_NIS
nis_ignore = false;
nis_ignore--;
#endif
return sgrp;
if (sgrp)
return sgrp;
return (0);
}
/*
@@ -447,23 +395,19 @@ int putsgent (const struct sgrp *sgrp, FILE * fp)
int i;
size_t size;
if ((NULL == fp) || (NULL == sgrp)) {
if (!fp || !sgrp)
return -1;
}
/* calculate the required buffer size */
size = strlen (sgrp->sg_name) + strlen (sgrp->sg_passwd) + 10;
for (i = 0; (NULL != sgrp->sg_adm) && (NULL != sgrp->sg_adm[i]); i++) {
for (i = 0; sgrp->sg_adm && sgrp->sg_adm[i]; i++)
size += strlen (sgrp->sg_adm[i]) + 1;
}
for (i = 0; (NULL != sgrp->sg_mem) && (NULL != sgrp->sg_mem[i]); i++) {
for (i = 0; sgrp->sg_mem && sgrp->sg_mem[i]; i++)
size += strlen (sgrp->sg_mem[i]) + 1;
}
buf = malloc (size);
if (NULL == buf) {
if (!buf)
return -1;
}
cp = buf;
/*
@@ -483,32 +427,27 @@ int putsgent (const struct sgrp *sgrp, FILE * fp)
* with a ",".
*/
for (i = 0; NULL != sgrp->sg_adm[i]; i++) {
if (i > 0) {
for (i = 0; sgrp->sg_adm[i]; i++) {
if (i > 0)
*cp++ = ',';
}
strcpy (cp, sgrp->sg_adm[i]);
cp += strlen (cp);
}
*cp = ':';
cp++;
*cp++ = ':';
/*
* Now do likewise with the group members.
*/
for (i = 0; NULL != sgrp->sg_mem[i]; i++) {
if (i > 0) {
*cp = ',';
cp++;
}
for (i = 0; sgrp->sg_mem[i]; i++) {
if (i > 0)
*cp++ = ',';
strcpy (cp, sgrp->sg_mem[i]);
cp += strlen (cp);
}
*cp = '\n';
cp++;
*cp++ = '\n';
*cp = '\0';
/*

View File

@@ -54,18 +54,18 @@ struct sgrp {
#include <stdio.h> /* for FILE */
#if __STDC__
/*@observer@*//*@null@*/struct sgrp *getsgent (void);
/*@observer@*//*@null@*/struct sgrp *getsgnam (const char *);
/*@observer@*//*@null@*/struct sgrp *sgetsgent (const char *);
/*@observer@*//*@null@*/struct sgrp *fgetsgent (/*@null@*/FILE *);
struct sgrp *getsgent (void);
struct sgrp *getsgnam (const char *);
struct sgrp *sgetsgent (const char *);
struct sgrp *fgetsgent (FILE *);
void setsgent (void);
void endsgent (void);
int putsgent (const struct sgrp *, FILE *);
#else
/*@observer@*//*@null@*/struct sgrp *getsgent ();
/*@observer@*//*@null@*/struct sgrp *getsgnam ();
/*@observer@*//*@null@*/struct sgrp *sgetsgent ();
/*@observer@*//*@null@*/struct sgrp *fgetsgent ();
struct sgrp *getsgent ();
struct sgrp *getsgnam ();
struct sgrp *sgetsgent ();
struct sgrp *fgetsgent ();
void setsgent ();
void endsgent ();
int putsgent ();

View File

@@ -1,12 +1,7 @@
/* Author: Peter Vrabec <pvrabec@redhat.com> */
#include <config.h>
#ifdef USE_NSCD
/* because of TEMP_FAILURE_RETRY */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <features.h>
#include <stdio.h>
@@ -16,11 +11,8 @@
#include <errno.h>
#include <sys/wait.h>
#include <sys/types.h>
#include "defines.h"
#include "nscd.h"
#define MSG_NSCD_FLUSH_CACHE_FAILED "Failed to flush the nscd cache.\n"
/*
* nscd_flush_cache - flush specified service buffer in nscd cache
*/
@@ -32,34 +24,27 @@ int nscd_flush_cache (const char *service)
char *spawnedEnv[] = {NULL};
/* spawn process */
err = posix_spawn (&pid, spawnedArgs[0], NULL, NULL,
spawnedArgs, spawnedEnv);
if(0 != err)
if( (err=posix_spawn(&pid, spawnedArgs[0], NULL, NULL,
spawnedArgs, spawnedEnv)) !=0 )
{
(void) fputs (_(MSG_NSCD_FLUSH_CACHE_FAILED), stderr);
(void) fprintf (stderr, "posix_spawn() error=%d\n", err);
fprintf(stderr, "posix_spawn() error=%d\n", err);
return -1;
}
/* Wait for the spawned process to exit */
/* Wait for the spawned process to exit */
termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
if (-1 == termpid)
if (termpid == -1)
{
(void) fputs (_(MSG_NSCD_FLUSH_CACHE_FAILED), stderr);
perror("waitpid");
return -1;
}
else if (termpid != pid)
{
(void) fputs (_(MSG_NSCD_FLUSH_CACHE_FAILED), stderr);
(void) fprintf (stderr, "waitpid returned %ld != %ld\n",
(long int) termpid, (long int) pid);
fprintf(stderr, "waitpid returned %ld != %ld\n",
(long int) termpid, (long int) pid);
return -1;
}
return 0;
}
#else /* USE_NSCD */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* USE_NSCD */

View File

@@ -4,10 +4,6 @@
/*
* nscd_flush_cache - flush specified service buffer in nscd cache
*/
#ifdef USE_NSCD
extern int nscd_flush_cache (const char *service);
#else
#define nscd_flush_cache(service) (0)
#endif
#endif

View File

@@ -28,31 +28,24 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <security/pam_appl.h>
#ifdef HAVE_SECURITY_PAM_MISC_H
# include <security/pam_misc.h>
#endif
#ifdef HAVE_SECURITY_OPENPAM_H
# include <security/openpam.h>
#endif
#include <security/pam_misc.h>
static struct pam_conv conv = {
SHADOW_PAM_CONVERSATION,
misc_conv,
NULL
};
/* compatibility with different versions of Linux-PAM */
#if !HAVE_DECL_PAM_ESTABLISH_CRED
#ifndef PAM_ESTABLISH_CRED
#define PAM_ESTABLISH_CRED PAM_CRED_ESTABLISH
#endif
#if !HAVE_DECL_PAM_DELETE_CRED
#ifndef PAM_DELETE_CRED
#define PAM_DELETE_CRED PAM_CRED_DELETE
#endif
#if !HAVE_DECL_PAM_NEW_AUTHTOK_REQD
#ifndef PAM_NEW_AUTHTOK_REQD
#define PAM_NEW_AUTHTOK_REQD PAM_AUTHTOKEN_REQD
#endif
#if !HAVE_DECL_PAM_DATA_SILENT
#ifndef PAM_DATA_SILENT
#define PAM_DATA_SILENT 0
#endif

View File

@@ -57,19 +57,15 @@ static int portcmp (const char *pattern, const char *port)
{
const char *orig = port;
while (('\0' != *pattern) && (*pattern == *port)) {
pattern++;
port++;
}
while (*pattern && *pattern == *port)
pattern++, port++;
if (('\0' == *pattern) && ('\0' == *port)) {
if (*pattern == 0 && *port == 0)
return 0;
}
if (('S' == orig[0]) && ('U' == orig[1]) && ('\0' == orig[2])) {
if (orig[0] == 'S' && orig[1] == 'U' && orig[2] == '\0')
return 1;
}
return (*pattern == '*') ? 0 : 1;
return *pattern == '*' ? 0 : 1;
}
/*
@@ -81,11 +77,10 @@ static int portcmp (const char *pattern, const char *port)
static void setportent (void)
{
if (NULL != ports) {
if (ports)
rewind (ports);
} else {
else
ports = fopen (PORTS, "r");
}
}
/*
@@ -98,9 +93,8 @@ static void setportent (void)
static void endportent (void)
{
if (NULL != ports) {
(void) fclose (ports);
}
if (ports)
fclose (ports);
ports = (FILE *) 0;
}
@@ -131,11 +125,10 @@ static struct port *getportent (void)
* since we want to search from the beginning each time.
*/
if (NULL == ports) {
if (!ports)
setportent ();
}
if (NULL == ports) {
if (!ports) {
errno = saveerr;
return 0;
}
@@ -157,13 +150,12 @@ static struct port *getportent (void)
* is a '\n'. Lines which begin with '#' are all ignored.
*/
if (fgets (buf, (int) sizeof buf, ports) == 0) {
if (fgets (buf, sizeof buf, ports) == 0) {
errno = saveerr;
return 0;
}
if ('#' == buf[0]) {
if (buf[0] == '#')
goto again;
}
/*
* Get the name of the TTY device. It is the first colon
@@ -177,24 +169,19 @@ static struct port *getportent (void)
port.pt_names = ttys;
for (cp = buf, j = 0; j < PORT_TTY; j++) {
port.pt_names[j] = cp;
while (('\0' != *cp) && (':' != *cp) && (',' != *cp)) {
while (*cp && *cp != ':' && *cp != ',')
cp++;
}
if ('\0' == *cp) {
if (!*cp)
goto again; /* line format error */
}
if (':' == *cp) { /* end of tty name list */
if (*cp == ':') /* end of tty name list */
break;
}
if (',' == *cp) { /* end of current tty name */
if (*cp == ',') /* end of current tty name */
*cp++ = '\0';
}
}
*cp = '\0';
cp++;
*cp++ = 0;
port.pt_names[j + 1] = (char *) 0;
/*
@@ -204,29 +191,24 @@ static struct port *getportent (void)
* The last entry in the list is a (char *) 0 pointer.
*/
if (':' != *cp) {
if (*cp != ':') {
port.pt_users = users;
port.pt_users[0] = cp;
for (j = 1; ':' != *cp; cp++) {
if ((',' == *cp) && (j < PORT_IDS)) {
*cp = '\0';
cp++;
port.pt_users[j] = cp;
j++;
for (j = 1; *cp != ':'; cp++) {
if (*cp == ',' && j < PORT_IDS) {
*cp++ = 0;
port.pt_users[j++] = cp;
}
}
port.pt_users[j] = 0;
} else {
} else
port.pt_users = 0;
}
if (':' != *cp) {
if (*cp != ':')
goto again;
}
*cp = '\0';
cp++;
*cp++ = 0;
/*
* Get the list of valid times. The times field is the third
@@ -241,7 +223,7 @@ static struct port *getportent (void)
* the starting time. Days are presumed to wrap at 0000.
*/
if ('\0' == *cp) {
if (*cp == '\0') {
port.pt_times = 0;
return &port;
}
@@ -252,7 +234,7 @@ static struct port *getportent (void)
* Get the next comma separated entry
*/
for (j = 0; ('\0' != *cp) && (j < PORT_TIMES); j++) {
for (j = 0; *cp && j < PORT_TIMES; j++) {
/*
* Start off with no days of the week
@@ -266,9 +248,7 @@ static struct port *getportent (void)
* week or the other two values.
*/
for (i = 0;
('\0' != cp[i]) && ('\0' != cp[i + 1]) && isalpha (cp[i]);
i += 2) {
for (i = 0; cp[i] && cp[i + 1] && isalpha (cp[i]); i += 2) {
switch ((cp[i] << 8) | (cp[i + 1])) {
case ('S' << 8) | 'u':
port.pt_times[j].t_days |= 01;
@@ -307,9 +287,8 @@ static struct port *getportent (void)
* The default is 'Al' if no days were seen.
*/
if (0 == i) {
if (i == 0)
port.pt_times[j].t_days = 0177;
}
/*
* The start and end times are separated from each
@@ -317,27 +296,19 @@ static struct port *getportent (void)
* representing the times of day.
*/
for (dtime = 0; ('\0' != cp[i]) && isdigit (cp[i]); i++) {
for (dtime = 0; cp[i] && isdigit (cp[i]); i++)
dtime = dtime * 10 + cp[i] - '0';
}
if (('-' != cp[i]) || (dtime > 2400) || ((dtime % 100) > 59)) {
if (cp[i] != '-' || dtime > 2400 || dtime % 100 > 59)
goto again;
}
port.pt_times[j].t_start = dtime;
cp = cp + i + 1;
for (dtime = 0, i = 0;
('\0' != cp[i]) && isdigit (cp[i]);
i++) {
for (dtime = i = 0; cp[i] && isdigit (cp[i]); i++)
dtime = dtime * 10 + cp[i] - '0';
}
if ( ((',' != cp[i]) && ('\0' != cp[i]))
|| (dtime > 2400)
|| ((dtime % 100) > 59)) {
if ((cp[i] != ',' && cp[i]) || dtime > 2400 || dtime % 100 > 59)
goto again;
}
port.pt_times[j].t_end = dtime;
cp = cp + i + 1;
@@ -369,32 +340,24 @@ static struct port *getttyuser (const char *tty, const char *user)
setportent ();
while ((port = getportent ()) != NULL) {
if ( (0 == port->pt_names)
|| (0 == port->pt_users)) {
while ((port = getportent ())) {
if (port->pt_names == 0 || port->pt_users == 0)
continue;
}
for (i = 0; NULL != port->pt_names[i]; i++) {
if (portcmp (port->pt_names[i], tty) == 0) {
for (i = 0; port->pt_names[i]; i++)
if (portcmp (port->pt_names[i], tty) == 0)
break;
}
}
if (port->pt_names[i] == 0) {
if (port->pt_names[i] == 0)
continue;
}
for (j = 0; NULL != port->pt_users[j]; j++) {
if ( (strcmp (user, port->pt_users[j]) == 0)
|| (strcmp (port->pt_users[j], "*") == 0)) {
for (j = 0; port->pt_users[j]; j++)
if (strcmp (user, port->pt_users[j]) == 0 ||
strcmp (port->pt_users[j], "*") == 0)
break;
}
}
if (port->pt_users[j] != 0) {
if (port->pt_users[j] != 0)
break;
}
}
endportent ();
return port;
@@ -407,7 +370,7 @@ static struct port *getttyuser (const char *tty, const char *user)
* the user name and TTY given.
*/
bool isttytime (const char *id, const char *port, time_t when)
int isttytime (const char *id, const char *port, time_t when)
{
int i;
int dtime;
@@ -416,27 +379,24 @@ bool isttytime (const char *id, const char *port, time_t when)
/*
* Try to find a matching entry for this user. Default to
* letting the user in - there are plenty of ways to have an
* letting the user in - there are pleny of ways to have an
* entry to match all users.
*/
pp = getttyuser (port, id);
if (NULL == pp) {
return true;
}
if (!(pp = getttyuser (port, id)))
return 1;
/*
* The entry is there, but has no time entries - don't
* ever let them login.
*/
if (0 == pp->pt_times) {
return false;
}
if (pp->pt_times == 0)
return 0;
/*
* The current time is converted to HHMM format for
* comparison against the time values in the TTY entry.
* comparision against the time values in the TTY entry.
*/
tm = localtime (&when);
@@ -445,25 +405,22 @@ bool isttytime (const char *id, const char *port, time_t when)
/*
* Each time entry is compared against the current
* time. For entries with the start after the end time,
* the comparison is made so that the time is between
* the comparision is made so that the time is between
* midnight and either the start or end time.
*/
for (i = 0; pp->pt_times[i].t_start != -1; i++) {
if (!(pp->pt_times[i].t_days & PORT_DAY (tm->tm_wday))) {
if (!(pp->pt_times[i].t_days & PORT_DAY (tm->tm_wday)))
continue;
}
if (pp->pt_times[i].t_start <= pp->pt_times[i].t_end) {
if ( (dtime >= pp->pt_times[i].t_start)
&& (dtime <= pp->pt_times[i].t_end)) {
return true;
}
if (dtime >= pp->pt_times[i].t_start &&
dtime <= pp->pt_times[i].t_end)
return 1;
} else {
if ( (dtime >= pp->pt_times[i].t_start)
|| (dtime <= pp->pt_times[i].t_end)) {
return true;
}
if (dtime >= pp->pt_times[i].t_start ||
dtime <= pp->pt_times[i].t_end)
return 1;
}
}
@@ -472,6 +429,5 @@ bool isttytime (const char *id, const char *port, time_t when)
* be let in right now.
*/
return false;
return 0;
}

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,12 +43,11 @@
#define _PROTOTYPES_H
#include <sys/stat.h>
#ifdef USE_UTMPX
#if HAVE_UTMPX_H
#include <utmpx.h>
#else
#include <utmp.h>
#endif
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <shadow.h>
@@ -57,18 +56,14 @@
#include "defines.h"
#include "commonio.h"
extern char *Prog;
/* addgrps.c */
#if defined (HAVE_SETGROUPS) && ! defined (USE_PAM)
extern int add_groups (const char *);
#endif
extern void add_cons_grps (void);
/* age.c */
extern void agecheck (/*@null@*/const struct spwd *);
extern int expire (const struct passwd *, /*@null@*/const struct spwd *);
/* isexpired.c */
extern int isexpired (const struct passwd *, /*@null@*/const struct spwd *);
extern void agecheck (const struct passwd *, const struct spwd *);
extern int expire (const struct passwd *, const struct spwd *);
extern int isexpired (const struct passwd *, const struct spwd *);
/* basename() renamed to Basename() to avoid libc name space confusion */
/* basename.c */
@@ -78,51 +73,16 @@ extern char *Basename (char *str);
extern int chown_tree (const char *, uid_t, uid_t, gid_t, gid_t);
/* chowntty.c */
extern void chown_tty (const struct passwd *);
/* cleanup.c */
typedef void (*cleanup_function) (/*@null@*/void *arg);
void add_cleanup (cleanup_function pcf, /*@null@*/void *arg);
void del_cleanup (cleanup_function pcf);
void do_cleanups (void);
/* cleanup_group.c */
struct cleanup_info_mod {
char *audit_msg;
char *action;
char *name;
};
void cleanup_report_add_group (void *group_name);
void cleanup_report_add_group_group (void *group_name);
#ifdef SHADOWGRP
void cleanup_report_add_group_gshadow (void *group_name);
#endif
void cleanup_report_del_group (void *group_name);
void cleanup_report_del_group_group (void *group_name);
#ifdef SHADOWGRP
void cleanup_report_del_group_gshadow (void *group_name);
#endif
void cleanup_report_mod_passwd (void *cleanup_info);
void cleanup_report_mod_group (void *cleanup_info);
void cleanup_report_mod_gshadow (void *cleanup_info);
void cleanup_unlock_group (/*@null@*/void *unused);
#ifdef SHADOWGRP
void cleanup_unlock_gshadow (/*@null@*/void *unused);
#endif
void cleanup_unlock_passwd (/*@null@*/void *unused);
extern void chown_tty (const char *, const struct passwd *);
/* console.c */
extern bool console (const char *);
extern int console (const char *);
/* copydir.c */
extern int copy_tree (const char *src_root, const char *dst_root,
long int uid, long int gid);
extern int remove_tree (const char *root);
#ifdef WITH_SELINUX
extern int selinux_file_context (const char *dst_name);
#endif
/* encrypt.c */
extern char *pw_encrypt (const char *, const char *);
@@ -130,7 +90,7 @@ extern char *pw_encrypt (const char *, const char *);
extern void pw_entry (const char *, struct passwd *);
/* env.c */
extern void addenv (const char *, /*@null@*/const char *);
extern void addenv (const char *, const char *);
extern void initenv (void);
extern void set_env (int, char *const *);
extern void sanitize_env (void);
@@ -139,89 +99,52 @@ extern void sanitize_env (void);
extern void change_field (char *, size_t, const char *);
extern int valid_field (const char *, const char *);
/* find_new_gid.c */
extern int find_new_gid (bool sys_group,
gid_t *gid,
/*@null@*/gid_t const *preferred_gid);
/* find_new_uid.c */
extern int find_new_uid (bool sys_user,
uid_t *uid,
/*@null@*/uid_t const *preferred_uid);
/* get_gid.c */
extern int get_gid (const char *gidstr, gid_t *gid);
/* getgr_nam_gid.c */
extern /*@null@*/struct group *getgr_nam_gid (const char *grname);
/* find_new_ids.c */
extern int find_new_uid (int sys_user, uid_t *uid, uid_t const *preferred_uid);
extern int find_new_gid (int sys_group, gid_t *gid, gid_t const *preferred_gid);
/* getlong.c */
extern int getlong (const char *numstr, /*@out@*/long int *result);
/* get_pid.c */
extern int get_pid (const char *pidstr, pid_t *pid);
/* getrange */
extern int getrange (char *range,
unsigned long *min, bool *has_min,
unsigned long *max, bool *has_max);
/* get_uid.c */
extern int get_uid (const char *uidstr, uid_t *uid);
/* getulong.c */
extern int getulong (const char *numstr, /*@out@*/unsigned long int *result);
extern int getlong(const char *numstr, long int *result);
/* fputsx.c */
extern /*@null@*/char *fgetsx (/*@returned@*/ /*@out@*/char *, int, FILE *);
extern char *fgetsx (char *, int, FILE *);
extern int fputsx (const char *, FILE *);
/* groupio.c */
extern void __gr_del_entry (const struct commonio_entry *ent);
extern /*@observer@*/const struct commonio_db *__gr_get_db (void);
extern /*@dependent@*/ /*@null@*/struct commonio_entry *__gr_get_head (void);
extern struct commonio_db *__gr_get_db (void);
extern struct commonio_entry *__gr_get_head (void);
extern void __gr_set_changed (void);
/* groupmem.c */
extern /*@null@*/ /*@only@*/struct group *__gr_dup (const struct group *grent);
extern void gr_free (/*@out@*/ /*@only@*/struct group *grent);
extern struct group *__gr_dup (const struct group *grent);
/* hushed.c */
extern bool hushed (const char *username);
extern int hushed (const struct passwd *);
/* audit_help.c */
#ifdef WITH_AUDIT
extern int audit_fd;
extern void audit_help_open (void);
/* Use AUDIT_NO_ID when a name is provided to audit_logger instead of an ID */
#define AUDIT_NO_ID ((unsigned int) -1)
typedef enum {
SHADOW_AUDIT_FAILURE = 0,
SHADOW_AUDIT_SUCCESS = 1} shadow_audit_result;
extern void audit_logger (int type, const char *pgname, const char *op,
const char *name, unsigned int id,
shadow_audit_result result);
void audit_logger_message (const char *message, shadow_audit_result result);
const char *name, unsigned int id, int result);
#endif
/* limits.c */
#ifndef USE_PAM
extern void setup_limits (const struct passwd *);
#endif
/* list.c */
extern /*@only@*/ /*@out@*/char **add_list (/*@returned@*/ /*@only@*/char **, const char *);
extern /*@only@*/ /*@out@*/char **del_list (/*@returned@*/ /*@only@*/char **, const char *);
extern /*@only@*/ /*@out@*/char **dup_list (char *const *);
extern bool is_on_list (char *const *list, const char *member);
extern /*@only@*/char **comma_to_list (const char *);
extern char **add_list (char **, const char *);
extern char **del_list (char **, const char *);
extern char **dup_list (char *const *);
extern int is_on_list (char *const *, const char *);
extern char **comma_to_list (const char *);
/* log.c */
extern void dolastlog (
struct lastlog *ll,
const struct passwd *pw,
/*@unique@*/const char *line,
/*@unique@*/const char *host);
extern void dolastlog (struct lastlog *ll,
const struct passwd *pw,
const char *line,
const char *host);
/* login_nopam.c */
extern int login_access (const char *user, const char *from);
@@ -236,37 +159,22 @@ extern void mailcheck (void);
extern void motd (void);
/* myname.c */
extern /*@null@*/struct passwd *get_my_pwent (void);
/* pam_pass_non_interractive.c */
#ifdef USE_PAM
extern int do_pam_passwd_non_interractive (const char *pam_service,
const char *username,
const char* password);
#endif /* USE_PAM */
extern struct passwd *get_my_pwent (void);
/* obscure.c */
#ifndef USE_PAM
extern int obscure (const char *, const char *, const struct passwd *);
#endif
/* pam_pass.c */
#ifdef USE_PAM
extern void do_pam_passwd (const char *user, bool silent, bool change_expired);
#endif
extern void do_pam_passwd (const char *, int, int);
/* port.c */
extern bool isttytime (const char *, const char *, time_t);
extern int isttytime (const char *, const char *, time_t);
/* pwd2spwd.c */
#ifndef USE_PAM
extern struct spwd *pwd_to_spwd (const struct passwd *);
#endif
/* pwdcheck.c */
#ifndef USE_PAM
extern void passwd_check (const char *, const char *, const char *);
#endif
/* pwd_init.c */
extern void pwd_init (void);
@@ -274,27 +182,21 @@ extern void pwd_init (void);
/* pwio.c */
extern void __pw_del_entry (const struct commonio_entry *ent);
extern struct commonio_db *__pw_get_db (void);
extern /*@dependent@*/ /*@null@*/struct commonio_entry *__pw_get_head (void);
extern struct commonio_entry *__pw_get_head (void);
/* pwmem.c */
extern /*@null@*/ /*@only@*/struct passwd *__pw_dup (const struct passwd *pwent);
extern void pw_free (/*@out@*/ /*@only@*/struct passwd *pwent);
extern struct passwd *__pw_dup (const struct passwd *pwent);
/* rlogin.c */
extern int do_rlogin (const char *remote_host, char *name, size_t namelen,
char *term, size_t termlen);
extern int do_rlogin (const char *, char *, int, char *, int);
/* salt.c */
extern /*@observer@*/const char *crypt_make_salt (/*@null@*/const char *meth, /*@null@*/void *arg);
extern char *crypt_make_salt (const char *meth, void *arg);
/* setugid.c */
extern int setup_groups (const struct passwd *info);
extern int change_uid (const struct passwd *info);
#if (defined HAVE_INITGROUPS) && (! defined USE_PAM)
extern int setup_uid_gid (const struct passwd *info, bool is_console);
#else
extern int setup_uid_gid (const struct passwd *info);
#endif
extern int setup_groups (const struct passwd *);
extern int change_uid (const struct passwd *);
extern int setup_uid_gid (const struct passwd *, int);
/* setup.c */
extern void setup (struct passwd *);
@@ -308,34 +210,21 @@ extern struct group *sgetgrent (const char *buf);
/* sgetpwent.c */
extern struct passwd *sgetpwent (const char *buf);
/* sgetspent.c */
#ifndef HAVE_SGETSPENT
extern struct spwd *sgetspent (const char *string);
#endif
/* sgroupio.c */
extern void __sgr_del_entry (const struct commonio_entry *ent);
extern /*@null@*/ /*@only@*/struct sgrp *__sgr_dup (const struct sgrp *sgent);
extern void sgr_free (/*@out@*/ /*@only@*/struct sgrp *sgent);
extern /*@dependent@*/ /*@null@*/struct commonio_entry *__sgr_get_head (void);
extern struct sgrp *__sgr_dup (const struct sgrp *sgent);
extern struct commonio_entry *__sgr_get_head (void);
extern void __sgr_set_changed (void);
/* shadowio.c */
extern /*@dependent@*/ /*@null@*/struct commonio_entry *__spw_get_head (void);
extern struct commonio_entry *__spw_get_head (void);
extern void __spw_del_entry (const struct commonio_entry *ent);
/* shadowmem.c */
extern /*@null@*/ /*@only@*/struct spwd *__spw_dup (const struct spwd *spent);
extern void spw_free (/*@out@*/ /*@only@*/struct spwd *spent);
extern struct spwd *__spw_dup (const struct spwd *spent);
/* shell.c */
extern int shell (const char *file, /*@null@*/const char *arg, char *const envp[]);
/* system.c */
extern int safe_system (const char *command,
const char *argv[],
const char *env[],
int ignore_stderr);
extern int shell (const char *, const char *, char *const *);
/* strtoday.c */
extern long strtoday (const char *);
@@ -344,10 +233,7 @@ extern long strtoday (const char *);
extern int check_su_auth (const char *actual_id, const char *wanted_id);
/* sulog.c */
extern void sulog (const char *tty,
bool success,
const char *oldname,
const char *name);
extern void sulog (const char *, int, const char *, const char *);
/* sub.c */
extern void subsystem (const struct passwd *);
@@ -356,51 +242,34 @@ extern void subsystem (const struct passwd *);
extern void ttytype (const char *);
/* tz.c */
#ifndef USE_PAM
extern char *tz (const char *);
#endif
/* ulimit.c */
extern int set_filesize_limit (int blocks);
/* user_busy.c */
extern int user_busy (const char *name, uid_t uid);
extern void set_filesize_limit (int);
/* utmp.c */
extern /*@null@*/struct utmp *get_current_utmp (void);
extern struct utmp *prepare_utmp (const char *name,
const char *line,
const char *host,
/*@null@*/const struct utmp *ut);
extern int setutmp (struct utmp *ut);
#ifdef USE_UTMPX
extern struct utmpx *prepare_utmpx (const char *name,
const char *line,
const char *host,
/*@null@*/const struct utmp *ut);
extern int setutmpx (struct utmpx *utx);
#endif /* USE_UTMPX */
extern void checkutmp (int);
extern void setutmp (const char *, const char *, const char *);
/* valid.c */
extern bool valid (const char *, const struct passwd *);
extern int valid (const char *, const struct passwd *);
/* xmalloc.c */
extern /*@maynotreturn@*/ /*@out@*//*@only@*/char *xmalloc (size_t size)
/*@ensures MaxSet(result) == (size - 1); @*/;
extern /*@maynotreturn@*/ /*@only@*/char *xstrdup (const char *);
extern char *xmalloc (size_t);
extern char *xstrdup (const char *);
/* xgetpwnam.c */
extern /*@null@*/ /*@only@*/struct passwd *xgetpwnam (const char *);
extern struct passwd *xgetpwnam (const char *);
/* xgetpwuid.c */
extern /*@null@*/ /*@only@*/struct passwd *xgetpwuid (uid_t);
extern struct passwd *xgetpwuid (uid_t);
/* xgetgrnam.c */
extern /*@null@*/ /*@only@*/struct group *xgetgrnam (const char *);
extern struct group *xgetgrnam (const char *);
/* xgetgrgid.c */
extern /*@null@*/ /*@only@*/struct group *xgetgrgid (gid_t);
extern struct group *xgetgrgid (gid_t);
/* xgetspnam.c */
extern /*@null@*/ /*@only@*/struct spwd *xgetspnam(const char *);
extern struct spwd *xgetspnam(const char *);
/* yesno.c */
extern bool yes_or_no (bool read_only);
extern int yes_or_no (int read_only);
#endif /* _PROTOTYPES_H */

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1992 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko
* Copyright (c) 2008 - 2009, Nicolas François
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -54,8 +54,8 @@ static const char *PROMPT = gettext_noop ("Password: ");
static const char *PROMPT = gettext_noop ("%s's Password: ");
#endif
bool wipe_clear_pass = true;
/*@null@*/char *clear_pass = NULL;
int wipe_clear_pass = 1;
char *clear_pass = NULL;
/*
* pw_auth - perform getpass/crypt authentication
@@ -65,10 +65,8 @@ bool wipe_clear_pass = true;
* compared.
*/
int pw_auth (const char *cipher,
const char *user,
int reason,
/*@null@*/const char *input)
int
pw_auth (const char *cipher, const char *user, int reason, const char *input)
{
char prompt[1024];
char *clear = NULL;
@@ -76,7 +74,7 @@ int pw_auth (const char *cipher,
int retval;
#ifdef SKEY
bool use_skey = false;
int use_skey = 0;
char challenge_info[40];
struct skey skey;
#endif
@@ -85,17 +83,15 @@ int pw_auth (const char *cipher,
* There are programs for adding and deleting authentication data.
*/
if ((PW_ADD == reason) || (PW_DELETE == reason)) {
if (reason == PW_ADD || reason == PW_DELETE)
return 0;
}
/*
* There are even programs for changing the user name ...
*/
if ((PW_CHANGE == reason) && (NULL != input)) {
if (reason == PW_CHANGE && input != (char *) 0)
return 0;
}
/*
* WARNING:
@@ -106,9 +102,8 @@ int pw_auth (const char *cipher,
* revisited.
*/
if ((PW_CHANGE == reason) && (getuid () == 0)) {
if (reason == PW_CHANGE && getuid () == 0)
return 0;
}
/*
* WARNING:
@@ -119,9 +114,8 @@ int pw_auth (const char *cipher,
* matter.
*/
if ((NULL == cipher) || ('\0' == *cipher)) {
if (cipher == (char *) 0 || *cipher == '\0')
return 0;
}
#ifdef SKEY
/*
@@ -138,9 +132,8 @@ int pw_auth (const char *cipher,
# define skeychallenge(s,u,c) skeychallenge(s,u,c,sizeof(c))
# endif
if (skeychallenge (&skey, user, challenge_info) == 0) {
use_skey = true;
}
if (skeychallenge (&skey, user, challenge_info) == 0)
use_skey = 1;
#endif
/*
@@ -148,20 +141,17 @@ int pw_auth (const char *cipher,
* get the cleartext password for us.
*/
if ((PW_FTP != reason) && (PW_REXEC != reason) && (NULL == input)) {
cp = getdef_str ("LOGIN_STRING");
if (NULL == cp) {
if (reason != PW_FTP && reason != PW_REXEC && !input) {
if (!(cp = getdef_str ("LOGIN_STRING")))
cp = _(PROMPT);
}
#ifdef SKEY
if (use_skey) {
if (use_skey)
printf ("[%s]\n", challenge_info);
}
#endif
snprintf (prompt, sizeof prompt, cp, user);
clear = getpass (prompt);
if (NULL == clear) {
if (!clear) {
static char c[1];
c[0] = '\0';
@@ -187,9 +177,9 @@ int pw_auth (const char *cipher,
* ...Re-prompt, with echo on.
* -- AR 8/22/1999
*/
if ((0 != retval) && ('\0' == input[0]) && use_skey) {
if (retval && !input[0] && (use_skey)) {
clear = getpass (prompt);
if (NULL == clear) {
if (!clear) {
static char c[1];
c[0] = '\0';
@@ -198,15 +188,13 @@ int pw_auth (const char *cipher,
input = clear;
}
if ((0 != retval) && use_skey) {
if (retval && use_skey) {
int passcheck = -1;
if (skeyverify (&skey, input) == 0) {
if (skeyverify (&skey, input) == 0)
passcheck = skey.n;
}
if (passcheck > 0) {
if (passcheck > 0)
retval = 0;
}
}
#endif
@@ -218,9 +206,8 @@ int pw_auth (const char *cipher,
*/
clear_pass = clear;
if (wipe_clear_pass && (NULL != clear) && ('\0' != *clear)) {
if (wipe_clear_pass && clear && *clear)
strzero (clear);
}
return retval;
}
#else /* !USE_PAM */

View File

@@ -2,7 +2,6 @@
* Copyright (c) 1992 - 1993, Julianne Frances Haugh
* Copyright (c) 1996 - 1997, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2009 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,10 +34,7 @@
*/
#ifndef USE_PAM
int pw_auth (const char *cipher,
const char *user,
int flag,
/*@null@*/const char *input);
int pw_auth (const char *cipher, const char *user, int flag, const char *input);
#endif /* !USE_PAM */
/*

View File

@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,18 +42,23 @@
#include "commonio.h"
#include "pwio.h"
static /*@null@*/ /*@only@*/void *passwd_dup (const void *ent)
static void *passwd_dup (const void *ent)
{
const struct passwd *pw = ent;
return __pw_dup (pw);
}
static void passwd_free (/*@out@*/ /*@only@*/void *ent)
static void passwd_free (void *ent)
{
struct passwd *pw = ent;
pw_free (pw);
free (pw->pw_name);
free (pw->pw_passwd);
free (pw->pw_gecos);
free (pw->pw_dir);
free (pw->pw_shell);
free (pw);
}
static const char *passwd_getname (const void *ent)
@@ -97,22 +102,17 @@ static struct commonio_db passwd_db = {
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
false, /* changed */
false, /* isopen */
false, /* locked */
false /* readonly */
0, /* changed */
0, /* isopen */
0, /* locked */
0 /* readonly */
};
int pw_setdbname (const char *filename)
int pw_name (const char *filename)
{
return commonio_setname (&passwd_db, filename);
}
/*@observer@*/const char *pw_dbname (void)
{
return passwd_db.filename;
}
int pw_lock (void)
{
return commonio_lock (&passwd_db);
@@ -123,12 +123,12 @@ int pw_open (int mode)
return commonio_open (&passwd_db, mode);
}
/*@observer@*/ /*@null@*/const struct passwd *pw_locate (const char *name)
const struct passwd *pw_locate (const char *name)
{
return commonio_locate (&passwd_db, name);
}
/*@observer@*/ /*@null@*/const struct passwd *pw_locate_uid (uid_t uid)
const struct passwd *pw_locate_uid (uid_t uid)
{
const struct passwd *pwd;
@@ -155,7 +155,7 @@ int pw_rewind (void)
return commonio_rewind (&passwd_db);
}
/*@observer@*/ /*@null@*/const struct passwd *pw_next (void)
const struct passwd *pw_next (void)
{
return commonio_next (&passwd_db);
}
@@ -170,7 +170,7 @@ int pw_unlock (void)
return commonio_unlock (&passwd_db);
}
/*@null@*/struct commonio_entry *__pw_get_head (void)
struct commonio_entry *__pw_get_head (void)
{
return passwd_db.head;
}

View File

@@ -31,25 +31,17 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* $Id$ */
#ifndef _PWIO_H
#define _PWIO_H
#include <sys/types.h>
#include <pwd.h>
extern int pw_close (void);
extern /*@observer@*/ /*@null@*/const struct passwd *pw_locate (const char *name);
extern /*@observer@*/ /*@null@*/const struct passwd *pw_locate_uid (uid_t uid);
extern const struct passwd *pw_locate (const char *);
extern const struct passwd *pw_locate_uid (uid_t uid);
extern int pw_lock (void);
extern int pw_setdbname (const char *filename);
extern /*@observer@*/const char *pw_dbname (void);
extern /*@observer@*/ /*@null@*/const struct passwd *pw_next (void);
extern int pw_open (int mode);
extern int pw_remove (const char *name);
extern int pw_name (const char *);
extern const struct passwd *pw_next (void);
extern int pw_open (int);
extern int pw_remove (const char *);
extern int pw_rewind (void);
extern int pw_unlock (void);
extern int pw_update (const struct passwd *pw);
extern int pw_update (const struct passwd *);
extern int pw_sort (void);
#endif

View File

@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François
* Copyright (c) 2007 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,52 +35,29 @@
#ident "$Id$"
#include <stdio.h>
#include "defines.h"
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
#include <stdio.h>
#include "pwio.h"
/*@null@*/ /*@only@*/struct passwd *__pw_dup (const struct passwd *pwent)
struct passwd *__pw_dup (const struct passwd *pwent)
{
struct passwd *pw;
pw = (struct passwd *) malloc (sizeof *pw);
if (NULL == pw) {
if (!(pw = (struct passwd *) malloc (sizeof *pw)))
return NULL;
}
*pw = *pwent;
pw->pw_name = strdup (pwent->pw_name);
if (NULL == pw->pw_name) {
if (!(pw->pw_name = strdup (pwent->pw_name)))
return NULL;
}
pw->pw_passwd = strdup (pwent->pw_passwd);
if (NULL == pw->pw_passwd) {
if (!(pw->pw_passwd = strdup (pwent->pw_passwd)))
return NULL;
}
pw->pw_gecos = strdup (pwent->pw_gecos);
if (NULL == pw->pw_gecos) {
if (!(pw->pw_gecos = strdup (pwent->pw_gecos)))
return NULL;
}
pw->pw_dir = strdup (pwent->pw_dir);
if (NULL == pw->pw_dir) {
if (!(pw->pw_dir = strdup (pwent->pw_dir)))
return NULL;
}
pw->pw_shell = strdup (pwent->pw_shell);
if (NULL == pw->pw_shell) {
if (!(pw->pw_shell = strdup (pwent->pw_shell)))
return NULL;
}
return pw;
}
void pw_free (/*@out@*/ /*@only@*/struct passwd *pwent)
{
free (pwent->pw_name);
memzero (pwent->pw_passwd, strlen (pwent->pw_passwd));
free (pwent->pw_passwd);
free (pwent->pw_gecos);
free (pwent->pw_dir);
free (pwent->pw_shell);
free (pwent);
}

View File

@@ -35,7 +35,6 @@
#ident "$Id$"
#include <stdio.h>
#include <sys/types.h>
#include <grp.h>
#include "defines.h"
#include "prototypes.h"
@@ -88,12 +87,10 @@ static char **list (char *s)
if (!s || s[0] == '\0')
break;
members[i++] = s;
while (('\0' != *s) && (',' != *s)) {
while (*s && *s != ',')
s++;
}
if ('\0' != *s) {
if (*s)
*s++ = '\0';
}
}
members[i] = (char *) 0;
return members;
@@ -123,32 +120,22 @@ struct group *sgetgrent (const char *buf)
}
strcpy (grpbuf, buf);
cp = strrchr (grpbuf, '\n');
if (NULL != cp) {
if ((cp = strrchr (grpbuf, '\n')))
*cp = '\0';
}
for (cp = grpbuf, i = 0; (i < NFIELDS) && (NULL != cp); i++) {
for (cp = grpbuf, i = 0; i < NFIELDS && cp; i++) {
grpfields[i] = cp;
cp = strchr (cp, ':');
if (NULL != cp) {
*cp = '\0';
cp++;
}
}
if (i < (NFIELDS - 1) || *grpfields[2] == '\0') {
return (struct group *) 0;
if ((cp = strchr (cp, ':')))
*cp++ = 0;
}
if (i < (NFIELDS - 1) || *grpfields[2] == '\0')
return 0;
grent.gr_name = grpfields[0];
grent.gr_passwd = grpfields[1];
if (get_gid (grpfields[2], &grent.gr_gid) == 0) {
return (struct group *) 0;
}
grent.gr_gid = atoi (grpfields[2]);
grent.gr_mem = list (grpfields[3]);
if (NULL == grent.gr_mem) {
if (!grent.gr_mem)
return (struct group *) 0; /* out of memory */
}
return &grent;
}

View File

@@ -60,6 +60,7 @@ struct passwd *sgetpwent (const char *buf)
static char pwdbuf[1024];
register int i;
register char *cp;
char *ep;
char *fields[NFIELDS];
/*
@@ -76,18 +77,15 @@ struct passwd *sgetpwent (const char *buf)
* field. The fields are converted into NUL terminated strings.
*/
for (cp = pwdbuf, i = 0; (i < NFIELDS) && (NULL != cp); i++) {
for (cp = pwdbuf, i = 0; i < NFIELDS && cp; i++) {
fields[i] = cp;
while (('\0' != *cp) && (':' != *cp)) {
cp++;
}
while (*cp && *cp != ':')
++cp;
if ('\0' != *cp) {
*cp = '\0';
cp++;
} else {
cp = NULL;
}
if (*cp)
*cp++ = '\0';
else
cp = 0;
}
/*
@@ -96,7 +94,7 @@ struct passwd *sgetpwent (const char *buf)
*/
if (i != NFIELDS || *fields[2] == '\0' || *fields[3] == '\0')
return NULL;
return 0;
/*
* Each of the fields is converted the appropriate data type
@@ -107,11 +105,13 @@ struct passwd *sgetpwent (const char *buf)
pwent.pw_name = fields[0];
pwent.pw_passwd = fields[1];
if (get_uid (fields[2], &pwent.pw_uid) == 0) {
return NULL;
if (fields[2][0] == '\0' ||
((pwent.pw_uid = strtol (fields[2], &ep, 10)) == 0 && *ep)) {
return 0;
}
if (get_gid (fields[3], &pwent.pw_gid) == 0) {
return NULL;
if (fields[3][0] == '\0' ||
((pwent.pw_gid = strtol (fields[3], &ep, 10)) == 0 && *ep)) {
return 0;
}
pwent.pw_gecos = fields[4];
pwent.pw_dir = fields[5];
@@ -119,4 +119,3 @@ struct passwd *sgetpwent (const char *buf)
return &pwent;
}

View File

@@ -2,7 +2,6 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2009 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,9 +31,6 @@
#include <config.h>
/* Newer versions of Linux libc already have shadow support. */
#ifndef HAVE_SGETSPENT
#ident "$Id$"
#include <sys/types.h>
@@ -60,41 +56,32 @@ struct spwd *sgetspent (const char *string)
* have to do that to our private copy.
*/
if (strlen (string) >= sizeof spwbuf) {
if (strlen (string) >= sizeof spwbuf)
return 0; /* fail if too long */
}
strcpy (spwbuf, string);
cp = strrchr (spwbuf, '\n');
if (NULL != cp) {
if ((cp = strrchr (spwbuf, '\n')))
*cp = '\0';
}
/*
* Tokenize the string into colon separated fields. Allow up to
* FIELDS different fields.
*/
for (cp = spwbuf, i = 0; ('\0' != *cp) && (i < FIELDS); i++) {
for (cp = spwbuf, i = 0; *cp && i < FIELDS; i++) {
fields[i] = cp;
while (('\0' != *cp) && (':' != *cp)) {
while (*cp && *cp != ':')
cp++;
}
if ('\0' != *cp) {
*cp = '\0';
cp++;
}
if (*cp)
*cp++ = '\0';
}
if (i == (FIELDS - 1)) {
if (i == (FIELDS - 1))
fields[i++] = cp;
}
if ( ((NULL != cp) && ('\0' != *cp)) ||
((i != FIELDS) && (i != OFIELDS)) ) {
if ((cp && *cp) || (i != FIELDS && i != OFIELDS))
return 0;
}
/*
* Start populating the structure. The fields are all in
@@ -110,34 +97,28 @@ struct spwd *sgetspent (const char *string)
* incorrectly formatted number.
*/
if (fields[2][0] == '\0') {
spwd.sp_lstchg = -1;
} else if ( (getlong (fields[2], &spwd.sp_lstchg) == 0)
|| (spwd.sp_lstchg < 0)) {
if ((spwd.sp_lstchg = strtol (fields[2], &cpp, 10)) == 0 && *cpp) {
return 0;
}
} else if (fields[2][0] == '\0')
spwd.sp_lstchg = -1;
/*
* Get the minimum period between password changes.
*/
if (fields[3][0] == '\0') {
spwd.sp_min = -1;
} else if ( (getlong (fields[3], &spwd.sp_min) == 0)
|| (spwd.sp_min < 0)) {
if ((spwd.sp_min = strtol (fields[3], &cpp, 10)) == 0 && *cpp) {
return 0;
}
} else if (fields[3][0] == '\0')
spwd.sp_min = -1;
/*
* Get the maximum number of days a password is valid.
*/
if (fields[4][0] == '\0') {
spwd.sp_max = -1;
} else if ( (getlong (fields[4], &spwd.sp_max) == 0)
|| (spwd.sp_max < 0)) {
if ((spwd.sp_max = strtol (fields[4], &cpp, 10)) == 0 && *cpp) {
return 0;
}
} else if (fields[4][0] == '\0')
spwd.sp_max = -1;
/*
* If there are only OFIELDS fields (this is a SVR3.2 /etc/shadow
@@ -145,10 +126,8 @@ struct spwd *sgetspent (const char *string)
*/
if (i == OFIELDS) {
spwd.sp_warn = -1;
spwd.sp_inact = -1;
spwd.sp_expire = -1;
spwd.sp_flag = SHADOW_SP_FLAG_UNSET;
spwd.sp_warn = spwd.sp_inact = spwd.sp_expire =
spwd.sp_flag = -1;
return &spwd;
}
@@ -157,52 +136,40 @@ struct spwd *sgetspent (const char *string)
* Get the number of days of password expiry warning.
*/
if (fields[5][0] == '\0') {
spwd.sp_warn = -1;
} else if ( (getlong (fields[5], &spwd.sp_warn) == 0)
|| (spwd.sp_warn < 0)) {
if ((spwd.sp_warn = strtol (fields[5], &cpp, 10)) == 0 && *cpp) {
return 0;
}
} else if (fields[5][0] == '\0')
spwd.sp_warn = -1;
/*
* Get the number of days of inactivity before an account is
* disabled.
*/
if (fields[6][0] == '\0') {
spwd.sp_inact = -1;
} else if ( (getlong (fields[6], &spwd.sp_inact) == 0)
|| (spwd.sp_inact < 0)) {
if ((spwd.sp_inact = strtol (fields[6], &cpp, 10)) == 0 && *cpp) {
return 0;
}
} else if (fields[6][0] == '\0')
spwd.sp_inact = -1;
/*
* Get the number of days after the epoch before the account is
* set to expire.
*/
if (fields[7][0] == '\0') {
spwd.sp_expire = -1;
} else if ( (getlong (fields[7], &spwd.sp_expire) == 0)
|| (spwd.sp_expire < 0)) {
if ((spwd.sp_expire = strtol (fields[7], &cpp, 10)) == 0 && *cpp) {
return 0;
}
} else if (fields[7][0] == '\0')
spwd.sp_expire = -1;
/*
* This field is reserved for future use. But it isn't supposed
* to have anything other than a valid integer in it.
*/
if (fields[8][0] == '\0') {
spwd.sp_flag = SHADOW_SP_FLAG_UNSET;
} else if (getlong (fields[8], &spwd.sp_flag) == 0) {
/* FIXME: add a getulong function */
if ((spwd.sp_flag = strtol (fields[8], &cpp, 10)) == 0 && *cpp) {
return 0;
}
} else if (fields[8][0] == '\0')
spwd.sp_flag = -1;
return (&spwd);
}
#else
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif

View File

@@ -42,113 +42,66 @@
#include "commonio.h"
#include "sgroupio.h"
/*@null@*/ /*@only@*/struct sgrp *__sgr_dup (const struct sgrp *sgent)
struct sgrp *__sgr_dup (const struct sgrp *sgent)
{
struct sgrp *sg;
int i;
sg = (struct sgrp *) malloc (sizeof *sg);
if (NULL == sg) {
if (!(sg = (struct sgrp *) malloc (sizeof *sg)))
return NULL;
}
*sg = *sgent;
sg->sg_name = strdup (sgent->sg_name);
if (NULL == sg->sg_name) {
free (sg);
if (!(sg->sg_name = strdup (sgent->sg_name)))
return NULL;
}
sg->sg_passwd = strdup (sgent->sg_passwd);
if (NULL == sg->sg_passwd) {
free (sg->sg_name);
free (sg);
if (!(sg->sg_passwd = strdup (sgent->sg_passwd)))
return NULL;
}
for (i = 0; NULL != sgent->sg_adm[i]; i++);
for (i = 0; sgent->sg_adm[i]; i++);
sg->sg_adm = (char **) malloc ((i + 1) * sizeof (char *));
if (NULL == sg->sg_adm) {
free (sg->sg_passwd);
free (sg->sg_name);
free (sg);
if (!sg->sg_adm)
return NULL;
}
for (i = 0; NULL != sgent->sg_adm[i]; i++) {
for (i = 0; sgent->sg_adm[i]; i++) {
sg->sg_adm[i] = strdup (sgent->sg_adm[i]);
if (NULL == sg->sg_adm[i]) {
for (i = 0; NULL != sg->sg_adm[i]; i++) {
free (sg->sg_adm[i]);
}
free (sg->sg_adm);
free (sg->sg_passwd);
free (sg->sg_name);
free (sg);
if (!sg->sg_adm[i])
return NULL;
}
}
sg->sg_adm[i] = NULL;
for (i = 0; NULL != sgent->sg_mem[i]; i++);
for (i = 0; sgent->sg_mem[i]; i++);
sg->sg_mem = (char **) malloc ((i + 1) * sizeof (char *));
if (NULL == sg->sg_mem) {
for (i = 0; NULL != sg->sg_adm[i]; i++) {
free (sg->sg_adm[i]);
}
free (sg->sg_adm);
free (sg->sg_passwd);
free (sg->sg_name);
free (sg);
if (!sg->sg_mem)
return NULL;
}
for (i = 0; NULL != sgent->sg_mem[i]; i++) {
for (i = 0; sgent->sg_mem[i]; i++) {
sg->sg_mem[i] = strdup (sgent->sg_mem[i]);
if (NULL == sg->sg_mem[i]) {
for (i = 0; NULL != sg->sg_mem[i]; i++) {
free (sg->sg_mem[i]);
}
free (sg->sg_mem);
for (i = 0; NULL != sg->sg_adm[i]; i++) {
free (sg->sg_adm[i]);
}
free (sg->sg_adm);
free (sg->sg_passwd);
free (sg->sg_name);
free (sg);
if (!sg->sg_mem[i])
return NULL;
}
}
sg->sg_mem[i] = NULL;
return sg;
}
static /*@null@*/ /*@only@*/void *gshadow_dup (const void *ent)
static void *gshadow_dup (const void *ent)
{
const struct sgrp *sg = ent;
return __sgr_dup (sg);
}
static void gshadow_free (/*@out@*/ /*@only@*/void *ent)
static void gshadow_free (void *ent)
{
struct sgrp *sg = ent;
sgr_free (sg);
}
void sgr_free (/*@out@*/ /*@only@*/struct sgrp *sgent)
{
free (sgent->sg_name);
memzero (sgent->sg_passwd, strlen (sgent->sg_passwd));
free (sgent->sg_passwd);
while (NULL != *(sgent->sg_adm)) {
free (*(sgent->sg_adm));
sgent->sg_adm++;
free (sg->sg_name);
free (sg->sg_passwd);
while (*(sg->sg_adm)) {
free (*(sg->sg_adm));
sg->sg_adm++;
}
while (NULL != *(sgent->sg_mem)) {
free (*(sgent->sg_mem));
sgent->sg_mem++;
while (*(sg->sg_mem)) {
free (*(sg->sg_mem));
sg->sg_mem++;
}
free (sgent);
free (sg);
}
static const char *gshadow_getname (const void *ent)
@@ -192,23 +145,18 @@ static struct commonio_db gshadow_db = {
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
false, /* changed */
false, /* isopen */
false, /* locked */
false /* readonly */
0, /* changed */
0, /* isopen */
0, /* locked */
0 /* readonly */
};
int sgr_setdbname (const char *filename)
int sgr_name (const char *filename)
{
return commonio_setname (&gshadow_db, filename);
}
/*@observer@*/const char *sgr_dbname (void)
{
return gshadow_db.filename;
}
bool sgr_file_present (void)
int sgr_file_present (void)
{
return commonio_present (&gshadow_db);
}
@@ -223,7 +171,7 @@ int sgr_open (int mode)
return commonio_open (&gshadow_db, mode);
}
/*@observer@*/ /*@null@*/const struct sgrp *sgr_locate (const char *name)
const struct sgrp *sgr_locate (const char *name)
{
return commonio_locate (&gshadow_db, name);
}
@@ -243,7 +191,7 @@ int sgr_rewind (void)
return commonio_rewind (&gshadow_db);
}
/*@null@*/const struct sgrp *sgr_next (void)
const struct sgrp *sgr_next (void)
{
return commonio_next (&gshadow_db);
}
@@ -260,10 +208,10 @@ int sgr_unlock (void)
void __sgr_set_changed (void)
{
gshadow_db.changed = true;
gshadow_db.changed = 1;
}
/*@dependent@*/ /*@null@*/struct commonio_entry *__sgr_get_head (void)
struct commonio_entry *__sgr_get_head (void)
{
return gshadow_db.head;
}

View File

@@ -31,22 +31,16 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* $Id$ */
#ifndef _SGROUPIO_H
#define _SGROUPIO_H
extern int sgr_close (void);
extern bool sgr_file_present (void);
extern /*@null@*/const struct sgrp *sgr_locate (const char *name);
extern int sgr_file_present (void);
extern const struct sgrp *sgr_locate (const char *);
extern int sgr_lock (void);
extern int sgr_setdbname (const char *filename);
extern /*@observer@*/const char *sgr_dbname (void);
extern /*@null@*/const struct sgrp *sgr_next (void);
extern int sgr_open (int mode);
extern int sgr_remove (const char *name);
extern int sgr_name (const char *);
extern const struct sgrp *sgr_next (void);
extern int sgr_open (int);
extern int sgr_remove (const char *);
extern int sgr_rewind (void);
extern int sgr_unlock (void);
extern int sgr_update (const struct sgrp *sg);
extern int sgr_update (const struct sgrp *);
extern int sgr_sort (void);
#endif

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2009 , Nicolas François
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -56,6 +56,8 @@ static int nis_vallen;
#endif
static FILE *shadow;
static char spwbuf[BUFSIZ];
static struct spwd spwd;
#define FIELDS 9
#define OFIELDS 5
@@ -70,9 +72,8 @@ void __setspNIS (int flag)
{
nis_ignore = !flag;
if (nis_ignore) {
if (nis_ignore)
nis_used = 0;
}
}
/*
@@ -123,8 +124,6 @@ void endspent (void)
static struct spwd *my_sgetspent (const char *string)
{
static char spwbuf[BUFSIZ];
static struct spwd spwd;
char *fields[FIELDS];
char *cp;
char *cpp;
@@ -183,58 +182,52 @@ static struct spwd *my_sgetspent (const char *string)
* incorrectly formatted number, unless we are using NIS.
*/
if (fields[2][0] == '\0') {
spwd.sp_lstchg = -1;
} else {
if (getlong (fields[2], &spwd.sp_lstchg) == 0) {
spwd.sp_lstchg = strtol (fields[2], &cpp, 10);
if ((spwd.sp_lstchg == 0) && *cpp) {
#ifdef USE_NIS
if (nis_used) {
spwd.sp_lstchg = -1;
} else
#endif
return 0;
} else if (spwd.sp_lstchg < 0) {
if (!nis_used)
return 0;
}
}
else
spwd.sp_lstchg = -1;
#else
return 0;
#endif
} else if (fields[2][0] == '\0')
spwd.sp_lstchg = -1;
/*
* Get the minimum period between password changes.
*/
if (fields[3][0] == '\0') {
spwd.sp_min = -1;
} else {
if (getlong (fields[3], &spwd.sp_min) == 0) {
spwd.sp_min = strtol (fields[3], &cpp, 10);
if ((spwd.sp_min == 0) && *cpp) {
#ifdef USE_NIS
if (nis_used) {
spwd.sp_min = -1;
} else
#endif
return 0;
} else if (spwd.sp_min < 0) {
if (!nis_used)
return 0;
}
}
else
spwd.sp_min = -1;
#else
return 0;
#endif
} else if (fields[3][0] == '\0')
spwd.sp_min = -1;
/*
* Get the maximum number of days a password is valid.
*/
if (fields[4][0] == '\0') {
spwd.sp_max = -1;
} else {
if (getlong (fields[4], &spwd.sp_max) == 0) {
spwd.sp_max = strtol (fields[4], &cpp, 10);
if ((spwd.sp_max == 0) && *cpp) {
#ifdef USE_NIS
if (nis_used) {
spwd.sp_max = -1;
} else
#endif
return 0;
} else if (spwd.sp_max < 0) {
if (!nis_used)
return 0;
}
}
else
spwd.sp_max = -1;
#else
return 0;
#endif
} else if (fields[4][0] == '\0')
spwd.sp_max = -1;
/*
* If there are only OFIELDS fields (this is a SVR3.2 /etc/shadow
@@ -242,10 +235,8 @@ static struct spwd *my_sgetspent (const char *string)
*/
if (i == OFIELDS) {
spwd.sp_warn = -1;
spwd.sp_inact = -1;
spwd.sp_expire = -1;
spwd.sp_flag = SHADOW_SP_FLAG_UNSET;
spwd.sp_warn = spwd.sp_inact = spwd.sp_expire =
spwd.sp_flag = -1;
return &spwd;
}
@@ -254,81 +245,72 @@ static struct spwd *my_sgetspent (const char *string)
* Get the number of days of password expiry warning.
*/
if (fields[5][0] == '\0') {
spwd.sp_warn = -1;
} else {
if (getlong (fields[5], &spwd.sp_warn) == 0) {
spwd.sp_warn = strtol (fields[5], &cpp, 10);
if ((spwd.sp_warn == 0) && *cpp) {
#ifdef USE_NIS
if (nis_used) {
spwd.sp_warn = -1;
} else
#endif
return 0;
} else if (spwd.sp_warn < 0) {
if (!nis_used)
return 0;
}
}
else
spwd.sp_warn = -1;
#else
return 0;
#endif
} else if (fields[5][0] == '\0')
spwd.sp_warn = -1;
/*
* Get the number of days of inactivity before an account is
* disabled.
*/
if (fields[6][0] == '\0') {
spwd.sp_inact = -1;
} else {
if (getlong (fields[6], &spwd.sp_inact) == 0) {
spwd.sp_inact = strtol (fields[6], &cpp, 10);
if ((spwd.sp_inact == 0) && *cpp) {
#ifdef USE_NIS
if (nis_used) {
spwd.sp_inact = -1;
} else
#endif
return 0;
} else if (spwd.sp_inact < 0) {
if (!nis_used)
return 0;
}
}
else
spwd.sp_inact = -1;
#else
return 0;
#endif
} else if (fields[6][0] == '\0')
spwd.sp_inact = -1;
/*
* Get the number of days after the epoch before the account is
* set to expire.
*/
if (fields[7][0] == '\0') {
spwd.sp_expire = -1;
} else {
if (getlong (fields[7], &spwd.sp_expire) == 0) {
spwd.sp_expire = strtol (fields[7], &cpp, 10);
if ((spwd.sp_expire == 0) && *cpp) {
#ifdef USE_NIS
if (nis_used) {
spwd.sp_expire = -1;
} else
#endif
return 0;
} else if (spwd.sp_expire < 0) {
if (!nis_used)
return 0;
}
}
else
spwd.sp_expire = -1;
#else
return 0;
#endif
} else if (fields[7][0] == '\0')
spwd.sp_expire = -1;
/*
* This field is reserved for future use. But it isn't supposed
* to have anything other than a valid integer in it.
*/
if (fields[8][0] == '\0') {
spwd.sp_flag = SHADOW_SP_FLAG_UNSET;
} else {
if (getlong (fields[8], &spwd.sp_flag) == 0) {
/* FIXME: add a getulong function */
spwd.sp_flag = strtol (fields[8], &cpp, 10);
if ((spwd.sp_flag == 0) && *cpp) {
#ifdef USE_NIS
if (nis_used) {
spwd.sp_flag = SHADOW_SP_FLAG_UNSET;
} else
#endif
return 0;
} else if (spwd.sp_flag < 0) {
if (!nis_used)
return 0;
}
}
else
spwd.sp_flag = -1;
#else
return 0;
#endif
} else if (fields[8][0] == '\0')
spwd.sp_flag = -1;
return (&spwd);
}
@@ -342,24 +324,21 @@ struct spwd *fgetspent (FILE * fp)
char buf[BUFSIZ];
char *cp;
if (NULL == fp) {
if (!fp)
return (0);
}
#ifdef USE_NIS
while (fgets (buf, (int) sizeof buf, fp) != (char *) 0)
while (fgets (buf, sizeof buf, fp) != (char *) 0)
#else
if (fgets (buf, (int) sizeof buf, fp) != (char *) 0)
if (fgets (buf, sizeof buf, fp) != (char *) 0)
#endif
{
cp = strchr (buf, '\n');
if (NULL != cp) {
if (NULL != cp)
*cp = '\0';
}
#ifdef USE_NIS
if (nis_ignore && IS_NISCHAR (buf[0])) {
if (nis_ignore && IS_NISCHAR (buf[0]))
continue;
}
#endif
return my_sgetspent (buf);
}
@@ -534,4 +513,3 @@ struct spwd *getspnam (const char *name)
#else
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif

View File

@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,18 +42,20 @@
#include "commonio.h"
#include "shadowio.h"
static /*@null@*/ /*@only@*/void *shadow_dup (const void *ent)
static void *shadow_dup (const void *ent)
{
const struct spwd *sp = ent;
return __spw_dup (sp);
}
static void shadow_free (/*@out@*//*@only@*/void *ent)
static void shadow_free (void *ent)
{
struct spwd *sp = ent;
spw_free (sp);
free (sp->sp_namp);
free (sp->sp_pwdp);
free (sp);
}
static const char *shadow_getname (const void *ent)
@@ -97,23 +99,18 @@ static struct commonio_db shadow_db = {
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
false, /* changed */
false, /* isopen */
false, /* locked */
false /* readonly */
0, /* changed */
0, /* isopen */
0, /* locked */
0 /* readonly */
};
int spw_setdbname (const char *filename)
int spw_name (const char *filename)
{
return commonio_setname (&shadow_db, filename);
}
/*@observer@*/const char *spw_dbname (void)
{
return shadow_db.filename;
}
bool spw_file_present (void)
int spw_file_present (void)
{
return commonio_present (&shadow_db);
}
@@ -128,7 +125,7 @@ int spw_open (int mode)
return commonio_open (&shadow_db, mode);
}
/*@observer@*/ /*@null@*/const struct spwd *spw_locate (const char *name)
const struct spwd *spw_locate (const char *name)
{
return commonio_locate (&shadow_db, name);
}
@@ -148,7 +145,7 @@ int spw_rewind (void)
return commonio_rewind (&shadow_db);
}
/*@observer@*/ /*@null@*/const struct spwd *spw_next (void)
const struct spwd *spw_next (void)
{
return commonio_next (&shadow_db);
}

View File

@@ -30,24 +30,16 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* $Id$ */
#ifndef _SHADOWIO_H
#define _SHADOWIO_H
#include "defines.h"
extern int spw_close (void);
extern bool spw_file_present (void);
extern /*@observer@*/ /*@null@*/const struct spwd *spw_locate (const char *name);
extern int spw_file_present (void);
extern const struct spwd *spw_locate (const char *);
extern int spw_lock (void);
extern int spw_setdbname (const char *filename);
extern /*@observer@*/const char *spw_dbname (void);
extern /*@observer@*/ /*@null@*/const struct spwd *spw_next (void);
extern int spw_open (int mode);
extern int spw_remove (const char *name);
extern int spw_name (const char *);
extern const struct spwd *spw_next (void);
extern int spw_open (int);
extern int spw_remove (const char *);
extern int spw_rewind (void);
extern int spw_unlock (void);
extern int spw_update (const struct spwd *sp);
extern int spw_update (const struct spwd *);
extern int spw_sort (void);
#endif

View File

@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,32 +41,17 @@
#include <stdio.h>
#include "shadowio.h"
/*@null@*/ /*@only@*/struct spwd *__spw_dup (const struct spwd *spent)
struct spwd *__spw_dup (const struct spwd *spent)
{
struct spwd *sp;
sp = (struct spwd *) malloc (sizeof *sp);
if (NULL == sp) {
if (!(sp = (struct spwd *) malloc (sizeof *sp)))
return NULL;
}
*sp = *spent;
sp->sp_namp = strdup (spent->sp_namp);
if (NULL == sp->sp_namp) {
if (!(sp->sp_namp = strdup (spent->sp_namp)))
return NULL;
}
sp->sp_pwdp = strdup (spent->sp_pwdp);
if (NULL == sp->sp_pwdp) {
if (!(sp->sp_pwdp = strdup (spent->sp_pwdp)))
return NULL;
}
return sp;
}
void spw_free (/*@out@*/ /*@only@*/struct spwd *spent)
{
free (spent->sp_namp);
memzero (spent->sp_pwdp, strlen (spent->sp_pwdp));
free (spent->sp_pwdp);
free (spent);
}

View File

@@ -14,9 +14,6 @@ libmisc_a_SOURCES = \
chkname.h \
chowndir.c \
chowntty.c \
cleanup.c \
cleanup_group.c \
cleanup_user.c \
console.c \
copydir.c \
entry.c \
@@ -24,12 +21,10 @@ libmisc_a_SOURCES = \
failure.c \
failure.h \
fields.c \
find_new_gid.c \
find_new_uid.c \
find_new_ids.c \
getdate.h \
getdate.y \
getgr_nam_gid.c \
getrange.c \
getlong.c \
hushed.c \
isexpired.c \
limits.c \
@@ -40,7 +35,6 @@ libmisc_a_SOURCES = \
myname.c \
obscure.c \
pam_pass.c \
pam_pass_non_interractive.c \
pwd2spwd.c \
pwdcheck.c \
pwd_init.c \
@@ -49,14 +43,12 @@ libmisc_a_SOURCES = \
setugid.c \
setupenv.c \
shell.c \
system.c \
strtoday.c \
sub.c \
sulog.c \
ttytype.c \
tz.c \
ulimit.c \
user_busy.c \
utmp.c \
valid.c \
xgetpwnam.c \

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2001 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,7 +32,7 @@
#include <config.h>
#if defined (HAVE_SETGROUPS) && ! defined (USE_PAM)
#ifdef HAVE_SETGROUPS
#include "prototypes.h"
#include "defines.h"
@@ -52,9 +52,7 @@
int add_groups (const char *list)
{
GETGROUPS_T *grouplist, *tmp;
size_t i;
int ngroups;
bool added;
int i, ngroups, added;
char *token;
char buf[1024];
@@ -67,13 +65,11 @@ int add_groups (const char *list)
i = 16;
for (;;) {
grouplist = (gid_t *) malloc (i * sizeof (GETGROUPS_T));
if (NULL == grouplist) {
if (!grouplist)
return -1;
}
ngroups = getgroups (i, grouplist);
if ((-1 == ngroups) || (i > (size_t)ngroups)) {
if (i > ngroups)
break;
}
/* not enough room, so try allocating a larger buffer */
free (grouplist);
i *= 2;
@@ -83,45 +79,40 @@ int add_groups (const char *list)
return -1;
}
added = false;
for (token = strtok (buf, SEP); NULL != token; token = strtok (NULL, SEP)) {
added = 0;
for (token = strtok (buf, SEP); token; token = strtok (NULL, SEP)) {
struct group *grp;
grp = getgrnam (token); /* local, no need for xgetgrnam */
if (NULL == grp) {
if (!grp) {
fprintf (stderr, _("Warning: unknown group %s\n"),
token);
continue;
}
for (i = 0; i < (size_t)ngroups && grouplist[i] != grp->gr_gid; i++);
for (i = 0; i < ngroups && grouplist[i] != grp->gr_gid; i++);
if (i < (size_t)ngroups) {
if (i < ngroups)
continue;
}
if (ngroups >= sysconf (_SC_NGROUPS_MAX)) {
fputs (_("Warning: too many groups\n"), stderr);
break;
}
tmp = (gid_t *) realloc (grouplist, (size_t)(ngroups + 1) * sizeof (GETGROUPS_T));
if (NULL == tmp) {
tmp = (gid_t *) realloc (grouplist, (ngroups + 1) * sizeof (GETGROUPS_T));
if (!tmp) {
free (grouplist);
return -1;
}
tmp[ngroups] = grp->gr_gid;
ngroups++;
tmp[ngroups++] = grp->gr_gid;
grouplist = tmp;
added = true;
added++;
}
if (added) {
return setgroups ((size_t)ngroups, grouplist);
}
if (added)
return setgroups (ngroups, grouplist);
return 0;
}
#else /* HAVE_SETGROUPS && !USE_PAM */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* HAVE_SETGROUPS && !USE_PAM */
#endif

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2001 - 2006, Tomasz Kłoczko
* Copyright (c) 2008 - 2009, Nicolas François
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -53,33 +53,31 @@
* expire() calls /bin/passwd to change the user's password
* if it has expired.
*/
int expire (const struct passwd *pw, /*@null@*/const struct spwd *sp)
int expire (const struct passwd *pw, const struct spwd *sp)
{
int status;
pid_t child;
pid_t pid;
int child;
int pid;
if (NULL == sp) {
return 0;
}
if (!sp)
sp = pwd_to_spwd (pw);
/*
* See if the user's password has expired, and if so
* force them to change their password.
*/
status = isexpired (pw, sp);
switch (status) {
switch (status = isexpired (pw, sp)) {
case 0:
return 0;
case 1:
(void) fputs (_("Your password has expired."), stdout);
fputs (_("Your password has expired."), stdout);
break;
case 2:
(void) fputs (_("Your password is inactive."), stdout);
fputs (_("Your password is inactive."), stdout);
break;
case 3:
(void) fputs (_("Your login has expired."), stdout);
fputs (_("Your login has expired."), stdout);
break;
}
@@ -90,12 +88,12 @@ int expire (const struct passwd *pw, /*@null@*/const struct spwd *sp)
* change that password.
*/
if ((status > 1) || (sp->sp_max < sp->sp_min)) {
(void) puts (_(" Contact the system administrator."));
exit (EXIT_FAILURE);
if (status > 1 || sp->sp_max < sp->sp_min) {
puts (_(" Contact the system administrator."));
exit (1);
}
(void) puts (_(" Choose a new password."));
(void) fflush (stdout);
puts (_(" Choose a new password."));
fflush (stdout);
/*
* Close all the files so that unauthorized access won't
@@ -117,8 +115,7 @@ int expire (const struct passwd *pw, /*@null@*/const struct spwd *sp)
* change their password before being able to use the account.
*/
pid = fork ();
if (0 == pid) {
if ((pid = fork ()) == 0) {
int err;
/*
@@ -126,32 +123,24 @@ int expire (const struct passwd *pw, /*@null@*/const struct spwd *sp)
* passwd to work just like it would had they executed
* it from the command line while logged in.
*/
#if defined(HAVE_INITGROUPS) && ! defined(USE_PAM)
if (setup_uid_gid (pw, false) != 0)
#else
if (setup_uid_gid (pw) != 0)
#endif
{
if (setup_uid_gid (pw, 0))
_exit (126);
}
(void) execl (PASSWD_PROGRAM, PASSWD_PROGRAM, pw->pw_name, (char *) 0);
execl (PASSWD_PROGRAM, PASSWD_PROGRAM, pw->pw_name, (char *) 0);
err = errno;
perror ("Can't execute " PASSWD_PROGRAM);
_exit ((ENOENT == err) ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
} else if ((pid_t) -1 == pid) {
_exit (err == ENOENT ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
} else if (pid == -1) {
perror ("fork");
exit (EXIT_FAILURE);
exit (1);
}
while ((child = wait (&status)) != pid && child != -1);
while (((child = wait (&status)) != pid) && (child != (pid_t)-1));
if ((child == pid) && (0 == status)) {
if (child == pid && status == 0)
return 1;
}
exit (EXIT_FAILURE);
/*@notreached@*/}
exit (1);
/*NOTREACHED*/}
/*
* agecheck - see if warning is needed for password expiration
@@ -160,42 +149,30 @@ int expire (const struct passwd *pw, /*@null@*/const struct spwd *sp)
* to expire and warns the user of the pending password expiration.
*/
void agecheck (/*@null@*/const struct spwd *sp)
void agecheck (const struct passwd *pw, const struct spwd *sp)
{
long now = (long) time ((time_t *) 0) / SCALE;
long now = time ((long *) 0) / SCALE;
long remain;
if (NULL == sp) {
return;
}
if (!sp)
sp = pwd_to_spwd (pw);
/*
* The last, max, and warn fields must be supported or the
* warning period cannot be calculated.
*/
if ( (-1 == sp->sp_lstchg)
|| (-1 == sp->sp_max)
|| (-1 == sp->sp_warn)) {
if (sp->sp_lstchg == -1 || sp->sp_max == -1 || sp->sp_warn == -1)
return;
}
if (0 == sp->sp_lstchg) {
(void) puts (_("You must change your password."));
return;
}
remain = sp->sp_lstchg + sp->sp_max - now;
if (remain <= sp->sp_warn) {
if ((remain = (sp->sp_lstchg + sp->sp_max) - now) <= sp->sp_warn) {
remain /= DAY / SCALE;
if (remain > 1) {
(void) printf (_("Your password will expire in %ld days.\n"),
remain);
} else if (1 == remain) {
(void) puts (_("Your password will expire tomorrow."));
} else if (remain == 0) {
(void) puts (_("Your password will expire today."));
}
if (remain > 1)
printf (_
("Your password will expire in %ld days.\n"),
remain);
else if (remain == 1)
puts (_("Your password will expire tomorrow."));
else if (remain == 0)
puts (_("Your password will expire today."));
}
}

View File

@@ -53,14 +53,11 @@ void audit_help_open (void)
if (audit_fd < 0) {
/* You get these only when the kernel doesn't have
* audit compiled in. */
if ( (errno == EINVAL)
|| (errno == EPROTONOSUPPORT)
|| (errno == EAFNOSUPPORT)) {
if (errno == EINVAL || errno == EPROTONOSUPPORT ||
errno == EAFNOSUPPORT)
return;
}
(void) fputs (_("Cannot open audit interface - aborting.\n"),
stderr);
exit (EXIT_FAILURE);
fprintf (stderr, "Cannot open audit interface - aborting.\n");
exit (1);
}
}
@@ -75,32 +72,16 @@ void audit_help_open (void)
* name - user's account or group name. If not available use NULL.
* id - uid or gid that the operation is being performed on. This is used
* only when user is NULL.
* result - 1 is "success" and 0 is "failed"
*/
void audit_logger (int type, const char *pgname, const char *op,
const char *name, unsigned int id,
shadow_audit_result result)
const char *name, unsigned int id, int result)
{
if (audit_fd < 0) {
if (audit_fd < 0)
return;
} else {
else
audit_log_acct_message (audit_fd, type, NULL, op, name, id,
NULL, NULL, NULL, (int) result);
}
}
void audit_logger_message (const char *message, shadow_audit_result result)
{
if (audit_fd < 0) {
return;
} else {
audit_log_user_message (audit_fd,
AUDIT_USYS_CONFIG,
message,
NULL, /* hostname */
NULL, /* addr */
NULL, /* tty */
(int) result);
}
NULL, NULL, NULL, result);
}
#else /* WITH_AUDIT */

View File

@@ -31,11 +31,8 @@
*/
/*
* is_valid_user_name(), is_valid_group_name() - check the new user/group
* name for validity;
* return values:
* true - OK
* false - bad name
* check_user_name(), check_group_name() - check the new user/group
* name for validity; return value: 1 - OK, 0 - bad name
*/
#include <config.h>
@@ -45,55 +42,57 @@
#include <ctype.h>
#include "defines.h"
#include "chkname.h"
static bool is_valid_name (const char *name)
#if HAVE_UTMPX_H
#include <utmpx.h>
#else
#include <utmp.h>
#endif
static int good_name (const char *name)
{
/*
* User/group names must match [a-z_][a-z0-9_-]*[$]
*/
if (('\0' == *name) ||
!((('a' <= *name) && ('z' >= *name)) || ('_' == *name))) {
return false;
if (!*name || !((*name >= 'a' && *name <= 'z') || *name == '_'))
return 0;
while (*++name) {
if (!((*name >= 'a' && *name <= 'z') ||
(*name >= '0' && *name <= '9') ||
*name == '_' || *name == '-' ||
(*name == '$' && *(name + 1) == '\0')))
return 0;
}
while ('\0' != *++name) {
if (!(( ('a' <= *name) && ('z' >= *name) ) ||
( ('0' <= *name) && ('9' >= *name) ) ||
('_' == *name) ||
('-' == *name) ||
( ('$' == *name) && ('\0' == *(name + 1)) )
)) {
return false;
}
}
return true;
return 1;
}
bool is_valid_user_name (const char *name)
int check_user_name (const char *name)
{
#if HAVE_UTMPX_H
struct utmpx ut;
#else
struct utmp ut;
#endif
/*
* User names are limited by whatever utmp can
* handle.
* handle (usually max 8 characters).
*/
if (strlen (name) > USER_NAME_MAX_LENGTH) {
return false;
}
if (strlen (name) > sizeof (ut.ut_user))
return 0;
return is_valid_name (name);
return good_name (name);
}
bool is_valid_group_name (const char *name)
int check_group_name (const char *name)
{
/*
* Arbitrary limit for group names.
* HP-UX 10 limits to 16 characters
* Arbitrary limit for group names - max 16
* characters (same as on HP-UX 10).
*/
if ( (GROUP_NAME_MAX_LENGTH > 0)
&& (strlen (name) > GROUP_NAME_MAX_LENGTH)) {
return false;
}
if (strlen (name) > 16)
return 0;
return is_valid_name (name);
return good_name (name);
}

View File

@@ -2,7 +2,6 @@
* Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1997 - 2000, Marek Michałkiewicz
* Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,16 +34,13 @@
#define _CHKNAME_H_
/*
* is_valid_user_name(), is_valid_group_name() - check the new user/group
* name for validity;
* return values:
* true - OK
* false - bad name
* check_user_name(), check_group_name() - check the new user/group
* name for validity; return value: 1 - OK, 0 - bad name
*/
#include "defines.h"
extern bool is_valid_user_name (const char *name);
extern bool is_valid_group_name (const char *name);
extern int check_user_name (const char *);
extern int check_group_name (const char *name);
#endif

View File

@@ -104,11 +104,9 @@ chown_tree (const char *root, uid_t old_uid, uid_t new_uid, gid_t old_gid,
* Do the entire subdirectory.
*/
rc = chown_tree (new_name, old_uid, new_uid,
old_gid, new_gid);
if (0 != rc) {
if ((rc = chown_tree (new_name, old_uid, new_uid,
old_gid, new_gid)))
break;
}
}
#ifndef HAVE_LCHOWN
/* don't use chown (follows symbolic links!) */
@@ -119,18 +117,16 @@ chown_tree (const char *root, uid_t old_uid, uid_t new_uid, gid_t old_gid,
LCHOWN (new_name, new_uid,
sb.st_gid == old_gid ? new_gid : sb.st_gid);
}
(void) closedir (dir);
closedir (dir);
/*
* Now do the root of the tree
*/
if (stat (root, &sb) == 0) {
if (sb.st_uid == old_uid) {
if (!stat (root, &sb)) {
if (sb.st_uid == old_uid)
LCHOWN (root, new_uid,
sb.st_gid == old_gid ? new_gid : sb.st_gid);
}
sb.st_gid == old_gid ? new_gid : sb.st_gid);
}
return rc;
}

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2001, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François
* Copyright (c) 2007 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,14 +43,31 @@
#include "defines.h"
#include <pwd.h>
#include "getdef.h"
/*
* is_my_tty -- determine if "tty" is the same as TTY stdin is using
*/
static int is_my_tty (const char *tty)
{
struct stat by_name, by_fd;
if (stat (tty, &by_name) || fstat (0, &by_fd))
return 0;
if (by_name.st_rdev != by_fd.st_rdev)
return 0;
else
return 1;
}
/*
* chown_tty() sets the login tty to be owned by the new user ID
* with TTYPERM modes
*/
void chown_tty (const struct passwd *info)
void chown_tty (const char *tty, const struct passwd *info)
{
char buf[200], full_tty[200];
char *group; /* TTY group name or number */
struct group *grent;
gid_t gid;
@@ -59,32 +76,45 @@ void chown_tty (const struct passwd *info)
* ID. Otherwise, use the user's primary group ID.
*/
grent = getgr_nam_gid (getdef_str ("TTYGROUP"));
if (NULL != grent) {
gid = grent->gr_gid;
} else {
if (!(group = getdef_str ("TTYGROUP")))
gid = info->pw_gid;
else if (group[0] >= '0' && group[0] <= '9')
gid = atoi (group);
else if ((grent = getgrnam (group))) /* local, no need for xgetgrnam */
gid = grent->gr_gid;
else
gid = info->pw_gid;
}
/*
* Change the permissions on the TTY to be owned by the user with
* the group as determined above.
*/
if ( (fchown (STDIN_FILENO, info->pw_uid, gid) != 0)
|| (fchmod (STDIN_FILENO, getdef_num ("TTYPERM", 0600)) != 0)) {
if (*tty != '/') {
snprintf (full_tty, sizeof full_tty, "/dev/%s", tty);
tty = full_tty;
}
if (!is_my_tty (tty)) {
SYSLOG ((LOG_WARN,
"unable to determine TTY name, got %s\n", tty));
closelog ();
exit (1);
}
if (chown (tty, info->pw_uid, gid) ||
chmod (tty, getdef_num ("TTYPERM", 0600))) {
int err = errno;
fprintf (stderr,
_("Unable to change owner or mode of tty stdin: %s"),
strerror (err));
snprintf (buf, sizeof buf, _("Unable to change tty %s"), tty);
perror (buf);
SYSLOG ((LOG_WARN,
"unable to change owner or mode of tty stdin for user `%s': %s\n",
info->pw_name, strerror (err)));
if (EROFS != err) {
closelog ();
exit (EXIT_FAILURE);
}
"unable to change tty `%s' for user `%s'\n", tty,
info->pw_name));
closelog ();
if (err != EROFS)
exit (1);
}
#ifdef __linux__
/*

View File

@@ -1,128 +0,0 @@
/*
* Copyright (c) 2008 , 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>
#include <assert.h>
#include <stdio.h>
#include "prototypes.h"
/*
* The cleanup_functions stack.
*/
#define CLEANUP_FUNCTIONS 10
static cleanup_function cleanup_functions[CLEANUP_FUNCTIONS];
static void * cleanup_function_args[CLEANUP_FUNCTIONS];
/*
* - Cleanup functions shall not fail.
* - You should register do_cleanups with atexit.
* - You should add cleanup functions to the stack with add_cleanup when
* an operation is expected to be executed later, and remove it from the
* stack with del_cleanup when it has been executed.
*
**/
/*
* do_cleanups - perform the actions stored in the cleanup_functions stack.
*
* It is intended to be used as:
* atexit (do_cleanups);
*/
void do_cleanups (void)
{
unsigned int i;
/* Make sure there were no overflow */
assert (NULL == cleanup_functions[CLEANUP_FUNCTIONS-1]);
i = CLEANUP_FUNCTIONS;
do {
i--;
if (cleanup_functions[i] != NULL) {
cleanup_functions[i] (cleanup_function_args[i]);
}
} while (i>0);
}
/*
* add_cleanup - Add a cleanup_function to the cleanup_functions stack.
*/
void add_cleanup (cleanup_function pcf, /*@null@*/void *arg)
{
unsigned int i;
assert (NULL != pcf);
assert (NULL == cleanup_functions[CLEANUP_FUNCTIONS-2]);
/* Add the cleanup_function at the end of the stack */
for (i=0; NULL != cleanup_functions[i]; i++);
cleanup_functions[i] = pcf;
cleanup_function_args[i] = arg;
}
/*
* del_cleanup - Remove a cleanup_function from the cleanup_functions stack.
*/
void del_cleanup (cleanup_function pcf)
{
unsigned int i;
assert (NULL != pcf);
/* Find the pcf cleanup function */
for (i=0; i<CLEANUP_FUNCTIONS; i++) {
if (cleanup_functions[i] == pcf) {
break;
}
}
/* Make sure the cleanup function was found */
assert (i<CLEANUP_FUNCTIONS);
/* Move the rest of the cleanup functions */
for (; i<CLEANUP_FUNCTIONS; i++) {
/* Make sure the cleanup function was specified only once */
assert (cleanup_functions[i+1] != pcf);
if (i == (CLEANUP_FUNCTIONS -1)) {
cleanup_functions[i] = NULL;
cleanup_function_args[i] = NULL;
} else {
cleanup_functions[i] = cleanup_functions[i+1];
cleanup_function_args[i] = cleanup_function_args[i+1];
}
/* A NULL indicates the end of the stack */
if (NULL == cleanup_functions[i]) {
break;
}
}
}

View File

@@ -1,237 +0,0 @@
/*
* Copyright (c) 2008 , 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>
#include <assert.h>
#include <stdio.h>
#include "defines.h"
#include "groupio.h"
#include "sgroupio.h"
#include "prototypes.h"
/*
* cleanup_report_add_group - Report failure to add a group to the system
*
* It should be registered when it is decided to add a group to the system.
*/
void cleanup_report_add_group (void *group_name)
{
const char *name = (const char *)group_name;
SYSLOG ((LOG_ERR, "failed to add group %s", name));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_GROUP, Prog,
"",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
/*
* cleanup_report_del_group - Report failure to remove a group from the system
*
* It should be registered when it is decided to remove a group from the system.
*/
void cleanup_report_del_group (void *group_name)
{
const char *name = (const char *)group_name;
SYSLOG ((LOG_ERR, "failed to remove group %s", name));
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_GROUP, Prog,
"",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
void cleanup_report_mod_group (void *cleanup_info)
{
const struct cleanup_info_mod *info;
info = (const struct cleanup_info_mod *)cleanup_info;
SYSLOG ((LOG_ERR,
"failed to change %s (%s)",
gr_dbname (),
info->action));
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_ACCT, Prog,
info->audit_msg,
info->name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
#ifdef SHADOWGRP
void cleanup_report_mod_gshadow (void *cleanup_info)
{
const struct cleanup_info_mod *info;
info = (const struct cleanup_info_mod *)cleanup_info;
SYSLOG ((LOG_ERR,
"failed to change %s (%s)",
sgr_dbname (),
info->action));
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_ACCT, Prog,
info->audit_msg,
info->name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
#endif
/*
* cleanup_report_add_group_group - Report failure to add a group to group
*
* It should be registered when it is decided to add a group to the
* group database.
*/
void cleanup_report_add_group_group (void *group_name)
{
const char *name = (const char *)group_name;
SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, gr_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_GROUP, Prog,
"adding group to /etc/group",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
#ifdef SHADOWGRP
/*
* cleanup_report_add_group_gshadow - Report failure to add a group to gshadow
*
* It should be registered when it is decided to add a group to the
* gshadow database.
*/
void cleanup_report_add_group_gshadow (void *group_name)
{
const char *name = (const char *)group_name;
SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, sgr_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_GROUP, Prog,
"adding group to /etc/gshadow",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
#endif
/*
* cleanup_report_del_group_group - Report failure to remove a group from the
* regular group database
*
* It should be registered when it is decided to remove a group from the
* regular group database.
*/
void cleanup_report_del_group_group (void *group_name)
{
const char *name = (const char *)group_name;
SYSLOG ((LOG_ERR,
"failed to remove group %s from %s",
name, gr_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_GROUP, Prog,
"removing group from /etc/group",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
#ifdef SHADOWGRP
/*
* cleanup_report_del_group_gshadow - Report failure to remove a group from
* gshadow
*
* It should be registered when it is decided to remove a group from the
* gshadow database.
*/
void cleanup_report_del_group_gshadow (void *group_name)
{
const char *name = (const char *)group_name;
SYSLOG ((LOG_ERR,
"failed to remove group %s from %s",
name, sgr_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_GROUP, Prog,
"removing group from /etc/gshadow",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
#endif
/*
* cleanup_unlock_group - Unlock the group file
*
* It should be registered after the group file is successfully locked.
*/
void cleanup_unlock_group (unused void *arg)
{
if (gr_unlock () == 0) {
fprintf (stderr,
_("%s: failed to unlock %s\n"),
Prog, gr_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
#ifdef WITH_AUDIT
audit_logger_message ("unlocking group file",
SHADOW_AUDIT_FAILURE);
#endif
}
}
#ifdef SHADOWGRP
/*
* cleanup_unlock_gshadow - Unlock the gshadow file
*
* It should be registered after the gshadow file is successfully locked.
*/
void cleanup_unlock_gshadow (unused void *arg)
{
if (sgr_unlock () == 0) {
fprintf (stderr,
_("%s: failed to unlock %s\n"),
Prog, sgr_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
#ifdef WITH_AUDIT
audit_logger_message ("unlocking gshadow file",
SHADOW_AUDIT_FAILURE);
#endif
}
}
#endif

View File

@@ -1,152 +0,0 @@
/*
* Copyright (c) 2008 , 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>
#include <assert.h>
#include <stdio.h>
#include "defines.h"
#include "pwio.h"
#include "shadowio.h"
#include "prototypes.h"
/*
* cleanup_report_add_user - Report failure to add an user to the system
*
* It should be registered when it is decided to add an user to the system.
*/
void cleanup_report_add_user (void *user_name)
{
const char *name = (const char *)user_name;
SYSLOG ((LOG_ERR, "failed to add user %s", name));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
"",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
void cleanup_report_mod_passwd (void *cleanup_info)
{
const struct cleanup_info_mod *info;
info = (const struct cleanup_info_mod *)cleanup_info;
SYSLOG ((LOG_ERR,
"failed to change %s (%s)",
pw_dbname (),
info->action));
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_ACCT, Prog,
info->audit_msg,
info->name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
/*
* cleanup_report_add_user_passwd - Report failure to add an user to
* /etc/passwd
*
* It should be registered when it is decided to add an user to the
* /etc/passwd database.
*/
void cleanup_report_add_user_passwd (void *user_name)
{
const char *name = (const char *)user_name;
SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, pw_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
"adding user to /etc/passwd",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
/*
* cleanup_report_add_user_shadow - Report failure to add an user to
* /etc/shadow
*
* It should be registered when it is decided to add an user to the
* /etc/shadow database.
*/
void cleanup_report_add_user_shadow (void *user_name)
{
const char *name = (const char *)user_name;
SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, spw_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
"adding user to /etc/shadow",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
/*
* cleanup_unlock_passwd - Unlock the /etc/passwd database
*
* It should be registered after the passwd database is successfully locked.
*/
void cleanup_unlock_passwd (unused void *arg)
{
if (pw_unlock () == 0) {
fprintf (stderr,
_("%s: failed to unlock %s\n"),
Prog, pw_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
#ifdef WITH_AUDIT
audit_logger_message ("unlocking passwd file",
SHADOW_AUDIT_FAILURE);
#endif
}
}
/*
* cleanup_unlock_shadow - Unlock the /etc/shadow database
*
* It should be registered after the shadow database is successfully locked.
*/
void cleanup_unlock_shadow (unused void *arg)
{
if (spw_unlock () == 0) {
fprintf (stderr,
_("%s: failed to unlock %s\n"),
Prog, spw_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
#ifdef WITH_AUDIT
audit_logger_message ("unlocking shadow file",
SHADOW_AUDIT_FAILURE);
#endif
}
}

View File

@@ -40,14 +40,14 @@
#ident "$Id$"
/* local function prototypes */
static bool is_listed (const char *cfgin, const char *tty, bool def);
static int is_listed (const char *cfgin, const char *tty, int def);
/*
* This is now rather generic function which decides if "tty" is listed
* under "cfgin" in config (directly or indirectly). Fallback to default if
* something is bad.
*/
static bool is_listed (const char *cfgin, const char *tty, bool def)
static int is_listed (const char *cfgin, const char *tty, int def)
{
FILE *fp;
char buf[200], *cons, *s;
@@ -57,10 +57,8 @@ static bool is_listed (const char *cfgin, const char *tty, bool def)
* fallback to default.
*/
cons = getdef_str (cfgin);
if (NULL == cons) {
if ((cons = getdef_str (cfgin)) == NULL)
return def;
}
/*
* If this isn't a filename, then it is a ":" delimited list of
@@ -68,15 +66,14 @@ static bool is_listed (const char *cfgin, const char *tty, bool def)
*/
if (*cons != '/') {
strcpy (buf, cons);
while ((s = strtok (buf, ":")) != NULL) {
if (strcmp (s, tty) == 0) {
return true;
}
cons = strcpy (buf, cons);
while ((s = strtok (cons, ":")) != NULL) {
if (strcmp (s, tty) == 0)
return 1;
cons = NULL;
}
return false;
return 0;
}
/*
@@ -84,20 +81,18 @@ static bool is_listed (const char *cfgin, const char *tty, bool def)
* console - otherwise root will never be allowed to login.
*/
fp = fopen (cons, "r");
if (NULL == fp) {
if ((fp = fopen (cons, "r")) == NULL)
return def;
}
/*
* See if this tty is listed in the console file.
*/
while (fgets (buf, (int) sizeof (buf), fp) != NULL) {
while (fgets (buf, sizeof (buf), fp) != NULL) {
buf[strlen (buf) - 1] = '\0';
if (strcmp (buf, tty) == 0) {
(void) fclose (fp);
return true;
return 1;
}
}
@@ -106,7 +101,7 @@ static bool is_listed (const char *cfgin, const char *tty, bool def)
*/
(void) fclose (fp);
return false;
return 0;
}
/*
@@ -119,12 +114,7 @@ static bool is_listed (const char *cfgin, const char *tty, bool def)
* that would allow an unauthorized root login.
*/
bool console (const char *tty)
int console (const char *tty)
{
if (strncmp (tty, "/dev/", 5) == 0) {
tty += 5;
}
return is_listed ("CONSOLE", tty, true);
return is_listed ("CONSOLE", tty, 1);
}

View File

@@ -34,7 +34,6 @@
#ident "$Id$"
#include <assert.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
@@ -44,37 +43,37 @@
#include "defines.h"
#ifdef WITH_SELINUX
#include <selinux/selinux.h>
static int selinux_enabled = -1;
#endif
static /*@null@*/const char *src_orig;
static /*@null@*/const char *dst_orig;
static const char *src_orig;
static const char *dst_orig;
struct link_name {
dev_t ln_dev;
ino_t ln_ino;
nlink_t ln_count;
int ln_count;
char *ln_name;
/*@dependent@*/struct link_name *ln_next;
struct link_name *ln_next;
};
static /*@exposed@*/struct link_name *links;
static struct link_name *links;
static int copy_entry (const char *src, const char *dst,
long int uid, long int gid);
static int copy_dir (const char *src, const char *dst,
const struct stat *statp, const struct timeval mt[],
const struct stat *statp, const struct timeval mt[2],
long int uid, long int gid);
#ifdef S_IFLNK
static char *readlink_malloc (const char *filename);
static int copy_symlink (const char *src, const char *dst,
const struct stat *statp, const struct timeval mt[],
const struct stat *statp, const struct timeval mt[2],
long int uid, long int gid);
#endif
static int copy_hardlink (const char *src, const char *dst,
struct link_name *lp);
static int copy_special (const char *dst,
const struct stat *statp, const struct timeval mt[],
const struct stat *statp, const struct timeval mt[2],
long int uid, long int gid);
static int copy_file (const char *src, const char *dst,
const struct stat *statp, const struct timeval mt[],
const struct stat *statp, const struct timeval mt[2],
long int uid, long int gid);
#ifdef WITH_SELINUX
@@ -85,21 +84,14 @@ static int copy_file (const char *src, const char *dst,
* 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);
*/
int selinux_file_context (const char *dst_name)
static int selinux_file_context (const char *dst_name)
{
static bool selinux_checked = false;
static bool selinux_enabled;
security_context_t scontext = NULL;
if (!selinux_checked) {
if (selinux_enabled < 0) {
selinux_enabled = is_selinux_enabled () > 0;
selinux_checked = true;
}
if (selinux_enabled) {
/* Get the default security context for this file */
if (matchpathcon (dst_name, 0, &scontext) < 0) {
@@ -122,7 +114,7 @@ int selinux_file_context (const char *dst_name)
/*
* remove_link - delete a link from the linked list
*/
static void remove_link (/*@only@*/struct link_name *ln)
static void remove_link (struct link_name *ln)
{
struct link_name *lp;
@@ -139,8 +131,6 @@ static void remove_link (/*@only@*/struct link_name *ln)
}
if (NULL == lp) {
free (ln->ln_name);
free (ln);
return;
}
@@ -153,19 +143,15 @@ static void remove_link (/*@only@*/struct link_name *ln)
* check_link - see if a file is really a link
*/
static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, const struct stat *sb)
static struct link_name *check_link (const char *name, const struct stat *sb)
{
struct link_name *lp;
size_t src_len;
size_t dst_len;
size_t name_len;
size_t len;
int src_len;
int dst_len;
int name_len;
int len;
/* copy_tree () must be the entry point */
assert (NULL != src_orig);
assert (NULL != dst_orig);
for (lp = links; NULL != lp; lp = lp->ln_next) {
for (lp = links; lp; lp = lp->ln_next) {
if ((lp->ln_dev == sb->st_dev) && (lp->ln_ino == sb->st_ino)) {
return lp;
}
@@ -183,7 +169,7 @@ static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, c
lp->ln_ino = sb->st_ino;
lp->ln_count = sb->st_nlink;
len = name_len - src_len + dst_len + 1;
lp->ln_name = (char *) xmalloc (len);
lp->ln_name = xmalloc (len);
snprintf (lp->ln_name, len, "%s%s", dst_orig, name + src_len);
lp->ln_next = links;
links = lp;
@@ -200,8 +186,10 @@ static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, c
int copy_tree (const char *src_root, const char *dst_root,
long int uid, long int gid)
{
char src_name[1024];
char dst_name[1024];
int err = 0;
bool set_orig = false;
int set_orig = 0;
struct DIRECT *ent;
DIR *dir;
@@ -228,10 +216,10 @@ int copy_tree (const char *src_root, const char *dst_root,
return -1;
}
if (src_orig == NULL) {
if (src_orig == 0) {
src_orig = src_root;
dst_orig = dst_root;
set_orig = true;
set_orig++;
}
while ((0 == err) && (ent = readdir (dir)) != NULL) {
/*
@@ -239,54 +227,35 @@ int copy_tree (const char *src_root, const char *dst_root,
*/
if ((strcmp (ent->d_name, ".") != 0) &&
(strcmp (ent->d_name, "..") != 0)) {
char *src_name;
char *dst_name;
size_t src_len = strlen (ent->d_name) + 2;
size_t dst_len = strlen (ent->d_name) + 2;
src_len += strlen (src_root);
dst_len += strlen (dst_root);
src_name = (char *) malloc (src_len);
dst_name = (char *) malloc (dst_len);
if ((NULL == src_name) || (NULL == dst_name)) {
/*
* Make sure the resulting source and destination
* filenames will fit in their buffers.
*/
if ( (strlen (src_root) + strlen (ent->d_name) + 2 >
sizeof src_name)
|| (strlen (dst_root) + strlen (ent->d_name) + 2 >
sizeof dst_name)) {
err = -1;
} else {
/*
* Build the filename for both the source and
* the destination files.
*/
snprintf (src_name, src_len, "%s/%s",
snprintf (src_name, sizeof src_name, "%s/%s",
src_root, ent->d_name);
snprintf (dst_name, dst_len, "%s/%s",
snprintf (dst_name, sizeof dst_name, "%s/%s",
dst_root, ent->d_name);
err = copy_entry (src_name, dst_name, uid, gid);
}
if (NULL != src_name) {
free (src_name);
}
if (NULL != dst_name) {
free (dst_name);
}
}
}
(void) closedir (dir);
if (set_orig) {
src_orig = NULL;
dst_orig = NULL;
src_orig = 0;
dst_orig = 0;
}
#ifdef WITH_SELINUX
/* Reset SELinux to create files with default contexts */
setfscreatecon (NULL);
#endif
/* FIXME: with the call to remove_link, we could also check that
* no links remain in links.
* assert (NULL == links); */
return err;
}
@@ -316,28 +285,16 @@ static int copy_entry (const char *src, const char *dst,
if (LSTAT (src, &sb) == -1) {
/* If we cannot stat the file, do not care. */
} else {
#ifdef HAVE_STRUCT_STAT_ST_ATIM
#if defined(_BSD_SOURCE) || defined(_SVID_SOURCE)
mt[0].tv_sec = sb.st_atim.tv_sec;
mt[0].tv_usec = sb.st_atim.tv_nsec / 1000;
#else
mt[0].tv_sec = sb.st_atime;
#ifdef HAVE_STRUCT_STAT_ST_ATIMENSEC
mt[0].tv_usec = sb.st_atimensec / 1000;
#else
mt[0].tv_usec = 0;
#endif
#endif
#ifdef HAVE_STRUCT_STAT_ST_MTIM
mt[1].tv_sec = sb.st_mtim.tv_sec;
mt[1].tv_usec = sb.st_mtim.tv_nsec / 1000;
#else
mt[0].tv_sec = sb.st_atime;
mt[0].tv_usec = sb.st_atimensec / 1000;
mt[1].tv_sec = sb.st_mtime;
#ifdef HAVE_STRUCT_STAT_ST_MTIMENSEC
mt[1].tv_usec = sb.st_mtimensec / 1000;
#else
mt[1].tv_usec = 0;
#endif
#endif
if (S_ISDIR (sb.st_mode)) {
@@ -396,7 +353,7 @@ static int copy_entry (const char *src, const char *dst,
* Return 0 on success, -1 on error.
*/
static int copy_dir (const char *src, const char *dst,
const struct stat *statp, const struct timeval mt[],
const struct stat *statp, const struct timeval mt[2],
long int uid, long int gid)
{
int err = 0;
@@ -423,41 +380,6 @@ static int copy_dir (const char *src, const char *dst,
}
#ifdef S_IFLNK
/*
* readlink_malloc - wrapper for readlink
*
* return NULL on error.
* The return string shall be freed by the caller.
*/
static char *readlink_malloc (const char *filename)
{
size_t size = 1024;
while (1) {
ssize_t nchars;
char *buffer = (char *) malloc (size);
if (NULL == buffer) {
return NULL;
}
nchars = readlink (filename, buffer, size);
if (nchars < 0) {
return NULL;
}
if ( (size_t) nchars < size) { /* The buffer was large enough */
/* readlink does not nul-terminate */
buffer[nchars] = '\0';
return buffer;
}
/* Try again with a bigger buffer */
free (buffer);
size *= 2;
}
}
/*
* copy_symlink - copy a symlink
*
@@ -469,14 +391,13 @@ static char *readlink_malloc (const char *filename)
* Return 0 on success, -1 on error.
*/
static int copy_symlink (const char *src, const char *dst,
const struct stat *statp, const struct timeval mt[],
const struct stat *statp, const struct timeval mt[2],
long int uid, long int gid)
{
char *oldlink;
/* copy_tree () must be the entry point */
assert (NULL != src_orig);
assert (NULL != dst_orig);
char oldlink[1024];
char dummy[1024];
int len;
int err = 0;
/*
* Get the name of the file which the link points
@@ -486,26 +407,17 @@ static int copy_symlink (const char *src, const char *dst,
* destination directory name.
*/
oldlink = readlink_malloc (src);
if (NULL == oldlink) {
len = readlink (src, oldlink, sizeof (oldlink) - 1);
if (len < 0) {
return -1;
}
/* If src was a link to an entry of the src_orig directory itself,
* create a link to the corresponding entry in the dst_orig
* directory.
* FIXME: This may change a relative link to an absolute link
*/
oldlink[len] = '\0'; /* readlink() does not NUL-terminate */
if (strncmp (oldlink, src_orig, strlen (src_orig)) == 0) {
size_t len = strlen (dst_orig) + strlen (oldlink) - strlen (src_orig) + 1;
char *dummy = (char *) malloc (len);
snprintf (dummy, len, "%s%s",
snprintf (dummy, sizeof dummy, "%s%s",
dst_orig,
oldlink + strlen (src_orig));
free (oldlink);
oldlink = dummy;
strcpy (oldlink, dummy);
}
#ifdef WITH_SELINUX
selinux_file_context (dst);
#endif
@@ -513,21 +425,17 @@ static int copy_symlink (const char *src, const char *dst,
|| (lchown (dst,
(uid == -1) ? statp->st_uid : (uid_t) uid,
(gid == -1) ? statp->st_gid : (gid_t) gid) != 0)) {
free (oldlink);
return -1;
}
free (oldlink);
#ifdef HAVE_LUTIMES
/* 2007-10-18: We don't care about
* exit status of lutimes because
* it returns ENOSYS on many system
* - not implemented
*/
lutimes (dst, mt);
#endif
return 0;
return err;
}
#endif
@@ -546,13 +454,10 @@ static int copy_hardlink (const char *src, const char *dst,
if (link (lp->ln_name, dst) != 0) {
return -1;
}
/* FIXME: why is it unlinked? This is a copy, not a move */
if (unlink (src) != 0) {
return -1;
}
/* FIXME: idem, although it may never be used again */
/* If the file could be unlinked, decrement the links counter,
* and delete the file if it was the last reference */
lp->ln_count--;
@@ -574,7 +479,7 @@ static int copy_hardlink (const char *src, const char *dst,
* Return 0 on success, -1 on error.
*/
static int copy_special (const char *dst,
const struct stat *statp, const struct timeval mt[],
const struct stat *statp, const struct timeval mt[2],
long int uid, long int gid)
{
int err = 0;
@@ -606,14 +511,14 @@ static int copy_special (const char *dst,
* Return 0 on success, -1 on error.
*/
static int copy_file (const char *src, const char *dst,
const struct stat *statp, const struct timeval mt[],
const struct stat *statp, const struct timeval mt[2],
long int uid, long int gid)
{
int err = 0;
int ifd;
int ofd;
char buf[1024];
ssize_t cnt;
int cnt;
ifd = open (src, O_RDONLY);
if (ifd < 0) {
@@ -622,40 +527,32 @@ static int copy_file (const char *src, const char *dst,
#ifdef WITH_SELINUX
selinux_file_context (dst);
#endif
ofd = open (dst, O_WRONLY | O_CREAT | O_TRUNC, statp->st_mode & 07777);
ofd = open (dst, O_WRONLY | O_CREAT | O_TRUNC, 0);
if ( (ofd < 0)
|| (fchown (ofd,
(uid == -1) ? statp->st_uid : (uid_t) uid,
(gid == -1) ? statp->st_gid : (gid_t) gid) != 0)
|| (fchmod (ofd, statp->st_mode & 07777) != 0)) {
|| (chown (dst,
(uid == -1) ? statp->st_uid : (uid_t) uid,
(gid == -1) ? statp->st_gid : (gid_t) gid) != 0)
|| (chmod (dst, statp->st_mode & 07777) != 0)) {
(void) close (ifd);
return -1;
}
while ((cnt = read (ifd, buf, sizeof buf)) > 0) {
if (write (ofd, buf, (size_t)cnt) != cnt) {
if (write (ofd, buf, cnt) != cnt) {
return -1;
}
}
(void) close (ifd);
#ifdef HAVE_FUTIMES
if (futimes (ofd, mt) != 0) {
return -1;
}
#endif
if (close (ofd) != 0) {
return -1;
}
#ifndef HAVE_FUTIMES
if (utimes(dst, mt) != 0) {
return -1;
}
#endif
return err;
}
@@ -669,12 +566,20 @@ static int copy_file (const char *src, const char *dst,
int remove_tree (const char *root)
{
char *new_name = NULL;
char new_name[1024];
int err = 0;
struct DIRECT *ent;
struct stat sb;
DIR *dir;
/*
* Make certain the directory exists.
*/
if (access (root, F_OK) != 0) {
return -1;
}
/*
* Open the source directory and read each entry. Every file
* entry in the directory is copied with the UID and GID set
@@ -688,7 +593,6 @@ int remove_tree (const char *root)
}
while ((ent = readdir (dir))) {
size_t new_len = strlen (root) + strlen (ent->d_name) + 2;
/*
* Skip the "." and ".." entries
@@ -703,15 +607,12 @@ int remove_tree (const char *root)
* Make the filename for the current entry.
*/
if (NULL != new_name) {
free (new_name);
}
new_name = (char *) malloc (new_len);
if (NULL == new_name) {
if (strlen (root) + strlen (ent->d_name) + 2 > sizeof new_name) {
err = -1;
break;
}
snprintf (new_name, new_len, "%s/%s", root, ent->d_name);
snprintf (new_name, sizeof new_name, "%s/%s", root,
ent->d_name);
if (LSTAT (new_name, &sb) == -1) {
continue;
}
@@ -734,9 +635,6 @@ int remove_tree (const char *root)
}
}
}
if (NULL != new_name) {
free (new_name);
}
(void) closedir (dir);
if (0 == err) {

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1992, Julianne Frances Haugh
* Copyright (c) 1996 - 1999, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2009, Nicolas François
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,6 @@
#ident "$Id$"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -47,7 +46,7 @@
*/
#define NEWENVP_STEP 16
size_t newenvc = 0;
/*@null@*/char **newenvp = NULL;
char **newenvp = NULL;
extern char **environ;
static const char *forbid[] = {
@@ -86,18 +85,15 @@ void initenv (void)
}
void addenv (const char *string, /*@null@*/const char *value)
void addenv (const char *string, const char *value)
{
char *cp, *newstring;
size_t i;
size_t n;
if (NULL != value) {
size_t len = strlen (string) + strlen (value) + 2;
int wlen;
newstring = xmalloc (len);
wlen = snprintf (newstring, len, "%s=%s", string, value);
assert (wlen == (int) len -1);
if (value) {
newstring = xmalloc (strlen (string) + strlen (value) + 2);
sprintf (newstring, "%s=%s", string, value);
} else {
newstring = xstrdup (string);
}
@@ -108,7 +104,7 @@ void addenv (const char *string, /*@null@*/const char *value)
*/
cp = strchr (newstring, '=');
if (NULL == cp) {
if (!cp) {
free (newstring);
return;
}
@@ -116,10 +112,9 @@ void addenv (const char *string, /*@null@*/const char *value)
n = (size_t) (cp - newstring);
for (i = 0; i < newenvc; i++) {
if ( (strncmp (newstring, newenvp[i], n) == 0)
&& (('=' == newenvp[i][n]) || ('\0' == newenvp[i][n]))) {
if (strncmp (newstring, newenvp[i], n) == 0 &&
(newenvp[i][n] == '=' || newenvp[i][n] == '\0'))
break;
}
}
if (i < newenvc) {
@@ -156,14 +151,12 @@ void addenv (const char *string, /*@null@*/const char *value)
* environ so that it doesn't point to some
* free memory area (realloc() could move it).
*/
if (environ == newenvp) {
if (environ == newenvp)
environ = __newenvp;
}
newenvp = __newenvp;
} else {
(void) fputs (_("Environment overflow\n"), stderr);
newenvc--;
free (newenvp[newenvc]);
fputs (_("Environment overflow\n"), stderr);
free (newenvp[--newenvc]);
}
}
@@ -185,28 +178,21 @@ void set_env (int argc, char *const *argv)
char *cp;
for (; argc > 0; argc--, argv++) {
if (strlen (*argv) >= sizeof variable) {
if (strlen (*argv) >= sizeof variable)
continue; /* ignore long entries */
}
cp = strchr (*argv, '=');
if (NULL == cp) {
int wlen;
wlen = snprintf (variable, sizeof variable, "L%d", noname);
assert (wlen < (int) sizeof(variable));
noname++;
if (!(cp = strchr (*argv, '='))) {
snprintf (variable, sizeof variable, "L%d", noname++);
addenv (variable, *argv);
} else {
const char **p;
for (p = forbid; NULL != *p; p++) {
if (strncmp (*argv, *p, strlen (*p)) == 0) {
for (p = forbid; *p; p++)
if (strncmp (*argv, *p, strlen (*p)) == 0)
break;
}
}
if (NULL != *p) {
strncpy (variable, *argv, (size_t)(cp - *argv));
if (*p) {
strncpy (variable, *argv, cp - *argv);
variable[cp - *argv] = '\0';
printf (_("You may not change $%s\n"),
variable);
@@ -234,32 +220,27 @@ void sanitize_env (void)
char **cur;
char **move;
for (cur = envp; NULL != *cur; cur++) {
for (bad = forbid; NULL != *bad; bad++) {
for (cur = envp; *cur; cur++) {
for (bad = forbid; *bad; bad++) {
if (strncmp (*cur, *bad, strlen (*bad)) == 0) {
for (move = cur; NULL != *move; move++) {
for (move = cur; *move; move++)
*move = *(move + 1);
}
cur--;
break;
}
}
}
for (cur = envp; NULL != *cur; cur++) {
for (bad = noslash; NULL != *bad; bad++) {
if (strncmp (*cur, *bad, strlen (*bad)) != 0) {
for (cur = envp; *cur; cur++) {
for (bad = noslash; *bad; bad++) {
if (strncmp (*cur, *bad, strlen (*bad)) != 0)
continue;
}
if (strchr (*cur, '/') != NULL) {
if (!strchr (*cur, '/'))
continue; /* OK */
}
for (move = cur; NULL != *move; move++) {
for (move = cur; *move; move++)
*move = *(move + 1);
}
cur--;
break;
}
}
}

View File

@@ -2,7 +2,6 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2002 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,7 +35,6 @@
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include "defines.h"
#include "faillog.h"
#include "getdef.h"
@@ -51,23 +49,13 @@
void failure (uid_t uid, const char *tty, struct faillog *fl)
{
int fd;
off_t offset_uid = (off_t) (sizeof *fl) * uid;
/*
* Don't do anything if failure logging isn't set up.
*/
if (access (FAILLOG_FILE, F_OK) != 0) {
if ((fd = open (FAILLOG_FILE, O_RDWR)) < 0)
return;
}
fd = open (FAILLOG_FILE, O_RDWR);
if (fd < 0) {
SYSLOG ((LOG_WARN,
"Can't write faillog entry for UID %lu in %s.",
(unsigned long) uid, FAILLOG_FILE));
return;
}
/*
* The file is indexed by UID value meaning that shared UID's
@@ -75,17 +63,9 @@ void failure (uid_t uid, const char *tty, struct faillog *fl)
* share just about everything else ...
*/
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|| (read (fd, (char *) fl, sizeof *fl) != (ssize_t) sizeof *fl)) {
/* This is not necessarily a failure. The file is
* initially zero length.
*
* If lseek() or read() failed for any other reason, this
* might reset the counter. But the new failure will be
* logged.
*/
lseek (fd, (off_t) (sizeof *fl) * uid, SEEK_SET);
if (read (fd, (char *) fl, sizeof *fl) != sizeof *fl)
memzero (fl, sizeof *fl);
}
/*
* Update the record. We increment the failure count to log the
@@ -94,12 +74,11 @@ void failure (uid_t uid, const char *tty, struct faillog *fl)
* updated as well.
*/
if (fl->fail_cnt + 1 > 0) {
if (fl->fail_cnt + 1 > 0)
fl->fail_cnt++;
}
strncpy (fl->fail_line, tty, sizeof fl->fail_line);
(void) time (&fl->fail_time);
time (&fl->fail_time);
/*
* Seek back to the correct position in the file and write the
@@ -108,34 +87,26 @@ void failure (uid_t uid, const char *tty, struct faillog *fl)
* seem that great.
*/
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|| (write (fd, (char *) fl, sizeof *fl) != (ssize_t) sizeof *fl)
|| (close (fd) != 0)) {
SYSLOG ((LOG_WARN,
"Can't write faillog entry for UID %lu in %s.",
(unsigned long) uid, FAILLOG_FILE));
(void) close (fd);
}
lseek (fd, (off_t) (sizeof *fl) * uid, SEEK_SET);
write (fd, (char *) fl, sizeof *fl);
close (fd);
}
static bool too_many_failures (const struct faillog *fl)
static int too_many_failures (const struct faillog *fl)
{
time_t now;
if ((0 == fl->fail_max) || (fl->fail_cnt < fl->fail_max)) {
return false;
}
if (fl->fail_max == 0 || fl->fail_cnt < fl->fail_max)
return 0;
if (0 == fl->fail_locktime) {
return true; /* locked until reset manually */
}
if (fl->fail_locktime == 0)
return 1; /* locked until reset manually */
(void) time (&now);
if ((fl->fail_time + fl->fail_locktime) < now) {
return false; /* enough time since last failure */
}
time (&now);
if (fl->fail_time + fl->fail_locktime < now)
return 0; /* enough time since last failure */
return true;
return 1;
}
/*
@@ -143,35 +114,21 @@ static bool too_many_failures (const struct faillog *fl)
*
* failcheck() is called AFTER the password has been validated. If the
* account has been "attacked" with too many login failures, failcheck()
* returns 0 to indicate that the login should be denied even though
* returns FALSE to indicate that the login should be denied even though
* the password is valid.
*
* failed indicates if the login failed AFTER the password has been
* validated.
*/
int failcheck (uid_t uid, struct faillog *fl, bool failed)
int failcheck (uid_t uid, struct faillog *fl, int failed)
{
int fd;
struct faillog fail;
off_t offset_uid = (off_t) (sizeof *fl) * uid;
/*
* Suppress the check if the log file isn't there.
*/
if (access (FAILLOG_FILE, F_OK) != 0) {
if ((fd = open (FAILLOG_FILE, O_RDWR)) < 0)
return 1;
}
fd = open (FAILLOG_FILE, failed?O_RDONLY:O_RDWR);
if (fd < 0) {
SYSLOG ((LOG_WARN,
"Can't open the faillog file (%s) to check UID %lu. "
"User access authorized.",
FAILLOG_FILE, (unsigned long) uid));
return 1;
}
/*
* Get the record from the file and determine if the user has
@@ -185,14 +142,14 @@ int failcheck (uid_t uid, struct faillog *fl, bool failed)
* no need to reset the count.
*/
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|| (read (fd, (char *) fl, sizeof *fl) != (ssize_t) sizeof *fl)) {
(void) close (fd);
lseek (fd, (off_t) (sizeof *fl) * uid, SEEK_SET);
if (read (fd, (char *) fl, sizeof *fl) != sizeof *fl) {
close (fd);
return 1;
}
if (too_many_failures (fl)) {
(void) close (fd);
close (fd);
return 0;
}
@@ -207,18 +164,10 @@ int failcheck (uid_t uid, struct faillog *fl, bool failed)
fail = *fl;
fail.fail_cnt = 0;
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|| (write (fd, (const void *) &fail, sizeof fail) != (ssize_t) sizeof fail)
|| (close (fd) != 0)) {
SYSLOG ((LOG_WARN,
"Can't reset faillog entry for UID %lu in %s.",
(unsigned long) uid, FAILLOG_FILE));
(void) close (fd);
}
} else {
(void) close (fd);
lseek (fd, (off_t) sizeof fail * uid, SEEK_SET);
write (fd, (char *) &fail, sizeof fail);
}
close (fd);
return 1;
}
@@ -241,18 +190,17 @@ void failprint (const struct faillog *fail)
#endif
time_t NOW;
if (0 == fail->fail_cnt) {
if (fail->fail_cnt == 0)
return;
}
tp = localtime (&(fail->fail_time));
(void) time (&NOW);
time (&NOW);
#if HAVE_STRFTIME
/*
* Print all information we have.
*/
(void) strftime (lasttimeb, sizeof lasttimeb, "%c", tp);
strftime (lasttimeb, sizeof lasttimeb, "%c", tp);
#else
/*
@@ -262,38 +210,35 @@ void failprint (const struct faillog *fail)
lasttime = asctime (tp);
lasttime[24] = '\0';
if ((NOW - fail->fail_time) < YEAR) {
if (NOW - fail->fail_time < YEAR)
lasttime[19] = '\0';
}
if ((NOW - fail->fail_time) < DAY) {
if (NOW - fail->fail_time < DAY)
lasttime = lasttime + 11;
}
if (' ' == *lasttime) {
if (*lasttime == ' ')
lasttime++;
}
#endif
(void) printf (ngettext ("%d failure since last login.\n"
"Last was %s on %s.\n",
"%d failures since last login.\n"
"Last was %s on %s.\n",
(unsigned long) fail->fail_cnt),
fail->fail_cnt, lasttime, fail->fail_line);
printf (ngettext ("%d failure since last login.\n"
"Last was %s on %s.\n",
"%d failures since last login.\n"
"Last was %s on %s.\n",
fail->fail_cnt),
fail->fail_cnt, lasttime, fail->fail_line);
}
/*
* failtmp - update the cumulative failure log
* failtmp - update the cummulative failure log
*
* failtmp updates the (struct utmp) formatted failure log which
* maintains a record of all login failures.
*/
void failtmp (const char *username,
#ifdef USE_UTMPX
void failtmp (
#ifdef HAVE_UTMPX_H
const struct utmpx *failent
#else /* !USE_UTMPX */
#else
const struct utmp *failent
#endif /* !USE_UTMPX */
#endif
)
{
char *ftmp;
@@ -304,38 +249,21 @@ void failtmp (const char *username,
* in login.defs, don't do this.
*/
ftmp = getdef_str ("FTMP_FILE");
if (NULL == ftmp) {
if (!(ftmp = getdef_str ("FTMP_FILE")))
return;
}
/*
* Open the file for append. It must already exist for this
* feature to be used.
*/
if (access (ftmp, F_OK) != 0) {
if ((fd = open (ftmp, O_WRONLY | O_APPEND)) == -1)
return;
}
fd = open (ftmp, O_WRONLY | O_APPEND);
if (-1 == fd) {
SYSLOG ((LOG_WARN,
"Can't append failure of user %s to %s.",
username, ftmp));
return;
}
/*
* Append the new failure record and close the log file.
* Output the new failure record and close the log file.
*/
if ( (write (fd, (const void *) failent, sizeof *failent) != (ssize_t) sizeof *failent)
|| (close (fd) != 0)) {
SYSLOG ((LOG_WARN,
"Can't append failure of user %s to %s.",
username, ftmp));
(void) close (fd);
}
write (fd, (const char *) failent, sizeof *failent);
close (fd);
}

View File

@@ -2,7 +2,6 @@
* Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1997 - 2000, Marek Michałkiewicz
* Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2008 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,11 +35,11 @@
#include "defines.h"
#include "faillog.h"
#ifdef USE_UTMPX
#ifdef HAVE_UTMPX_H
#include <utmpx.h>
#else /* !USE_UTMPX */
#else
#include <utmp.h>
#endif /* !USE_UTMPX */
#endif
/*
* failure - make failure entry
@@ -58,7 +57,7 @@ extern void failure (uid_t, const char *, struct faillog *);
* returns FALSE to indicate that the login should be denied even though
* the password is valid.
*/
extern int failcheck (uid_t uid, struct faillog *fl, bool failed);
extern int failcheck (uid_t, struct faillog *, int);
/*
* failprint - print line of failure information
@@ -74,11 +73,11 @@ extern void failprint (const struct faillog *);
* failtmp updates the (struct utmp) formatted failure log which
* maintains a record of all login failures.
*/
#ifdef USE_UTMPX
extern void failtmp (const char *username, const struct utmpx *);
#else /* !USE_UTMPX */
extern void failtmp (const char *username, const struct utmp *);
#endif /* !USE_UTMPX */
#ifdef HAVE_UTMPX_H
extern void failtmp (const struct utmpx *);
#else
extern void failtmp (const struct utmp *);
#endif
#endif

View File

@@ -1,184 +0,0 @@
/*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 2008 - 2009, 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>
#include <assert.h>
#include <stdio.h>
#include "prototypes.h"
#include "groupio.h"
#include "getdef.h"
/*
* find_new_gid - Find a new unused GID.
*
* If successful, find_new_gid provides an unused group ID in the
* [GID_MIN:GID_MAX] range.
* This ID should be higher than all the used GID, but if not possible,
* the lowest unused ID in the range will be returned.
*
* Return 0 on success, -1 if no unused GIDs are available.
*/
int find_new_gid (bool sys_group,
gid_t *gid,
/*@null@*/gid_t const *preferred_gid)
{
const struct group *grp;
gid_t gid_min, gid_max, group_id, id;
bool *used_gids;
assert (gid != NULL);
if (!sys_group) {
gid_min = (gid_t) getdef_ulong ("GID_MIN", 1000UL);
gid_max = (gid_t) getdef_ulong ("GID_MAX", 60000UL);
} else {
gid_min = (gid_t) getdef_ulong ("SYS_GID_MIN", 101UL);
gid_max = (gid_t) getdef_ulong ("GID_MIN", 1000UL) - 1;
gid_max = (gid_t) getdef_ulong ("SYS_GID_MAX", (unsigned long) gid_max);
}
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;
}
/*
* Search the entire group file,
* looking for the largest unused value.
*
* 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.
*/
if (sys_group) {
/* setgrent / getgrent / endgrent can be very slow with
* LDAP configurations (and many accounts).
* 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--) {
if (getgrgid (id) != NULL) {
group_id = id - 1;
used_gids[id] = true;
}
}
gr_rewind ();
while ((grp = gr_next ()) != NULL) {
if ((grp->gr_gid <= group_id) && (grp->gr_gid >= gid_min)) {
group_id = grp->gr_gid - 1;
}
/* create index of used GIDs */
if (grp->gr_gid <= gid_max) {
used_gids[grp->gr_gid] = true;
}
}
} else {
group_id = gid_min;
setgrent ();
while ((grp = getgrent ()) != NULL) {
if ((grp->gr_gid >= group_id) && (grp->gr_gid <= gid_max)) {
group_id = grp->gr_gid + 1;
}
/* create index of used GIDs */
if (grp->gr_gid <= gid_max) {
used_gids[grp->gr_gid] = true;
}
}
endgrent ();
gr_rewind ();
while ((grp = gr_next ()) != NULL) {
if ((grp->gr_gid >= group_id) && (grp->gr_gid <= gid_max)) {
group_id = grp->gr_gid + 1;
}
/* create index of used GIDs */
if (grp->gr_gid <= gid_max) {
used_gids[grp->gr_gid] = true;
}
}
}
/*
* If a group with GID equal to GID_MAX exists, the above algorithm
* will give us GID_MAX+1 even if not unique. Search for the first
* free GID starting with GID_MIN.
*/
if (sys_group) {
if (group_id == gid_min - 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;
}

205
libmisc/find_new_ids.c Normal file
View File

@@ -0,0 +1,205 @@
/*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 2008 , 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>
#include <assert.h>
#include <stdio.h>
#include "prototypes.h"
#include "pwio.h"
#include "groupio.h"
#include "getdef.h"
/*
* find_new_uid - Find a new unused UID.
*
* If successful, find_new_uid provides an unused user ID in the
* [UID_MIN:UID_MAX] range.
* This ID should be higher than all the used UID, but if not possible,
* the lowest unused ID in the range will be returned.
*
* Return 0 on success, -1 if no unused UIDs are available.
*/
int find_new_uid (int sys_user, uid_t *uid, uid_t const *preferred_uid)
{
const struct passwd *pwd;
uid_t uid_min, uid_max, user_id;
assert (uid != NULL);
if (sys_user == 0) {
uid_min = getdef_unum ("UID_MIN", 1000);
uid_max = getdef_unum ("UID_MAX", 60000);
} else {
uid_min = getdef_unum ("SYS_UID_MIN", 1);
uid_max = getdef_unum ("UID_MIN", 1000) - 1;
uid_max = getdef_unum ("SYS_UID_MAX", uid_max);
}
if ( (NULL != preferred_uid)
&& (*preferred_uid >= uid_min)
&& (*preferred_uid <= uid_max)
/* Check if the user exists according to NSS */
&& (getpwuid (*preferred_uid) == NULL)
/* Check also the local database in case of uncommitted
* changes */
&& (pw_locate_uid (*preferred_uid) == NULL)) {
*uid = *preferred_uid;
return 0;
}
user_id = uid_min;
/*
* 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.
*/
setpwent ();
pw_rewind ();
while ( ((pwd = getpwent ()) != NULL)
|| ((pwd = pw_next ()) != NULL)) {
if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) {
user_id = pwd->pw_uid + 1;
}
}
endpwent ();
/*
* If a user with UID equal to UID_MAX exists, the above algorithm
* will give us UID_MAX+1 even if not unique. Search for the first
* free UID starting with UID_MIN (it's O(n*n) but can be avoided
* by not having users with UID equal to UID_MAX). --marekm
*/
if (user_id == uid_max + 1) {
for (user_id = uid_min; user_id < uid_max; user_id++) {
/* local, no need for xgetpwuid */
if ( (getpwuid (user_id) == NULL)
&& (pw_locate_uid (user_id) == NULL)) {
break;
}
}
if (user_id == uid_max) {
fputs (_("Can't get unique UID (no more available UIDs)\n"), stderr);
return -1;
}
}
*uid = user_id;
return 0;
}
/*
* find_new_gid - Find a new unused GID.
*
* If successful, find_new_gid provides an unused group ID in the
* [GID_MIN:GID_MAX] range.
* This ID should be higher than all the used GID, but if not possible,
* the lowest unused ID in the range will be returned.
*
* Return 0 on success, -1 if no unused GIDs are available.
*/
int find_new_gid (int sys_group, gid_t *gid, gid_t const *preferred_gid)
{
const struct group *grp;
gid_t gid_min, gid_max, group_id;
assert (gid != NULL);
if (sys_group == 0) {
gid_min = getdef_unum ("GID_MIN", 1000);
gid_max = getdef_unum ("GID_MAX", 60000);
} else {
gid_min = getdef_unum ("SYS_GID_MIN", 1);
gid_max = getdef_unum ("GID_MIN", 1000) - 1;
gid_max = getdef_unum ("SYS_GID_MAX", gid_max);
}
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;
}
group_id = gid_min;
/*
* Search the entire group 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 groups were created but the changes were not committed yet.
*/
setgrent ();
gr_rewind ();
while ( ((grp = getgrent ()) != NULL)
|| ((grp = gr_next ()) != NULL)) {
if ((grp->gr_gid >= group_id) && (grp->gr_gid <= gid_max)) {
group_id = grp->gr_gid + 1;
}
}
endgrent ();
/*
* If a group with GID equal to GID_MAX exists, the above algorithm
* will give us GID_MAX+1 even if not unique. Search for the first
* free GID starting with GID_MIN (it's O(n*n) but can be avoided
* by not having users with GID equal to GID_MAX). --marekm
*/
if (group_id == gid_max + 1) {
for (group_id = gid_min; group_id < gid_max; group_id++) {
/* local, no need for xgetgrgid */
if ( (getgrgid (group_id) == NULL)
&& (gr_locate_gid (group_id) == NULL)) {
break;
}
}
if (group_id == gid_max) {
fputs (_("Can't get unique GID (no more available GIDs)\n"), stderr);
return -1;
}
}
*gid = group_id;
return 0;
}

View File

@@ -1,184 +0,0 @@
/*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 2008 - 2009, 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>
#include <assert.h>
#include <stdio.h>
#include "prototypes.h"
#include "pwio.h"
#include "getdef.h"
/*
* find_new_uid - Find a new unused UID.
*
* If successful, find_new_uid provides an unused user ID in the
* [UID_MIN:UID_MAX] range.
* This ID should be higher than all the used UID, but if not possible,
* the lowest unused ID in the range will be returned.
*
* Return 0 on success, -1 if no unused UIDs are available.
*/
int find_new_uid (bool sys_user,
uid_t *uid,
/*@null@*/uid_t const *preferred_uid)
{
const struct passwd *pwd;
uid_t uid_min, uid_max, user_id, id;
bool *used_uids;
assert (uid != NULL);
if (!sys_user) {
uid_min = (uid_t) getdef_ulong ("UID_MIN", 1000UL);
uid_max = (uid_t) getdef_ulong ("UID_MAX", 60000UL);
} else {
uid_min = (uid_t) getdef_ulong ("SYS_UID_MIN", 101UL);
uid_max = (uid_t) getdef_ulong ("UID_MIN", 1000UL) - 1;
uid_max = (uid_t) getdef_ulong ("SYS_UID_MAX", (unsigned long) uid_max);
}
used_uids = alloca (sizeof (bool) * (uid_max +1));
memset (used_uids, false, sizeof (bool) * (uid_max + 1));
if ( (NULL != preferred_uid)
&& (*preferred_uid >= uid_min)
&& (*preferred_uid <= uid_max)
/* Check if the user exists according to NSS */
&& (getpwuid (*preferred_uid) == NULL)
/* Check also the local database in case of uncommitted
* changes */
&& (pw_locate_uid (*preferred_uid) == NULL)) {
*uid = *preferred_uid;
return 0;
}
/*
* 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) {
/* setpwent / getpwent / endpwent can be very slow with
* LDAP configurations (and many accounts).
* 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--) {
if (getpwuid (id) != NULL) {
user_id = id - 1;
used_uids[id] = true;
}
}
pw_rewind ();
while ((pwd = pw_next ()) != NULL) {
if ((pwd->pw_uid <= user_id) && (pwd->pw_uid >= uid_min)) {
user_id = pwd->pw_uid - 1;
}
/* create index of used UIDs */
if (pwd->pw_uid <= uid_max) {
used_uids[pwd->pw_uid] = true;
}
}
} else {
user_id = uid_min;
setpwent ();
while ((pwd = getpwent ()) != NULL) {
if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) {
user_id = pwd->pw_uid + 1;
}
/* create index of used UIDs */
if (pwd->pw_uid <= uid_max) {
used_uids[pwd->pw_uid] = true;
}
}
endpwent ();
pw_rewind ();
while ((pwd = pw_next ()) != NULL) {
if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) {
user_id = pwd->pw_uid + 1;
}
/* create index of used UIDs */
if (pwd->pw_uid <= uid_max) {
used_uids[pwd->pw_uid] = true;
}
}
}
/*
* If a user with UID equal to UID_MAX exists, the above algorithm
* will give us UID_MAX+1 even if not unique. Search for the first
* free UID starting with UID_MIN.
*/
if (sys_user) {
if (user_id == uid_min - 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;
}

View File

@@ -395,7 +395,7 @@ relunit : tUNUMBER tYEAR_UNIT {
number : tUNUMBER
{
if ((yyHaveTime != 0) && (yyHaveDate != 0) && (yyHaveRel == 0))
if (yyHaveTime && yyHaveDate && !yyHaveRel)
yyYear = $1;
else
{
@@ -647,10 +647,10 @@ static int LookupWord (char *buff)
register char *q;
register const TABLE *tp;
int i;
bool abbrev;
int abbrev;
/* Make it lowercase. */
for (p = buff; '\0' != *p; p++)
for (p = buff; *p; p++)
if (ISUPPER (*p))
*p = tolower (*p);
@@ -667,14 +667,14 @@ static int LookupWord (char *buff)
/* See if we have an abbreviation for a month. */
if (strlen (buff) == 3)
abbrev = true;
abbrev = 1;
else if (strlen (buff) == 4 && buff[3] == '.')
{
abbrev = true;
abbrev = 1;
buff[3] = '\0';
}
else
abbrev = false;
abbrev = 0;
for (tp = MonthDayTable; tp->name; tp++)
{
@@ -743,14 +743,14 @@ static int LookupWord (char *buff)
}
/* Drop out any periods and try the timezone table again. */
for (i = 0, p = q = buff; '\0' != *q; q++)
for (i = 0, p = q = buff; *q; q++)
if (*q != '.')
*p++ = *q;
else
i++;
*p = '\0';
if (0 != i)
for (tp = TimezoneTable; NULL != tp->name; tp++)
if (i)
for (tp = TimezoneTable; tp->name; tp++)
if (strcmp (buff, tp->name) == 0)
{
yylval.Number = tp->value;
@@ -790,7 +790,7 @@ yylex (void)
yyInput--;
if (sign < 0)
yylval.Number = -yylval.Number;
return (0 != sign) ? tSNUMBER : tUNUMBER;
return sign ? tSNUMBER : tUNUMBER;
}
if (ISALPHA (c))
{
@@ -874,8 +874,7 @@ time_t get_date (const char *p, const time_t *now)
tm.tm_year = ToYear (yyYear) - TM_YEAR_ORIGIN + yyRelYear;
tm.tm_mon = yyMonth - 1 + yyRelMonth;
tm.tm_mday = yyDay + yyRelDay;
if ((yyHaveTime != 0) ||
( (yyHaveRel != 0) && (yyHaveDate == 0) && (yyHaveDay == 0) ))
if (yyHaveTime || (yyHaveRel && !yyHaveDate && !yyHaveDay))
{
tm.tm_hour = ToHour (yyHour, yyMeridian);
if (tm.tm_hour < 0)

View File

@@ -1,66 +0,0 @@
/*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2000 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, 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 <stdlib.h>
#include <errno.h>
#include <grp.h>
#include "prototypes.h"
/*
* getgr_nam_gid - Return a pointer to the group specified by a string.
* The string may be a valid GID or a valid groupname.
* If the group does not exist on the system, NULL is returned.
*/
extern /*@null@*/struct group *getgr_nam_gid (const char *grname)
{
long long int gid;
char *endptr;
if (NULL == grname) {
return NULL;
}
errno = 0;
gid = strtoll (grname, &endptr, 10);
if ( ('\0' != *grname)
&& ('\0' == *endptr)
&& (ERANGE != errno)
&& (/*@+longintegral@*/gid == (gid_t)gid)/*@=longintegral@*/) {
return xgetgrgid ((gid_t) gid);
}
return xgetgrnam (grname);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007 - 2009, Nicolas François
* Copyright (c) 2007 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,27 +31,17 @@
#ident "$Id$"
#include <stdlib.h>
#include <errno.h>
#include "prototypes.h"
#include "defines.h"
/*
* getlong - extract a long integer provided by the numstr string in *result
*
* It supports decimal, hexadecimal or octal representations.
*
* Returns 0 on failure, 1 on success.
*/
int getlong (const char *numstr, /*@out@*/long int *result)
int getlong(const char *numstr, long int *result)
{
long val;
char *endptr;
errno = 0;
val = strtol (numstr, &endptr, 0);
if (('\0' == *numstr) || ('\0' != *endptr) || (ERANGE == errno)) {
val = strtol (numstr, &endptr, 10);
if (*endptr || errno == ERANGE)
return 0;
}
*result = val;
return 1;

View File

@@ -1,124 +0,0 @@
/*
* Copyright (c) 2008 , 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 <ctype.h>
#include <stdlib.h>
#include "defines.h"
#include "prototypes.h"
/*
* Parse a range and indicate if the range is valid.
* Valid ranges are in the form:
* <long> -> min=max=long has_min has_max
* -<long> -> max=long !has_min has_max
* <long>- -> min=long has_min !has_max
* <long1>-<long2> -> min=long1 max=long2 has_min has_max
*
* If the range is valid, getrange returns 1.
* If the range is not valid, getrange returns 0.
*/
int getrange (char *range,
unsigned long *min, bool *has_min,
unsigned long *max, bool *has_max)
{
char *endptr;
unsigned long n;
if (NULL == range) {
return 0;
}
if ('-' == range[0]) {
if (!isdigit(range[1])) {
/* invalid */
return 0;
}
errno = 0;
n = strtoul (&range[1], &endptr, 10);
if (('\0' != *endptr) || (ERANGE == errno)) {
/* invalid */
return 0;
}
/* -<long> */
*has_min = false;
*has_max = true;
*max = n;
} else {
errno = 0;
n = strtoul (range, &endptr, 10);
if (ERANGE == errno) {
/* invalid */
return 0;
}
switch (*endptr) {
case '\0':
/* <long> */
*has_min = true;
*has_max = true;
*min = n;
*max = n;
break;
case '-':
endptr++;
if ('\0' == *endptr) {
/* <long>- */
*has_min = true;
*has_max = false;
*min = n;
} else if (!isdigit (*endptr)) {
/* invalid */
return 0;
} else {
*has_min = true;
*min = n;
errno = 0;
n = strtoul (endptr, &endptr, 10);
if ( ('\0' != *endptr)
|| (ERANGE == errno)) {
/* invalid */
return 0;
}
/* <long>-<long> */
*has_max = true;
*max = n;
}
break;
default:
return 0;
}
}
return 1;
}

View File

@@ -3,7 +3,6 @@
* Copyright (c) 1991 - 1993, Chip Rosenthal
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,22 +36,21 @@
#include <sys/types.h>
#include <stdio.h>
#include <pwd.h>
#include "defines.h"
#include "prototypes.h"
#include "getdef.h"
#include <pwd.h>
/*
* hushed - determine if a user receives login messages
*
* Look in the hushed-logins file (or user's home directory) to see
* if the user is to receive the login-time messages.
*/
bool hushed (const char *username)
int hushed (const struct passwd *pw)
{
struct passwd *pw;
char *hushfile;
char buf[BUFSIZ];
bool found;
int found;
FILE *fp;
/*
@@ -60,15 +58,8 @@ bool hushed (const char *username)
* defined, default to a noisy login.
*/
hushfile = getdef_str ("HUSHLOGIN_FILE");
if (NULL == hushfile) {
return false;
}
pw = getpwnam (username);
if (NULL == pw) {
return false;
}
if ((hushfile = getdef_str ("HUSHLOGIN_FILE")) == NULL)
return 0;
/*
* If this is not a fully rooted path then see if the
@@ -82,19 +73,17 @@ bool hushed (const char *username)
/*
* If this is a fully rooted path then go through the file
* and see if this user, or its shell is in there.
* and see if this user is in there.
*/
fp = fopen (hushfile, "r");
if (NULL == fp) {
return false;
}
for (found = false; !found && (fgets (buf, (int) sizeof buf, fp) == buf);) {
if ((fp = fopen (hushfile, "r")) == NULL)
return 0;
for (found = 0; !found && fgets (buf, sizeof buf, fp);) {
buf[strlen (buf) - 1] = '\0';
found = (strcmp (buf, pw->pw_shell) == 0) ||
(strcmp (buf, pw->pw_name) == 0);
found = !strcmp (buf,
buf[0] == '/' ? pw->pw_shell : pw->pw_name);
}
(void) fclose (fp);
return found;
}

View File

@@ -2,7 +2,6 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1997, Marek Michałkiewicz
* Copyright (c) 2001 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -51,23 +50,15 @@
*
* isexpired calculates the expiration date based on the
* password expiration criteria.
*
* Return value:
* 0: The password is still valid
* 1: The password has expired, it must be changed
* 2: The password has expired since a long time and the account is
* now disabled. (password cannot be changed)
* 3: The account has expired
*/
int isexpired (const struct passwd *pw, /*@null@*/const struct spwd *sp)
/*ARGSUSED*/ int isexpired (const struct passwd *pw, const struct spwd *sp)
{
long now;
now = (long) time ((time_t *) 0) / SCALE;
now = time ((time_t *) 0) / SCALE;
if (NULL == sp) {
return 0;
}
if (!sp)
sp = pwd_to_spwd (pw);
/*
* Quick and easy - there is an expired account field
@@ -75,9 +66,8 @@ int isexpired (const struct passwd *pw, /*@null@*/const struct spwd *sp)
* one first since it is worse.
*/
if ((sp->sp_expire > 0) && (now >= sp->sp_expire)) {
if (sp->sp_expire > 0 && now >= sp->sp_expire)
return 3;
}
/*
* Last changed date 1970-01-01 (not very likely) means that
@@ -87,17 +77,12 @@ int isexpired (const struct passwd *pw, /*@null@*/const struct spwd *sp)
* if /etc/shadow doesn't exist, getspnam() still succeeds and
* returns sp_lstchg==0 (must change password) instead of -1!
*/
if ( (0 == sp->sp_lstchg)
&& (strcmp (pw->pw_passwd, SHADOW_PASSWD_STRING) == 0)) {
if (sp->sp_lstchg == 0 && !strcmp (pw->pw_passwd, SHADOW_PASSWD_STRING))
return 1;
}
if ( (sp->sp_lstchg > 0)
&& (sp->sp_max >= 0)
&& (sp->sp_inact >= 0)
&& (now >= (sp->sp_lstchg + sp->sp_max + sp->sp_inact))) {
if (sp->sp_lstchg > 0 && sp->sp_max >= 0 && sp->sp_inact >= 0 &&
now >= sp->sp_lstchg + sp->sp_max + sp->sp_inact)
return 2;
}
/*
* The last and max fields must be present for an account
@@ -105,11 +90,9 @@ int isexpired (const struct passwd *pw, /*@null@*/const struct spwd *sp)
* is considered to be infinite.
*/
if ( (-1 == sp->sp_lstchg)
|| (-1 == sp->sp_max)
|| (sp->sp_max >= (10000L * DAY / SCALE))) {
if (sp->sp_lstchg == -1 ||
sp->sp_max == -1 || sp->sp_max >= (10000L * DAY / SCALE))
return 0;
}
/*
* Calculate today's day and the day on which the password
@@ -117,9 +100,7 @@ int isexpired (const struct passwd *pw, /*@null@*/const struct spwd *sp)
* the password has expired.
*/
if (now >= (sp->sp_lstchg + sp->sp_max)) {
if (now >= sp->sp_lstchg + sp->sp_max)
return 1;
}
return 0;
}

View File

@@ -65,53 +65,49 @@
* multiplier - value*multiplier is the actual limit
*/
static int
setrlimit_value (unsigned int resource, const char *value,
setrlimit_value (unsigned int rlimit, const char *value,
unsigned int multiplier)
{
struct rlimit rlim;
long limit;
char **endptr = (char **) &value;
const char *value_orig = value;
if (getlong (value, &limit) == 0) {
limit = strtol (value, endptr, 10);
if (limit == 0 && value_orig == *endptr) /* no chars read */
return 0;
}
limit *= multiplier;
if (limit != (rlim_t) limit) {
return 0;
}
rlim.rlim_cur = (rlim_t) limit;
rlim.rlim_max = (rlim_t) limit;
if (setrlimit (resource, &rlim) != 0) {
rlim.rlim_cur = limit;
rlim.rlim_max = limit;
if (setrlimit (rlimit, &rlim))
return LOGIN_ERROR_RLIMIT;
}
return 0;
}
static int set_prio (const char *value)
{
long prio;
int prio;
char **endptr = (char **) &value;
if ( (getlong (value, &prio) == 0)
|| (prio != (int) prio)) {
prio = strtol (value, endptr, 10);
if ((prio == 0) && (value == *endptr))
return 0;
}
if (setpriority (PRIO_PROCESS, 0, (int) prio) != 0) {
if (setpriority (PRIO_PROCESS, 0, prio))
return LOGIN_ERROR_RLIMIT;
}
return 0;
}
static int set_umask (const char *value)
{
unsigned long int mask;
mode_t mask;
char **endptr = (char **) &value;
if ( (getulong (value, &mask) == 0)
|| (mask != (mode_t) mask)) {
mask = strtol (value, endptr, 8) & 0777;
if ((mask == 0) && (value == *endptr))
return 0;
}
(void) umask ((mode_t) mask);
umask (mask);
return 0;
}
@@ -119,49 +115,46 @@ static int set_umask (const char *value)
/* Counts the number of user logins and check against the limit */
static int check_logins (const char *name, const char *maxlogins)
{
#ifdef USE_UTMPX
#if HAVE_UTMPX_H
struct utmpx *ut;
#else /* !USE_UTMPX */
#else
struct utmp *ut;
#endif /* !USE_UTMPX */
unsigned long limit, count;
#endif
unsigned int limit, count;
char **endptr = (char **) &maxlogins;
const char *ml_orig = maxlogins;
if (getulong (maxlogins, &limit) == 0) {
limit = strtol (maxlogins, endptr, 10);
if (limit == 0 && ml_orig == *endptr) /* no chars read */
return 0;
}
if (0 == limit) { /* maximum 0 logins ? */
if (limit == 0) { /* maximum 0 logins ? */
SYSLOG ((LOG_WARN, "No logins allowed for `%s'\n", name));
return LOGIN_ERROR_LOGIN;
}
count = 0;
#ifdef USE_UTMPX
#if HAVE_UTMPX_H
setutxent ();
while ((ut = getutxent ())) {
#else /* !USE_UTMPX */
#else
setutent ();
while ((ut = getutent ())) {
#endif /* !USE_UTMPX */
if (USER_PROCESS != ut->ut_type) {
#endif
if (ut->ut_type != USER_PROCESS)
continue;
}
if ('\0' == ut->ut_user[0]) {
if (ut->ut_user[0] == '\0')
continue;
}
if (strncmp (name, ut->ut_user, sizeof (ut->ut_user)) != 0) {
if (strncmp (name, ut->ut_user, sizeof (ut->ut_user)) != 0)
continue;
}
count++;
if (count > limit) {
if (++count > limit)
break;
}
}
#ifdef USE_UTMPX
#if HAVE_UTMPX_H
endutxent ();
#else /* !USE_UTMPX */
#else
endutent ();
#endif /* !USE_UTMPX */
#endif
/*
* This is called after setutmp(), so the number of logins counted
* includes the user who is currently trying to log in.
@@ -210,11 +203,10 @@ static int do_user_limits (const char *buf, const char *name)
{
const char *pp;
int retval = 0;
bool reported = false;
pp = buf;
while ('\0' != *pp) {
while (*pp != '\0')
switch (*pp++) {
#ifdef RLIMIT_AS
case 'a':
@@ -306,24 +298,14 @@ static int do_user_limits (const char *buf, const char *name)
break;
case 'l':
case 'L':
/* LIMIT the number of concurrent logins */
/* LIMIT the number of concurent logins */
retval |= check_logins (name, pp);
break;
case 'p':
case 'P':
retval |= set_prio (pp);
break;
default:
/* Only report invalid strings once */
if (!reported) {
SYSLOG ((LOG_WARN,
"Invalid limit string: '%s'",
pp-1));
reported = true;
retval |= LOGIN_ERROR_RLIMIT;
}
}
}
return retval;
}
@@ -354,9 +336,8 @@ static int setup_user_limits (const char *uname)
* - username must start on first column
* A better (smarter) checking should be done --cristiang */
while (fgets (buf, 1024, fil) != NULL) {
if (('#' == buf[0]) || ('\n' == buf[0])) {
if (buf[0] == '#' || buf[0] == '\n')
continue;
}
memzero (tempbuf, sizeof (tempbuf));
/* a valid line should have a username, then spaces,
* then limits
@@ -376,12 +357,11 @@ static int setup_user_limits (const char *uname)
}
}
}
(void) fclose (fil);
fclose (fil);
if (limits[0] == '\0') {
/* no user specific limits */
if (deflimits[0] == '\0') { /* no default limits */
if (deflimits[0] == '\0') /* no default limits */
return 0;
}
strcpy (limits, deflimits); /* use the default limits */
}
return do_user_limits (limits, uname);
@@ -392,21 +372,19 @@ static int setup_user_limits (const char *uname)
static void setup_usergroups (const struct passwd *info)
{
const struct group *grp;
mode_t tmpmask;
mode_t oldmask;
/*
* if not root, and UID == GID, and username is the same as primary
* group name, set umask group bits to be the same as owner bits
* (examples: 022 -> 002, 077 -> 007).
*/
if ((0 != info->pw_uid) && (info->pw_uid == info->pw_gid)) {
if (info->pw_uid != 0 && info->pw_uid == info->pw_gid) {
/* local, no need for xgetgrgid */
grp = getgrgid (info->pw_gid);
if ( (NULL != grp)
&& (strcmp (info->pw_name, grp->gr_name) == 0)) {
tmpmask = umask (0777);
tmpmask = (tmpmask & ~070) | ((tmpmask >> 3) & 070);
(void) umask (tmpmask);
if (grp && (strcmp (info->pw_name, grp->gr_name) == 0)) {
oldmask = umask (0777);
umask ((oldmask & ~070) | ((oldmask >> 3) & 070));
}
}
}
@@ -418,10 +396,11 @@ static void setup_usergroups (const struct passwd *info)
void setup_limits (const struct passwd *info)
{
char *cp;
int i;
long l;
if (getdef_bool ("USERGROUPS_ENAB")) {
if (getdef_bool ("USERGROUPS_ENAB"))
setup_usergroups (info);
}
/*
* See if the GECOS field contains values for NICE, UMASK or ULIMIT.
@@ -431,59 +410,33 @@ void setup_limits (const struct passwd *info)
if (getdef_bool ("QUOTAS_ENAB")) {
#ifdef LIMITS
if (info->pw_uid != 0) {
if (info->pw_uid != 0)
if (setup_user_limits (info->pw_name) &
LOGIN_ERROR_LOGIN) {
(void) fputs (_("Too many logins.\n"), stderr);
(void) sleep (2); /* XXX: Should be FAIL_DELAY */
exit (EXIT_FAILURE);
fputs (_("Too many logins.\n"), stderr);
sleep (2);
exit (1);
}
}
#endif
for (cp = info->pw_gecos; cp != NULL; cp = strchr (cp, ',')) {
if (',' == *cp) {
if (*cp == ',')
cp++;
}
if (strncmp (cp, "pri=", 4) == 0) {
long int inc;
if ( (getlong (cp + 4, &inc) == 1)
&& (inc >= -20) && (inc <= 20)) {
errno = 0;
if ( (nice ((int) inc) != -1)
|| (0 != errno)) {
continue;
}
}
/* Failed to parse or failed to nice() */
SYSLOG ((LOG_WARN,
"Can't set the nice value for user %s",
info->pw_name));
i = atoi (cp + 4);
if (i >= -20 && i <= 20)
(void) nice (i);
continue;
}
if (strncmp (cp, "ulimit=", 7) == 0) {
long int blocks;
if ( (getlong (cp + 7, &blocks) == 0)
|| (blocks != (int) blocks)
|| (set_filesize_limit ((int) blocks) != 0)) {
SYSLOG ((LOG_WARN,
"Can't set the ulimit for user %s",
info->pw_name));
}
l = strtol (cp + 7, (char **) 0, 10);
set_filesize_limit (l);
continue;
}
if (strncmp (cp, "umask=", 6) == 0) {
unsigned long int mask;
if ( (getulong (cp + 6, &mask) == 0)
|| (mask != (mode_t) mask)) {
SYSLOG ((LOG_WARN,
"Can't set umask value for user %s",
info->pw_name));
} else {
(void) umask ((mode_t) mask);
}
i = strtol (cp + 6, (char **) 0, 8) & 0777;
(void) umask (i);
continue;
}

View File

@@ -29,11 +29,13 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Removed duplicated code from gpmain.c, useradd.c, userdel.c and
usermod.c. --marekm */
#include <config.h>
#ident "$Id$"
#include <assert.h>
#include "prototypes.h"
#include "defines.h"
/*
@@ -43,14 +45,11 @@
* name, and if not present it is added to a freshly allocated
* list of users.
*/
/*@only@*/ /*@out@*/char **add_list (/*@returned@*/ /*@only@*/char **list, const char *member)
char **add_list (char **list, const char *member)
{
int i;
char **tmp;
assert (NULL != member);
assert (NULL != list);
/*
* Scan the list for the new name. Return the original list
* pointer if it is present.
@@ -93,14 +92,11 @@
* list of users.
*/
/*@only@*/ /*@out@*/char **del_list (/*@returned@*/ /*@only@*/char **list, const char *member)
char **del_list (char **list, const char *member)
{
int i, j;
char **tmp;
assert (NULL != member);
assert (NULL != list);
/*
* Scan the list for the old name. Return the original list
* pointer if it is not present.
@@ -141,19 +137,17 @@
return tmp;
}
/*@only@*/ /*@out@*/char **dup_list (char *const *list)
char **dup_list (char *const *list)
{
int i;
char **tmp;
assert (NULL != list);
for (i = 0; NULL != list[i]; i++);
for (i = 0; list[i]; i++);
tmp = (char **) xmalloc ((i + 1) * sizeof (char *));
i = 0;
while (NULL != *list) {
while (*list) {
tmp[i] = xstrdup (*list);
i++;
list++;
@@ -163,34 +157,27 @@
return tmp;
}
bool is_on_list (char *const *list, const char *member)
int is_on_list (char *const *list, const char *member)
{
assert (NULL != member);
assert (NULL != list);
while (NULL != *list) {
while (*list) {
if (strcmp (*list, member) == 0) {
return true;
return 1;
}
list++;
}
return false;
return 0;
}
/*
* comma_to_list - convert comma-separated list to (char *) array
*/
/*@only@*/char **comma_to_list (const char *comma)
char **comma_to_list (const char *comma)
{
char *members;
char **array;
int i;
const char *cp;
char *cp2;
assert (NULL != comma);
char *cp, *cp2;
/*
* Make a copy since we are going to be modifying the list

View File

@@ -49,11 +49,9 @@
* UID is extracted from the global (struct passwd) entry and the
* TTY information is gotten from the (struct utmp).
*/
void dolastlog (
struct lastlog *ll,
const struct passwd *pw,
/*@unique@*/const char *line,
/*@unique@*/const char *host)
void
dolastlog (struct lastlog *ll, const struct passwd *pw, const char *line,
const char *host)
{
int fd;
off_t offset;
@@ -64,23 +62,18 @@ void dolastlog (
* If the file does not exist, don't create it.
*/
fd = open (LASTLOG_FILE, O_RDWR);
if (-1 == fd) {
if ((fd = open (LASTLOG_FILE, O_RDWR)) == -1)
return;
}
/*
* The file is indexed by UID number. Seek to the record
* for this UID. Negative UID's will create problems, but ...
*/
offset = (off_t) pw->pw_uid * sizeof newlog;
offset = (unsigned long) pw->pw_uid * sizeof newlog;
if (lseek (fd, offset, SEEK_SET) != offset) {
SYSLOG ((LOG_WARN,
"Can't read last lastlog entry for UID %lu in %s. Entry not updated.",
(unsigned long) pw->pw_uid, LASTLOG_FILE));
(void) close (fd);
close (fd);
return;
}
@@ -90,27 +83,19 @@ void dolastlog (
* the way we read the old one in.
*/
if (read (fd, (void *) &newlog, sizeof newlog) != (ssize_t) sizeof newlog) {
if (read (fd, (char *) &newlog, sizeof newlog) != sizeof newlog)
memzero (&newlog, sizeof newlog);
}
if (NULL != ll) {
if (ll)
*ll = newlog;
}
ll_time = newlog.ll_time;
(void) time (&ll_time);
time (&ll_time);
newlog.ll_time = ll_time;
strncpy (newlog.ll_line, line, sizeof newlog.ll_line);
#if HAVE_LL_HOST
strncpy (newlog.ll_host, host, sizeof newlog.ll_host);
#endif
if ( (lseek (fd, offset, SEEK_SET) != offset)
|| (write (fd, (const void *) &newlog, sizeof newlog) != (ssize_t) sizeof newlog)
|| (close (fd) != 0)) {
SYSLOG ((LOG_WARN,
"Can't write lastlog entry for UID %lu in %s.",
(unsigned long) pw->pw_uid, LASTLOG_FILE));
(void) close (fd);
}
if (lseek (fd, offset, SEEK_SET) == offset)
write (fd, (char *) &newlog, sizeof newlog);
close (fd);
}

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1993, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2009, Nicolas François
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,6 @@
#ident "$Id$"
#include <assert.h>
#include <stdio.h>
#include <signal.h>
#include <ctype.h>
@@ -44,7 +43,7 @@
static void login_exit (unused int sig)
{
exit (EXIT_FAILURE);
exit (1);
}
/*
@@ -87,21 +86,17 @@ void login_prompt (const char *prompt, char *name, int namesize)
* be displayed and display it before the prompt.
*/
if (NULL != prompt) {
if (prompt) {
cp = getdef_str ("ISSUE_FILE");
if (NULL != cp) {
fp = fopen (cp, "r");
if (NULL != fp) {
while ((i = getc (fp)) != EOF) {
(void) putc (i, stdout);
}
if (cp && (fp = fopen (cp, "r"))) {
while ((i = getc (fp)) != EOF)
putc (i, stdout);
(void) fclose (fp);
}
fclose (fp);
}
gethostname (buf, sizeof buf);
printf (prompt, buf);
(void) fflush (stdout);
fflush (stdout);
}
/*
@@ -110,14 +105,12 @@ void login_prompt (const char *prompt, char *name, int namesize)
*/
memzero (buf, sizeof buf);
if (fgets (buf, (int) sizeof buf, stdin) != buf) {
exit (EXIT_FAILURE);
}
if (fgets (buf, sizeof buf, stdin) != buf)
exit (1);
cp = strchr (buf, '\n');
if (NULL == cp) {
exit (EXIT_FAILURE);
}
if (!cp)
exit (1);
*cp = '\0'; /* remove \n [ must be there ] */
/*
@@ -129,13 +122,11 @@ void login_prompt (const char *prompt, char *name, int namesize)
for (cp = buf; *cp == ' ' || *cp == '\t'; cp++);
for (i = 0; i < namesize - 1 && isgraph (*cp); name[i++] = *cp++);
while (isgraph (*cp)) {
while (isgraph (*cp))
cp++;
}
if ('\0' != *cp) {
if (*cp)
cp++;
}
name[i] = '\0';
@@ -145,23 +136,19 @@ void login_prompt (const char *prompt, char *name, int namesize)
* to do this, and I just take the easy way out.
*/
if ('\0' != *cp) { /* process new variables */
if (*cp != '\0') { /* process new variables */
char *nvar;
int count = 1;
for (envc = 0; envc < MAX_ENV; envc++) {
nvar = strtok ((0 != envc) ? (char *) 0 : cp, " \t,");
if (NULL == nvar) {
nvar = strtok (envc ? (char *) 0 : cp, " \t,");
if (!nvar)
break;
}
if (strchr (nvar, '=') != NULL) {
if (strchr (nvar, '=')) {
envp[envc] = nvar;
} else {
size_t len = strlen (nvar) + 32;
int wlen;
envp[envc] = xmalloc (len);
wlen = snprintf (envp[envc], len, "L%d=%s", count++, nvar);
assert (wlen == (int) len -1);
envp[envc] = xmalloc (strlen (nvar) + 32);
sprintf (envp[envc], "L%d=%s", count++, nvar);
}
}
set_env (envc, envp);
@@ -171,9 +158,8 @@ void login_prompt (const char *prompt, char *name, int namesize)
* Set the SIGQUIT handler back to its original value
*/
(void) signal (SIGQUIT, sigquit);
signal (SIGQUIT, sigquit);
#ifdef SIGTSTP
(void) signal (SIGTSTP, sigtstp);
signal (SIGTSTP, sigtstp);
#endif
}

View File

@@ -2,7 +2,6 @@
* Copyright (c) 1989 - 1991, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,7 +32,6 @@
#include <config.h>
#include "prototypes.h"
#include "defines.h"
#include <assert.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
@@ -48,45 +46,34 @@ void mailcheck (void)
struct stat statbuf;
char *mailbox;
if (!getdef_bool ("MAIL_CHECK_ENAB")) {
if (!getdef_bool ("MAIL_CHECK_ENAB"))
return;
}
/*
* Check incoming mail in Maildir format - J.
*/
mailbox = getenv ("MAILDIR");
if (NULL != mailbox) {
if ((mailbox = getenv ("MAILDIR"))) {
char *newmail;
size_t len = strlen (mailbox) + 5;
int wlen;
newmail = xmalloc (len);
wlen = snprintf (newmail, len, "%s/new", mailbox);
assert (wlen == (int) len - 1);
newmail = xmalloc (strlen (mailbox) + 5);
sprintf (newmail, "%s/new", mailbox);
if (stat (newmail, &statbuf) != -1 && statbuf.st_size != 0) {
if (statbuf.st_mtime > statbuf.st_atime) {
free (newmail);
(void) puts (_("You have new mail."));
puts (_("You have new mail."));
return;
}
}
free (newmail);
}
mailbox = getenv ("MAIL");
if (NULL == mailbox) {
if (!(mailbox = getenv ("MAIL")))
return;
}
if ( (stat (mailbox, &statbuf) == -1)
|| (statbuf.st_size == 0)) {
(void) puts (_("No mail."));
} else if (statbuf.st_atime > statbuf.st_mtime) {
(void) puts (_("You have mail."));
} else {
(void) puts (_("You have new mail."));
}
if (stat (mailbox, &statbuf) == -1 || statbuf.st_size == 0)
puts (_("No mail."));
else if (statbuf.st_atime > statbuf.st_mtime)
puts (_("You have mail."));
else
puts (_("You have new mail."));
}

View File

@@ -1,7 +1,7 @@
/*
* Copyright (c) 1996 - 1997, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François
* Copyright (c) 2007 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,7 +41,7 @@
#include "defines.h"
#include <pwd.h>
#include "prototypes.h"
/*@null@*/ /*@only@*/struct passwd *get_my_pwent (void)
struct passwd *get_my_pwent (void)
{
struct passwd *pw;
const char *cp = getlogin ();
@@ -57,12 +57,8 @@
* XXX - when running from su, will return the current user (not
* the original user, like getlogin() does). Does this matter?
*/
if ((NULL != cp) && ('\0' != *cp)) {
pw = xgetpwnam (cp);
if ((NULL != pw) && (pw->pw_uid == ruid)) {
return pw;
}
}
if (cp && *cp && (pw = xgetpwnam (cp)) && pw->pw_uid == ruid)
return pw;
return xgetpwuid (ruid);
}

View File

@@ -50,26 +50,24 @@
/*
* can't be a palindrome - like `R A D A R' or `M A D A M'
*/
static bool palindrome (unused const char *old, const char *new)
static int palindrome (unused const char *old, const char *new)
{
size_t i, j;
int i, j;
i = strlen (new);
for (j = 0; j < i; j++) {
if (new[i - j - 1] != new[j]) {
return false;
}
}
for (j = 0; j < i; j++)
if (new[i - j - 1] != new[j])
return 0;
return true;
return 1;
}
/*
* more than half of the characters are different ones.
*/
static bool similar (const char *old, const char *new)
static int similar (const char *old, const char *new)
{
int i, j;
@@ -79,21 +77,17 @@ static bool similar (const char *old, const char *new)
* the new password is long enough. Please feel free to suggest
* something better... --marekm
*/
if (strlen (new) >= 8) {
return false;
}
if (strlen (new) >= 8)
return 0;
for (i = j = 0; ('\0' != new[i]) && ('\0' != old[i]); i++) {
if (strchr (new, old[i]) != NULL) {
for (i = j = 0; new[i] && old[i]; i++)
if (strchr (new, old[i]))
j++;
}
}
if (i >= j * 2) {
return false;
}
if (i >= j * 2)
return 0;
return true;
return 1;
}
/*
@@ -102,23 +96,22 @@ static bool similar (const char *old, const char *new)
static int simple (unused const char *old, const char *new)
{
bool digits = false;
bool uppers = false;
bool lowers = false;
bool others = false;
int digits = 0;
int uppers = 0;
int lowers = 0;
int others = 0;
int size;
int i;
for (i = 0; '\0' != new[i]; i++) {
if (isdigit (new[i])) {
digits = true;
} else if (isupper (new[i])) {
uppers = true;
} else if (islower (new[i])) {
lowers = true;
} else {
others = true;
}
for (i = 0; new[i]; i++) {
if (isdigit (new[i]))
digits++;
else if (isupper (new[i]))
uppers++;
else if (islower (new[i]))
lowers++;
else
others++;
}
/*
@@ -127,33 +120,27 @@ static int simple (unused const char *old, const char *new)
*/
size = 9;
if (digits) {
if (digits)
size--;
}
if (uppers) {
if (uppers)
size--;
}
if (lowers) {
if (lowers)
size--;
}
if (others) {
if (others)
size--;
}
if (size <= i) {
return false;
}
if (size <= i)
return 0;
return true;
return 1;
}
static char *str_lower (char *string)
{
char *cp;
for (cp = string; '\0' != *cp; cp++) {
for (cp = string; *cp; cp++)
*cp = tolower (*cp);
}
return string;
}
@@ -173,9 +160,8 @@ static const char *password_check (const char *old, const char *new,
#endif
#endif
if (strcmp (new, old) == 0) {
if (strcmp (new, old) == 0)
return _("no change");
}
newmono = str_lower (xstrdup (new));
oldmono = str_lower (xstrdup (old));
@@ -183,32 +169,33 @@ static const char *password_check (const char *old, const char *new,
strcpy (wrapped, oldmono);
strcat (wrapped, oldmono);
if (palindrome (oldmono, newmono)) {
if (palindrome (oldmono, newmono))
msg = _("a palindrome");
} else if (strcmp (oldmono, newmono) == 0) {
msg = _("case changes only");
} else if (similar (oldmono, newmono)) {
msg = _("too similar");
} else if (simple (old, new)) {
msg = _("too simple");
} else if (strstr (wrapped, newmono) != NULL) {
msg = _("rotated");
} else {
#ifdef HAVE_LIBCRACK
/*
* Invoke Alec Muffett's cracklib routines.
*/
dictpath = getdef_str ("CRACKLIB_DICTPATH");
if (NULL != dictpath) {
if (!msg && strcmp (oldmono, newmono) == 0)
msg = _("case changes only");
if (!msg && similar (oldmono, newmono))
msg = _("too similar");
if (!msg && simple (old, new))
msg = _("too simple");
if (!msg && strstr (wrapped, newmono))
msg = _("rotated");
#ifdef HAVE_LIBCRACK
/*
* Invoke Alec Muffett's cracklib routines.
*/
if (!msg && (dictpath = getdef_str ("CRACKLIB_DICTPATH")))
#ifdef HAVE_LIBCRACK_PW
msg = FascistCheckPw (new, dictpath, pwdp);
msg = FascistCheckPw (new, dictpath, pwdp);
#else
msg = FascistCheck (new, dictpath);
msg = FascistCheck (new, dictpath);
#endif
}
#endif
}
strzero (newmono);
strzero (oldmono);
strzero (wrapped);
@@ -219,11 +206,11 @@ static const char *password_check (const char *old, const char *new,
return msg;
}
/*ARGSUSED*/
static const char *obscure_msg (const char *old, const char *new,
/*ARGSUSED*/
static const char *obscure_msg (const char *old, const char *new,
const struct passwd *pwdp)
{
size_t maxlen, oldlen, newlen;
int maxlen, oldlen, newlen;
char *new1, *old1;
const char *msg;
char *result;
@@ -231,60 +218,50 @@ static const char *obscure_msg (const char *old, const char *new,
oldlen = strlen (old);
newlen = strlen (new);
if (newlen < (size_t) getdef_num ("PASS_MIN_LEN", 0)) {
if (newlen < getdef_num ("PASS_MIN_LEN", 0))
return _("too short");
}
/*
* Remaining checks are optional.
*/
if (!getdef_bool ("OBSCURE_CHECKS_ENAB")) {
if (!getdef_bool ("OBSCURE_CHECKS_ENAB"))
return NULL;
}
msg = password_check (old, new, pwdp);
if (NULL != msg) {
if (msg)
return msg;
}
result = getdef_str ("ENCRYPT_METHOD");
if (NULL == result) {
if ((result = getdef_str ("ENCRYPT_METHOD")) == NULL) {
/* The traditional crypt() truncates passwords to 8 chars. It is
possible to circumvent the above checks by choosing an easy
8-char password and adding some random characters to it...
Example: "password$%^&*123". So check it again, this time
truncated to the maximum length. Idea from npasswd. --marekm */
if (getdef_bool ("MD5_CRYPT_ENAB")) {
if (getdef_bool ("MD5_CRYPT_ENAB"))
return NULL;
}
} else {
if ( (strcmp (result, "MD5") == 0)
if ( !strcmp (result, "MD5")
#ifdef USE_SHA_CRYPT
|| (strcmp (result, "SHA256") == 0)
|| (strcmp (result, "SHA512") == 0)
|| !strcmp (result, "SHA256")
|| !strcmp (result, "SHA512")
#endif
) {
)
return NULL;
}
}
maxlen = (size_t) getdef_num ("PASS_MAX_LEN", 8);
if ( (oldlen <= maxlen)
&& (newlen <= maxlen)) {
maxlen = getdef_num ("PASS_MAX_LEN", 8);
if (oldlen <= maxlen && newlen <= maxlen)
return NULL;
}
new1 = xstrdup (new);
old1 = xstrdup (old);
if (newlen > maxlen) {
if (newlen > maxlen)
new1[maxlen] = '\0';
}
if (oldlen > maxlen) {
if (oldlen > maxlen)
old1[maxlen] = '\0';
}
msg = password_check (old1, new1, pwdp);
@@ -308,7 +285,7 @@ int obscure (const char *old, const char *new, const struct passwd *pwdp)
{
const char *msg = obscure_msg (old, new, pwdp);
if (NULL != msg) {
if (msg) {
printf (_("Bad password: %s. "), msg);
return 0;
}

View File

@@ -37,7 +37,10 @@
/*
* Change the user's password using PAM.
* Change the user's password using PAM. Requires libpam and libpam_misc
* (for misc_conv). Note: libpam_misc is probably Linux-PAM specific,
* so you may have to port it if you want to use this code on non-Linux
* systems with PAM (such as Solaris 2.6). --marekm
*/
#include <stdio.h>
#include <stdlib.h>
@@ -47,7 +50,7 @@
#include "pam_defs.h"
#include "prototypes.h"
void do_pam_passwd (const char *user, bool silent, bool change_expired)
void do_pam_passwd (const char *user, int silent, int change_expired)
{
pam_handle_t *pamh = NULL;
int flags = 0, ret;
@@ -73,7 +76,7 @@ void do_pam_passwd (const char *user, bool silent, bool change_expired)
}
fputs (_("passwd: password updated successfully\n"), stderr);
(void) pam_end (pamh, PAM_SUCCESS);
pam_end (pamh, PAM_SUCCESS);
}
#else /* !USE_PAM */
extern int errno; /* warning: ANSI C forbids an empty source file */

View File

@@ -1,167 +0,0 @@
/*
* Copyright (c) 2009, 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:$"
#ifdef USE_PAM
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <security/pam_appl.h>
#include "prototypes.h"
/*@null@*/ /*@only@*/static char *non_interactive_password = NULL;
static int ni_conv (int num_msg,
const struct pam_message **msg,
struct pam_response **resp,
unused void *appdata_ptr);
static struct pam_conv non_interactive_pam_conv = {
ni_conv,
NULL
};
static int ni_conv (int num_msg,
const struct pam_message **msg,
struct pam_response **resp,
unused void *appdata_ptr)
{
struct pam_response *responses;
int count;
assert (NULL != non_interactive_password);
if (num_msg <= 0) {
return PAM_CONV_ERR;
}
responses = (struct pam_response *) calloc ((size_t) num_msg,
sizeof (*responses));
if (NULL == responses) {
return PAM_CONV_ERR;
}
for (count=0; count < num_msg; count++) {
responses[count].resp_retcode = 0;
switch (msg[count]->msg_style) {
case PAM_PROMPT_ECHO_ON:
fprintf (stderr,
_("%s: PAM modules requesting echoing are not supported.\n"),
Prog);
goto failed_conversation;
case PAM_PROMPT_ECHO_OFF:
responses[count].resp = strdup (non_interactive_password);
if (NULL == responses[count].resp) {
goto failed_conversation;
}
break;
case PAM_ERROR_MSG:
if ( (NULL == msg[count]->msg)
|| (fprintf (stderr, "%s\n", msg[count]->msg) <0)) {
goto failed_conversation;
}
responses[count].resp = NULL;
break;
case PAM_TEXT_INFO:
if ( (NULL == msg[count]->msg)
|| (fprintf (stdout, "%s\n", msg[count]->msg) <0)) {
goto failed_conversation;
}
responses[count].resp = NULL;
break;
default:
(void) fprintf (stderr,
_("%s: conversation type %d not supported.\n"),
Prog, msg[count]->msg_style);
goto failed_conversation;
}
}
*resp = responses;
return PAM_SUCCESS;
failed_conversation:
for (count=0; count < num_msg; count++) {
if (NULL != responses[count].resp) {
memset (responses[count].resp, 0,
strlen (responses[count].resp));
free (responses[count].resp);
responses[count].resp = NULL;
}
}
free (responses);
*resp = NULL;
return PAM_CONV_ERR;
}
/*
* Change non interactively the user's password using PAM.
*
* Return 0 on success, 1 on failure.
*/
int do_pam_passwd_non_interractive (const char *pam_service,
const char *username,
const char* password)
{
pam_handle_t *pamh = NULL;
int ret;
ret = pam_start (pam_service, username, &non_interactive_pam_conv, &pamh);
if (ret != PAM_SUCCESS) {
fprintf (stderr,
_("%s: (user %s) pam_start failure %d\n"),
Prog, username, ret);
return 1;
}
non_interactive_password = password;
ret = pam_chauthtok (pamh, 0);
if (ret != PAM_SUCCESS) {
fprintf (stderr,
_("%s: (user %s) pam_chauthtok() failed, error:\n"
"%s\n"),
Prog, username, pam_strerror (pamh, ret));
}
(void) pam_end (pamh, PAM_SUCCESS);
return ((PAM_SUCCESS == ret) ? 0 : 1);
}
#else /* !USE_PAM */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !USE_PAM */

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1997, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François
* Copyright (c) 2007 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,8 +34,6 @@
#ident "$Id$"
#ifndef USE_PAM
#include <sys/types.h>
#include "prototypes.h"
#include "defines.h"
@@ -66,12 +64,7 @@ struct spwd *pwd_to_spwd (const struct passwd *pw)
*/
sp.sp_min = 0;
sp.sp_max = (10000L * DAY) / SCALE;
sp.sp_lstchg = (long) time ((time_t *) 0) / SCALE;
if (0 == sp.sp_lstchg) {
/* Better disable aging than requiring a password
* change */
sp.sp_lstchg = -1;
}
sp.sp_lstchg = time ((time_t *) 0) / SCALE;
}
/*
@@ -81,11 +74,7 @@ struct spwd *pwd_to_spwd (const struct passwd *pw)
sp.sp_warn = -1;
sp.sp_expire = -1;
sp.sp_inact = -1;
sp.sp_flag = SHADOW_SP_FLAG_UNSET;
sp.sp_flag = -1;
return &sp;
}
#else /* USE_PAM */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !USE_PAM */

View File

@@ -40,7 +40,7 @@
#include "defines.h"
#include "pwauth.h"
void passwd_check (const char *user, const char *passwd, unused const char *progname)
void passwd_check (const char *user, const char *passwd, const char *progname)
{
struct spwd *sp;
@@ -50,9 +50,9 @@ void passwd_check (const char *user, const char *passwd, unused const char *prog
}
if (pw_auth (passwd, user, PW_LOGIN, (char *) 0) != 0) {
SYSLOG ((LOG_WARN, "incorrect password for `%s'", user));
(void) sleep (1);
sleep (1);
fprintf (stderr, _("Incorrect password for %s.\n"), user);
exit (EXIT_FAILURE);
exit (1);
}
}
#else /* USE_PAM */

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1999, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2008, Nicolas François
* Copyright (c) 2007 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -110,30 +110,26 @@ static struct {
-1, -1}
};
static void get_remote_string (char *buf, size_t size)
static void get_remote_string (char *buf, int size)
{
for (;;) {
if (read (0, buf, 1) != 1) {
exit (EXIT_FAILURE);
}
if ('\0' == *buf) {
if (read (0, buf, 1) != 1)
exit (1);
if (*buf == '\0')
return;
}
--size;
if (size > 0) {
if (--size > 0)
++buf;
}
}
/*NOTREACHED*/}
int
do_rlogin (const char *remote_host, char *name, size_t namelen, char *term,
size_t termlen)
do_rlogin (const char *remote_host, char *name, int namelen, char *term,
int termlen)
{
struct passwd *pwd;
char remote_name[32];
char *cp;
unsigned long remote_speed = 9600;
int remote_speed = 9600;
int speed_name = B9600;
int i;
TERMIO termio;
@@ -142,23 +138,17 @@ do_rlogin (const char *remote_host, char *name, size_t namelen, char *term,
get_remote_string (name, namelen);
get_remote_string (term, termlen);
cp = strchr (term, '/');
if (NULL != cp) {
*cp = '\0';
cp++;
if ((cp = strchr (term, '/'))) {
*cp++ = '\0';
if (getulong (cp, &remote_speed) == 0) {
if (!(remote_speed = atoi (cp)))
remote_speed = 9600;
}
}
for (i = 0;
( (speed_table[i].spd_baud != remote_speed)
&& (speed_table[i].spd_name != -1));
i++);
for (i = 0; speed_table[i].spd_baud != remote_speed &&
speed_table[i].spd_name != -1; i++);
if (-1 != speed_table[i].spd_name) {
if (speed_table[i].spd_name != -1)
speed_name = speed_table[i].spd_name;
}
/*
* Put the terminal in cooked mode with echo turned on.
@@ -175,10 +165,8 @@ do_rlogin (const char *remote_host, char *name, size_t namelen, char *term,
#endif
STTY (0, &termio);
pwd = getpwnam (name); /* local, no need for xgetpwnam */
if (NULL == pwd) {
if (!(pwd = getpwnam (name))) /* local, no need for xgetpwnam */
return 0;
}
/*
* ruserok() returns 0 for success on modern systems, and 1 on

View File

@@ -20,15 +20,18 @@
#include "getdef.h"
/* local function prototypes */
#ifndef HAVE_L64A
char *l64a(long value);
#endif /* !HAVE_L64A */
static void seedRNG (void);
static /*@observer@*/const char *gensalt (size_t salt_size);
static char *gensalt (unsigned int salt_size);
#ifdef USE_SHA_CRYPT
static size_t SHA_salt_size (void);
static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds);
static unsigned int SHA_salt_size (void);
static const char *SHA_salt_rounds (int *prefered_rounds);
#endif /* USE_SHA_CRYPT */
#ifndef HAVE_L64A
static /*@observer@*/char *l64a(long value)
static char *l64a(long value)
{
static char buf[8];
char *s = buf;
@@ -43,15 +46,14 @@ static /*@observer@*/char *l64a(long value)
for (i = 0; value != 0 && i < 6; i++) {
digit = value & 0x3f;
if (digit < 2) {
if (digit < 2)
*s = digit + '.';
} else if (digit < 12) {
else if (digit < 12)
*s = digit + '0' - 2;
} else if (digit < 38) {
else if (digit < 38)
*s = digit + 'A' - 12;
} else {
else
*s = digit + 'a' - 38;
}
value >>= 6;
s++;
@@ -69,8 +71,8 @@ static void seedRNG (void)
static int seeded = 0;
if (0 == seeded) {
(void) gettimeofday (&tv, NULL);
srandom (tv.tv_sec ^ tv.tv_usec ^ getpid ());
gettimeofday(&tv, NULL);
srandom (tv.tv_sec + tv.tv_usec);
seeded = 1;
}
}
@@ -86,14 +88,18 @@ static void seedRNG (void)
* The size of the salt string is between 8 and 16 bytes for the SHA crypt
* methods.
*/
static size_t SHA_salt_size (void)
static unsigned int SHA_salt_size (void)
{
double rand_size;
seedRNG ();
rand_size = (double) 9.0 * random () / RAND_MAX;
return (size_t) (8 + rand_size);
return 8 + rand_size;
}
/* ! Arguments evaluated twice ! */
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define MIN(x,y) ((x) < (y) ? (x) : (y))
/* Default number of rounds if not explicitly specified. */
#define ROUNDS_DEFAULT 5000
/* Minimum number of rounds. */
@@ -104,7 +110,7 @@ static size_t SHA_salt_size (void)
/*
* Return a salt prefix specifying the rounds number for the SHA crypt methods.
*/
static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds)
static const char *SHA_salt_rounds (int *prefered_rounds)
{
static char rounds_prefix[18];
long rounds;
@@ -114,49 +120,41 @@ static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds
long max_rounds = getdef_long ("SHA_CRYPT_MAX_ROUNDS", -1);
double rand_rounds;
if ((-1 == min_rounds) && (-1 == max_rounds)) {
if (-1 == min_rounds && -1 == max_rounds)
return "";
}
if (-1 == min_rounds) {
if (-1 == min_rounds)
min_rounds = max_rounds;
}
if (-1 == max_rounds) {
if (-1 == max_rounds)
max_rounds = min_rounds;
}
if (min_rounds > max_rounds) {
if (min_rounds > max_rounds)
max_rounds = min_rounds;
}
seedRNG ();
rand_rounds = (double) (max_rounds-min_rounds+1.0) * random ();
rand_rounds /= RAND_MAX;
rounds = min_rounds + rand_rounds;
} else if (0 == *prefered_rounds) {
} else if (0 == *prefered_rounds)
return "";
} else {
else
rounds = *prefered_rounds;
}
/* Sanity checks. The libc should also check this, but this
* protects against a rounds_prefix overflow. */
if (rounds < ROUNDS_MIN) {
if (rounds < ROUNDS_MIN)
rounds = ROUNDS_MIN;
}
if (rounds > ROUNDS_MAX) {
if (rounds > ROUNDS_MAX)
rounds = ROUNDS_MAX;
}
snprintf (rounds_prefix, 18, "rounds=%ld$", rounds);
/* Sanity checks. That should not be necessary. */
rounds_prefix[17] = '\0';
if ('$' != rounds_prefix[16]) {
if ('$' != rounds_prefix[16])
rounds_prefix[17] = '$';
}
return rounds_prefix;
}
@@ -168,7 +166,7 @@ static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds
#define MAX_SALT_SIZE 16
#define MIN_SALT_SIZE 8
static /*@observer@*/const char *gensalt (size_t salt_size)
static char *gensalt (unsigned int salt_size)
{
static char salt[32];
@@ -181,7 +179,6 @@ static /*@observer@*/const char *gensalt (size_t salt_size)
do {
strcat (salt, l64a (random()));
} while (strlen (salt) < salt_size);
salt[salt_size] = '\0';
return salt;
@@ -202,7 +199,7 @@ static /*@observer@*/const char *gensalt (size_t salt_size)
* * For the SHA256 and SHA512 method, this specifies the number of rounds
* (if not NULL).
*/
/*@observer@*/const char *crypt_make_salt (/*@null@*/const char *meth, /*@null@*/void *arg)
char *crypt_make_salt (const char *meth, void *arg)
{
/* Max result size for the SHA methods:
* +3 $5$
@@ -219,10 +216,8 @@ static /*@observer@*/const char *gensalt (size_t salt_size)
if (NULL != meth)
method = meth;
else {
method = getdef_str ("ENCRYPT_METHOD");
if (NULL == method) {
method = getdef_bool ("MD5_CRYPT_ENAB") ? "MD5" : "DES";
}
if ((method = getdef_str ("ENCRYPT_METHOD")) == NULL)
method = getdef_bool ("MD5_CRYPT_ENAB") ? "MD5" : "DES";
}
if (0 == strcmp (method, "MD5")) {

View File

@@ -2,7 +2,6 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,21 +39,14 @@
#include <stdio.h>
#include <grp.h>
#include <errno.h>
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
#include "getdef.h"
/*
* setup_groups - set the group credentials
* set the group ID to the value from the password file entry
* set the supplementary group IDs
*
* In case of PAM enabled configurations, this shall be called before
* pam_setcred.
*
* Returns 0 on success, or -1 on failure.
* setup_uid_gid() split in two functions for PAM support -
* pam_setcred() needs to be called after initgroups(), but
* before setuid().
*/
int setup_groups (const struct passwd *info)
{
@@ -63,10 +55,9 @@ int setup_groups (const struct passwd *info)
* file.
*/
if (setgid (info->pw_gid) == -1) {
int err = errno;
perror ("setgid");
SYSLOG ((LOG_ERR, "bad group ID `%d' for user `%s': %s\n",
info->pw_gid, info->pw_name, strerror (err)));
SYSLOG ((LOG_ERR, "bad group ID `%d' for user `%s': %m\n",
info->pw_gid, info->pw_name));
closelog ();
return -1;
}
@@ -76,10 +67,9 @@ int setup_groups (const struct passwd *info)
* the group set from the /etc/group file.
*/
if (initgroups (info->pw_name, info->pw_gid) == -1) {
int err = errno;
perror ("initgroups");
SYSLOG ((LOG_ERR, "initgroups failed for user `%s': %s\n",
info->pw_name, strerror (err)));
SYSLOG ((LOG_ERR, "initgroups failed for user `%s': %m\n",
info->pw_name));
closelog ();
return -1;
}
@@ -87,21 +77,15 @@ int setup_groups (const struct passwd *info)
return 0;
}
/*
* change_uid - Set the real UID
*
* Returns 0 on success, or -1 on failure.
*/
int change_uid (const struct passwd *info)
{
/*
* Set the real UID to the UID value in the password file.
*/
if (setuid (info->pw_uid) != 0) {
int err = errno;
if (setuid (info->pw_uid)) {
perror ("setuid");
SYSLOG ((LOG_ERR, "bad user ID `%d' for user `%s': %s\n",
(int) info->pw_uid, info->pw_name, strerror (err)));
SYSLOG ((LOG_ERR, "bad user ID `%d' for user `%s': %m\n",
(int) info->pw_uid, info->pw_name));
closelog ();
return -1;
}
@@ -119,30 +103,22 @@ int change_uid (const struct passwd *info)
* Returns 0 on success, or -1 on failure.
*/
#if defined (HAVE_INITGROUPS) && ! (defined USE_PAM)
int setup_uid_gid (const struct passwd *info, bool is_console)
#else
int setup_uid_gid (const struct passwd *info)
#endif
int setup_uid_gid (const struct passwd *info, int is_console)
{
if (setup_groups (info) < 0) {
if (setup_groups (info) < 0)
return -1;
}
#if defined (HAVE_INITGROUPS) && ! defined (USE_PAM)
#ifdef HAVE_INITGROUPS
if (is_console) {
char *cp = getdef_str ("CONSOLE_GROUPS");
if ((NULL != cp) && (add_groups (cp) != 0)) {
if (cp && add_groups (cp))
perror ("Warning: add_groups");
}
}
#endif /* HAVE_INITGROUPS && !USE_PAM*/
#endif /* HAVE_INITGROUPS */
if (change_uid (info) < 0) {
if (change_uid (info) < 0)
return -1;
}
return 0;
}

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François
* Copyright (c) 2007 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,7 +38,6 @@
#ident "$Id$"
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
@@ -53,13 +52,9 @@ static void
addenv_path (const char *varname, const char *dirname, const char *filename)
{
char *buf;
size_t len = strlen (dirname) + strlen (filename) + 2;
int wlen;
buf = xmalloc (len);
wlen = snprintf (buf, len, "%s/%s", dirname, filename);
assert (wlen == (int) len - 1);
buf = xmalloc (strlen (dirname) + strlen (filename) + 2);
sprintf (buf, "%s/%s", dirname, filename);
addenv (varname, buf);
free (buf);
}
@@ -71,38 +66,31 @@ static void read_env_file (const char *filename)
char *cp, *name, *val;
fp = fopen (filename, "r");
if (NULL == fp) {
if (!fp)
return;
}
while (fgets (buf, sizeof buf, fp) == buf) {
cp = strrchr (buf, '\n');
if (NULL == cp) {
if (!cp)
break;
}
*cp = '\0';
cp = buf;
/* ignore whitespace and comments */
while (('\0' != *cp) && isspace (*cp)) {
while (*cp && isspace (*cp))
cp++;
}
if (('\0' == *cp) || ('#' == *cp)) {
if (*cp == '\0' || *cp == '#')
continue;
}
/*
* ignore lines which don't follow the name=value format
* (for example, the "export NAME" shell commands)
*/
name = cp;
while (('\0' != *cp) && !isspace (*cp) && ('=' != *cp)) {
while (*cp && !isspace (*cp) && *cp != '=')
cp++;
}
if ('=' != *cp) {
if (*cp != '=')
continue;
}
/* NUL-terminate the name */
*cp = '\0';
cp++;
*cp++ = '\0';
val = cp;
#if 0 /* XXX untested, and needs rewrite with fewer goto's :-) */
/*
@@ -186,7 +174,7 @@ static void read_env_file (const char *filename)
*/
addenv (name, val);
}
(void) fclose (fp);
fclose (fp);
}
#endif /* USE_PAM */
@@ -225,9 +213,9 @@ void setup_env (struct passwd *info)
"unable to cd to `%s' for user `%s'\n",
info->pw_dir, info->pw_name));
closelog ();
exit (EXIT_FAILURE);
exit (1);
}
(void) puts (_("No directory, logging in with HOME=/"));
puts (_("No directory, logging in with HOME=/"));
info->pw_dir = temp_pw_dir;
}
@@ -241,8 +229,8 @@ void setup_env (struct passwd *info)
* Create the SHELL environmental variable and export it.
*/
if ((NULL == info->pw_shell) || ('\0' == *info->pw_shell)) {
static char temp_pw_shell[] = SHELL;
if (info->pw_shell == (char *) 0 || !*info->pw_shell) {
static char temp_pw_shell[] = "/bin/sh";
info->pw_shell = temp_pw_shell;
}
@@ -263,7 +251,7 @@ void setup_env (struct passwd *info)
cp = getdef_str ((info->pw_uid == 0) ? "ENV_SUPATH" : "ENV_PATH");
if (NULL == cp) {
if (!cp) {
/* not specified, use a minimal default */
addenv ("PATH=/bin:/usr/bin", NULL);
} else if (strchr (cp, '=')) {
@@ -281,30 +269,23 @@ void setup_env (struct passwd *info)
*/
if (getdef_bool ("MAIL_CHECK_ENAB")) {
cp = getdef_str ("MAIL_DIR");
if (NULL != cp) {
if ((cp = getdef_str ("MAIL_DIR")))
addenv_path ("MAIL", cp, info->pw_name);
} else {
cp = getdef_str ("MAIL_FILE");
if (NULL != cp) {
addenv_path ("MAIL", info->pw_dir, cp);
} else {
else if ((cp = getdef_str ("MAIL_FILE")))
addenv_path ("MAIL", info->pw_dir, cp);
else {
#if defined(MAIL_SPOOL_FILE)
addenv_path ("MAIL", info->pw_dir, MAIL_SPOOL_FILE);
addenv_path ("MAIL", info->pw_dir, MAIL_SPOOL_FILE);
#elif defined(MAIL_SPOOL_DIR)
addenv_path ("MAIL", MAIL_SPOOL_DIR, info->pw_name);
addenv_path ("MAIL", MAIL_SPOOL_DIR, info->pw_name);
#endif
}
}
}
/*
* Read environment from optional config file. --marekm
*/
envf = getdef_str ("ENVIRON_FILE");
if (NULL != envf) {
if ((envf = getdef_str ("ENVIRON_FILE")))
read_env_file (envf);
}
#endif /* !USE_PAM */
}

View File

@@ -2,7 +2,6 @@
* Copyright (c) 1989 - 1991, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko
* Copyright (c) 2009 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -47,11 +46,14 @@ extern size_t newenvc;
* shell begins by trying to figure out what argv[0] is going to
* be for the named process. The user may pass in that argument,
* or it will be the last pathname component of the file with a
* '-' prepended.
* Then, it executes the named file.
* '-' prepended. The first attempt is to just execute the named
* file. If the errno comes back "ENOEXEC", the file is assumed
* at first glance to be a shell script. The first two characters
* must be "#!", in which case "/bin/sh" is executed to process
* the file. If all that fails, give up in disgust ...
*/
int shell (const char *file, /*@null@*/const char *arg, char *const envp[])
int shell (const char *file, const char *arg, char *const envp[])
{
char arg0[1024];
int err;
@@ -80,14 +82,30 @@ int shell (const char *file, /*@null@*/const char *arg, char *const envp[])
execle (file, arg, (char *) 0, envp);
err = errno;
if (access (file, R_OK|X_OK) == 0) {
/*
* Assume this is a shell script (with no shebang).
* Interpret it with /bin/sh
*/
execle (SHELL, "sh", "-", file, (char *)0, envp);
err = errno;
/* Linux handles #! in the kernel, and bash doesn't make
sense of "#!" so it wouldn't work anyway... --marekm */
#ifndef __linux__
/*
* It is perfectly OK to have a shell script for a login
* shell, and this code attempts to support that. It
* relies on the standard shell being able to make sense
* of the "#!" magic number.
*/
if (err == ENOEXEC) {
FILE *fp;
if ((fp = fopen (file, "r"))) {
if (getc (fp) == '#' && getc (fp) == '!') {
fclose (fp);
execle ("/bin/sh", "sh",
file, (char *) 0, envp);
err = errno;
} else {
fclose (fp);
}
}
}
#endif
/*
* Obviously something is really wrong - I can't figure out
@@ -99,4 +117,3 @@ int shell (const char *file, /*@null@*/const char *arg, char *const envp[])
perror (arg0);
return err;
}

View File

@@ -69,16 +69,14 @@ long strtoday (const char *str)
* which is not what we expect, unless you're a BOFH :-).
* (useradd sets sp_expire = current date for new lusers)
*/
if ((NULL == str) || ('\0' == *str)) {
if (!str || *str == '\0')
return -1;
}
t = get_date (str, (time_t *) 0);
if ((time_t) - 1 == t) {
if (t == (time_t) - 1)
return -1;
}
/* convert seconds to days since 1970-01-01 */
return (long) (t + DAY / 2) / DAY;
return (t + DAY / 2) / DAY;
}
#else /* !USE_GETDATE */
@@ -131,16 +129,14 @@ long strtoday (const char *str)
memzero (&tp, sizeof tp);
for (fmt = date_formats; *fmt; fmt++) {
cp = strptime ((char *) str, *fmt, &tp);
if ((NULL == cp) || ('\0' != *cp)) {
if (!cp || *cp != '\0')
continue;
}
result = mktime (&tp);
if ((time_t) - 1 == result) {
if (result == (time_t) - 1)
continue;
}
return (long) (result / DAY); /* success */
return result / DAY; /* success */
}
return -1;
#else
@@ -155,9 +151,8 @@ long strtoday (const char *str)
* is compiled in ...
*/
if (sscanf (str, "%d/%d/%d%c", &year, &month, &day, slop) != 3) {
if (sscanf (str, "%d/%d/%d%c", &year, &month, &day, slop) != 3)
return -1;
}
/*
* the month, day of the month, and year are checked for
@@ -165,28 +160,23 @@ long strtoday (const char *str)
* 1970 and 2069.
*/
if ((month < 1) || (month > 12)) {
if (month < 1 || month > 12)
return -1;
}
if (day < 1) {
if (day < 1)
return -1;
}
if ( ((2 != month) || ((year % 4) != 0))
&& (day > days[month])) {
if ((month != 2 || (year % 4) != 0) && day > days[month])
return -1;
} else if ((month == 2) && ((year % 4) == 0) && (day > 29)) {
else if ((month == 2 && (year % 4) == 0) && day > 29)
return -1;
}
if (year < 0) {
if (year < 0)
return -1;
} else if (year <= 69) {
else if (year <= 69)
year += 2000;
} else if (year <= 99) {
else if (year <= 99)
year += 1900;
}
/*
* On systems with 32-bit signed time_t, time wraps around in 2038
@@ -194,9 +184,8 @@ long strtoday (const char *str)
* This limit can be removed once no one is using 32-bit systems
* anymore :-). --marekm
*/
if ((year < 1970) || (year > 2037)) {
if (year < 1970 || year > 2037)
return -1;
}
/*
* the total number of days is the total number of days in all

View File

@@ -58,7 +58,7 @@ void subsystem (const struct passwd *pw)
printf (_("Invalid root directory '%s'\n"), pw->pw_dir);
SYSLOG ((LOG_WARN, BAD_SUBROOT2, pw->pw_dir, pw->pw_name));
closelog ();
exit (EXIT_FAILURE);
exit (1);
}
/*
@@ -71,6 +71,6 @@ void subsystem (const struct passwd *pw)
pw->pw_dir);
SYSLOG ((LOG_WARN, NO_SUBROOT2, pw->pw_dir, pw->pw_name));
closelog ();
exit (EXIT_FAILURE);
exit (1);
}
}

View File

@@ -2,7 +2,6 @@
* Copyright (c) 1989 - 1992, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,11 +40,10 @@
#include "prototypes.h"
#include "defines.h"
#include "getdef.h"
/*
* sulog - log a SU command execution result
*/
void sulog (const char *tty, bool success, const char *oldname, const char *name)
void sulog (const char *tty, int success, const char *oldname, const char *name)
{
char *sulog_file;
time_t now;
@@ -76,29 +74,25 @@ void sulog (const char *tty, bool success, const char *oldname, const char *name
oldgid = 0;
}
fp = fopen (sulog_file, "a+");
(void) umask (oldmask);
umask (oldmask);
if ((oldgid != 0) && (setgid (oldgid) != 0)) {
perror ("setgid");
SYSLOG ((LOG_ERR,
"can't switch back to group `%d' in sulog",
oldgid));
/* Do not return if the group permission were raised. */
exit (EXIT_FAILURE);
exit (1);
}
if (fp == (FILE *) 0) {
if (fp == (FILE *) 0)
return; /* can't open or create logfile */
}
(void) time (&now);
time (&now);
tm = localtime (&now);
fprintf (fp, "SU %.02d/%.02d %.02d:%.02d %c %s %s-%s\n",
tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
success ? '+' : '-', tty, oldname, name);
(void) fflush (fp);
fsync (fileno (fp));
fflush (fp);
fclose (fp);
/* TODO: log if failure */
}

View File

@@ -1,72 +0,0 @@
/*
* Copyright (c) 2009 , Dan Walsh <dwalsh@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>
#ident "$Id$"
#include <stdio.h>
#include <sys/wait.h>
#include <fcntl.h>
#include "prototypes.h"
#include "defines.h"
int safe_system (const char *command,
const char *argv[],
const char *env[],
int ignore_stderr)
{
int status = -1;
int fd;
pid_t pid;
pid = fork();
if (pid < 0) {
return -1;
}
if (pid) { /* Parent */
if (waitpid (pid, &status, 0) > 0) {
return status;
} else {
return -1;
}
}
fd = open ("/dev/null", O_RDWR);
/* Child */
dup2 (fd, 0); // Close Stdin
if (ignore_stderr) {
dup2 (fd, 2); // Close Stderr
}
execve (command, (char *const *) argv, (char *const *) env);
fprintf (stderr, _("Failed to exec '%s'\n"), argv[0]);
exit (EXIT_FAILURE);
}

View File

@@ -2,7 +2,6 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1997, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -50,41 +49,30 @@ void ttytype (const char *line)
char type[BUFSIZ];
char port[BUFSIZ];
if (getenv ("TERM") != NULL) {
if (getenv ("TERM"))
return;
}
typefile = getdef_str ("TTYTYPE_FILE");
if (NULL == typefile) {
if ((typefile = getdef_str ("TTYTYPE_FILE")) == NULL)
return;
}
if (access (typefile, F_OK) != 0) {
if (access (typefile, F_OK))
return;
}
fp = fopen (typefile, "r");
if (NULL == fp) {
if (!(fp = fopen (typefile, "r"))) {
perror (typefile);
return;
}
while (fgets (buf, (int) sizeof buf, fp) == buf) {
if (buf[0] == '#') {
while (fgets (buf, sizeof buf, fp)) {
if (buf[0] == '#')
continue;
}
cp = strchr (buf, '\n');
if (NULL != cp) {
if ((cp = strchr (buf, '\n')))
*cp = '\0';
}
if ((sscanf (buf, "%s %s", type, port) == 2) &&
(strcmp (line, port) == 0)) {
if (sscanf (buf, "%s %s", type, port) == 2 &&
strcmp (line, port) == 0)
break;
}
}
if ((feof (fp) == 0) && (ferror (fp) == 0)) {
if (!feof (fp) && !ferror (fp))
addenv ("TERM", type);
}
(void) fclose (fp);
fclose (fp);
}

View File

@@ -33,8 +33,6 @@
#include <config.h>
#ifndef USE_PAM
#ident "$Id$"
#include <stdio.h>
@@ -42,7 +40,6 @@
#include "defines.h"
#include "prototypes.h"
#include "getdef.h"
/*
* tz - return local timezone name
*
@@ -56,9 +53,11 @@ char *tz (const char *fname)
const char *def_tz = "TZ=CST6CDT";
if ((fp = fopen (fname, "r")) == NULL ||
fgets (tzbuf, (int) sizeof (tzbuf), fp) == NULL) {
fgets (tzbuf, sizeof (tzbuf), fp) == NULL) {
#ifndef USE_PAM
if (!(def_tz = getdef_str ("ENV_TZ")) || def_tz[0] == '/')
def_tz = "TZ=CST6CDT";
#endif /* !USE_PAM */
strcpy (tzbuf, def_tz);
} else
@@ -69,7 +68,3 @@ char *tz (const char *fname)
return tzbuf;
}
#else /* !USE_PAM */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !USE_PAM */

View File

@@ -50,21 +50,14 @@
#endif
#include "prototypes.h"
int set_filesize_limit (int blocks)
void set_filesize_limit (int blocks)
{
int ret = -1;
#if HAVE_ULIMIT_H
if (ulimit (UL_SETFSIZE, blocks) != -1) {
ret = 0;
}
ulimit (UL_SETFSIZE, blocks);
#elif defined(RLIMIT_FSIZE)
struct rlimit rlimit_fsize;
rlimit_fsize.rlim_cur = 512L * blocks;
rlimit_fsize.rlim_max = rlimit_fsize.rlim_cur;
ret = setrlimit (RLIMIT_FSIZE, &rlimit_fsize);
rlimit_fsize.rlim_cur = rlimit_fsize.rlim_max = 512L * blocks;
setrlimit (RLIMIT_FSIZE, &rlimit_fsize);
#endif
return ret;
}

View File

@@ -1,228 +0,0 @@
/*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2000 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, 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 <assert.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include "defines.h"
#include "prototypes.h"
#ifdef __linux__
static int check_status (const char *sname, uid_t uid);
static int user_busy_processes (uid_t uid);
#else /* !__linux__ */
static int user_busy_utmp (const char *name);
#endif /* !__linux__ */
/*
* user_busy - check if an user if currently running processes
*/
int user_busy (const char *name, uid_t uid)
{
/* There are no standard ways to get the list of processes.
* An option could be to run an external tool (ps).
*/
#ifdef __linux__
/* On Linux, directly parse /proc */
return user_busy_processes (uid);
#else /* !__linux__ */
/* If we cannot rely on /proc, check is there is a record in utmp
* indicating that the user is still logged in */
return user_busy_utmp (name);
#endif /* !__linux__ */
}
#ifndef __linux__
static int user_busy_utmp (const char *name)
{
#ifdef USE_UTMPX
struct utmpx *utent;
setutxent ();
while ((utent = getutxent ()) != NULL)
#else /* !USE_UTMPX */
struct utmp *utent;
setutent ();
while ((utent = getutent ()) != NULL)
#endif /* !USE_UTMPX */
{
if (utent->ut_type != USER_PROCESS) {
continue;
}
if (strncmp (utent->ut_user, name, sizeof utent->ut_user) != 0) {
continue;
}
if (kill (utent->ut_pid, 0) != 0) {
continue;
}
return 1;
}
return 0;
}
#endif /* !__linux__ */
#ifdef __linux__
static int check_status (const char *sname, uid_t uid)
{
/* 40: /proc/xxxxxxxxxx/task/xxxxxxxxxx/status + \0 */
char status[40];
char line[1024];
FILE *sfile;
snprintf (status, 40, "/proc/%s/status", sname);
status[39] = '\0';
sfile = fopen (status, "r");
if (NULL == sfile) {
return 0;
}
while (fgets (line, sizeof (line), sfile) == line) {
if (strncmp (line, "Uid:\t", 5) == 0) {
unsigned long ruid, euid, suid;
assert (uid == (unsigned long) uid);
if (sscanf (line,
"Uid:\t%lu\t%lu\t%lu\n",
&ruid, &euid, &suid) == 3) {
if ( (ruid == (unsigned long) uid)
|| (euid == (unsigned long) uid)
|| (suid == (unsigned long) uid)) {
(void) fclose (sfile);
return 1;
}
} else {
/* Ignore errors. This is just a best effort. */
}
(void) fclose (sfile);
return 0;
}
}
(void) fclose (sfile);
return 0;
}
static int user_busy_processes (uid_t uid)
{
DIR *proc;
struct dirent *ent;
char *tmp_d_name;
pid_t pid;
DIR *task_dir;
/* 22: /proc/xxxxxxxxxx/task + \0 */
char task_path[22];
char root_path[22];
struct stat sbroot;
struct stat sbroot_process;
proc = opendir ("/proc");
if (proc == NULL) {
perror ("opendir /proc");
return 0;
}
if (stat ("/", &sbroot) != 0) {
perror ("stat (\"/\")");
(void) closedir (proc);
return 0;
}
while ((ent = readdir (proc)) != NULL) {
tmp_d_name = ent->d_name;
/*
* Ingo Molnar's patch introducing NPTL for 2.4 hides
* threads in the /proc directory by prepending a period.
* This patch is applied by default in some RedHat
* kernels.
*/
if ( (strcmp (tmp_d_name, ".") == 0)
|| (strcmp (tmp_d_name, "..") == 0)) {
continue;
}
if (*tmp_d_name == '.') {
tmp_d_name++;
}
/* Check if this is a valid PID */
if (get_pid (tmp_d_name, &pid) == 0) {
continue;
}
/* Check if the process is in our chroot */
snprintf (root_path, 22, "/proc/%lu/root", (unsigned long) pid);
root_path[21] = '\0';
if (stat (root_path, &sbroot_process) != 0) {
continue;
}
if ( (sbroot.st_dev != sbroot_process.st_dev)
|| (sbroot.st_ino != sbroot_process.st_ino)) {
continue;
}
if (check_status (tmp_d_name, uid) != 0) {
(void) closedir (proc);
return 1;
}
snprintf (task_path, 22, "/proc/%lu/task", (unsigned long) pid);
task_path[21] = '\0';
task_dir = opendir (task_path);
if (task_dir != NULL) {
while ((ent = readdir (task_dir)) != NULL) {
pid_t tid;
if (get_pid (ent->d_name, &tid) == 0) {
continue;
}
if (tid == pid) {
continue;
}
if (check_status (task_path+6, uid) != 0) {
(void) closedir (proc);
return 1;
}
}
(void) closedir (task_dir);
} else {
/* Ignore errors. This is just a best effort */
}
}
(void) closedir (proc);
return 0;
}
#endif /* __linux__ */

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1999, Marek Michałkiewicz
* Copyright (c) 2001 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2009, Nicolas François
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,102 +37,193 @@
#include <utmp.h>
#ifdef USE_UTMPX
#if HAVE_UTMPX_H
#include <utmpx.h>
#endif
#include <assert.h>
#include <netdb.h>
#include <fcntl.h>
#include <stdio.h>
#ident "$Id$"
#if HAVE_UTMPX_H
struct utmpx utxent;
#endif
struct utmp utent;
#define NO_UTENT \
_("No utmp entry. You must exec \"login\" from the lowest level \"sh\"")
#define NO_TTY \
_("Unable to determine your tty name.")
/*
* is_my_tty -- determine if "tty" is the same TTY stdin is using
* checkutmp - see if utmp file is correct for this process
*
* System V is very picky about the contents of the utmp file
* and requires that a slot for the current process exist.
* The utmp file is scanned for an entry with the same process
* ID. If no entry exists the process exits with a message.
*
* The "picky" flag is for network and other logins that may
* use special flags. It allows the pid checks to be overridden.
* This means that getty should never invoke login with any
* command line flags.
*/
static bool is_my_tty (const char *tty)
{
/* full_tty shall be at least sizeof utmp.ut_line + 5 */
char full_tty[200];
/* tmptty shall be bigger than full_tty */
static char tmptty[sizeof (full_tty)+1];
if ('/' != *tty) {
(void) snprintf (full_tty, sizeof full_tty, "/dev/%s", tty);
tty = &full_tty[0];
}
if ('\0' == tmptty[0]) {
const char *tname = ttyname (STDIN_FILENO);
if (NULL != tname) {
(void) strncpy (tmptty, tname, sizeof tmptty);
tmptty[sizeof (tmptty) - 1] = '\0';
}
}
if (NULL == tmptty) {
(void) puts (_("Unable to determine your tty name."));
exit (EXIT_FAILURE);
} else if (strncmp (tty, tmptty, sizeof (tmptty)) != 0) {
return false;
} else {
return true;
}
}
/*
* get_current_utmp - return the most probable utmp entry for the current
* session
*
* The utmp file is scanned for an entry with the same process ID.
* The line enterred by the *getty / telnetd, etc. should also match
* the current terminal.
*
* When an entry is returned by get_current_utmp, and if the utmp
* structure has a ut_id field, this field should be used to update
* the entry information.
*
* Return NULL if no entries exist in utmp for the current process.
*/
/*@null@*/ /*@only@*/struct utmp *get_current_utmp (void)
#if defined(__linux__) /* XXX */
void checkutmp (int picky)
{
char *line;
struct utmp *ut;
struct utmp *ret = NULL;
pid_t pid = getpid ();
setutent ();
/* First, try to find a valid utmp entry for this process. */
while ((ut = getutent ()) != NULL) {
if ( (ut->ut_pid == getpid ())
#ifdef HAVE_STRUCT_UTMP_UT_ID
&& ('\0' != ut->ut_id[0])
#endif
#ifdef HAVE_STRUCT_UTMP_UT_TYPE
&& ( (LOGIN_PROCESS == ut->ut_type)
|| (USER_PROCESS == ut->ut_type))
#endif
/* A process may have failed to close an entry
* Check if this entry refers to the current tty */
&& is_my_tty (ut->ut_line)) {
while ((ut = getutent ()))
if (ut->ut_pid == pid && ut->ut_line[0] && ut->ut_id[0] &&
(ut->ut_type == LOGIN_PROCESS
|| ut->ut_type == USER_PROCESS))
break;
/* If there is one, just use it, otherwise create a new one. */
if (ut) {
utent = *ut;
} else {
if (picky) {
puts (NO_UTENT);
exit (1);
}
line = ttyname (0);
if (!line) {
puts (NO_TTY);
exit (1);
}
if (strncmp (line, "/dev/", 5) == 0)
line += 5;
memset ((void *) &utent, 0, sizeof utent);
utent.ut_type = LOGIN_PROCESS;
utent.ut_pid = pid;
strncpy (utent.ut_line, line, sizeof utent.ut_line);
/* XXX - assumes /dev/tty?? */
strncpy (utent.ut_id, utent.ut_line + 3, sizeof utent.ut_id);
strcpy (utent.ut_user, "LOGIN");
utent.ut_time = time (NULL);
}
if (NULL != ut) {
ret = (struct utmp *) xmalloc (sizeof (*ret));
memcpy (ret, ut, sizeof (*ret));
}
endutent ();
return ret;
}
#elif defined(LOGIN_PROCESS)
void checkutmp (int picky)
{
char *line;
struct utmp *ut;
#if HAVE_UTMPX_H
struct utmpx *utx;
#endif
pid_t pid = getpid ();
#if HAVE_UTMPX_H
setutxent ();
#endif
setutent ();
if (picky) {
#if HAVE_UTMPX_H
while ((utx = getutxent ()))
if (utx->ut_pid == pid)
break;
if (utx)
utxent = *utx;
#endif
while ((ut = getutent ()))
if (ut->ut_pid == pid)
break;
if (ut)
utent = *ut;
#if HAVE_UTMPX_H
endutxent ();
#endif
endutent ();
if (!ut) {
puts (NO_UTENT);
exit (1);
}
#ifndef UNIXPC
/*
* If there is no ut_line value in this record, fill
* it in by getting the TTY name and stuffing it in
* the structure. The UNIX/PC is broken in this regard
* and needs help ...
*/
if (utent.ut_line[0] == '\0')
#endif /* !UNIXPC */
{
if (!(line = ttyname (0))) {
puts (NO_TTY);
exit (1);
}
if (strncmp (line, "/dev/", 5) == 0)
line += 5;
strncpy (utent.ut_line, line, sizeof utent.ut_line);
#if HAVE_UTMPX_H
strncpy (utxent.ut_line, line, sizeof utxent.ut_line);
#endif
}
} else {
if (!(line = ttyname (0))) {
puts (NO_TTY);
exit (1);
}
if (strncmp (line, "/dev/", 5) == 0)
line += 5;
strncpy (utent.ut_line, line, sizeof utent.ut_line);
if ((ut = getutline (&utent)))
strncpy (utent.ut_id, ut->ut_id, sizeof ut->ut_id);
strcpy (utent.ut_user, "LOGIN");
utent.ut_pid = getpid ();
utent.ut_type = LOGIN_PROCESS;
utent.ut_time = time (NULL);
#if HAVE_UTMPX_H
strncpy (utxent.ut_line, line, sizeof utxent.ut_line);
if ((utx = getutxline (&utxent)))
strncpy (utxent.ut_id, utx->ut_id, sizeof utxent.ut_id);
strcpy (utxent.ut_user, "LOGIN");
utxent.ut_pid = utent.ut_pid;
utxent.ut_type = utent.ut_type;
if (sizeof (utxent.ut_tv) == sizeof (struct timeval))
gettimeofday ((struct timeval *) &utxent.ut_tv, NULL);
else {
struct timeval tv;
gettimeofday (&tv, NULL);
utxent.ut_tv.tv_sec = tv.tv_sec;
utxent.ut_tv.tv_usec = tv.tv_usec;
}
utent.ut_time = utxent.ut_tv.tv_sec;
#endif
}
}
#endif
/*
* Some systems already have updwtmp() and possibly updwtmpx(). Others
* don't, so we re-implement these functions if necessary.
* don't, so we re-implement these functions if necessary. --marekm
*/
#ifndef HAVE_UPDWTMP
static void updwtmp (const char *filename, const struct utmp *ut)
{
@@ -146,7 +237,7 @@ static void updwtmp (const char *filename, const struct utmp *ut)
}
#endif /* ! HAVE_UPDWTMP */
#ifdef USE_UTMPX
#ifdef HAVE_UTMPX_H
#ifndef HAVE_UPDWTMPX
static void updwtmpx (const char *filename, const struct utmpx *utx)
{
@@ -159,297 +250,131 @@ static void updwtmpx (const char *filename, const struct utmpx *utx)
}
}
#endif /* ! HAVE_UPDWTMPX */
#endif /* ! USE_UTMPX */
#endif /* ! HAVE_UTMPX_H */
/*
* prepare_utmp - prepare an utmp entry so that it can be logged in a
* utmp/wtmp file.
* setutmp - put a USER_PROCESS entry in the utmp file
*
* It accepts an utmp entry in input (ut) to return an entry with
* the right ut_id. This is typically an entry returned by
* get_current_utmp
* If ut is NULL, ut_id will be forged based on the line argument.
*
* The ut_host field of the input structure may also be kept, and is
* used to define the ut_addr/ut_addr_v6 fields. (if these fields
* exist)
*
* Other fields are discarded and filed with new values (if they
* exist).
*
* The returned structure shall be freed by the caller.
* setutmp changes the type of the current utmp entry to
* USER_PROCESS. the wtmp file will be updated as well.
*/
/*@only@*/struct utmp *prepare_utmp (const char *name,
const char *line,
const char *host,
/*@null@*/const struct utmp *ut)
#if defined(__linux__) /* XXX */
void setutmp (const char *name, const char *line, const char *host)
{
struct timeval tv;
char *hostname = NULL;
struct utmp *utent;
assert (NULL != name);
assert (NULL != line);
if ( (NULL != host)
&& ('\0' != host[0])) {
hostname = (char *) xmalloc (strlen (host) + 1);
strcpy (hostname, host);
#ifdef HAVE_STRUCT_UTMP_UT_HOST
} else if ( (NULL != ut)
&& (NULL != ut->ut_host)
&& ('\0' != ut->ut_host[0])) {
hostname = (char *) xmalloc (sizeof (ut->ut_host) + 1);
strncpy (hostname, ut->ut_host, sizeof (ut->ut_host));
hostname[sizeof (ut->ut_host)] = '\0';
#endif /* HAVE_STRUCT_UTMP_UT_HOST */
}
if (strncmp(line, "/dev/", 5) == 0) {
line += 5;
}
utent = (struct utmp *) xmalloc (sizeof (*utent));
memzero (utent, sizeof (*utent));
#ifdef HAVE_STRUCT_UTMP_UT_TYPE
utent->ut_type = USER_PROCESS;
#endif /* HAVE_STRUCT_UTMP_UT_TYPE */
utent->ut_pid = getpid ();
strncpy (utent->ut_line, line, sizeof (utent->ut_line));
#ifdef HAVE_STRUCT_UTMP_UT_ID
if (NULL != ut) {
strncpy (utent->ut_id, ut->ut_id, sizeof (utent->ut_id));
} else {
/* XXX - assumes /dev/tty?? */
strncpy (utent->ut_id, line + 3, sizeof (utent->ut_id));
}
#endif /* HAVE_STRUCT_UTMP_UT_ID */
#ifdef HAVE_STRUCT_UTMP_UT_NAME
strncpy (utent->ut_name, name, sizeof (utent->ut_name));
#endif /* HAVE_STRUCT_UTMP_UT_NAME */
#ifdef HAVE_STRUCT_UTMP_UT_USER
strncpy (utent->ut_user, name, sizeof (utent->ut_user));
#endif /* HAVE_STRUCT_UTMP_UT_USER */
if (NULL != hostname) {
struct addrinfo *info = NULL;
#ifdef HAVE_STRUCT_UTMP_UT_HOST
strncpy (utent->ut_host, hostname, sizeof (utent->ut_host));
#endif /* HAVE_STRUCT_UTMP_UT_HOST */
#ifdef HAVE_STRUCT_UTMP_UT_SYSLEN
utent->ut_syslen = MIN (strlen (hostname),
sizeof (utent->ut_host));
#endif /* HAVE_STRUCT_UTMP_UT_SYSLEN */
#if defined(HAVE_STRUCT_UTMP_UT_ADDR) || defined(HAVE_STRUCT_UTMP_UT_ADDR_V6)
if (getaddrinfo (hostname, NULL, NULL, &info) == 0) {
/* getaddrinfo might not be reliable.
* Just try to log what may be useful.
*/
if (info->ai_family == AF_INET) {
struct sockaddr_in *sa =
(struct sockaddr_in *) info->ai_addr;
#ifdef HAVE_STRUCT_UTMP_UT_ADDR
memcpy (&(utent->ut_addr),
&(sa->sin_addr),
MIN (sizeof (utent->ut_addr),
sizeof (sa->sin_addr)));
#endif /* HAVE_STRUCT_UTMP_UT_ADDR */
#ifdef HAVE_STRUCT_UTMP_UT_ADDR_V6
memcpy (utent->ut_addr_v6,
&(sa->sin_addr),
MIN (sizeof (utent->ut_addr_v6),
sizeof (sa->sin_addr)));
} else if (info->ai_family == AF_INET6) {
struct sockaddr_in6 *sa =
(struct sockaddr_in6 *) info->ai_addr;
memcpy (utent->ut_addr_v6,
&(sa->sin6_addr),
MIN (sizeof (utent->ut_addr_v6),
sizeof (sa->sin6_addr)));
#endif /* HAVE_STRUCT_UTMP_UT_ADDR_V6 */
}
freeaddrinfo (info);
}
#endif /* HAVE_STRUCT_UTMP_UT_ADDR || HAVE_STRUCT_UTMP_UT_ADDR_V6 */
free (hostname);
}
/* ut_exit is only for DEAD_PROCESS */
utent->ut_session = getsid (0);
if (gettimeofday (&tv, NULL) == 0) {
#ifdef HAVE_STRUCT_UTMP_UT_TIME
utent->ut_time = tv.tv_sec;
#endif /* HAVE_STRUCT_UTMP_UT_TIME */
#ifdef HAVE_STRUCT_UTMP_UT_XTIME
utent->ut_xtime = tv.tv_usec;
#endif /* HAVE_STRUCT_UTMP_UT_XTIME */
#ifdef HAVE_STRUCT_UTMP_UT_TV
utent->ut_tv.tv_sec = tv.tv_sec;
utent->ut_tv.tv_usec = tv.tv_usec;
#endif /* HAVE_STRUCT_UTMP_UT_TV */
}
return utent;
}
/*
* setutmp - Update an entry in utmp and log an entry in wtmp
*
* Return 1 on failure and 0 on success.
*/
int setutmp (struct utmp *ut)
{
int err = 0;
assert (NULL != ut);
utent.ut_type = USER_PROCESS;
strncpy (utent.ut_user, name, sizeof utent.ut_user);
utent.ut_time = time (NULL);
/* other fields already filled in by checkutmp above */
setutent ();
if (pututline (ut) == NULL) {
err = 1;
}
pututline (&utent);
endutent ();
updwtmp (_WTMP_FILE, ut);
return err;
updwtmp (_WTMP_FILE, &utent);
}
#ifdef USE_UTMPX
/*
* prepare_utmpx - the UTMPX version for prepare_utmp
*/
/*@only@*/struct utmpx *prepare_utmpx (const char *name,
const char *line,
const char *host,
/*@null@*/const struct utmp *ut)
#elif HAVE_UTMPX_H
void setutmp (const char *name, const char *line, const char *host)
{
struct timeval tv;
char *hostname = NULL;
struct utmpx *utxent;
struct utmp *utmp, utline;
struct utmpx *utmpx, utxline;
pid_t pid = getpid ();
int found_utmpx = 0, found_utmp = 0;
assert (NULL != name);
assert (NULL != line);
/*
* The canonical device name doesn't include "/dev/"; skip it
* if it is already there.
*/
if ( (NULL != host)
&& ('\0' != host[0])) {
hostname = (char *) xmalloc (strlen (host) + 1);
strcpy (hostname, host);
#ifdef HAVE_STRUCT_UTMP_UT_HOST
} else if ( (NULL != ut)
&& (NULL != ut->ut_host)
&& ('\0' != ut->ut_host[0])) {
hostname = (char *) xmalloc (sizeof (ut->ut_host) + 1);
strncpy (hostname, ut->ut_host, sizeof (ut->ut_host));
hostname[sizeof (ut->ut_host)] = '\0';
#endif /* HAVE_STRUCT_UTMP_UT_TYPE */
}
if (strncmp(line, "/dev/", 5) == 0) {
if (strncmp (line, "/dev/", 5) == 0)
line += 5;
}
utxent = (struct utmpx *) xmalloc (sizeof (*utxent));
memzero (utxent, sizeof (*utxent));
utxent->ut_type = USER_PROCESS;
utxent->ut_pid = getpid ();
strncpy (utxent->ut_line, line, sizeof (utxent->ut_line));
/* existence of ut->ut_id is enforced by configure */
if (NULL != ut) {
strncpy (utxent->ut_id, ut->ut_id, sizeof (utxent->ut_id));
} else {
/* XXX - assumes /dev/tty?? */
strncpy (utxent->ut_id, line + 3, sizeof (utxent->ut_id));
}
#ifdef HAVE_STRUCT_UTMPX_UT_NAME
strncpy (utxent->ut_name, name, sizeof (utxent->ut_name));
#endif /* HAVE_STRUCT_UTMPX_UT_NAME */
strncpy (utxent->ut_user, name, sizeof (utxent->ut_user));
if (NULL != hostname) {
struct addrinfo *info = NULL;
#ifdef HAVE_STRUCT_UTMPX_UT_HOST
strncpy (utxent->ut_host, hostname, sizeof (utxent->ut_host));
#endif /* HAVE_STRUCT_UTMPX_UT_HOST */
#ifdef HAVE_STRUCT_UTMPX_UT_SYSLEN
utxent->ut_syslen = MIN (strlen (hostname),
sizeof (utxent->ut_host));
#endif /* HAVE_STRUCT_UTMPX_UT_SYSLEN */
#if defined(HAVE_STRUCT_UTMPX_UT_ADDR) || defined(HAVE_STRUCT_UTMPX_UT_ADDR_V6)
if (getaddrinfo (hostname, NULL, NULL, &info) == 0) {
/* getaddrinfo might not be reliable.
* Just try to log what may be useful.
*/
if (info->ai_family == AF_INET) {
struct sockaddr_in *sa =
(struct sockaddr_in *) info->ai_addr;
#ifdef HAVE_STRUCT_UTMPX_UT_ADDR
memcpy (utxent->ut_addr,
&(sa->sin_addr),
MIN (sizeof (utxent->ut_addr),
sizeof (sa->sin_addr)));
#endif /* HAVE_STRUCT_UTMPX_UT_ADDR */
#ifdef HAVE_STRUCT_UTMPX_UT_ADDR_V6
memcpy (utxent->ut_addr_v6,
&(sa->sin_addr),
MIN (sizeof (utxent->ut_addr_v6),
sizeof (sa->sin_addr)));
} else if (info->ai_family == AF_INET6) {
struct sockaddr_in6 *sa =
(struct sockaddr_in6 *) info->ai_addr;
memcpy (utxent->ut_addr_v6,
&(sa->sin6_addr),
MIN (sizeof (utxent->ut_addr_v6),
sizeof (sa->sin6_addr)));
#endif /* HAVE_STRUCT_UTMPX_UT_ADDR_V6 */
}
freeaddrinfo (info);
}
#endif /* HAVE_STRUCT_UTMPX_UT_ADDR || HAVE_STRUCT_UTMPX_UT_ADDR_V6 */
free (hostname);
}
/* ut_exit is only for DEAD_PROCESS */
utxent->ut_session = getsid (0);
if (gettimeofday (&tv, NULL) == 0) {
#ifdef HAVE_STRUCT_UTMPX_UT_TIME
utxent->ut_time = tv.tv_sec;
#endif /* HAVE_STRUCT_UTMPX_UT_TIME */
#ifdef HAVE_STRUCT_UTMPX_UT_XTIME
utxent->ut_xtime = tv.tv_usec;
#endif /* HAVE_STRUCT_UTMPX_UT_XTIME */
utxent->ut_tv.tv_sec = tv.tv_sec;
utxent->ut_tv.tv_usec = tv.tv_usec;
}
return utxent;
}
/*
* setutmpx - the UTMPX version for setutmp
*/
int setutmpx (struct utmpx *utx)
{
int err = 0;
assert (NULL != utx);
/*
* Update utmpx. We create an empty entry in case there is
* no matching entry in the utmpx file.
*/
setutxent ();
if (pututxline (utx) == NULL) {
err = 1;
setutent ();
while (utmpx = getutxent ()) {
if (utmpx->ut_pid == pid) {
found_utmpx = 1;
break;
}
}
while (utmp = getutent ()) {
if (utmp->ut_pid == pid) {
found_utmp = 1;
break;
}
}
endutxent ();
updwtmpx (_WTMP_FILE "x", utx);
/*
* If the entry matching `pid' cannot be found, create a new
* entry with the device name in it.
*/
return err;
if (!found_utmpx) {
memset ((void *) &utxline, 0, sizeof utxline);
strncpy (utxline.ut_line, line, sizeof utxline.ut_line);
utxline.ut_pid = getpid ();
} else {
utxline = *utmpx;
if (strncmp (utxline.ut_line, "/dev/", 5) == 0) {
memmove (utxline.ut_line, utxline.ut_line + 5,
sizeof utxline.ut_line - 5);
utxline.ut_line[sizeof utxline.ut_line - 5] = '\0';
}
}
if (!found_utmp) {
memset ((void *) &utline, 0, sizeof utline);
strncpy (utline.ut_line, utxline.ut_line,
sizeof utline.ut_line);
utline.ut_pid = utxline.ut_pid;
} else {
utline = *utmp;
if (strncmp (utline.ut_line, "/dev/", 5) == 0) {
memmove (utline.ut_line, utline.ut_line + 5,
sizeof utline.ut_line - 5);
utline.ut_line[sizeof utline.ut_line - 5] = '\0';
}
}
/*
* Fill in the fields in the utmpx entry and write it out. Do
* the utmp entry at the same time to make sure things don't
* get messed up.
*/
strncpy (utxline.ut_user, name, sizeof utxline.ut_user);
strncpy (utline.ut_user, name, sizeof utline.ut_user);
utline.ut_type = utxline.ut_type = USER_PROCESS;
if (sizeof (utxline.ut_tv) == sizeof (struct timeval))
gettimeofday ((struct timeval *) &utxline.ut_tv, NULL);
else {
struct timeval tv;
gettimeofday (&tv, NULL);
utxline.ut_tv.tv_sec = tv.tv_sec;
utxline.ut_tv.tv_usec = tv.tv_usec;
}
utline.ut_time = utxline.ut_tv.tv_sec;
strncpy (utxline.ut_host, host ? host : "", sizeof utxline.ut_host);
pututxline (&utxline);
pututline (&utline);
updwtmpx (_WTMP_FILE "x", &utxline);
updwtmp (_WTMP_FILE, &utline);
utxent = utxline;
utent = utline;
}
#endif /* USE_UTMPX */
#endif

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1993, Julianne Frances Haugh
* Copyright (c) 1996 - 1999, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2008, Nicolas François
* Copyright (c) 2007 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -49,7 +49,7 @@
* is used to indicate that a dummy salt must be used to encrypt the
* password anyway.
*/
bool valid (const char *password, const struct passwd *ent)
int valid (const char *password, const struct passwd *ent)
{
const char *encrypted;
const char *salt;
@@ -61,19 +61,18 @@ bool valid (const char *password, const struct passwd *ent)
* routine is meant to waste CPU time.
*/
if ((NULL != ent->pw_name) && ('\0' == ent->pw_passwd[0])) {
if ('\0' == password[0]) {
return true; /* user entered nothing */
} else {
return false; /* user entered something! */
}
if (ent->pw_name && !ent->pw_passwd[0]) {
if (!password[0])
return (1); /* user entered nothing */
else
return (0); /* user entered something! */
}
/*
* If there is no entry then we need a salt to use.
*/
if ((NULL == ent->pw_name) || ('\0' == ent->pw_passwd[0])) {
if (ent->pw_name == (char *) 0 || ent->pw_passwd[0] == '\0') {
salt = "xx";
} else {
salt = ent->pw_passwd;
@@ -94,11 +93,9 @@ bool valid (const char *password, const struct passwd *ent)
* cause non-existent users to not be validated.
*/
if ( (NULL != ent->pw_name)
&& (strcmp (encrypted, ent->pw_passwd) == 0)) {
return true;
} else {
return false;
}
if (ent->pw_name && strcmp (encrypted, ent->pw_passwd) == 0)
return (1);
else
return (0);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007 - 2009, Nicolas François
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -52,7 +52,7 @@
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <config.h>
#include "prototypes.h"
#define XFUNCTION_NAME XPREFIX (FUNCTION_NAME)
@@ -64,7 +64,7 @@
#define STRINGIZE(name) STRINGIZE1 (name)
#define STRINGIZE1(name) #name
/*@null@*/ /*@only@*/LOOKUP_TYPE *XFUNCTION_NAME (ARG_TYPE ARG_NAME)
LOOKUP_TYPE *XFUNCTION_NAME (ARG_TYPE ARG_NAME)
{
#if HAVE_FUNCTION_R
LOOKUP_TYPE *result=NULL;
@@ -79,7 +79,7 @@
exit (13);
}
while (true) {
do {
int status;
LOOKUP_TYPE *resbuf = NULL;
buffer = (char *)realloc (buffer, length);
@@ -91,7 +91,7 @@
errno = 0;
status = REENTRANT_NAME(ARG_NAME, result, buffer,
length, &resbuf);
if ((0 ==status) && (resbuf == result)) {
if (!status && (resbuf == result)) {
/* Build a result structure that can be freed by
* the shadow *_free functions. */
LOOKUP_TYPE *ret_result = DUP_FUNCTION(result);
@@ -106,14 +106,8 @@
return NULL;
}
if (length <= ((size_t)-1 / 4)) {
length *= 4;
} else if (length == (size_t) -1) {
break;
} else {
length = (size_t) -1;
}
}
length *= 4;
} while (length < MAX_LENGTH);
free(buffer);
free(result);

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