Compare commits

..

No commits in common. "master" and "4.18.0" have entirely different histories.

496 changed files with 10780 additions and 15270 deletions

View File

@ -22,5 +22,5 @@ runs:
sudo apt-mark hold grub-efi-amd64-bin grub-efi-amd64-signed
sudo apt-get update
sudo apt-get -y dist-upgrade
sudo apt-get -y install ubuntu-dev-tools automake autopoint xsltproc gettext expect libtool libbsd-dev libltdl-dev libsystemd-dev pkgconf
sudo apt-get -y install ubuntu-dev-tools automake autopoint xsltproc gettext expect libtool libbsd-dev libltdl-dev pkgconf
sudo apt-get -y build-dep shadow

View File

@ -10,10 +10,7 @@ on:
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, ubuntu-22.04]
runs-on: ${{ matrix.os }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: debug
@ -65,7 +62,7 @@ jobs:
tar -zxf $f
d=$(basename $f .tar.gz)
cd $d
./configure --disable-logind
./configure
make -j5
make check

View File

@ -56,49 +56,3 @@ jobs:
with:
severity: warning
token: ${{ secrets.GITHUB_TOKEN }}
python-linter:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/setup-python@v5
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup virtual environment
working-directory: ./tests/system
run: |
sudo apt-get update
pip3 install virtualenv
python3 -m venv .venv
source .venv/bin/activate
pip3 install -r ./requirements.txt
pip3 install flake8 pycodestyle isort mypy black
- name: flake8
if: always()
working-directory: ./tests/system
run: source .venv/bin/activate && flake8 .
- name: pycodestyle
if: always()
working-directory: ./tests/system
run: source .venv/bin/activate && pycodestyle .
- name: isort
if: always()
working-directory: ./tests/system
run: source .venv/bin/activate && isort --check-only .
- name: black
if: always()
working-directory: ./tests/system
run: source .venv/bin/activate && black --check --diff .
- name: mypy
if: always()
working-directory: ./tests/system
run: source .venv/bin/activate && mypy --install-types --non-interactive tests

10
.gitignore vendored
View File

@ -21,16 +21,24 @@ test-driver
/ABOUT-NLS
/aclocal.m4
/autom4te.cache
/compile
/config.cache
/config.guess
/config.h
/config.h.in
/config.log
/config.rpath
/config.status
/config.sub
/configure
/depcomp
/install-sh
/libtool
/ltmain.sh
/m4
/build-aux/
/missing
/stamp-h1
/test-driver
/ylwrap
/po/*.header

View File

@ -1,5 +1,4 @@
## Process this file with automake to produce Makefile.in
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = lib

View File

@ -5,21 +5,12 @@ autoreconf -v -f --install "$(dirname "$0")" || exit 1
CFLAGS="-O2"
CFLAGS="$CFLAGS -Wall"
CFLAGS="$CFLAGS -Wextra"
CFLAGS="$CFLAGS -Werror=discarded-qualifiers"
CFLAGS="$CFLAGS -Werror=implicit-function-declaration"
CFLAGS="$CFLAGS -Werror=implicit-int"
CFLAGS="$CFLAGS -Werror=incompatible-pointer-types"
CFLAGS="$CFLAGS -Werror=int-conversion"
CFLAGS="$CFLAGS -Werror=sign-compare"
CFLAGS="$CFLAGS -Werror=sizeof-pointer-div"
CFLAGS="$CFLAGS -Werror=unused-but-set-parameter"
CFLAGS="$CFLAGS -Werror=unused-function"
CFLAGS="$CFLAGS -Werror=unused-label"
CFLAGS="$CFLAGS -Werror=unused-local-typedefs"
CFLAGS="$CFLAGS -Werror=unused-parameter"
CFLAGS="$CFLAGS -Werror=unused-variable"
CFLAGS="$CFLAGS -Werror=unused-const-variable=1"
CFLAGS="$CFLAGS -Werror=unused-value"
CFLAGS="$CFLAGS -Wno-expansion-to-defined"
CFLAGS="$CFLAGS -Wno-unknown-attributes"
CFLAGS="$CFLAGS -Wno-unknown-warning-option"
@ -27,7 +18,6 @@ CFLAGS="$CFLAGS -Wno-unknown-warning-option"
"$(dirname "$0")"/configure \
CFLAGS="$CFLAGS" \
--enable-lastlog \
--disable-logind \
--enable-man \
--enable-maintainer-mode \
--enable-shared \

View File

@ -1,20 +1,15 @@
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
m4_define([libsubid_abi_major], [5])
m4_define([libsubid_abi_minor], [0])
m4_define([libsubid_abi_micro], [0])
m4_define([libsubid_abi_major], 5)
m4_define([libsubid_abi_minor], 0)
m4_define([libsubid_abi_micro], 0)
m4_define([libsubid_abi], [libsubid_abi_major.libsubid_abi_minor.libsubid_abi_micro])
AC_INIT([shadow], [4.19.0], [pkg-shadow-devel@lists.alioth.debian.org], [],
AC_INIT([shadow], [4.18.0], [pkg-shadow-devel@lists.alioth.debian.org], [],
[https://github.com/shadow-maint/shadow])
AC_CONFIG_MACRO_DIRS([m4])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects tar-pax])
AC_CONFIG_MACRO_DIRS([m4])
AM_SILENT_RULES([yes])
AC_SUBST([AM_DISTCHECK_CONFIGURE_FLAGS], ["$ac_configure_args"])
AC_CONFIG_HEADERS([config.h])
AC_SUBST([LIBSUBID_ABI_MAJOR], [libsubid_abi_major])
AC_SUBST([LIBSUBID_ABI_MINOR], [libsubid_abi_minor])
@ -22,8 +17,8 @@ AC_SUBST([LIBSUBID_ABI_MICRO], [libsubid_abi_micro])
AC_SUBST([LIBSUBID_ABI], [libsubid_abi])
dnl Some hacks...
test "x$prefix" = "xNONE" && prefix="/usr"
test "X$prefix" = "X/usr" && exec_prefix=""
test "$prefix" = "NONE" && prefix="/usr"
test "$prefix" = "/usr" && exec_prefix=""
AC_USE_SYSTEM_EXTENSIONS
@ -41,15 +36,15 @@ LT_LIB_DLLOAD
dnl Checks for libraries.
dnl shadow now uses the libc's shadow implementation
AC_CHECK_HEADER([shadow.h],[],[AC_MSG_ERROR([You need a libc with shadow.h])])
AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])])
AC_CHECK_FUNCS([arc4random_buf \
AC_CHECK_FUNCS(arc4random_buf \
getentropy getrandom \
lckpwdf lutimes \
updwtmpx innetgr \
getspnam_r \
rpmatch \
memset_explicit explicit_bzero stpecpy stpeprintf])
memset_explicit explicit_bzero stpecpy stpeprintf)
AC_SYS_LARGEFILE
dnl Checks for typedefs, structures, and compiler characteristics.
@ -60,230 +55,227 @@ AC_CHECK_MEMBERS([struct utmpx.ut_name,
struct utmpx.ut_addr,
struct utmpx.ut_addr_v6,
struct utmpx.ut_time,
struct utmpx.ut_xtime],[],[],[[#include <utmpx.h>]])
struct utmpx.ut_xtime],,,[[#include <utmpx.h>]])
dnl Checks for library functions.
AC_FUNC_UTIME_NULL
AC_REPLACE_FUNCS([putgrent putpwent putspent])
AC_REPLACE_FUNCS([sgetgrent sgetpwent sgetspent])
AC_REPLACE_FUNCS(putgrent putpwent putspent)
AC_REPLACE_FUNCS(sgetgrent sgetpwent sgetspent)
AC_CHECK_FUNC([setpgrp])
AC_CHECK_FUNC([secure_getenv],
[AC_DEFINE([HAS_SECURE_GETENV],[1],[Defined to 1 if you have the declaration of 'secure_getenv'])]
)
AC_CHECK_FUNC(setpgrp)
AC_CHECK_FUNC(secure_getenv, [AC_DEFINE(HAS_SECURE_GETENV,
1,
[Defined to 1 if you have the declaration of 'secure_getenv'])])
AC_CACHE_CHECK([location of shared mail directory], [shadow_cv_maildir],
AC_CACHE_CHECK([location of shared mail directory], shadow_cv_maildir,
[for shadow_cv_maildir in /var/mail /var/spool/mail /usr/spool/mail /usr/mail none; do
if test -d $shadow_cv_maildir; then
break
fi
done])
if test $shadow_cv_maildir != none; then
AC_DEFINE_UNQUOTED([MAIL_SPOOL_DIR], ["$shadow_cv_maildir"],
AC_DEFINE_UNQUOTED(MAIL_SPOOL_DIR, "$shadow_cv_maildir",
[Location of system mail spool directory.])
fi
AC_CACHE_CHECK([location of user mail file], [shadow_cv_mailfile],
AC_CACHE_CHECK([location of user mail file], shadow_cv_mailfile,
[for shadow_cv_mailfile in Mailbox mailbox Mail mail .mail none; do
if test -f $HOME/$shadow_cv_mailfile; then
break
fi
done])
if test $shadow_cv_mailfile != none; then
AC_DEFINE_UNQUOTED([MAIL_SPOOL_FILE], ["$shadow_cv_mailfile"],
AC_DEFINE_UNQUOTED(MAIL_SPOOL_FILE, "$shadow_cv_mailfile",
[Name of user's mail spool file if stored in user's home directory.])
fi
AC_CACHE_CHECK([location of faillog/lastlog/wtmp], [shadow_cv_logdir],
AC_CACHE_CHECK([location of faillog/lastlog/wtmp], shadow_cv_logdir,
[for shadow_cv_logdir in /var/log /var/adm /usr/adm /etc; do
if test -d $shadow_cv_logdir; then
break
fi
done])
AC_DEFINE_UNQUOTED([FAILLOG_FILE], ["$shadow_cv_logdir/faillog"],
AC_DEFINE_UNQUOTED(_WTMP_FILE, "$shadow_cv_logdir/wtmp",
[Path for wtmp file.])
AC_DEFINE_UNQUOTED(LASTLOG_FILE, "$shadow_cv_logdir/lastlog",
[Path for lastlog file.])
AC_DEFINE_UNQUOTED(FAILLOG_FILE, "$shadow_cv_logdir/faillog",
[Path for faillog file.])
AC_DEFINE_UNQUOTED([PASSWD_PROGRAM], ["$exec_prefix/bin/passwd"],
AC_DEFINE_UNQUOTED(PASSWD_PROGRAM, "$exec_prefix/bin/passwd",
[Path to passwd program.])
AC_ARG_ENABLE([shadowgrp],
AC_ARG_ENABLE(shadowgrp,
[AS_HELP_STRING([--enable-shadowgrp], [enable shadow group support @<:@default=yes@:>@])],
[case "${enableval}" in
yes) enable_shadowgrp="yes" ;;
no) enable_shadowgrp="no" ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-shadowgrp]) ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-shadowgrp) ;;
esac],
[enable_shadowgrp="yes"]
)
AC_ARG_ENABLE([man],
AC_ARG_ENABLE(man,
[AS_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_ARG_ENABLE(account-tools-setuid,
[AS_HELP_STRING([--enable-account-tools-setuid],
[Install the user and group management tools setuid and authenticate the callers. This requires --with-libpam.])],
[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])
*) AC_MSG_ERROR(bad value ${enableval} for --enable-account-tools-setuid)
;;
esac],
[enable_acct_tools_setuid="no"]
)
AC_ARG_ENABLE([subordinate-ids],
AC_ARG_ENABLE(subordinate-ids,
[AS_HELP_STRING([--enable-subordinate-ids],
[support subordinate ids @<:@default=yes@:>@])],
[enable_subids="${enableval}"],
[enable_subids="maybe"]
)
AC_ARG_ENABLE([lastlog],
AC_ARG_ENABLE(lastlog,
[AS_HELP_STRING([--enable-lastlog],
[enable lastlog @<:@default=no@:>@])],
[enable_lastlog="${enableval}"],
[enable_lastlog="no"]
)
AC_ARG_ENABLE([logind],
[AS_HELP_STRING([--disable-logind],
[disable logind integration])],
[
AS_CASE([${enableval}],
[yes],[],
[no],[],
[AC_MSG_ERROR([bad parameter value for --enable-logind=${enableval}. ]dnl
[Supported values are: --enable-logind (or --enable-logind=yes) and --disable-logind (or --enable-logind=no).])]
)
],
AC_ARG_ENABLE(logind,
[AS_HELP_STRING([--enable-logind],
[enable logind @<:@default=yes@:>@])],
[enable_logind="${enableval}"],
[enable_logind="yes"]
)
AC_ARG_WITH([audit],
AC_ARG_WITH(audit,
[AS_HELP_STRING([--with-audit], [use auditing support @<:@default=yes if found@:>@])],
[with_audit=$withval], [with_audit=maybe])
AC_ARG_WITH([libpam],
AC_ARG_WITH(libpam,
[AS_HELP_STRING([--with-libpam], [use libpam for PAM support @<:@default=yes if found@:>@])],
[with_libpam=$withval], [with_libpam=maybe])
AC_ARG_WITH([btrfs],
AC_ARG_WITH(btrfs,
[AS_HELP_STRING([--with-btrfs], [add BtrFS support @<:@default=yes if found@:>@])],
[with_btrfs=$withval], [with_btrfs=maybe])
AC_ARG_WITH([selinux],
AC_ARG_WITH(selinux,
[AS_HELP_STRING([--with-selinux], [use SELinux support @<:@default=yes if found@:>@])],
[with_selinux=$withval], [with_selinux=maybe])
AC_ARG_WITH([acl],
AC_ARG_WITH(acl,
[AS_HELP_STRING([--with-acl], [use ACL support @<:@default=yes if found@:>@])],
[with_acl=$withval], [with_acl=maybe])
AC_ARG_WITH([attr],
AC_ARG_WITH(attr,
[AS_HELP_STRING([--with-attr], [use Extended Attribute support @<:@default=yes if found@:>@])],
[with_attr=$withval], [with_attr=maybe])
AC_ARG_WITH([skey],
AC_ARG_WITH(skey,
[AS_HELP_STRING([--with-skey], [use S/Key support @<:@default=no@:>@])],
[with_skey=$withval], [with_skey=no])
AC_ARG_WITH([tcb],
AC_ARG_WITH(tcb,
[AS_HELP_STRING([--with-tcb], [use tcb support (incomplete) @<:@default=yes if found@:>@])],
[with_tcb=$withval], [with_tcb=maybe])
AC_ARG_WITH([sha-crypt],
AC_ARG_WITH(sha-crypt,
[AS_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([bcrypt],
AC_ARG_WITH(bcrypt,
[AS_HELP_STRING([--with-bcrypt], [allow the bcrypt password encryption algorithm @<:@default=no@:>@])],
[with_bcrypt=$withval], [with_bcrypt=no])
AC_ARG_WITH([yescrypt],
AC_ARG_WITH(yescrypt,
[AS_HELP_STRING([--with-yescrypt], [allow the yescrypt password encryption algorithm @<:@default=no@:>@])],
[with_yescrypt=$withval], [with_yescrypt=no])
AC_ARG_WITH([nscd],
AC_ARG_WITH(nscd,
[AS_HELP_STRING([--with-nscd], [enable support for nscd @<:@default=yes@:>@])],
[with_nscd=$withval], [with_nscd=yes])
AC_ARG_WITH([sssd],
AC_ARG_WITH(sssd,
[AS_HELP_STRING([--with-sssd], [enable support for flushing sssd caches @<:@default=yes@:>@])],
[with_sssd=$withval], [with_sssd=yes])
AC_ARG_WITH([group-name-max-length],
AC_ARG_WITH(group-name-max-length,
[AS_HELP_STRING([--with-group-name-max-length], [set max group name length @<:@default=32@:>@])],
[with_group_name_max_length=$withval], [with_group_name_max_length=yes])
AC_ARG_WITH([su],
AC_ARG_WITH(su,
[AS_HELP_STRING([--with-su], [build and install su program and man page @<:@default=yes@:>@])],
[with_su=$withval], [with_su=yes])
AC_ARG_WITH([libbsd],
AC_ARG_WITH(libbsd,
[AS_HELP_STRING([--with-libbsd], [use libbsd support @<:@default=yes if found@:>@])],
[with_libbsd=$withval], [with_libbsd=yes])
if test "X$with_group_name_max_length" = "Xno" ; then
if test "$with_group_name_max_length" = "no" ; then
with_group_name_max_length=0
elif test "X$with_group_name_max_length" = "Xyes" ; then
elif test "$with_group_name_max_length" = "yes" ; then
with_group_name_max_length=32
fi
AC_DEFINE_UNQUOTED([GROUP_NAME_MAX_LENGTH], [$with_group_name_max_length], [max group name length])
AC_SUBST([GROUP_NAME_MAX_LENGTH])
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 "X$with_sha_crypt" = "Xyes"; then
AC_DEFINE([USE_SHA_CRYPT], [1], [Define to allow the SHA256 and SHA512 password encryption algorithms])
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
AM_CONDITIONAL([USE_BCRYPT], [test "x$with_bcrypt" = "xyes"])
if test "X$with_bcrypt" = "Xyes"; then
AC_DEFINE([USE_BCRYPT], [1], [Define to allow the bcrypt password encryption algorithm])
AM_CONDITIONAL(USE_BCRYPT, test "x$with_bcrypt" = "xyes")
if test "$with_bcrypt" = "yes"; then
AC_DEFINE(USE_BCRYPT, 1, [Define to allow the bcrypt password encryption algorithm])
fi
AM_CONDITIONAL([USE_YESCRYPT], [test "x$with_yescrypt" = "xyes"])
if test "X$with_yescrypt" = "Xyes"; then
AC_DEFINE([USE_YESCRYPT], [1], [Define to allow the yescrypt password encryption algorithm])
AM_CONDITIONAL(USE_YESCRYPT, test "x$with_yescrypt" = "xyes")
if test "$with_yescrypt" = "yes"; then
AC_DEFINE(USE_YESCRYPT, 1, [Define to allow the yescrypt password encryption algorithm])
fi
if test "X$with_nscd" = "Xyes"; then
AC_CHECK_FUNC([posix_spawn],
[AC_DEFINE([USE_NSCD], [1], [Define to support flushing of nscd caches])],
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])])
fi
if test "X$with_sssd" = "Xyes"; then
AC_CHECK_FUNC([posix_spawn],
[AC_DEFINE([USE_SSSD], [1], [Define to support flushing of sssd caches])],
if test "$with_sssd" = "yes"; then
AC_CHECK_FUNC(posix_spawn,
[AC_DEFINE(USE_SSSD, 1, [Define to support flushing of sssd caches])],
[AC_MSG_ERROR([posix_spawn is needed for sssd support])])
fi
AS_IF([test "$with_su" != "no"], [AC_DEFINE([WITH_SU], [1], [Build with su])])
AS_IF([test "$with_su" != "no"], AC_DEFINE(WITH_SU, 1, [Build with su]))
AM_CONDITIONAL([WITH_SU], [test "x$with_su" != "xno"])
dnl Check for some functions in libc first, only if not found check for
dnl other libraries. This should prevent linking libnsl if not really
dnl needed (Linux glibc, Irix), but still link it if needed (Solaris).
AC_SEARCH_LIBS([gethostbyname], [nsl])
AC_SEARCH_LIBS(gethostbyname, nsl)
PKG_CHECK_MODULES([CMOCKA], [cmocka], [have_cmocka="yes"],
[AC_MSG_WARN([libcmocka not found, cmocka tests will not be built])])
AM_CONDITIONAL([HAVE_CMOCKA], [test x$have_cmocka = xyes])
AC_ARG_ENABLE([vendordir],
[AS_HELP_STRING([--enable-vendordir=DIR], [Directory for distribution provided configuration files])],[],[])
AC_CHECK_LIB([econf],[econf_readDirs],[LIBECONF="-leconf"],[LIBECONF=""])
if test -n "$LIBECONF"; then
AC_DEFINE_UNQUOTED([VENDORDIR], ["$enable_vendordir"],
[Directory for distribution provided configuration files])
ECONF_CPPFLAGS="-DUSE_ECONF=1"
AC_ARG_ENABLE([vendordir],
AS_HELP_STRING([--enable-vendordir=DIR], [Directory for distribution provided configuration files]),,[])
fi
AC_SUBST([ECONF_CPPFLAGS])
AC_SUBST([LIBECONF])
AC_SUBST(ECONF_CPPFLAGS)
AC_SUBST(LIBECONF)
AC_SUBST([VENDORDIR], [$enable_vendordir])
if test "x$enable_vendordir" != x; then
AC_DEFINE([HAVE_VENDORDIR], [1], [Define to support vendor settings.])
AC_DEFINE(HAVE_VENDORDIR, 1, [Define to support vendor settings.])
fi
AM_CONDITIONAL([HAVE_VENDORDIR], [test "x$enable_vendordir" != x])
if test "X$enable_shadowgrp" = "Xyes"; then
AC_DEFINE([SHADOWGRP], [1], [Define to support the shadow group file.])
if test "$enable_shadowgrp" = "yes"; then
AC_DEFINE(SHADOWGRP, 1, [Define to support the shadow group file.])
fi
AM_CONDITIONAL([SHADOWGRP], [test "x$enable_shadowgrp" = "xyes"])
AM_CONDITIONAL(SHADOWGRP, test "x$enable_shadowgrp" = "xyes")
if test "X$enable_man" = "Xyes"; then
if test "$enable_man" = "yes"; then
dnl
dnl Check for xsltproc
dnl
@ -295,21 +287,21 @@ if test "X$enable_man" = "Xyes"; then
dnl check for DocBook DTD and stylesheets in the local catalog.
JH_CHECK_XML_CATALOG([-//OASIS//DTD DocBook XML V4.5//EN],
[DocBook XML DTD V4.5], [], [enable_man=no])
[DocBook XML DTD V4.5], [], enable_man=no)
JH_CHECK_XML_CATALOG([http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl],
[DocBook XSL Stylesheets >= 1.70.1], [], [enable_man=no])
[DocBook XSL Stylesheets >= 1.70.1], [], enable_man=no)
fi
AM_CONDITIONAL([ENABLE_REGENERATE_MAN], [test "x$enable_man" != "xno"])
AM_CONDITIONAL(ENABLE_REGENERATE_MAN, test "x$enable_man" != "xno")
if test "$enable_subids" != "no"; then
dnl
dnl FIXME: check if 32 bit UIDs/GIDs are supported by libc
dnl
AC_CHECK_SIZEOF([uid_t],[], [[#include "sys/types.h"]])
AC_CHECK_SIZEOF([gid_t],[], [[#include "sys/types.h"]])
AC_CHECK_SIZEOF([uid_t],, [#include "sys/types.h"])
AC_CHECK_SIZEOF([gid_t],, [#include "sys/types.h"])
if test "$ac_cv_sizeof_uid_t" -ge 4 && test "$ac_cv_sizeof_gid_t" -ge 4; then
AC_DEFINE([ENABLE_SUBIDS], [1], [Define to support the subordinate IDs.])
AC_DEFINE(ENABLE_SUBIDS, 1, [Define to support the subordinate IDs.])
enable_subids="yes"
else
if test "x$enable_subids" = "xyes"; then
@ -318,54 +310,55 @@ if test "$enable_subids" != "no"; then
enable_subids="no"
fi
fi
AM_CONDITIONAL([ENABLE_SUBIDS], [test "x$enable_subids" != "xno"])
AM_CONDITIONAL(ENABLE_SUBIDS, test "x$enable_subids" != "xno")
if test "X$enable_lastlog" = "Xyes" && test "X$ac_cv_header_lastlog_h" = "Xyes"; then
AC_CACHE_CHECK([for ll_host in struct lastlog],
[ac_cv_struct_lastlog_ll_host],
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <lastlog.h>]],
[struct lastlog ll; char *cp = ll.ll_host;])],
if test "$enable_lastlog" = "yes" && test "$ac_cv_header_lastlog_h" = "yes"; then
AC_CACHE_CHECK(for ll_host in struct lastlog,
ac_cv_struct_lastlog_ll_host,
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <lastlog.h>],
[struct lastlog ll; char *cp = ll.ll_host;]
)],
[ac_cv_struct_lastlog_ll_host=yes],
[ac_cv_struct_lastlog_ll_host=no])
]
[ac_cv_struct_lastlog_ll_host=no]
)
)
if test "X$ac_cv_struct_lastlog_ll_host" = "Xyes"; then
AC_DEFINE([HAVE_LL_HOST], [1],
if test "$ac_cv_struct_lastlog_ll_host" = "yes"; then
AC_DEFINE(HAVE_LL_HOST, 1,
[Define if struct lastlog has ll_host])
AC_DEFINE([ENABLE_LASTLOG], [1], [Define to support lastlog.])
AC_DEFINE(ENABLE_LASTLOG, 1, [Define to support lastlog.])
enable_lastlog="yes"
else
AC_MSG_ERROR([Cannot enable support for lastlog on systems where the data structures aren't available])
enable_lastlog="no"
fi
fi
AM_CONDITIONAL([ENABLE_LASTLOG], [test "x$enable_lastlog" != "xno"])
AM_CONDITIONAL(ENABLE_LASTLOG, test "x$enable_lastlog" != "xno")
AC_SUBST([LIBSYSTEMD])
if test "X$enable_logind" = "Xyes"; then
AC_CHECK_LIB([systemd], [sd_session_get_remote_host],
[
LIBSYSTEMD=-lsystemd
AC_DEFINE([ENABLE_LOGIND], [1], [Define to manage session support with logind.])
],[
AC_MSG_ERROR([libsystemd not found. If logind integration is not required, disable it using the --disable-logind option. ]dnl
[ If logind integration is required, consider installing systemd or another package that provides libsystemd.])
]
)
AC_SUBST(LIBSYSTEMD)
if test "$enable_logind" = "yes"; then
AC_CHECK_LIB(systemd, sd_session_get_remote_host,
[enable_logind="yes"; [LIBSYSTEMD=-lsystemd];
AC_DEFINE(ENABLE_LOGIND, 1,
[Define to manage session support with logind.])],
[enable_logind="no"])
fi
AM_CONDITIONAL([ENABLE_LOGIND], [test "X$enable_logind" = "Xyes"])
AM_CONDITIONAL(ENABLE_LOGIND, test "x$enable_logind" != "xno")
AC_CHECK_LIB([crypt], [crypt], [LIBCRYPT=-lcrypt],
AC_SUBST(LIBCRYPT)
AC_CHECK_LIB(crypt, crypt, [LIBCRYPT=-lcrypt],
[AC_MSG_ERROR([crypt() not found])])
AC_SUBST([LIBCRYPT])
AC_SUBST([LIBBSD])
AC_SUBST(LIYESCRYPT)
AC_CHECK_LIB(crypt, crypt, [LIYESCRYPT=-lcrypt],
[AC_MSG_ERROR([crypt() not found])])
AC_SUBST(LIBBSD)
if test "$with_libbsd" != "no"; then
AC_SEARCH_LIBS([readpassphrase], [bsd], [], [
AC_MSG_ERROR([readpassphrase() is missing, either from libc or libbsd])
])
AS_IF([test "X$ac_cv_search_readpassphrase" = "X-lbsd"], [
AS_IF([test "$ac_cv_search_readpassphrase" = "-lbsd"], [
PKG_CHECK_MODULES([LIBBSD], [libbsd-overlay])
])
dnl Make sure either the libc or libbsd provide the header.
@ -376,29 +369,29 @@ if test "$with_libbsd" != "no"; then
AC_MSG_ERROR([readpassphrase.h is missing])
])
CFLAGS="$save_CFLAGS"
AC_DEFINE([WITH_LIBBSD], [1], [Build shadow with libbsd support])
AC_DEFINE(WITH_LIBBSD, 1, [Build shadow with libbsd support])
else
AC_DEFINE([WITH_LIBBSD], [0], [Build shadow without libbsd support])
AC_DEFINE(WITH_LIBBSD, 0, [Build shadow without libbsd support])
fi
AM_CONDITIONAL([WITH_LIBBSD], [test x$with_libbsd = xyes])
AM_CONDITIONAL(WITH_LIBBSD, test x$with_libbsd = xyes)
AC_SUBST([LIBACL])
AC_SUBST(LIBACL)
if test "$with_acl" != "no"; then
AC_CHECK_HEADERS([acl/libacl.h attr/error_context.h], [acl_header="yes"], [acl_header="no"])
if test "X$acl_header$with_acl" = "Xnoyes" ; then
AC_CHECK_HEADERS(acl/libacl.h attr/error_context.h, [acl_header="yes"], [acl_header="no"])
if test "$acl_header$with_acl" = "noyes" ; then
AC_MSG_ERROR([acl/libacl.h or attr/error_context.h is missing])
elif test "X$acl_header" = "Xyes" ; then
AC_CHECK_LIB([acl], [perm_copy_file],
[AC_CHECK_LIB([acl], [perm_copy_fd],
elif test "$acl_header" = "yes" ; then
AC_CHECK_LIB(acl, perm_copy_file,
[AC_CHECK_LIB(acl, perm_copy_fd,
[acl_lib="yes"],
[acl_lib="no"])],
[acl_lib="no"])
if test "X$acl_lib$with_acl" = "Xnoyes" ; then
if test "$acl_lib$with_acl" = "noyes" ; then
AC_MSG_ERROR([libacl not found])
elif test "X$acl_lib" = "Xno" ; then
elif test "$acl_lib" = "no" ; then
with_acl="no"
else
AC_DEFINE([WITH_ACL], [1],
AC_DEFINE(WITH_ACL, 1,
[Build shadow with ACL support])
LIBACL="-lacl"
with_acl="yes"
@ -408,29 +401,55 @@ if test "$with_acl" != "no"; then
fi
fi
AC_SUBST([LIBAUDIT])
AC_SUBST(LIBATTR)
if test "$with_attr" != "no"; then
AC_CHECK_HEADERS(attr/libattr.h attr/error_context.h, [attr_header="yes"], [attr_header="no"])
if test "$attr_header$with_attr" = "noyes" ; then
AC_MSG_ERROR([attr/libattr.h or attr/error_context.h is missing])
elif test "$attr_header" = "yes" ; then
AC_CHECK_LIB(attr, attr_copy_file,
[AC_CHECK_LIB(attr, attr_copy_fd,
[attr_lib="yes"],
[attr_lib="no"])],
[attr_lib="no"])
if test "$attr_lib$with_attr" = "noyes" ; then
AC_MSG_ERROR([libattr not found])
elif test "$attr_lib" = "no" ; then
with_attr="no"
else
AC_DEFINE(WITH_ATTR, 1,
[Build shadow with Extended Attributes support])
LIBATTR="-lattr"
with_attr="yes"
fi
else
with_attr="no"
fi
fi
AC_SUBST(LIBAUDIT)
if test "$with_audit" != "no"; then
AC_CHECK_HEADER([libaudit.h], [audit_header="yes"], [audit_header="no"])
if test "X$audit_header$with_audit" = "Xnoyes" ; then
AC_CHECK_HEADER(libaudit.h, [audit_header="yes"], [audit_header="no"])
if test "$audit_header$with_audit" = "noyes" ; then
AC_MSG_ERROR([libaudit.h is missing])
elif test "X$audit_header" = "Xyes"; 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 "X$audit_header$with_audit" = "Xnoyes" ; then
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 "X$audit_header" = "Xyes"; then
AC_CHECK_LIB([audit], [audit_log_acct_message],
if test "$audit_header" = "yes"; then
AC_CHECK_LIB(audit, audit_log_acct_message,
[audit_lib="yes"], [audit_lib="no"])
if test "X$audit_lib$with_audit" = "Xnoyes" ; then
if test "$audit_lib$with_audit" = "noyes" ; then
AC_MSG_ERROR([libaudit not found])
elif test "X$audit_lib" = "Xno" ; then
elif test "$audit_lib" = "no" ; then
with_audit="no"
else
AC_DEFINE([WITH_AUDIT], [1],
AC_DEFINE(WITH_AUDIT, 1,
[Define if you want to enable Audit messages])
LIBAUDIT="-laudit"
with_audit="yes"
@ -443,43 +462,43 @@ fi
if test "$with_btrfs" != "no"; then
AC_CHECK_HEADERS([sys/statfs.h linux/magic.h linux/btrfs_tree.h], \
[btrfs_headers="yes"], [btrfs_headers="no"])
if test "X$btrfs_headers$with_btrfs" = "Xnoyes" ; then
if test "$btrfs_headers$with_btrfs" = "noyes" ; then
AC_MSG_ERROR([One of sys/statfs.h linux/magic.h linux/btrfs_tree.h is missing])
fi
if test "X$btrfs_headers" = "Xyes" ; then
AC_DEFINE([WITH_BTRFS], [1], [Build shadow with BtrFS support])
if test "$btrfs_headers" = "yes" ; then
AC_DEFINE(WITH_BTRFS, 1, [Build shadow with BtrFS support])
with_btrfs="yes"
fi
fi
AM_CONDITIONAL([WITH_BTRFS], [test x$with_btrfs = xyes])
AM_CONDITIONAL(WITH_BTRFS, test x$with_btrfs = xyes)
AC_SUBST([LIBSELINUX])
AC_SUBST([LIBSEMANAGE])
AC_SUBST(LIBSELINUX)
AC_SUBST(LIBSEMANAGE)
if test "$with_selinux" != "no"; then
AC_CHECK_HEADERS([selinux/selinux.h], [selinux_header="yes"], [selinux_header="no"])
if test "X$selinux_header$with_selinux" = "Xnoyes" ; then
AC_CHECK_HEADERS(selinux/selinux.h, [selinux_header="yes"], [selinux_header="no"])
if test "$selinux_header$with_selinux" = "noyes" ; then
AC_MSG_ERROR([selinux/selinux.h is missing])
fi
AC_CHECK_HEADERS([semanage/semanage.h], [semanage_header="yes"], [semanage_header="no"])
if test "X$semanage_header$with_selinux" = "Xnoyes" ; then
AC_CHECK_HEADERS(semanage/semanage.h, [semanage_header="yes"], [semanage_header="no"])
if test "$semanage_header$with_selinux" = "noyes" ; then
AC_MSG_ERROR([semanage/semanage.h is missing])
fi
if test "X$selinux_header$semanage_header" = "Xyesyes" ; then
AC_CHECK_LIB([selinux], [is_selinux_enabled], [selinux_lib="yes"], [selinux_lib="no"])
if test "X$selinux_lib$with_selinux" = "Xnoyes" ; then
if test "$selinux_header$semanage_header" = "yesyes" ; then
AC_CHECK_LIB(selinux, is_selinux_enabled, [selinux_lib="yes"], [selinux_lib="no"])
if test "$selinux_lib$with_selinux" = "noyes" ; then
AC_MSG_ERROR([libselinux not found])
fi
AC_CHECK_LIB([semanage], [semanage_connect], [semanage_lib="yes"], [semanage_lib="no"])
if test "X$semanage_lib$with_selinux" = "Xnoyes" ; then
AC_CHECK_LIB(semanage, semanage_connect, [semanage_lib="yes"], [semanage_lib="no"])
if test "$semanage_lib$with_selinux" = "noyes" ; then
AC_MSG_ERROR([libsemanage not found])
fi
if test "X$selinux_lib$semanage_lib" = "Xyesyes" ; then
AC_DEFINE([WITH_SELINUX], [1],
if test "$selinux_lib$semanage_lib" = "yesyes" ; then
AC_DEFINE(WITH_SELINUX, 1,
[Build shadow with SELinux support])
LIBSELINUX="-lselinux"
LIBSEMANAGE="-lsemanage"
@ -492,19 +511,19 @@ if test "$with_selinux" != "no"; then
fi
fi
AC_SUBST([LIBTCB])
AC_SUBST(LIBTCB)
if test "$with_tcb" != "no"; then
AC_CHECK_HEADERS([tcb.h], [tcb_header="yes"], [tcb_header="no"])
if test "X$tcb_header$with_tcb" = "Xnoyes" ; then
AC_CHECK_HEADERS(tcb.h, [tcb_header="yes"], [tcb_header="no"])
if test "$tcb_header$with_tcb" = "noyes" ; then
AC_MSG_ERROR([tcb.h is missing])
elif test "X$tcb_header" = "Xyes" ; then
AC_CHECK_LIB([tcb], [tcb_is_suspect], [tcb_lib="yes"], [tcb_lib="no"])
if test "X$tcb_lib$with_tcb" = "Xnoyes" ; then
elif test "$tcb_header" = "yes" ; then
AC_CHECK_LIB(tcb, tcb_is_suspect, [tcb_lib="yes"], [tcb_lib="no"])
if test "$tcb_lib$with_tcb" = "noyes" ; then
AC_MSG_ERROR([libtcb not found])
elif test "X$tcb_lib" = "Xno" ; then
elif test "$tcb_lib" = "no" ; then
with_tcb="no"
else
AC_DEFINE([WITH_TCB], [1], [Build shadow with tcb support (incomplete)])
AC_DEFINE(WITH_TCB, 1, [Build shadow with tcb support (incomplete)])
LIBTCB="-ltcb"
with_tcb="yes"
fi
@ -512,39 +531,39 @@ if test "$with_tcb" != "no"; then
with_tcb="no"
fi
fi
AM_CONDITIONAL([WITH_TCB], [test x$with_tcb = xyes])
AM_CONDITIONAL(WITH_TCB, test x$with_tcb = xyes)
AC_SUBST([LIBPAM])
AC_SUBST(LIBPAM)
if test "$with_libpam" != "no"; then
AC_CHECK_LIB([pam], [pam_start],
AC_CHECK_LIB(pam, pam_start,
[pam_lib="yes"], [pam_lib="no"])
if test "X$pam_lib$with_libpam" = "Xnoyes" ; then
AC_MSG_ERROR([libpam not found])
if test "$pam_lib$with_libpam" = "noyes" ; then
AC_MSG_ERROR(libpam not found)
fi
LIBPAM="-lpam"
pam_conv_function="no"
AC_CHECK_LIB([pam], [openpam_ttyconv],
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"])]
AC_CHECK_LIB(pam_misc, misc_conv,
[pam_conv_function="misc_conv"; LIBPAM="$LIBPAM -lpam_misc"])
)
if test "X$pam_conv_function$with_libpam" = "Xnoyes" ; then
AC_MSG_ERROR([PAM conversation function not found])
if test "$pam_conv_function$with_libpam" = "noyes" ; then
AC_MSG_ERROR(PAM conversation function 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 "X$pam_headers_found$with_libpam" = "Xnoyes" ; then
AC_MSG_ERROR([PAM headers not found])
[ #include <security/pam_appl.h> ] )
if test "$pam_headers_found$with_libpam" = "noyes" ; then
AC_MSG_ERROR(PAM headers not found)
fi
if test "X$pam_lib$pam_headers_found" = "Xyesyes" && test "$pam_conv_function" != "no" ; then
if test "$pam_lib$pam_headers_found" = "yesyes" -a "$pam_conv_function" != "no" ; then
with_libpam="yes"
else
with_libpam="no"
@ -552,86 +571,87 @@ if test "$with_libpam" != "no"; then
fi
fi
dnl Now with_libpam is either yes or no
if test "X$with_libpam" = "Xyes"; then
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>]])
[], [], [#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'])])
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 conversation to use])
AC_DEFINE(USE_PAM, 1, [Define to support Pluggable Authentication Modules])
AC_DEFINE_UNQUOTED(SHADOW_PAM_CONVERSATION, [$pam_conv_function],[PAM conversation to use])
AM_CONDITIONAL(USE_PAM, [true])
AC_MSG_CHECKING([use login and su access checking if PAM not used])
AC_MSG_RESULT([no])
AC_MSG_CHECKING(use login and su access checking if PAM not used)
AC_MSG_RESULT(no)
else
AC_DEFINE([SU_ACCESS], [1], [Define to support /etc/suauth su access control.])
AC_MSG_CHECKING([use login and su access checking if PAM not used])
AC_MSG_RESULT([yes])
AC_DEFINE(SU_ACCESS, 1, [Define to support /etc/suauth su access control.])
AM_CONDITIONAL(USE_PAM, [false])
AC_MSG_CHECKING(use login and su access checking if PAM not used)
AC_MSG_RESULT(yes)
fi
AM_CONDITIONAL([USE_PAM], [test "X$with_libpam" = "Xyes"])
if test "$enable_acct_tools_setuid" != "no"; then
if test "$with_libpam" != "yes"; then
if test "X$enable_acct_tools_setuid" = "Xyes"; then
AC_MSG_ERROR([PAM support is required for --enable-account-tools-setuid])
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 "X$enable_acct_tools_setuid" = "Xyes"; then
AC_DEFINE([ACCT_TOOLS_SETUID],
[1],
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"])
AM_CONDITIONAL(ACCT_TOOLS_SETUID, test "x$enable_acct_tools_setuid" = "xyes")
AC_ARG_WITH([fcaps],
AC_ARG_WITH(fcaps,
[AS_HELP_STRING([--with-fcaps], [use file capabilities instead of suid binaries for newuidmap/newgidmap @<:@default=no@:>@])],
[with_fcaps=$withval], [with_fcaps=no])
AM_CONDITIONAL([FCAPS], [test "x$with_fcaps" = "xyes"])
AM_CONDITIONAL(FCAPS, test "x$with_fcaps" = "xyes")
if test "x$with_fcaps" = "xyes"; then
AC_CHECK_PROGS([capcmd], ["setcap"])
AC_CHECK_PROGS(capcmd, "setcap")
if test "x$capcmd" = "x" ; then
AC_MSG_ERROR([setcap command not available])
fi
fi
AC_SUBST([LIBSKEY])
AC_SUBST([LIBMD])
if test "X$with_skey" = "Xyes"; then
AC_CHECK_LIB([md], [MD5Init], [LIBMD=-lmd])
AC_CHECK_LIB([skey], [skeychallenge], [LIBSKEY=-lskey],
AC_SUBST(LIBSKEY)
AC_SUBST(LIBMD)
if test "$with_skey" = "yes"; then
AC_CHECK_LIB(md, MD5Init, [LIBMD=-lmd])
AC_CHECK_LIB(skey, skeychallenge, [LIBSKEY=-lskey],
[AC_MSG_ERROR([libskey missing. You can download S/Key source code from http://rsync1.it.gentoo.org/gentoo/distfiles/skey-1.1.5.tar.bz2])])
AC_DEFINE([SKEY], [1], [Define to support S/Key logins.])
AC_DEFINE(SKEY, 1, [Define to support S/Key logins.])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <stdio.h>
#include <skey.h>
]], [[
skeychallenge((void*)0, (void*)0, (void*)0, 0);
]])],[AC_DEFINE([SKEY_BSD_STYLE], [1], [Define to support newer BSD S/Key API])],[])
]])],[AC_DEFINE(SKEY_BSD_STYLE, 1, [Define to support newer BSD S/Key API])],[])
fi
AC_CHECK_FUNC([fgetpwent_r], [AC_DEFINE([HAVE_FGETPWENT_R], [1], [Defined to 1 if you have the declaration of 'fgetpwent_r'])])
AC_CHECK_FUNC(fgetpwent_r, [AC_DEFINE(HAVE_FGETPWENT_R, 1, [Defined to 1 if you have the declaration of 'fgetpwent_r'])])
AC_DEFINE_UNQUOTED([SHELL], ["$SHELL"], [The default shell.])
AC_DEFINE_UNQUOTED(SHELL, ["$SHELL"], [The default shell.])
AM_GNU_GETTEXT_VERSION([0.19])
AM_GNU_GETTEXT([external], [need-ngettext])
AM_CONDITIONAL([USE_NLS], [test "x$USE_NLS" = "xyes"])
AM_CONDITIONAL(USE_NLS, test "x$USE_NLS" = "xyes")
AC_CONFIG_FILES([
Makefile
@ -670,28 +690,30 @@ AC_CONFIG_FILES([
])
AC_OUTPUT
AC_MSG_NOTICE([shadow ${PACKAGE_VERSION} has been configured with the following features:
auditing support: $with_audit
PAM support: $with_libpam
suid account management tools: $enable_acct_tools_setuid
SELinux support: $with_selinux
BtrFS support: $with_btrfs
ACL support: $with_acl
Extended Attributes support: $with_attr
tcb support (incomplete): $with_tcb
shadow group support: $enable_shadowgrp
S/Key support: $with_skey
SHA passwords encryption: $with_sha_crypt
bcrypt passwords encryption: $with_bcrypt
yescrypt passwords encryption: $with_yescrypt
nscd support: $with_nscd
sssd support: $with_sssd
subordinate IDs support: $enable_subids
enable lastlog: $enable_lastlog
enable logind: $enable_logind
use file caps: $with_fcaps
install su: $with_su
enabled vendor dir: $enable_vendordir
])
echo
echo "shadow will be compiled with the following features:"
echo
echo " auditing support: $with_audit"
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 " BtrFS support: $with_btrfs"
echo " ACL support: $with_acl"
echo " Extended Attributes support: $with_attr"
echo " tcb support (incomplete): $with_tcb"
echo " shadow group support: $enable_shadowgrp"
echo " S/Key support: $with_skey"
echo " SHA passwords encryption: $with_sha_crypt"
echo " bcrypt passwords encryption: $with_bcrypt"
echo " yescrypt passwords encryption: $with_yescrypt"
echo " nscd support: $with_nscd"
echo " sssd support: $with_sssd"
echo " subordinate IDs support: $enable_subids"
echo " enable lastlog: $enable_lastlog"
echo " enable logind: $enable_logind"
echo " use file caps: $with_fcaps"
echo " install su: $with_su"
echo " enabled vendor dir: $enable_vendordir"
echo

View File

@ -346,7 +346,7 @@
return value points to static data whose content is overwritten by
each call.
Warning: the key space consists of 2**56 equal 7.2e16 possible values.
Warning: The key space consists of 2**56 equal 7.2e16 possible values.
Exhaustive searches of this key space are possible using massively
parallel computers. Software, such as crack(1), is available which
will search the portion of this key space that is generally used by
@ -996,7 +996,7 @@
sudo for the shadow suite, is available as at:
<ftp://sunsite.unc.edu/pub/Linux/system/Admin/sudo-1.2-shadow.tgz>
Warning: when you install sudo your /etc/sudoers file will be replaced
Warning: When you install sudo your /etc/sudoers file will be replaced
with a default one, so you need to make a backup of it if you have
added anything to the default one. (you could also edit the Makefile
and remove the line that copies the default file to /etc).

View File

@ -73,31 +73,3 @@ were running some of the CI checks locally:
```
share/container-build.sh
```
### Container troubleshooting
When working with containers for testing or development,
you may encounter issues.
Here are common troubleshooting steps:
**Post-test inspection:**
- **Container persistence**: after tests complete, containers are left running
to allow inspection of the test environment and debugging of any failures.
This enables you to examine logs, file states, and system configuration
that existed when tests ran.
**Container management:**
- **List containers**: `docker ps -a` to see all containers and their status.
- **Access container**: `docker exec -it <container-name> bash` to get shell access.
- **Container logs**: `docker logs <container-name>` to view container output.
- **Remove containers**: `docker rm <container-name>` to clean up stopped containers.
**Common issues:**
- **Container not found**: ensure you've run the Ansible playbook
to create the required containers.
- **Permission issues**: verify the container has proper privileges
for user/group operations.
- **Network connectivity**: check that containers can communicate
if tests involve network operations.
- **Resource constraints**: ensure sufficient disk space and memory
for container operations.

View File

@ -12,27 +12,9 @@ be triggered locally by following the instructions specified in the
## System tests
The project runs system tests to verify functionality
across different environments
using two complementary approaches:
### Bash system tests
Legacy Bash system tests run on Ubuntu in a VM environment.
These provide coverage for Ubuntu-specific scenarios and legacy test cases.
You can run this step locally by following the instructions provided
in the [Tests](tests.md#bash-system-tests) page.
### Python system tests
The new Python system tests use pytest and pytest-mh,
running across multiple distributions (Fedora, Debian, Alpine, openSUSE)
in containerized environments.
These tests provide cross-distribution compatibility
and improved environment management compared to the Bash tests.
For local execution of Python system tests,
follow the instructions in the [Tests](tests.md#python-system-tests) page.
The project is tested on Ubuntu. For that purpose it is built & installed in
this distribution in a VM. You can run this step locally by following the
instructions provided in the [Tests](tests.md#system-tests) page.
## Static code analysis

View File

@ -1,96 +1,12 @@
# Coding style
The Shadow project is developed in C,
with Python used for testing purposes.
Each language follows its own established conventions and style guidelines.
## C code
* For a general guidance refer to the
[Linux kernel coding style](https://www.kernel.org/doc/html/latest/process/coding-style.html)
* Patches that change the existing coding style are not welcome, as they make
downstream porting harder for the distributions
### Indentation
## Indentation
Tabs are preferred over spaces for indentation. Loading the `.editorconfig`
file in your preferred IDE may help you configure it.
## Python code
Python code in the Shadow project is primarily found
in the system test framework (`tests/system/`).
Follow these conventions for consistency:
### General conventions
* **PEP 8 compliance**: follow [PEP 8](https://pep8.org/) style guidelines.
* **Code quality enforcement**: all Python code must pass flake8, pycodestyle, isort, mypy, and black checks.
* **Import organization**: use absolute imports with `from __future__ import annotations`.
* **Type hints**: use modern type hints (e.g., `str | None` instead of `Optional[str]`).
* **Line length**: maximum 119 characters per line.
* **Configuration**: all formatting and linting settings are defined in `tests/system/pyproject.toml`.
### Test code style
**File and test naming:**
* Test files: `test_<command>.py` (e.g., `test_useradd.py`).
* Test functions: `test_<command>__<specific_behavior>` using double underscores.
* Use descriptive names that clearly indicate what is being tested.
**Test structure (AAA pattern):**
```python
@pytest.mark.topology(KnownTopology.Shadow)
def test_useradd__add_user(shadow: Shadow):
"""
:title: Descriptive test title
:setup:
1. Setup steps
:steps:
1. Test steps
:expectedresults:
1. Expected outcomes
:customerscenario: False
"""
# Arrange
setup_code_here()
# Act
result = shadow.command_to_test()
# Assert
assert result is not None, "Descriptive failure message"
```
**Avoiding flakiness:**
* Use deterministic test data (avoid random values).
* Clean up test artifacts properly (handled automatically by framework).
* Use appropriate timeouts for time-sensitive operations.
* Leverage the framework's automatic backup/restore functionality.
### Formatting and imports
**Required tools:**
* **flake8**: for style guide enforcement and error detection.
* **pycodestyle**: for PEP 8 style checking.
* **isort**: for import sorting with profiles that work well with Black.
* **Black**: for consistent code formatting.
* **mypy**: for static type checking.
**Import order:**
1. Standard library imports.
2. Third-party imports (`pytest`, `pytest_mh`).
3. Local framework imports (`framework.*`).
### Error handling and logging
**Error handling:**
* Prefer explicit exceptions over silent failures.
* Use `ProcessError` for command execution failures.
* Provide context in error messages.
**Logging guidance:**
* Use structured logging for test utilities in `tests/system/framework/`.
* Include relevant context (command, parameters, expected vs actual results).
* Leverage the framework's automatic artifact collection for debugging.

View File

@ -1,8 +1,6 @@
# Tests
Currently, shadow provides unit tests and system tests.
System tests are split in two:
Bash system tests and Python system tests.
Currently, shadow provides unit and system tests.
## Unit tests
@ -22,243 +20,15 @@ make check
## System tests
System tests verify the behavior of shadow utilities
in a complete system environment.
There are two types of system tests available.
These type of tests are written in shell. Unfortunately, the testing framework
is tightly coupled to the Ubuntu distribution and it can only be run in this
distribution. Besides, if anything fails during the execution the system can
be left in an unstable state. Taking that into account you shouldn't run this
workflow in your host machine, we recommend to use a disposable system like a
VM or a container instead.
### Bash system tests
These tests are written in shell
and are tightly coupled to the Ubuntu distribution.
They can only be run on Ubuntu,
and if anything fails during execution,
the system can be left in an unstable state.
You shouldn't run this workflow on your host machine—we recommend using a disposable system
like a VM or a container instead.
You can execute Bash system tests by running:
You can execute system tests by running:
```
cd tests && ./run_all
```
### Python system tests
The new system tests use Python,
[pytest](https://pytest.org/)
and [pytest-mh](https://pytest-mh.readthedocs.io/).
The Python framework provides several advantages over Bash tests:
**Cross-distribution compatibility**: works on all distributions in CI
(Alpine, Debian, Fedora and openSUSE)
unlike Bash tests which only run on Ubuntu.
**Proper environment management**: ensures clean setup and teardown
with environment restoration even when tests fail.
**Improved test maintainability**: provides a rich, high-level API
that reduces complex test code
and makes tests easier to understand.
**Automated artifact collection**: automatically collects logs and artifacts
when tests finish (even if they fail).
**Flexible infrastructure**: supports both VMs and containers for testing
with local execution capabilities.
**Future extensibility**: enables potential filtering by ticket
or importance and other advanced features.
[Read more about the benefits and rationale](https://github.com/shadow-maint/shadow/issues/835).
**For all new contributions,
we recommend using the Python system test framework.**
#### Contribution guidance
The framework is under active development
and welcomes contributions for missing features.
When contributing:
1. **Framework improvements**: enhance the infrastructure in `tests/system/framework/`.
2. **Proposing new tests**: place them in `tests/system/tests/`.
Review existing examples in `tests/system/tests/`
to understand the established patterns and conventions.
3. **Missing features**: if you're comfortable implementing missing pytest-mh features,
contributions are encouraged.
#### Running tests
##### Environment setup
A testing environment is required to run the system test framework.
While the same system can be used,
a disposable environment (container or VM) is recommended.
The default configuration relies on a pre-built container named `builder`
that must be available in your container environment.
This container contains:
- A complete shadow-utils installation
- All required system dependencies
**Setup steps:**
1. **Build the container environment**: follow the instructions in [build_install.md](build_install.md)
to create the required `builder` container.
2. **Verify container availability**: ensure the `builder` container is accessible via Docker.
The default `mhc.yaml` configuration expects this container
to be available as `builder`.
To ensure dependency isolation and system protection,
run the tests within a Python virtual environment:
```bash
cd tests/system
python -m venv .venv
source .venv/bin/activate
pip install -r ./requirements.txt
```
##### Configuration
The default configuration located in `tests/system` should be enough
if you are using containers.
If you run another environment you'll need to tune `tests/system/mhc.yaml`.
Instructions are available in the
[pytest-mh mhc.yaml documentation](https://pytest-mh.readthedocs.io/en/latest/articles/mhc-yaml.html).
##### Execution
Run all Python system tests:
```bash
pytest --mh-config=mhc.yaml --mh-lazy-ssh -v
```
Run tests in a file:
```bash
pytest --mh-config=mhc.yaml --mh-lazy-ssh -v tests/test_useradd.py
```
Run a single test case:
```bash
pytest --mh-config=mhc.yaml --mh-lazy-ssh -v -k test_useradd__add_user
```
**Command options explained:**
- `--mh-config=mhc.yaml`: specifies the multihost configuration file
- `--mh-lazy-ssh`: enables lazy SSH connections for better performance
- `-v`: verbose output showing individual test results
- `-k`: filters tests by name pattern
For additional running options,
see the [pytest-mh running tests documentation](https://pytest-mh.readthedocs.io/en/latest/articles/running-tests.html).
#### Advanced testing features
The Python testing framework includes several advanced features
for comprehensive testing:
**Test markers:**
- `@pytest.mark.topology(KnownTopology.Shadow)`: specifies the test topology.
- `@pytest.mark.builtwith("gshadow")`: skips tests when specific features are unavailable.
- `@pytest.mark.parametrize()`: extensive parameterized testing
for edge cases and different inputs.
**Rich command parsing:**
All shadow command outputs are parsed into structured Python objects
using the `jc` library:
- `PasswdEntry`, `ShadowEntry`, `GroupEntry`, `GShadowEntry` for file entries
- `ID` command parsing with group membership verification
- Structured error handling and validation
#### Test development patterns
When writing new Python tests,
follow these established patterns:
**Basic test structure:**
```python
@pytest.mark.topology(KnownTopology.Shadow)
def test_command__specific_behavior(shadow: Shadow):
"""
:title: Descriptive test title
:setup:
1. Setup steps
:steps:
1. Test steps
:expectedresults:
1. Expected outcomes
:customerscenario: False
"""
# Arrange
shadow.useradd("testuser")
# Act
result = shadow.tools.getent.passwd("testuser")
# Assert
assert result is not None, "User should exist"
assert result.name == "testuser", "Username should match"
```
**Distribution-specific testing:**
```python
if "Debian" in shadow.host.distro_name:
assert result.shell == "/bin/sh"
else:
assert result.shell == "/bin/bash"
```
**Parameterized testing:**
```python
@pytest.mark.parametrize(
"input_date, expected_epoch",
[
("1970-01-01", 0),
("2025-01-01", 20089),
("0", 0),
],
)
def test_date_handling(shadow: Shadow, input_date: str, expected_epoch: int):
# Test implementation
```
#### Debugging information
**Test artifacts:**
- **Location**: `tests/system/artifacts/` directory.
- **Content**: automatically collected logs and system state information.
- **Collection**: happens automatically when tests finish,
regardless of success or failure.
**System state management:**
The framework automatically manages shadow system files:
- **Backup**: complete backup of `/etc/passwd`, `/etc/shadow`, `/etc/group`, `/etc/gshadow`, `/home`
before tests.
- **Restore**: automatic restoration after each test.
- **Verification**: file mismatch detection
to ensure unmodified files remain unchanged.
**Common debugging steps:**
1. **Check container status**: ensure the `builder` container is running and accessible.
2. **Verify artifacts**: examine collected logs in the `artifacts/` directory.
3. **Manual testing**: access the container directly
to reproduce issues manually.
4. **File state**: check if unexpected file modifications caused test failures.
#### Troubleshooting & FAQs
**Common pitfalls:**
- **Missing virtual environment**: always activate the Python virtual environment
before running tests.
- **Mismatched environment**: ensure your `mhc.yaml` configuration matches your testing environment.
- **Container vs host confusion**: remember that tests run inside containers by default;
adjust expectations accordingly.
**Tips for disposable environments:**
- Use containers or VMs to avoid system state pollution.
- Ensure proper cleanup in the framework between test runs.
- Verify container/VM has necessary privileges for user/group operations.
For additional information about the testing framework,
see the [pytest-mh documentation](https://pytest-mh.readthedocs.io).

View File

@ -6,7 +6,7 @@
#
# Delay in seconds before being allowed another attempt after a login failure
# Note: when PAM is used, some modules may enforce a minimum delay (e.g.
# Note: When PAM is used, some modules may enforce a minimum delay (e.g.
# pam_unix(8) enforces a 2s delay)
#
FAIL_DELAY 3
@ -276,7 +276,7 @@ PASS_ALWAYS_WARN yes
#
# Number of significant characters in the password for crypt().
# Default is 8, don't change unless your crypt() is better.
# Only used for DES encryption algorithm.
# Ignored if MD5_CRYPT_ENAB set to "yes".
#
#PASS_MAX_LEN 8
@ -308,7 +308,7 @@ CHFN_RESTRICT rwh
# Set to "no" if you need to copy encrypted passwords to other systems
# which don't understand the new algorithm. Default is "no".
#
# Note: if you use PAM, it is recommended to use a value consistent with
# Note: If you use PAM, it is recommended to use a value consistent with
# the PAM modules configuration.
#
# This variable is deprecated. You should use ENCRYPT_METHOD instead.
@ -326,7 +326,7 @@ CHFN_RESTRICT rwh
# MD5 and DES should not be used for new hashes, see crypt(5) for recommendations.
# Overrides the MD5_CRYPT_ENAB option
#
# Note: if you use PAM, it is recommended to use a value consistent with
# Note: If you use PAM, it is recommended to use a value consistent with
# the PAM modules configuration.
#
#ENCRYPT_METHOD DES
@ -467,7 +467,7 @@ PREVENT_NO_AUTH superuser
# Used in pam_timestamp module to calculate the keyed-hash message
# authentication code.
#
# Note: it is recommended to check hmac(3) to see the possible algorithms
# Note: It is recommended to check hmac(3) to see the possible algorithms
# that are available in your system.
#
#HMAC_CRYPTO_ALGO SHA512

View File

@ -37,10 +37,30 @@ libshadow_la_SOURCES = \
alloc/realloc.h \
alloc/reallocf.c \
alloc/reallocf.h \
atoi/a2i.c \
atoi/a2i.h \
alloc/x/xcalloc.c \
alloc/x/xcalloc.h \
alloc/x/xmalloc.c \
alloc/x/xmalloc.h \
alloc/x/xrealloc.c \
alloc/x/xrealloc.h \
atoi/a2i/a2i.c \
atoi/a2i/a2i.h \
atoi/a2i/a2s.c \
atoi/a2i/a2s.h \
atoi/a2i/a2s_c.c \
atoi/a2i/a2s_c.h \
atoi/a2i/a2s_nc.c \
atoi/a2i/a2s_nc.h \
atoi/a2i/a2u.c \
atoi/a2i/a2u.h \
atoi/a2i/a2u_c.c \
atoi/a2i/a2u_c.h \
atoi/a2i/a2u_nc.c \
atoi/a2i/a2u_nc.h \
atoi/getnum.c \
atoi/getnum.h \
atoi/str2i.c \
atoi/str2i.h \
atoi/strtoi/strtoi.c \
atoi/strtoi/strtoi.h \
atoi/strtoi/strtou.c \
@ -55,8 +75,6 @@ libshadow_la_SOURCES = \
cast.h \
chkname.c \
chkname.h \
chkhash.c \
chkhash.h \
chowndir.c \
chowntty.c \
cleanup.c \
@ -70,8 +88,6 @@ libshadow_la_SOURCES = \
defines.h \
encrypt.c \
env.c \
exit_if_null.c \
exit_if_null.h \
exitcodes.h \
faillog.h \
failure.c \
@ -83,6 +99,7 @@ libshadow_la_SOURCES = \
find_new_uid.c \
find_new_sub_gids.c \
find_new_sub_uids.c \
fputsx.c \
fs/mkstemp/fmkomstemp.c \
fs/mkstemp/fmkomstemp.h \
fs/mkstemp/mkomstemp.c \
@ -100,6 +117,7 @@ libshadow_la_SOURCES = \
groupio.c \
groupmem.c \
groupio.h \
gshadow.c \
hushed.c \
idmapping.h \
idmapping.c \
@ -147,38 +165,18 @@ libshadow_la_SOURCES = \
semanage.c \
setugid.c \
setupenv.c \
sgetgrent.c \
sgetpwent.c \
sgetspent.c \
sgroupio.c \
sgroupio.h \
shadow/group/sgetgrent.c \
shadow/group/sgetgrent.h \
sgroupio.h\
shadow/grp/agetgroups.c \
shadow/grp/agetgroups.h \
shadow/gshadow/endsgent.c \
shadow/gshadow/endsgent.h \
shadow/gshadow/fgetsgent.c \
shadow/gshadow/fgetsgent.h \
shadow/gshadow/getsgent.c \
shadow/gshadow/getsgent.h \
shadow/gshadow/getsgnam.c \
shadow/gshadow/getsgnam.h \
shadow/gshadow/gshadow.c \
shadow/gshadow/gshadow.h \
shadow/gshadow/putsgent.c \
shadow/gshadow/putsgent.h \
shadow/gshadow/setsgent.c \
shadow/gshadow/setsgent.h \
shadow/gshadow/sgetsgent.c \
shadow/gshadow/sgetsgent.h \
shadow/gshadow/sgrp.c \
shadow/gshadow/sgrp.h \
shadow/passwd/sgetpwent.c \
shadow/passwd/sgetpwent.h \
shadow/shadow/sgetspent.c \
shadow/shadow/sgetspent.h \
shadowio.c \
shadowio.h \
shadowlog.c \
shadowlog.h \
shadowlog_internal.h \
shadowmem.c \
shell.c \
sizeof.h \
@ -201,6 +199,8 @@ libshadow_la_SOURCES = \
string/sprintf/snprintf.h \
string/sprintf/stpeprintf.c \
string/sprintf/stpeprintf.h \
string/sprintf/xaprintf.c \
string/sprintf/xaprintf.h \
string/strchr/strchrcnt.c \
string/strchr/strchrcnt.h \
string/strchr/strchrscnt.c \
@ -213,8 +213,6 @@ libshadow_la_SOURCES = \
string/strcmp/strcaseprefix.h \
string/strcmp/streq.c \
string/strcmp/streq.h \
string/strcmp/strneq.c \
string/strcmp/strneq.h \
string/strcmp/strprefix.c \
string/strcmp/strprefix.h \
string/strcpy/stpecpy.c \
@ -225,14 +223,12 @@ libshadow_la_SOURCES = \
string/strcpy/strncpy.h \
string/strcpy/strtcpy.c \
string/strcpy/strtcpy.h \
string/strdup/strdup.c \
string/strdup/strdup.h \
string/strdup/strndupa.c \
string/strdup/strndupa.h \
string/strdup/strndup.c \
string/strdup/strndup.h \
string/strerrno.c \
string/strerrno.h \
string/strdup/xstrdup.c \
string/strdup/xstrdup.h \
string/strdup/xstrndup.c \
string/strdup/xstrndup.h \
string/strftime.c \
string/strftime.h \
string/strspn/stpspn.c \
@ -253,6 +249,8 @@ libshadow_la_SOURCES = \
string/strtok/strsep2arr.h \
string/strtok/strsep2ls.c \
string/strtok/strsep2ls.h \
string/strtok/xastrsep2ls.c \
string/strtok/xastrsep2ls.h \
strtoday.c \
sub.c \
subordinateio.h \
@ -308,4 +306,5 @@ endif
EXTRA_DIST = \
.indent.pro \
gshadow_.h \
xgetXXbyYY.c

View File

@ -6,7 +6,7 @@
// SPDX-License-Identifier: BSD-3-Clause
#include "config.h"
#include <config.h>
#if !defined(USE_PAM)
@ -24,8 +24,6 @@
#include "shadow/grp/agetgroups.h"
#include "shadowlog.h"
#include "string/strchr/strchrscnt.h"
#include "string/strcmp/streq.h"
#include "string/strerrno.h"
/*
@ -36,7 +34,8 @@
int
add_groups(const char *list)
{
char *dup;
char *g, *p, *dup;
FILE *shadow_logfd = log_get_logfd();
gid_t *gids;
size_t n;
@ -44,34 +43,29 @@ add_groups(const char *list)
if (gids == NULL)
return -1;
gids = reallocf_T(gids, n + strchrscnt(list, ",:") + 1, gid_t);
gids = REALLOCF(gids, n + strchrscnt(list, ",:") + 1, gid_t);
if (gids == NULL)
return -1;
dup = strdup(list);
p = dup = strdup(list);
if (dup == NULL)
goto free_gids;
if (!streq(dup, "")) {
char *g, *p;
while (NULL != (g = strsep(&p, ",:"))) {
struct group *grp;
p = dup;
while (NULL != (g = strsep(&p, ",:"))) {
struct group *grp;
grp = getgrnam(g); /* local, no need for xgetgrnam */
if (NULL == grp) {
fprintf(log_get_logfd(), _("Warning: unknown group %s\n"), g);
continue;
}
LSEARCH(gid_t, &grp->gr_gid, gids, &n);
grp = getgrnam(g); /* local, no need for xgetgrnam */
if (NULL == grp) {
fprintf(shadow_logfd, _("Warning: unknown group %s\n"), g);
continue;
}
LSEARCH(&grp->gr_gid, gids, &n);
}
free(dup);
if (setgroups(n, gids) == -1) {
fprintf(log_get_logfd(), "setgroups: %s\n", strerrno());
fprintf(shadow_logfd, "setgroups: %s\n", strerror(errno));
goto free_gids;
}

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: BSD-3-Clause
#include "config.h"
#include <config.h>
#include "adds.h"

View File

@ -6,7 +6,7 @@
#define SHADOW_INCLUDE_LIB_ADDS_H_
#include "config.h"
#include <config.h>
#include <errno.h>
#include <limits.h>
@ -55,7 +55,7 @@ addslN(size_t n, long addend[n])
e = errno;
while (n > 1) {
QSORT(long, addend, n);
QSORT(addend, n);
errno = 0;
addend[0] = addsl2(addend[0], addend[--n]);

View File

@ -7,7 +7,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "config.h"
#include <config.h>
#include <sys/types.h>
#include <stdio.h>
@ -20,7 +20,6 @@
#include "defines.h"
#include "exitcodes.h"
#include "prototypes.h"
#include "shadow/gshadow/endsgent.h"
#ident "$Id$"

View File

@ -5,7 +5,7 @@
*/
#include "config.h"
#include <config.h>
#include "agetpass.h"
@ -106,7 +106,7 @@ agetpass_internal(const char *prompt, int flags)
* Let's add one more byte, and if the password uses it, it
* means the introduced password was longer than PASS_MAX.
*/
pass = malloc_T(PASS_MAX + 2, char);
pass = MALLOC(PASS_MAX + 2, char);
if (pass == NULL)
return NULL;
@ -135,7 +135,7 @@ agetpass(const char *prompt)
char *
agetpass_stdin()
{
return agetpass_internal("", RPP_STDIN);
return agetpass_internal(NULL, RPP_STDIN);
}
void

View File

@ -8,7 +8,7 @@
#define SHADOW_INCLUDE_LIB_AGETPASS_H_
#include "config.h"
#include <config.h>
#include "attr.h"
#include "defines.h"

View File

@ -6,6 +6,6 @@
// SPDX-License-Identifier: BSD-3-Clause
#include "config.h"
#include <config.h>
#include "alloc/calloc.h"

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <alx@kernel.org>
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
@ -6,24 +6,15 @@
#define SHADOW_INCLUDE_LIB_ALLOC_CALLOC_H_
#include "config.h"
#include <config.h>
#include <stdlib.h>
#include "exit_if_null.h"
#include "sizeof.h"
// calloc_T - calloc type-safe
#define calloc_T(n, T) calloc_T_(n, typeas(T))
#define calloc_T_(n, T) \
({ \
(T *){calloc(n, sizeof(T))}; \
})
// xcalloc_T - exit-on-error calloc type-safe
#define xcalloc_T(n, T) exit_if_null(calloc_T(n, T))
#define CALLOC(n, type) \
( \
(type *) calloc(n, sizeof(type)) \
)
#endif // include guard

View File

@ -6,7 +6,7 @@
// SPDX-License-Identifier: BSD-3-Clause
#include "config.h"
#include <config.h>
#include "alloc/malloc.h"

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <alx@kernel.org>
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
@ -6,28 +6,19 @@
#define SHADOW_INCLUDE_LIB_ALLOC_MALLOC_H_
#include "config.h"
#include <config.h>
#include <stdlib.h>
#include "attr.h"
#include "exit_if_null.h"
#include "sizeof.h"
// malloc_T - malloc type-safe
#define malloc_T(n, T) malloc_T_(n, typeas(T))
#define malloc_T_(n, T) \
({ \
(T *){mallocarray(n, sizeof(T))}; \
})
#define MALLOC(n, type) \
( \
(type *) mallocarray(n, sizeof(type)) \
)
// xmalloc_T - exit-on-error malloc type-safe
#define xmalloc_T(n, T) exit_if_null(malloc_T(n, T))
// mallocarray - malloc array
ATTR_ALLOC_SIZE(1, 2)
ATTR_MALLOC(free)
inline void *mallocarray(size_t nmemb, size_t size);

View File

@ -6,6 +6,6 @@
// SPDX-License-Identifier: BSD-3-Clause
#include "config.h"
#include <config.h>
#include "alloc/realloc.h"

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <alx@kernel.org>
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
@ -6,27 +6,15 @@
#define SHADOW_INCLUDE_LIB_ALLOC_REALLOC_H_
#include "config.h"
#include <config.h>
#include <stdlib.h>
#include "exit_if_null.h"
#include "sizeof.h"
// realloc_T - realloc type-safe
#define realloc_T(p, n, T) realloc_T_(p, n, typeas(T))
#define realloc_T_(p, n, T) \
({ \
_Generic(p, T *: (void)0); \
(T *){reallocarray_(p, n, sizeof(T))}; \
})
#define reallocarray_(p, n, size) reallocarray(p, (n) ?: 1, (size) ?: 1)
// xrealloc_T - exit-on-error realloc type-safe
#define xrealloc_T(p, n, T) exit_if_null(realloc_T(p, n, T))
#define REALLOC(p, n, type) \
( \
_Generic(p, type *: (type *) reallocarray(p, (n) ?: 1, sizeof(type))) \
)
#endif // include guard

View File

@ -6,7 +6,7 @@
// SPDX-License-Identifier: BSD-3-Clause
#include "config.h"
#include <config.h>
#include "alloc/reallocf.h"

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <alx@kernel.org>
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
@ -6,27 +6,20 @@
#define SHADOW_INCLUDE_LIB_ALLOC_REALLOCF_H_
#include "config.h"
#include <config.h>
#include <stddef.h>
#include <stdlib.h>
#include "attr.h"
#include "sizeof.h"
// reallocf_T - realloc free-on-error type-safe
#define reallocf_T(p, n, T) reallocf_T_(p, n, typeas(T))
#define reallocf_T_(p, n, T) \
({ \
_Generic(p, T *: (void)0); \
(T *){reallocarrayf_(p, n, sizeof(T))}; \
})
#define reallocarrayf_(p, n, size) reallocarrayf(p, (n) ?: 1, (size) ?: 1)
#define REALLOCF(p, n, type) \
( \
_Generic(p, type *: (type *) reallocarrayf(p, (n) ?: 1, sizeof(type)))\
)
// reallocarrayf - realloc array free-on-error
ATTR_ALLOC_SIZE(2, 3)
ATTR_MALLOC(free)
inline void *reallocarrayf(void *p, size_t nmemb, size_t size);

36
lib/alloc/x/xcalloc.c Normal file
View File

@ -0,0 +1,36 @@
// SPDX-FileCopyrightText: 1990-1994, Julianne Frances Haugh
// SPDX-FileCopyrightText: 1996-1998, Marek Michałkiewicz
// SPDX-FileCopyrightText: 2003-2006, Tomasz Kłoczko
// SPDX-FileCopyrightText: 2008 , Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "alloc/x/xcalloc.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "defines.h"
#include "shadowlog.h"
void *
xcalloc(size_t nmemb, size_t size)
{
void *p;
p = calloc(nmemb, size);
if (p == NULL)
goto x;
return p;
x:
fprintf(log_get_logfd(), _("%s: %s\n"),
log_get_progname(), strerror(errno));
exit(13);
}

28
lib/alloc/x/xcalloc.h Normal file
View File

@ -0,0 +1,28 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ALLOC_X_XCALLOC_H_
#define SHADOW_INCLUDE_LIB_ALLOC_X_XCALLOC_H_
#include <config.h>
#include <stddef.h>
#include <stdlib.h>
#include "attr.h"
#define XCALLOC(n, type) \
( \
(type *) xcalloc(n, sizeof(type)) \
)
ATTR_ALLOC_SIZE(1, 2)
ATTR_MALLOC(free)
void *xcalloc(size_t nmemb, size_t size);
#endif // include guard

16
lib/alloc/x/xmalloc.c Normal file
View File

@ -0,0 +1,16 @@
// SPDX-FileCopyrightText: 1990-1994, Julianne Frances Haugh
// SPDX-FileCopyrightText: 1996-1998, Marek Michałkiewicz
// SPDX-FileCopyrightText: 2003-2006, Tomasz Kłoczko
// SPDX-FileCopyrightText: 2008 , Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "alloc/x/xmalloc.h"
#include <stddef.h>
extern inline void *xmallocarray(size_t nmemb, size_t size);

35
lib/alloc/x/xmalloc.h Normal file
View File

@ -0,0 +1,35 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ALLOC_X_XMALLOC_H_
#define SHADOW_INCLUDE_LIB_ALLOC_X_XMALLOC_H_
#include <config.h>
#include <stddef.h>
#include "alloc/x/xrealloc.h"
#include "attr.h"
#define XMALLOC(n, type) \
( \
(type *) xmallocarray(n, sizeof(type)) \
)
ATTR_ALLOC_SIZE(1, 2)
ATTR_MALLOC(free)
inline void *xmallocarray(size_t nmemb, size_t size);
inline void *
xmallocarray(size_t nmemb, size_t size)
{
return xreallocarray(NULL, nmemb, size);
}
#endif // include guard

35
lib/alloc/x/xrealloc.c Normal file
View File

@ -0,0 +1,35 @@
// SPDX-FileCopyrightText: 1990-1994, Julianne Frances Haugh
// SPDX-FileCopyrightText: 1996-1998, Marek Michałkiewicz
// SPDX-FileCopyrightText: 2003-2006, Tomasz Kłoczko
// SPDX-FileCopyrightText: 2008 , Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "alloc/x/xrealloc.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "alloc/reallocf.h"
#include "defines.h"
#include "shadowlog.h"
void *
xreallocarray(void *p, size_t nmemb, size_t size)
{
p = reallocarrayf(p, nmemb, size);
if (p == NULL)
goto x;
return p;
x:
fprintf(log_get_logfd(), _("%s: %s\n"),
log_get_progname(), strerror(errno));
exit(13);
}

31
lib/alloc/x/xrealloc.h Normal file
View File

@ -0,0 +1,31 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_MALLOC_H_
#define SHADOW_INCLUDE_LIB_MALLOC_H_
#include <config.h>
#include <assert.h>
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include "attr.h"
#define XREALLOC(ptr, n, type) \
( \
_Generic(ptr, type *: (type *) xreallocarray(ptr, n, sizeof(type))) \
)
ATTR_ALLOC_SIZE(2, 3)
ATTR_MALLOC(free)
void *xreallocarray(void *p, size_t nmemb, size_t size);
#endif // include guard

View File

@ -1,69 +0,0 @@
// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_H_
#define SHADOW_INCLUDE_LIB_ATOI_A2I_H_
#include "config.h"
#include <errno.h>
#include <stddef.h>
#include "atoi/strtoi/strtoi.h"
#include "atoi/strtoi/strtou_noneg.h"
#include "typetraits.h"
// a2i - alpha to integer
#define a2i(T, n, s, endp, base, min, max) \
({ \
T *n_ = n; \
QChar_of(s) **endp_ = endp; \
T min_ = min; \
T max_ = max; \
\
int status; \
\
*n_ = _Generic((T){0}, \
short: strtoi_, \
int: strtoi_, \
long: strtoi_, \
long long: strtoi_, \
unsigned short: strtou_noneg, \
unsigned int: strtou_noneg, \
unsigned long: strtou_noneg, \
unsigned long long: strtou_noneg \
)(s, (char **) endp_, base, min_, max_, &status); \
\
if (status != 0) \
errno = status; \
-!!status; \
})
#define a2sh(...) a2i(short, __VA_ARGS__)
#define a2si(...) a2i(int, __VA_ARGS__)
#define a2sl(...) a2i(long, __VA_ARGS__)
#define a2sll(...) a2i(long long, __VA_ARGS__)
#define a2uh(...) a2i(unsigned short, __VA_ARGS__)
#define a2ui(...) a2i(unsigned int, __VA_ARGS__)
#define a2ul(...) a2i(unsigned long, __VA_ARGS__)
#define a2ull(...) a2i(unsigned long long, __VA_ARGS__)
#define str2i(T, ...) a2i(T, __VA_ARGS__, NULL, 0, type_min(T), type_max(T))
#define str2sh(...) str2i(short, __VA_ARGS__)
#define str2si(...) str2i(int, __VA_ARGS__)
#define str2sl(...) str2i(long, __VA_ARGS__)
#define str2sll(...) str2i(long long, __VA_ARGS__)
#define str2uh(...) str2i(unsigned short, __VA_ARGS__)
#define str2ui(...) str2i(unsigned int, __VA_ARGS__)
#define str2ul(...) str2i(unsigned long, __VA_ARGS__)
#define str2ull(...) str2i(unsigned long long, __VA_ARGS__)
#endif // include guard

View File

@ -2,6 +2,6 @@
// SPDX-License-Identifier: BSD-3-Clause
#include "config.h"
#include <config.h>
#include "string/strdup/strdup.h"
#include "atoi/a2i/a2i.h"

62
lib/atoi/a2i/a2i.h Normal file
View File

@ -0,0 +1,62 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2I_H_
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2I_H_
#include <config.h>
#include "atoi/a2i/a2s_c.h"
#include "atoi/a2i/a2s_nc.h"
#include "atoi/a2i/a2u_c.h"
#include "atoi/a2i/a2u_nc.h"
/*
* See the manual of these macros in liba2i's documentation:
* <http://www.alejandro-colomar.es/share/dist/liba2i/git/HEAD/liba2i-HEAD.pdf>
*/
#define a2i(TYPE, n, s, ...) \
( \
_Generic((void (*)(TYPE, typeof(s))) 0, \
void (*)(short, const char *): a2sh_c, \
void (*)(short, const void *): a2sh_c, \
void (*)(short, char *): a2sh_nc, \
void (*)(short, void *): a2sh_nc, \
void (*)(int, const char *): a2si_c, \
void (*)(int, const void *): a2si_c, \
void (*)(int, char *): a2si_nc, \
void (*)(int, void *): a2si_nc, \
void (*)(long, const char *): a2sl_c, \
void (*)(long, const void *): a2sl_c, \
void (*)(long, char *): a2sl_nc, \
void (*)(long, void *): a2sl_nc, \
void (*)(long long, const char *): a2sll_c, \
void (*)(long long, const void *): a2sll_c, \
void (*)(long long, char *): a2sll_nc, \
void (*)(long long, void *): a2sll_nc, \
void (*)(unsigned short, const char *): a2uh_c, \
void (*)(unsigned short, const void *): a2uh_c, \
void (*)(unsigned short, char *): a2uh_nc, \
void (*)(unsigned short, void *): a2uh_nc, \
void (*)(unsigned int, const char *): a2ui_c, \
void (*)(unsigned int, const void *): a2ui_c, \
void (*)(unsigned int, char *): a2ui_nc, \
void (*)(unsigned int, void *): a2ui_nc, \
void (*)(unsigned long, const char *): a2ul_c, \
void (*)(unsigned long, const void *): a2ul_c, \
void (*)(unsigned long, char *): a2ul_nc, \
void (*)(unsigned long, void *): a2ul_nc, \
void (*)(unsigned long long, const char *): a2ull_c, \
void (*)(unsigned long long, const void *): a2ull_c, \
void (*)(unsigned long long, char *): a2ull_nc, \
void (*)(unsigned long long, void *): a2ull_nc \
)(n, s, __VA_ARGS__) \
)
#endif // include guard

7
lib/atoi/a2i/a2s.c Normal file
View File

@ -0,0 +1,7 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/a2i/a2s.h"

20
lib/atoi/a2i/a2s.h Normal file
View File

@ -0,0 +1,20 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_H_
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_H_
#include <config.h>
#include "atoi/a2i/a2i.h"
#define a2sh(...) a2i(short, __VA_ARGS__)
#define a2si(...) a2i(int, __VA_ARGS__)
#define a2sl(...) a2i(long, __VA_ARGS__)
#define a2sll(...) a2i(long long, __VA_ARGS__)
#endif // include guard

17
lib/atoi/a2i/a2s_c.c Normal file
View File

@ -0,0 +1,17 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/a2i/a2s_c.h"
extern inline int a2sh_c(short *restrict n, const char *s,
const char **restrict endp, int base, short min, short max);
extern inline int a2si_c(int *restrict n, const char *s,
const char **restrict endp, int base, int min, int max);
extern inline int a2sl_c(long *restrict n, const char *s,
const char **restrict endp, int base, long min, long max);
extern inline int a2sll_c(long long *restrict n, const char *s,
const char **restrict endp, int base, long long min, long long max);

64
lib/atoi/a2i/a2s_c.h Normal file
View File

@ -0,0 +1,64 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_C_H_
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_C_H_
#include <config.h>
#include <errno.h>
#include <inttypes.h>
#include "atoi/a2i/a2s_nc.h"
#include "attr.h"
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2sh_c(short *restrict n, const char *s,
const char **restrict endp, int base, short min, short max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2si_c(int *restrict n, const char *s,
const char **restrict endp, int base, int min, int max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2sl_c(long *restrict n, const char *s,
const char **restrict endp, int base, long min, long max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2sll_c(long long *restrict n, const char *s,
const char **restrict endp, int base, long long min, long long max);
inline int
a2sh_c(short *restrict n, const char *s,
const char **restrict endp, int base, short min, short max)
{
return a2sh_nc(n, (char *) s, (char **) endp, base, min, max);
}
inline int
a2si_c(int *restrict n, const char *s,
const char **restrict endp, int base, int min, int max)
{
return a2si_nc(n, (char *) s, (char **) endp, base, min, max);
}
inline int
a2sl_c(long *restrict n, const char *s,
const char **restrict endp, int base, long min, long max)
{
return a2sl_nc(n, (char *) s, (char **) endp, base, min, max);
}
inline int
a2sll_c(long long *restrict n, const char *s,
const char **restrict endp, int base, long long min, long long max)
{
return a2sll_nc(n, (char *) s, (char **) endp, base, min, max);
}
#endif // include guard

17
lib/atoi/a2i/a2s_nc.c Normal file
View File

@ -0,0 +1,17 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/a2i/a2s_nc.h"
extern inline int a2sh_nc(short *restrict n, char *s,
char **restrict endp, int base, short min, short max);
extern inline int a2si_nc(int *restrict n, char *s,
char **restrict endp, int base, int min, int max);
extern inline int a2sl_nc(long *restrict n, char *s,
char **restrict endp, int base, long min, long max);
extern inline int a2sll_nc(long long *restrict n, char *s,
char **restrict endp, int base, long long min, long long max);

91
lib/atoi/a2i/a2s_nc.h Normal file
View File

@ -0,0 +1,91 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_NC_H_
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_NC_H_
#include <config.h>
#include <errno.h>
#include "atoi/strtoi/strtoi.h"
#include "attr.h"
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2sh_nc(short *restrict n, char *s,
char **restrict endp, int base, short min, short max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2si_nc(int *restrict n, char *s,
char **restrict endp, int base, int min, int max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2sl_nc(long *restrict n, char *s,
char **restrict endp, int base, long min, long max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2sll_nc(long long *restrict n, char *s,
char **restrict endp, int base, long long min, long long max);
inline int
a2sh_nc(short *restrict n, char *s,
char **restrict endp, int base, short min, short max)
{
int status;
*n = strtoi_(s, endp, base, min, max, &status);
if (status != 0) {
errno = status;
return -1;
}
return 0;
}
inline int
a2si_nc(int *restrict n, char *s,
char **restrict endp, int base, int min, int max)
{
int status;
*n = strtoi_(s, endp, base, min, max, &status);
if (status != 0) {
errno = status;
return -1;
}
return 0;
}
inline int
a2sl_nc(long *restrict n, char *s,
char **restrict endp, int base, long min, long max)
{
int status;
*n = strtoi_(s, endp, base, min, max, &status);
if (status != 0) {
errno = status;
return -1;
}
return 0;
}
inline int
a2sll_nc(long long *restrict n, char *s,
char **restrict endp, int base, long long min, long long max)
{
int status;
*n = strtoi_(s, endp, base, min, max, &status);
if (status != 0) {
errno = status;
return -1;
}
return 0;
}
#endif // include guard

7
lib/atoi/a2i/a2u.c Normal file
View File

@ -0,0 +1,7 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/a2i/a2u.h"

20
lib/atoi/a2i/a2u.h Normal file
View File

@ -0,0 +1,20 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_H_
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_H_
#include <config.h>
#include "atoi/a2i/a2i.h"
#define a2uh(...) a2i(unsigned short, __VA_ARGS__)
#define a2ui(...) a2i(unsigned int, __VA_ARGS__)
#define a2ul(...) a2i(unsigned long, __VA_ARGS__)
#define a2ull(...) a2i(unsigned long long, __VA_ARGS__)
#endif // include guard

19
lib/atoi/a2i/a2u_c.c Normal file
View File

@ -0,0 +1,19 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/a2i/a2u_c.h"
extern inline int a2uh_c(unsigned short *restrict n, const char *s,
const char **restrict endp, int base, unsigned short min,
unsigned short max);
extern inline int a2ui_c(unsigned int *restrict n, const char *s,
const char **restrict endp, int base, unsigned int min, unsigned int max);
extern inline int a2ul_c(unsigned long *restrict n, const char *s,
const char **restrict endp, int base, unsigned long min, unsigned long max);
extern inline int a2ull_c(unsigned long long *restrict n, const char *s,
const char **restrict endp, int base, unsigned long long min,
unsigned long long max);

65
lib/atoi/a2i/a2u_c.h Normal file
View File

@ -0,0 +1,65 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_C_H_
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_C_H_
#include <config.h>
#include "atoi/a2i/a2u_nc.h"
#include "attr.h"
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2uh_c(unsigned short *restrict n, const char *s,
const char **restrict endp, int base, unsigned short min,
unsigned short max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2ui_c(unsigned int *restrict n, const char *s,
const char **restrict endp, int base, unsigned int min, unsigned int max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2ul_c(unsigned long *restrict n, const char *s,
const char **restrict endp, int base, unsigned long min, unsigned long max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2ull_c(unsigned long long *restrict n, const char *s,
const char **restrict endp, int base, unsigned long long min,
unsigned long long max);
inline int
a2uh_c(unsigned short *restrict n, const char *s,
const char **restrict endp, int base, unsigned short min,
unsigned short max)
{
return a2uh_nc(n, (char *) s, (char **) endp, base, min, max);
}
inline int
a2ui_c(unsigned int *restrict n, const char *s,
const char **restrict endp, int base, unsigned int min, unsigned int max)
{
return a2ui_nc(n, (char *) s, (char **) endp, base, min, max);
}
inline int
a2ul_c(unsigned long *restrict n, const char *s,
const char **restrict endp, int base, unsigned long min, unsigned long max)
{
return a2ul_nc(n, (char *) s, (char **) endp, base, min, max);
}
inline int
a2ull_c(unsigned long long *restrict n, const char *s,
const char **restrict endp, int base, unsigned long long min,
unsigned long long max)
{
return a2ull_nc(n, (char *) s, (char **) endp, base, min, max);
}
#endif // include guard

18
lib/atoi/a2i/a2u_nc.c Normal file
View File

@ -0,0 +1,18 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/a2i/a2u_nc.h"
extern inline int a2uh_nc(unsigned short *restrict n, char *s,
char **restrict endp, int base, unsigned short min, unsigned short max);
extern inline int a2ui_nc(unsigned int *restrict n, char *s,
char **restrict endp, int base, unsigned int min, unsigned int max);
extern inline int a2ul_nc(unsigned long *restrict n, char *s,
char **restrict endp, int base, unsigned long min, unsigned long max);
extern inline int a2ull_nc(unsigned long long *restrict n, char *s,
char **restrict endp, int base, unsigned long long min,
unsigned long long max);

94
lib/atoi/a2i/a2u_nc.h Normal file
View File

@ -0,0 +1,94 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_NC_H_
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_NC_H_
#include <config.h>
#include <errno.h>
#include "atoi/strtoi/strtou_noneg.h"
#include "attr.h"
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2uh_nc(unsigned short *restrict n, char *s,
char **restrict endp, int base, unsigned short min, unsigned short max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2ui_nc(unsigned int *restrict n, char *s,
char **restrict endp, int base, unsigned int min, unsigned int max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2ul_nc(unsigned long *restrict n, char *s,
char **restrict endp, int base, unsigned long min, unsigned long max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2ull_nc(unsigned long long *restrict n, char *s,
char **restrict endp, int base, unsigned long long min,
unsigned long long max);
inline int
a2uh_nc(unsigned short *restrict n, char *s,
char **restrict endp, int base, unsigned short min,
unsigned short max)
{
int status;
*n = strtou_noneg(s, endp, base, min, max, &status);
if (status != 0) {
errno = status;
return -1;
}
return 0;
}
inline int
a2ui_nc(unsigned int *restrict n, char *s,
char **restrict endp, int base, unsigned int min, unsigned int max)
{
int status;
*n = strtou_noneg(s, endp, base, min, max, &status);
if (status != 0) {
errno = status;
return -1;
}
return 0;
}
inline int
a2ul_nc(unsigned long *restrict n, char *s,
char **restrict endp, int base, unsigned long min, unsigned long max)
{
int status;
*n = strtou_noneg(s, endp, base, min, max, &status);
if (status != 0) {
errno = status;
return -1;
}
return 0;
}
inline int
a2ull_nc(unsigned long long *restrict n, char *s,
char **restrict endp, int base, unsigned long long min,
unsigned long long max)
{
int status;
*n = strtou_noneg(s, endp, base, min, max, &status);
if (status != 0) {
errno = status;
return -1;
}
return 0;
}
#endif // include guard

View File

@ -3,7 +3,7 @@
// SPDX-License-Identifier: BSD-3-Clause
#include "config.h"
#include <config.h>
#include <sys/types.h>

View File

@ -7,13 +7,14 @@
#define SHADOW_INCLUDE_LIB_ATOI_GETNUM_H_
#include "config.h"
#include <config.h>
#include <limits.h>
#include <stddef.h>
#include <sys/types.h>
#include "atoi/a2i.h"
#include "atoi/a2i/a2i.h"
#include "atoi/a2i/a2s.h"
#include "attr.h"
#include "typetraits.h"

View File

@ -1,7 +1,8 @@
// SPDX-FileCopyrightText: 2007-2009, Nicolas François
// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include "config.h"
#include <config.h>
#include "atoi/a2i.h"
#include "atoi/str2i.h"

31
lib/atoi/str2i.h Normal file
View File

@ -0,0 +1,31 @@
// SPDX-FileCopyrightText: 2007-2009, Nicolas François
// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_STR2I_H_
#define SHADOW_INCLUDE_LIB_ATOI_STR2I_H_
#include <config.h>
#include <stddef.h>
#include "atoi/a2i/a2i.h"
#include "typetraits.h"
#define str2i(T, ...) a2i(T, __VA_ARGS__, NULL, 0, type_min(T), type_max(T))
#define str2sh(...) str2i(short, __VA_ARGS__)
#define str2si(...) str2i(int, __VA_ARGS__)
#define str2sl(...) str2i(long, __VA_ARGS__)
#define str2sll(...) str2i(long long, __VA_ARGS__)
#define str2uh(...) str2i(unsigned short, __VA_ARGS__)
#define str2ui(...) str2i(unsigned int, __VA_ARGS__)
#define str2ul(...) str2i(unsigned long, __VA_ARGS__)
#define str2ull(...) str2i(unsigned long long, __VA_ARGS__)
#endif // include guard

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: BSD-3-Clause
#include "config.h"
#include <config.h>
#include "atoi/strtoi/strtoi.h"

View File

@ -6,7 +6,7 @@
#define SHADOW_INCLUDE_LIB_ATOI_STRTOI_STRTOI_H_
#include "config.h"
#include <config.h>
#include <errno.h>
#include <inttypes.h>

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: BSD-3-Clause
#include "config.h"
#include <config.h>
#include "atoi/strtoi/strtou.h"

View File

@ -6,7 +6,7 @@
#define SHADOW_INCLUDE_LIB_ATOI_STRTOI_STRTOU_H_
#include "config.h"
#include <config.h>
#include <errno.h>
#include <inttypes.h>

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: BSD-3-Clause
#include "config.h"
#include <config.h>
#include "atoi/strtoi/strtou_noneg.h"

View File

@ -6,7 +6,7 @@
#define SHADOW_INCLUDE_LIB_ATOI_STRTOI_STRTOU_NONEG_H_
#include "config.h"
#include <config.h>
#include <errno.h>
#include <stddef.h>

View File

@ -5,38 +5,17 @@
#include "config.h"
#if !defined(__has_c_attribute)
# define __has_c_attribute(x) 0
#endif
#if __has_c_attribute(maybe_unused)
# define MAYBE_UNUSED [[maybe_unused]]
#else
# define MAYBE_UNUSED
#endif
#if __has_c_attribute(noreturn)
# define NORETURN [[noreturn]]
#else
# define NORETURN
#endif
#if __has_c_attribute(gnu::format)
#if (__GNUC__ >= 10)
# define MAYBE_UNUSED [[gnu::unused]]
# define NORETURN [[gnu::__noreturn__]]
# define format_attr(type, fmt, va) [[gnu::format(type, fmt, va)]]
#else
# define format_attr(type, fmt, va)
#endif
#if __has_c_attribute(gnu::access)
# define ATTR_ACCESS(...) [[gnu::access(__VA_ARGS__)]]
#else
# define ATTR_ACCESS(...)
#endif
#if __has_c_attribute(gnu::alloc_size)
# define ATTR_ALLOC_SIZE(...) [[gnu::alloc_size(__VA_ARGS__)]]
#else
# define MAYBE_UNUSED
# define NORETURN
# define format_attr(type, fmt, va)
# define ATTR_ACCESS(...)
# define ATTR_ALLOC_SIZE(...)
#endif
@ -46,17 +25,11 @@
# define ATTR_MALLOC(deallocator)
#endif
#if __has_c_attribute(gnu::null_terminated_string_arg)
#if (__GNUC__ >= 14)
# define ATTR_STRING(i) [[gnu::null_terminated_string_arg(i)]]
#else
# define ATTR_STRING(i)
#endif
#if __has_c_attribute(gnu::nonstring)
# define ATTR_NONSTRING [[gnu::nonstring]]
#else
# define ATTR_NONSTRING
#endif
#endif // include guard

View File

@ -11,7 +11,7 @@
*
*/
#include "config.h"
#include <config.h>
#ifdef WITH_AUDIT
@ -56,12 +56,13 @@ void audit_help_open (void)
*
* type - type of message. A list of possible values is available in
* "audit-records.h" file.
* pgname - program's name
* op - operation. "adding user", "changing finger info", "deleting group"
* 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.
*/
void audit_logger (int type, const char *op,
void audit_logger (int type, MAYBE_UNUSED const char *pgname, const char *op,
const char *name, unsigned int id,
shadow_audit_result result)
{
@ -104,10 +105,10 @@ audit_logger_with_group(int type, const char *op, const char *name,
len = strnlen(grp, sizeof(enc_group)/2);
if (audit_value_needs_encoding(grp, len)) {
stprintf_a(buf, "%s %s=%s", op, grp_type,
SNPRINTF(buf, "%s %s=%s", op, grp_type,
audit_encode_value(enc_group, grp, len));
} else {
stprintf_a(buf, "%s %s=\"%s\"", op, grp_type, grp);
SNPRINTF(buf, "%s %s=\"%s\"", op, grp_type, grp);
}
audit_log_acct_message(audit_fd, type, NULL, buf, name, id,

View File

@ -11,7 +11,7 @@
* --marekm
*/
#include "config.h"
#include <config.h>
#include <stddef.h>
#include <stdlib.h>

View File

@ -5,7 +5,7 @@
*/
#include "config.h"
#include <config.h>
#ident "$Id$"

View File

@ -9,7 +9,7 @@
#define SHADOW_INCLUDE_LIB_BIT_H_
#include "config.h"
#include <config.h>
#include <limits.h>

View File

@ -6,7 +6,7 @@
#define SHADOW_INCLUDE_LIB_CAST_H_
#include "config.h"
#include <config.h>
#define const_cast(T, p) _Generic(p, const T: (T) (p))

View File

@ -1,82 +0,0 @@
#include "config.h"
#include "chkhash.h"
#include <regex.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include "string/strcmp/streq.h"
#include "string/strcmp/strprefix.h"
/*
* match_regex - return true if match, false if not
*/
bool
match_regex(const char *pattern, const char *string)
{
regex_t regex;
int result;
if (regcomp(&regex, pattern, REG_EXTENDED) != 0)
return false;
result = regexec(&regex, string, 0, NULL, 0);
regfree(&regex);
return result == 0;
}
/*
* is_valid_hash - check if the string is a valid shadow(5) 2nd field.
*
* regex from: https://man.archlinux.org/man/crypt.5.en
*/
bool
is_valid_hash(const char *hash)
{
// Password temporarily locked
hash = strprefix(hash, "!") ?: hash;
// Passwordless account; discouraged
if (streq(hash, ""))
return true;
// Password permanently locked (and forgotten)
if (streq(hash, "*"))
return true;
// Minimum hash length
if (strlen(hash) < 13)
return false;
// Yescrypt: $y$ + algorithm parameters + $ + salt + $ + 43-char (minimum) hash
if (match_regex("^\\$y\\$[./A-Za-z0-9]+\\$[./A-Za-z0-9]{1,86}\\$[./A-Za-z0-9]{43}$", hash))
return true;
// Bcrypt: $2[abxy]$ + 2-digit cost + $ + 53-char hash
if (match_regex("^\\$2[abxy]\\$[0-9]{2}\\$[./A-Za-z0-9]{53}$", hash))
return true;
// SHA-512: $6$ + salt + $ + 86-char hash
if (match_regex("^\\$6\\$(rounds=[1-9][0-9]{3,8}\\$)?[^$:\\n]{1,16}\\$[./A-Za-z0-9]{86}$", hash))
return true;
// SHA-256: $5$ + salt + $ + 43-char hash
if (match_regex("^\\$5\\$(rounds=[1-9][0-9]{3,8}\\$)?[^$:\\n]{1,16}\\$[./A-Za-z0-9]{43}$", hash))
return true;
// MD5: $1$ + salt + $ + 22-char hash
if (match_regex("^\\$1\\$[^$:\\n]{1,8}\\$[./A-Za-z0-9]{22}$", hash))
return true;
// DES: exactly 13 characters from [A-Za-z0-9./]
if (match_regex("^[./A-Za-z0-9]{13}$", hash))
return true;
// Not a valid hash
return false;
}

View File

@ -1,13 +0,0 @@
#ifndef SHADOW_INCLUDE_CHKHASH_H
#define SHADOW_INCLUDE_CHKHASH_H
#include "config.h"
#include <stdbool.h>
bool is_valid_hash(const char *hash);
#endif

View File

@ -13,13 +13,12 @@
* true - OK
* false - bad name
* errors:
* EINVAL Invalid name
* EILSEQ Invalid name character sequence (acceptable with --badname)
* EINVAL Invalid name characters or sequences
* EOVERFLOW Name longer than maximum size
*/
#include "config.h"
#include <config.h>
#ident "$Id$"
@ -28,15 +27,12 @@
#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include "defines.h"
#include "chkname.h"
#include "string/ctype/strchrisascii/strchriscntrl.h"
#include "string/ctype/strisascii/strisdigit.h"
#include "string/strcmp/streq.h"
#include "string/strcmp/strcaseeq.h"
#ifndef LOGIN_NAME_MAX
@ -63,37 +59,35 @@ login_name_max_size(void)
static bool
is_valid_name(const char *name)
{
if (streq(name, "")
|| streq(name, ".")
|| streq(name, "..")
|| strspn(name, "-")
|| strpbrk(name, " \"#',/:;")
|| strchriscntrl(name)
|| strisdigit(name))
{
errno = EINVAL;
return false;
}
if (allow_bad_names) {
return true;
}
/*
* User/group names must match BRE regex:
* [a-zA-Z0-9_.][a-zA-Z0-9_.-]*$\?
*
* as a non-POSIX, extension, allow "$" as the last char for
* sake of Samba 3.x "add machine script"
*/
* User/group names must match BRE regex:
* [a-zA-Z0-9_.][a-zA-Z0-9_.-]*$\?
*
* as a non-POSIX, extension, allow "$" as the last char for
* sake of Samba 3.x "add machine script"
*
* Also do not allow fully numeric names or just "." or "..".
*/
if (!((*name >= 'a' && *name <= 'z') ||
if (strisdigit(name)) {
errno = EINVAL;
return false;
}
if (streq(name, "") ||
streq(name, ".") ||
streq(name, "..") ||
!((*name >= 'a' && *name <= 'z') ||
(*name >= 'A' && *name <= 'Z') ||
(*name >= '0' && *name <= '9') ||
*name == '_' ||
*name == '.'))
{
errno = EILSEQ;
errno = EINVAL;
return false;
}
@ -107,7 +101,7 @@ is_valid_name(const char *name)
streq(name, "$")
))
{
errno = EILSEQ;
errno = EINVAL;
return false;
}
}

View File

@ -21,7 +21,7 @@
*/
#include "config.h"
#include <config.h>
#include <stdbool.h>
#include <stddef.h>

View File

@ -7,7 +7,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "config.h"
#include <config.h>
#ident "$Id$"

View File

@ -7,7 +7,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "config.h"
#include <config.h>
#ident "$Id$"
@ -53,8 +53,9 @@ void chown_tty (const struct passwd *info)
if ( (fchown (STDIN_FILENO, info->pw_uid, gid) != 0)
|| (fchmod (STDIN_FILENO, getdef_num ("TTYPERM", 0600)) != 0)) {
int err = errno;
FILE *shadow_logfd = log_get_logfd();
fprintf (log_get_logfd(),
fprintf (shadow_logfd,
_("Unable to change owner or mode of tty stdin: %s"),
strerror (err));
SYSLOG ((LOG_WARN,

View File

@ -4,7 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "config.h"
#include <config.h>
#include <assert.h>
#include <stdio.h>

View File

@ -4,7 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "config.h"
#include <config.h>
#include <assert.h>
#include <stdio.h>
@ -27,7 +27,7 @@ void cleanup_report_add_group (void *group_name)
SYSLOG ((LOG_ERR, "failed to add group %s", name));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_GROUP,
audit_logger (AUDIT_ADD_GROUP, log_get_progname(),
"",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
@ -45,7 +45,7 @@ void cleanup_report_del_group (void *group_name)
SYSLOG ((LOG_ERR, "failed to remove group %s", name));
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_GROUP,
audit_logger (AUDIT_DEL_GROUP, log_get_progname(),
"",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
@ -62,7 +62,7 @@ void cleanup_report_mod_group (void *cleanup_info)
gr_dbname (),
info->action));
#ifdef WITH_AUDIT
audit_logger (AUDIT_GRP_MGMT,
audit_logger (AUDIT_GRP_MGMT, log_get_progname(),
info->audit_msg,
info->name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
@ -80,7 +80,7 @@ void cleanup_report_mod_gshadow (void *cleanup_info)
sgr_dbname (),
info->action));
#ifdef WITH_AUDIT
audit_logger (AUDIT_GRP_MGMT,
audit_logger (AUDIT_GRP_MGMT, log_get_progname(),
info->audit_msg,
info->name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
@ -100,7 +100,7 @@ void cleanup_report_add_group_group (void *group_name)
SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, gr_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_GROUP,
audit_logger (AUDIT_ADD_GROUP, log_get_progname(),
"adding-group",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
@ -120,7 +120,7 @@ void cleanup_report_add_group_gshadow (void *group_name)
SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, sgr_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_GRP_MGMT,
audit_logger (AUDIT_GRP_MGMT, log_get_progname(),
"adding-shadow-group",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
@ -143,7 +143,7 @@ void cleanup_report_del_group_group (void *group_name)
"failed to remove group %s from %s",
name, gr_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_GROUP,
audit_logger (AUDIT_DEL_GROUP, log_get_progname(),
"removing-group",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
@ -166,7 +166,7 @@ void cleanup_report_del_group_gshadow (void *group_name)
"failed to remove group %s from %s",
name, sgr_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_GRP_MGMT,
audit_logger (AUDIT_GRP_MGMT, log_get_progname(),
"removing-shadow-group",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
@ -179,11 +179,9 @@ void cleanup_report_del_group_gshadow (void *group_name)
*
* It should be registered after the group file is successfully locked.
*/
void cleanup_unlock_group (void *process_selinux)
void cleanup_unlock_group (MAYBE_UNUSED void *arg)
{
bool process = *((bool *) process_selinux);
if (gr_unlock (process) == 0) {
if (gr_unlock () == 0) {
fprintf (log_get_logfd(),
_("%s: failed to unlock %s\n"),
log_get_progname(), gr_dbname ());
@ -201,11 +199,9 @@ void cleanup_unlock_group (void *process_selinux)
*
* It should be registered after the gshadow file is successfully locked.
*/
void cleanup_unlock_gshadow (void *process_selinux)
void cleanup_unlock_gshadow (MAYBE_UNUSED void *arg)
{
bool process = *((bool *) process_selinux);
if (sgr_unlock (process) == 0) {
if (sgr_unlock () == 0) {
fprintf (log_get_logfd(),
_("%s: failed to unlock %s\n"),
log_get_progname(), sgr_dbname ());

View File

@ -4,11 +4,12 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "config.h"
#include <config.h>
#include <assert.h>
#include <stdio.h>
#include "attr.h"
#include "defines.h"
#include "pwio.h"
#include "shadowio.h"
@ -26,7 +27,7 @@ void cleanup_report_add_user (void *user_name)
SYSLOG ((LOG_ERR, "failed to add user %s", name));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER,
audit_logger (AUDIT_ADD_USER, log_get_progname(),
"",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
@ -43,7 +44,7 @@ void cleanup_report_mod_passwd (void *cleanup_info)
pw_dbname (),
info->action));
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_MGMT,
audit_logger (AUDIT_USER_MGMT, log_get_progname(),
info->audit_msg,
info->name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
@ -63,7 +64,7 @@ void cleanup_report_add_user_passwd (void *user_name)
SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, pw_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER,
audit_logger (AUDIT_ADD_USER, log_get_progname(),
"adding-user",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
@ -83,7 +84,7 @@ void cleanup_report_add_user_shadow (void *user_name)
SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, spw_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_MGMT,
audit_logger (AUDIT_USER_MGMT, log_get_progname(),
"adding-shadow-user",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
@ -95,11 +96,9 @@ void cleanup_report_add_user_shadow (void *user_name)
*
* It should be registered after the passwd database is successfully locked.
*/
void cleanup_unlock_passwd (void *process_selinux)
void cleanup_unlock_passwd (MAYBE_UNUSED void *arg)
{
bool process = *((bool *) process_selinux);
if (pw_unlock (process) == 0) {
if (pw_unlock () == 0) {
fprintf (log_get_logfd(),
_("%s: failed to unlock %s\n"),
log_get_progname(), pw_dbname ());
@ -116,11 +115,9 @@ void cleanup_unlock_passwd (void *process_selinux)
*
* It should be registered after the shadow database is successfully locked.
*/
void cleanup_unlock_shadow (void *process_selinux)
void cleanup_unlock_shadow (MAYBE_UNUSED void *arg)
{
bool process = *((bool *) process_selinux);
if (spw_unlock (process) == 0) {
if (spw_unlock () == 0) {
fprintf (log_get_logfd(),
_("%s: failed to unlock %s\n"),
log_get_progname(), spw_dbname ());

View File

@ -7,7 +7,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "config.h"
#include <config.h>
#ident "$Id$"
@ -16,7 +16,6 @@
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
@ -24,31 +23,32 @@
#include <utime.h>
#include "alloc/malloc.h"
#include "alloc/reallocf.h"
#include "atoi/getnum.h"
#include "commonio.h"
#include "defines.h"
#include "fs/mkstemp/fmkomstemp.h"
#include "nscd.h"
#ifdef WITH_TCB
#include <tcb.h>
#endif /* WITH_TCB */
#include "prototypes.h"
#include "shadowlog.h"
#include "shadowlog_internal.h"
#include "sssd.h"
#include "string/memset/memzero.h"
#include "string/sprintf/aprintf.h"
#include "string/sprintf/snprintf.h"
#include "string/strcmp/streq.h"
#include "string/strcmp/strprefix.h"
#include "string/strerrno.h"
#include "string/strtok/stpsep.h"
/* local function prototypes */
static int lrename (const char *, const char *);
static int check_link_count (const char *file, bool log);
static int do_lock_file (const char *file, const char *lock, bool log);
static /*@null@*/ /*@dependent@*/FILE *fmkstemp_set_perms (
char *name,
static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms (
const char *name,
const char *mode,
const struct stat *sb);
static int create_backup (const char *, FILE *);
static void free_linked_list (struct commonio_db *);
@ -68,24 +68,50 @@ static /*@dependent@*/ /*@null@*/struct commonio_entry *next_entry_by_name (
static int lock_count = 0;
static bool nscd_need_reload = false;
/*
* Simple rename(P) alternative that attempts to rename to symlink
* target.
*/
int lrename (const char *old, const char *new)
{
int res;
char *r = NULL;
struct stat sb;
if (lstat (new, &sb) == 0 && S_ISLNK (sb.st_mode)) {
r = realpath (new, NULL);
if (NULL == r) {
perror ("realpath in lrename()");
} else {
new = r;
}
}
res = rename (old, new);
free (r);
return res;
}
static int check_link_count (const char *file, bool log)
{
struct stat sb;
if (stat (file, &sb) != 0) {
if (log) {
(void) fprintf (log_get_logfd(),
(void) fprintf (shadow_logfd,
"%s: %s file stat error: %s\n",
log_get_progname(), file, strerrno());
shadow_progname, file, strerror (errno));
}
return 0;
}
if (sb.st_nlink != 2) {
if (log) {
fprintf(log_get_logfd(),
fprintf(shadow_logfd,
"%s: %s: lock file already used (nlink: %ju)\n",
log_get_progname(), file, (uintmax_t) sb.st_nlink);
shadow_progname, file, (uintmax_t) sb.st_nlink);
}
return 0;
}
@ -105,21 +131,21 @@ static int do_lock_file (const char *file, const char *lock, bool log)
fd = open (file, O_CREAT | O_TRUNC | O_WRONLY, 0600);
if (-1 == fd) {
if (log) {
(void) fprintf (log_get_logfd(),
(void) fprintf (shadow_logfd,
"%s: %s: %s\n",
log_get_progname(), file, strerrno());
shadow_progname, file, strerror (errno));
}
return 0;
}
pid = getpid ();
stprintf_a(buf, "%lu", (unsigned long) pid);
SNPRINTF(buf, "%lu", (unsigned long) pid);
len = (ssize_t) strlen (buf) + 1;
if (write_full(fd, buf, len) == -1) {
if (log) {
(void) fprintf (log_get_logfd(),
(void) fprintf (shadow_logfd,
"%s: %s file write error: %s\n",
log_get_progname(), file, strerrno());
shadow_progname, file, strerror (errno));
}
(void) close (fd);
unlink (file);
@ -127,9 +153,9 @@ static int do_lock_file (const char *file, const char *lock, bool log)
}
if (fdatasync (fd) == -1) {
if (log) {
(void) fprintf (log_get_logfd(),
(void) fprintf (shadow_logfd,
"%s: %s file sync error: %s\n",
log_get_progname(), file, strerrno());
shadow_progname, file, strerror (errno));
}
(void) close (fd);
unlink (file);
@ -146,21 +172,21 @@ static int do_lock_file (const char *file, const char *lock, bool log)
fd = open (lock, O_RDWR);
if (-1 == fd) {
if (log) {
(void) fprintf (log_get_logfd(),
(void) fprintf (shadow_logfd,
"%s: %s: %s\n",
log_get_progname(), lock, strerrno());
shadow_progname, lock, strerror (errno));
}
unlink (file);
errno = EINVAL;
return 0;
}
len = read(fd, buf, sizeof(buf) - 1);
len = read (fd, buf, sizeof (buf) - 1);
close (fd);
if (len <= 0) {
if (log) {
(void) fprintf (log_get_logfd(),
(void) fprintf (shadow_logfd,
"%s: existing lock file %s without a PID\n",
log_get_progname(), lock);
shadow_progname, lock);
}
unlink (file);
errno = EINVAL;
@ -169,9 +195,9 @@ static int do_lock_file (const char *file, const char *lock, bool log)
stpcpy(&buf[len], "");
if (get_pid(buf, &pid) == -1) {
if (log) {
(void) fprintf (log_get_logfd(),
(void) fprintf (shadow_logfd,
"%s: existing lock file %s with an invalid PID '%s'\n",
log_get_progname(), lock, buf);
shadow_progname, lock, buf);
}
unlink (file);
errno = EINVAL;
@ -179,9 +205,9 @@ static int do_lock_file (const char *file, const char *lock, bool log)
}
if (kill (pid, 0) == 0) {
if (log) {
(void) fprintf (log_get_logfd(),
(void) fprintf (shadow_logfd,
"%s: lock %s already used by PID %lu\n",
log_get_progname(), lock, (unsigned long) pid);
shadow_progname, lock, (unsigned long) pid);
}
unlink (file);
errno = EEXIST;
@ -189,9 +215,9 @@ static int do_lock_file (const char *file, const char *lock, bool log)
}
if (unlink (lock) != 0) {
if (log) {
(void) fprintf (log_get_logfd(),
(void) fprintf (shadow_logfd,
"%s: cannot get lock %s: %s\n",
log_get_progname(), lock, strerrno());
shadow_progname, lock, strerror (errno));
}
unlink (file);
return 0;
@ -202,9 +228,9 @@ static int do_lock_file (const char *file, const char *lock, bool log)
retval = check_link_count (file, log);
} else {
if (log) {
(void) fprintf (log_get_logfd(),
(void) fprintf (shadow_logfd,
"%s: cannot get lock %s: %s\n",
log_get_progname(), lock, strerrno());
shadow_progname, lock, strerror (errno));
}
}
@ -213,13 +239,17 @@ static int do_lock_file (const char *file, const char *lock, bool log)
}
static /*@null@*/ /*@dependent@*/FILE *fmkstemp_set_perms (
char *name,
static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms (
const char *name,
const char *mode,
const struct stat *sb)
{
FILE *fp;
mode_t mask;
fp = fmkomstemp(name, 0, 0600);
mask = umask (0777);
fp = fopen (name, mode);
(void) umask (mask);
if (NULL == fp) {
return NULL;
}
@ -235,26 +265,24 @@ static /*@null@*/ /*@dependent@*/FILE *fmkstemp_set_perms (
fail:
(void) fclose (fp);
/* fmkstemp_set_perms is used for intermediate files */
/* fopen_set_perms is used for intermediate files */
(void) unlink (name);
return NULL;
}
static int create_backup (const char *name, FILE * fp)
static int create_backup (const char *backup, FILE * fp)
{
char tmpf[PATH_MAX], target[PATH_MAX];
struct stat sb;
struct utimbuf ub;
FILE *bkfp;
int c;
stprintf_a(tmpf, "%s.cioXXXXXX", name);
if (fstat (fileno (fp), &sb) != 0) {
return -1;
}
bkfp = fmkstemp_set_perms(tmpf, &sb);
bkfp = fopen_set_perms (backup, "w", &sb);
if (NULL == bkfp) {
return -1;
}
@ -270,28 +298,22 @@ static int create_backup (const char *name, FILE * fp)
}
if ((c != EOF) || (ferror (fp) != 0) || (fflush (bkfp) != 0)) {
(void) fclose (bkfp);
unlink(tmpf);
/* FIXME: unlink the backup file? */
return -1;
}
if (fsync (fileno (bkfp)) != 0) {
(void) fclose (bkfp);
unlink(tmpf);
/* FIXME: unlink the backup file? */
return -1;
}
if (fclose (bkfp) != 0) {
unlink(tmpf);
return -1;
}
stprintf_a(target, "%s-", name);
if (rename(tmpf, target) != 0) {
unlink(tmpf);
/* FIXME: unlink the backup file? */
return -1;
}
ub.actime = sb.st_atime;
ub.modtime = sb.st_mtime;
(void) utime(target, &ub);
(void) utime (backup, &ub);
return 0;
}
@ -306,8 +328,9 @@ static void free_linked_list (struct commonio_db *db)
free (p->line);
if (NULL != p->eptr)
db->ops->cio_free(p->eptr);
if (NULL != p->eptr) {
db->ops->free (p->eptr);
}
free (p);
}
@ -317,7 +340,7 @@ static void free_linked_list (struct commonio_db *db)
int commonio_setname (struct commonio_db *db, const char *name)
{
stprintf_a(db->filename, "%s", name);
SNPRINTF(db->filename, "%s", name);
db->setname = true;
return 1;
}
@ -379,9 +402,9 @@ int commonio_lock (struct commonio_db *db)
if (0 == lock_count) {
if (lckpwdf () == -1) {
if (geteuid () != 0) {
(void) fprintf (log_get_logfd(),
(void) fprintf (shadow_logfd,
"%s: Permission denied.\n",
log_get_progname());
shadow_progname);
}
return 0; /* failure */
}
@ -415,8 +438,8 @@ int commonio_lock (struct commonio_db *db)
}
/* no unnecessary retries on "permission denied" errors */
if (geteuid () != 0) {
(void) fprintf (log_get_logfd(), "%s: Permission denied.\n",
log_get_progname());
(void) fprintf (shadow_logfd, "%s: Permission denied.\n",
shadow_progname);
return 0;
}
}
@ -444,13 +467,13 @@ static void dec_lock_count (void)
}
int commonio_unlock (struct commonio_db *db, bool process_selinux)
int commonio_unlock (struct commonio_db *db)
{
char lock[1029];
if (db->isopen) {
db->readonly = true;
if (commonio_close (db, process_selinux) == 0) {
if (commonio_close (db) == 0) {
if (db->locked) {
dec_lock_count ();
}
@ -463,7 +486,7 @@ int commonio_unlock (struct commonio_db *db, bool process_selinux)
* then call ulckpwdf() (if used) on last unlock.
*/
db->locked = false;
stprintf_a(lock, "%s.lock", db->filename);
SNPRINTF(lock, "%s.lock", db->filename);
unlink (lock);
dec_lock_count ();
return 1;
@ -525,7 +548,7 @@ static void add_one_entry_nis (struct commonio_db *db,
struct commonio_entry *p;
for (p = db->head; NULL != p; p = p->next) {
if (name_is_nis (p->eptr ? db->ops->cio_getname(p->eptr)
if (name_is_nis (p->eptr ? db->ops->getname (p->eptr)
: p->line)) {
/*@-mustfreeonly@*/
newp->next = p;
@ -544,9 +567,11 @@ static void add_one_entry_nis (struct commonio_db *db,
}
#endif /* KEEP_NIS_AT_END */
/* Initial buffer size, as well as increment if not sufficient
(for reading very long lines in group files). */
#define BUFLEN 4096
int
commonio_open(struct commonio_db *db, int mode)
int commonio_open (struct commonio_db *db, int mode)
{
char *buf;
char *line;
@ -608,12 +633,31 @@ commonio_open(struct commonio_db *db, int mode)
return 0;
}
buf = NULL;
while (getline(&buf, &buflen, db->fp) != -1) {
buflen = BUFLEN;
buf = MALLOC(buflen, char);
if (NULL == buf)
goto cleanup_errno;
while (db->ops->fgets (buf, buflen, db->fp) == buf) {
struct commonio_entry *p;
if (stpsep(buf, "\n") == NULL)
goto cleanup_buf;
while ( (strrchr (buf, '\n') == NULL)
&& (feof (db->fp) == 0)) {
size_t len;
buflen += BUFLEN;
buf = REALLOCF(buf, buflen, char);
if (NULL == buf)
goto cleanup_errno;
len = strlen (buf);
if (db->ops->fgets (buf + len,
(int) (buflen - len),
db->fp) == NULL) {
goto cleanup_buf;
}
}
stpsep(buf, "\n");
line = strdup (buf);
if (NULL == line) {
@ -623,16 +667,16 @@ commonio_open(struct commonio_db *db, int mode)
if (name_is_nis (line)) {
eptr = NULL;
} else {
eptr = db->ops->cio_parse(line);
eptr = db->ops->parse (line);
if (NULL != eptr) {
eptr = db->ops->cio_dup(eptr);
eptr = db->ops->dup (eptr);
if (NULL == eptr) {
goto cleanup_line;
}
}
}
p = malloc_T(1, struct commonio_entry);
p = MALLOC(1, struct commonio_entry);
if (NULL == p) {
goto cleanup_entry;
}
@ -650,7 +694,7 @@ commonio_open(struct commonio_db *db, int mode)
goto cleanup_errno;
}
if ((NULL != db->ops->cio_open_hook) && (db->ops->cio_open_hook() == 0)) {
if ((NULL != db->ops->open_hook) && (db->ops->open_hook () == 0)) {
goto cleanup_errno;
}
@ -658,8 +702,9 @@ commonio_open(struct commonio_db *db, int mode)
return 1;
cleanup_entry:
if (NULL != eptr)
db->ops->cio_free(eptr);
if (NULL != eptr) {
db->ops->free (eptr);
}
cleanup_line:
free (line);
cleanup_buf:
@ -674,7 +719,6 @@ commonio_open(struct commonio_db *db, int mode)
return 0;
}
/*
* Sort given db according to cmp function (usually compares uids)
*/
@ -708,7 +752,7 @@ commonio_sort (struct commonio_db *db, int (*cmp) (const void *, const void *))
return 0;
}
entries = malloc_T(n, struct commonio_entry *);
entries = MALLOC(n, struct commonio_entry *);
if (entries == NULL) {
return -1;
}
@ -727,7 +771,7 @@ commonio_sort (struct commonio_db *db, int (*cmp) (const void *, const void *))
entries[n] = ptr;
n++;
}
qsort(entries, n, sizeof(struct commonio_entry *), cmp);
qsort (entries, n, sizeof (struct commonio_entry *), cmp);
/* Take care of the head and tail separately */
db->head = entries[0];
@ -776,14 +820,14 @@ int commonio_sort_wrt (struct commonio_db *shadow,
if (NULL == pw_ptr->eptr) {
continue;
}
name = passwd->ops->cio_getname(pw_ptr->eptr);
name = passwd->ops->getname (pw_ptr->eptr);
for (spw_ptr = shadow->head;
NULL != spw_ptr;
spw_ptr = spw_ptr->next) {
if (NULL == spw_ptr->eptr) {
continue;
}
if (streq(name, shadow->ops->cio_getname(spw_ptr->eptr)))
if (streq(name, shadow->ops->getname(spw_ptr->eptr)))
break;
}
if (NULL == spw_ptr) {
@ -825,13 +869,13 @@ static int write_all (const struct commonio_db *db)
if (p->changed) {
eptr = p->eptr;
assert (NULL != eptr);
if (db->ops->cio_put(eptr, db->fp) != 0) {
if (db->ops->put (eptr, db->fp) != 0) {
return -1;
}
} else if (NULL != p->line) {
if (fputs(p->line, db->fp) == EOF)
if (db->ops->fputs (p->line, db->fp) == EOF) {
return -1;
}
if (putc ('\n', db->fp) == EOF) {
return -1;
}
@ -841,11 +885,10 @@ static int write_all (const struct commonio_db *db)
}
int
commonio_close(struct commonio_db *db, MAYBE_UNUSED bool process_selinux)
int commonio_close (struct commonio_db *db)
{
bool errors = false;
char tmpf[PATH_MAX];
char buf[1024];
struct stat sb;
if (!db->isopen) {
@ -862,11 +905,11 @@ commonio_close(struct commonio_db *db, MAYBE_UNUSED bool process_selinux)
goto success;
}
if ((NULL != db->ops->cio_close_hook) && (db->ops->cio_close_hook() == 0)) {
if ((NULL != db->ops->close_hook) && (db->ops->close_hook () == 0)) {
goto fail;
}
memzero(&sb, sizeof(sb));
memzero (&sb, sizeof sb);
if (NULL != db->fp) {
if (fstat (fileno (db->fp), &sb) != 0) {
(void) fclose (db->fp);
@ -877,13 +920,18 @@ commonio_close(struct commonio_db *db, MAYBE_UNUSED bool process_selinux)
/*
* Create backup file.
*/
if (SNPRINTF(buf, "%s-", db->filename) == -1) {
(void) fclose (db->fp);
db->fp = NULL;
goto fail;
}
#ifdef WITH_SELINUX
if (process_selinux
&& set_selinux_file_context (db->filename, S_IFREG) != 0) {
if (set_selinux_file_context (db->filename, S_IFREG) != 0) {
errors = true;
}
#endif
if (create_backup(db->filename, db->fp) != 0) {
if (create_backup (buf, db->fp) != 0) {
errors = true;
}
@ -894,8 +942,7 @@ commonio_close(struct commonio_db *db, MAYBE_UNUSED bool process_selinux)
db->fp = NULL;
#ifdef WITH_SELINUX
if (process_selinux
&& reset_selinux_file_context () != 0) {
if (reset_selinux_file_context () != 0) {
errors = true;
}
#endif
@ -910,17 +957,16 @@ commonio_close(struct commonio_db *db, MAYBE_UNUSED bool process_selinux)
sb.st_gid = db->st_gid;
}
if (stprintf_a(tmpf, "%s.cioXXXXXX", db->filename) == -1)
if (SNPRINTF(buf, "%s+", db->filename) == -1)
goto fail;
#ifdef WITH_SELINUX
if (process_selinux
&& set_selinux_file_context (db->filename, S_IFREG) != 0) {
if (set_selinux_file_context (db->filename, S_IFREG) != 0) {
errors = true;
}
#endif
db->fp = fmkstemp_set_perms(tmpf, &sb);
db->fp = fopen_set_perms (buf, "w", &sb);
if (NULL == db->fp) {
goto fail;
}
@ -944,17 +990,16 @@ commonio_close(struct commonio_db *db, MAYBE_UNUSED bool process_selinux)
db->fp = NULL;
if (errors) {
unlink(tmpf);
unlink (buf);
goto fail;
}
if (rename(tmpf, db->filename) != 0) {
if (lrename (buf, db->filename) != 0) {
goto fail;
}
#ifdef WITH_SELINUX
if (process_selinux
&& reset_selinux_file_context () != 0) {
if (reset_selinux_file_context () != 0) {
goto fail;
}
#endif
@ -984,7 +1029,7 @@ static /*@dependent@*/ /*@null@*/struct commonio_entry *next_entry_by_name (
for (p = pos; NULL != p; p = p->next) {
ep = p->eptr;
if ( (NULL != ep)
&& streq(db->ops->cio_getname(ep), name)) {
&& streq(db->ops->getname(ep), name)) {
break;
}
}
@ -1008,19 +1053,19 @@ int commonio_update (struct commonio_db *db, const void *eptr)
errno = EINVAL;
return 0;
}
nentry = db->ops->cio_dup(eptr);
nentry = db->ops->dup (eptr);
if (NULL == nentry) {
errno = ENOMEM;
return 0;
}
p = find_entry_by_name(db, db->ops->cio_getname(eptr));
p = find_entry_by_name (db, db->ops->getname (eptr));
if (NULL != p) {
if (next_entry_by_name(db, p->next, db->ops->cio_getname(eptr)) != NULL) {
fprintf(log_get_logfd(), _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), db->ops->cio_getname(eptr), db->filename);
db->ops->cio_free(nentry);
if (next_entry_by_name (db, p->next, db->ops->getname (eptr)) != NULL) {
fprintf (shadow_logfd, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), db->ops->getname (eptr), db->filename);
db->ops->free (nentry);
return 0;
}
db->ops->cio_free(p->eptr);
db->ops->free (p->eptr);
p->eptr = nentry;
p->changed = true;
db->cursor = p;
@ -1029,9 +1074,9 @@ int commonio_update (struct commonio_db *db, const void *eptr)
return 1;
}
/* not found, new entry */
p = malloc_T(1, struct commonio_entry);
p = MALLOC(1, struct commonio_entry);
if (NULL == p) {
db->ops->cio_free(nentry);
db->ops->free (nentry);
errno = ENOMEM;
return 0;
}
@ -1060,15 +1105,15 @@ int commonio_append (struct commonio_db *db, const void *eptr)
errno = EINVAL;
return 0;
}
nentry = db->ops->cio_dup(eptr);
nentry = db->ops->dup (eptr);
if (NULL == nentry) {
errno = ENOMEM;
return 0;
}
/* new entry */
p = malloc_T(1, struct commonio_entry);
p = MALLOC(1, struct commonio_entry);
if (NULL == p) {
db->ops->cio_free(nentry);
db->ops->free (nentry);
errno = ENOMEM;
return 0;
}
@ -1121,7 +1166,7 @@ int commonio_remove (struct commonio_db *db, const char *name)
return 0;
}
if (next_entry_by_name (db, p->next, name) != NULL) {
fprintf (log_get_logfd(), _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), name, db->filename);
fprintf (shadow_logfd, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), name, db->filename);
return 0;
}
@ -1129,8 +1174,9 @@ int commonio_remove (struct commonio_db *db, const char *name)
free (p->line);
if (NULL != p->eptr)
db->ops->cio_free(p->eptr);
if (NULL != p->eptr) {
db->ops->free (p->eptr);
}
free(p);

View File

@ -35,30 +35,39 @@ 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 *(*cio_dup)(const void *);
/*@null@*/ /*@only@*/void *(*dup) (const void *);
/*
* free() the object including any strings pointed by it.
*/
void (*cio_free)(/*@only@*/void *);
void (*free)(/*@only@*/void *);
/*
* Return the name of the object (for example, pw_name
* for struct passwd).
*/
const char *(*cio_getname)(const void *);
const char *(*getname) (const void *);
/*
* Parse a string, return object (in static area -
* should be copied using the dup operation above).
*/
void *(*cio_parse)(const char *);
void *(*parse) (const char *);
/*
* Write the object to the file (this calls putpwent()
* for struct passwd, for example).
*/
int (*cio_put)(const void *, FILE *);
int (*put) (const void *, FILE *);
/*
* fgets and fputs (can be replaced by versions that
* understand line continuation conventions).
*/
ATTR_ACCESS(write_only, 1, 2)
/*@null@*/char *(*fgets)(/*@returned@*/char *restrict s, int n,
FILE *restrict stream);
int (*fputs) (const char *, FILE *);
/*
* open_hook and close_hook.
@ -66,8 +75,8 @@ struct commonio_ops {
* is open or before it is closed.
* They return 0 on failure and 1 on success.
*/
/*@null@*/int (*cio_open_hook)(void);
/*@null@*/int (*cio_close_hook)(void);
/*@null@*/int (*open_hook) (void);
/*@null@*/int (*close_hook) (void);
};
/*
@ -94,7 +103,7 @@ struct commonio_db {
#endif
/*
* Default permissions and owner for newly created data file.
*/
*/
mode_t st_mode;
uid_t st_uid;
gid_t st_gid;
@ -129,8 +138,8 @@ extern int commonio_append (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 int commonio_close (struct commonio_db *, bool);
extern int commonio_unlock (struct commonio_db *, bool);
extern int commonio_close (struct commonio_db *);
extern int commonio_unlock (struct commonio_db *);
extern void commonio_del_entry (struct commonio_db *,
const struct commonio_entry *);
extern int commonio_sort_wrt (struct commonio_db *shadow,

View File

@ -8,7 +8,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "config.h"
#include <config.h>
#include <stdio.h>
#include <string.h>
@ -52,7 +52,7 @@ is_listed(const char *cfgin, const char *tty, bool def)
if (*cons != '/') {
char *pbuf;
strtcpy_a(buf, cons);
STRTCPY(buf, cons);
pbuf = buf;
while (NULL != (s = strsep(&pbuf, ":"))) {
if (streq(s, tty)) {
@ -76,7 +76,7 @@ is_listed(const char *cfgin, const char *tty, bool def)
* See if this tty is listed in the console file.
*/
while (fgets(buf, sizeof(buf), fp) != NULL) {
while (fgets (buf, sizeof (buf), fp) != NULL) {
stpsep(buf, "\n");
if (streq(buf, tty)) {
(void) fclose (fp);

View File

@ -7,7 +7,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "config.h"
#include <config.h>
#ident "$Id$"
@ -19,7 +19,7 @@
#include <stdio.h>
#include <string.h>
#include "alloc/malloc.h"
#include "alloc/x/xmalloc.h"
#include "attr.h"
#include "fs/readlink/areadlink.h"
#include "prototypes.h"
@ -27,16 +27,21 @@
#ifdef WITH_SELINUX
#include <selinux/selinux.h>
#endif /* WITH_SELINUX */
#if defined(WITH_ACL)
#if defined(WITH_ACL) || defined(WITH_ATTR)
#include <stdarg.h>
#include <attr/error_context.h>
#endif /* WITH_ACL || WITH_ATTR */
#ifdef WITH_ACL
#include <acl/libacl.h>
#endif /* WITH_ACL */
#ifdef WITH_ATTR
#include <attr/libattr.h>
#endif /* WITH_ATTR */
#include "shadowlog.h"
#include "string/sprintf/aprintf.h"
#include "string/sprintf/xaprintf.h"
#include "string/strcmp/streq.h"
#include "string/strcmp/strprefix.h"
#include "string/strerrno.h"
static /*@null@*/const char *src_orig;
@ -58,23 +63,29 @@ struct path_info {
};
static int copy_entry (const struct path_info *src, const struct path_info *dst,
bool reset_selinux,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static int copy_dir (const struct path_info *src, const struct path_info *dst,
bool reset_selinux,
const struct stat *statp, const struct timespec mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static int copy_symlink (const struct path_info *src, const struct path_info *dst,
MAYBE_UNUSED bool reset_selinux,
const struct stat *statp, const struct timespec mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static int copy_hardlink (const struct path_info *dst,
MAYBE_UNUSED bool reset_selinux,
struct link_name *lp);
static int copy_special (const struct path_info *src, const struct path_info *dst,
bool reset_selinux,
const struct stat *statp, const struct timespec mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static int copy_file (const struct path_info *src, const struct path_info *dst,
bool reset_selinux,
const struct stat *statp, const struct timespec mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
@ -85,15 +96,15 @@ static int fchown_if_needed (int fdst, const struct stat *statp,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
#if defined(WITH_ACL)
#if defined(WITH_ACL) || defined(WITH_ATTR)
/*
* error_acl - format the error messages for the ACL and EQ libraries.
*/
format_attr(printf, 2, 3)
static void
error_acl(struct error_context *, const char *fmt, ...)
static void error_acl (MAYBE_UNUSED struct error_context *ctx, const char *fmt, ...)
{
va_list ap;
FILE *shadow_logfd = log_get_logfd();
/* ignore the case when destination does not support ACLs
* or extended attributes */
@ -103,18 +114,18 @@ error_acl(struct error_context *, const char *fmt, ...)
}
va_start (ap, fmt);
(void) fprintf (log_get_logfd(), _("%s: "), log_get_progname());
if (vfprintf (log_get_logfd(), fmt, ap) != 0) {
(void) fputs (_(": "), log_get_logfd());
(void) fprintf (shadow_logfd, _("%s: "), log_get_progname());
if (vfprintf (shadow_logfd, fmt, ap) != 0) {
(void) fputs (_(": "), shadow_logfd);
}
(void) fprintf(log_get_logfd(), "%s\n", strerrno());
(void) fprintf (shadow_logfd, "%s\n", strerror (errno));
va_end (ap);
}
static struct error_context ctx = {
error_acl, NULL, NULL
};
#endif /* WITH_ACL */
#endif /* WITH_ACL || WITH_ATTR */
#ifdef WITH_ACL
static int perm_copy_path(const struct path_info *src,
@ -141,6 +152,32 @@ static int perm_copy_path(const struct path_info *src,
}
#endif /* WITH_ACL */
#ifdef WITH_ATTR
static int attr_copy_path(const struct path_info *src,
const struct path_info *dst,
int (*callback) (const char *, struct error_context *),
struct error_context *errctx)
{
int src_fd, dst_fd, ret;
src_fd = openat(src->dirfd, src->name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
if (src_fd < 0) {
return -1;
}
dst_fd = openat(dst->dirfd, dst->name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
if (dst_fd < 0) {
(void) close (src_fd);
return -1;
}
ret = attr_copy_fd(src->full_path, src_fd, dst->full_path, dst_fd, callback, errctx);
(void) close (src_fd);
(void) close (dst_fd);
return ret;
}
#endif /* WITH_ATTR */
/*
* remove_link - delete a link from the linked list
*/
@ -193,7 +230,7 @@ static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, c
return NULL;
}
lp = xmalloc_T(1, struct link_name);
lp = XMALLOC(1, struct link_name);
lp->ln_dev = sb->st_dev;
lp->ln_ino = sb->st_ino;
lp->ln_count = sb->st_nlink;
@ -205,7 +242,7 @@ static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, c
}
static int copy_tree_impl (const struct path_info *src, const struct path_info *dst,
bool copy_root,
bool copy_root, bool reset_selinux,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{
@ -233,7 +270,8 @@ static int copy_tree_impl (const struct path_info *src, const struct path_info *
return -1;
}
return copy_entry (src, dst, old_uid, new_uid, old_gid, new_gid);
return copy_entry (src, dst, reset_selinux,
old_uid, new_uid, old_gid, new_gid);
}
/*
@ -272,7 +310,7 @@ static int copy_tree_impl (const struct path_info *src, const struct path_info *
dst_orig = dst->full_path;
set_orig = true;
}
while (0 == err && NULL != (ent = readdir(dir))) {
while ((0 == err) && (ent = readdir (dir)) != NULL) {
char *src_name = NULL;
char *dst_name;
struct path_info src_entry, dst_entry;
@ -304,7 +342,7 @@ static int copy_tree_impl (const struct path_info *src, const struct path_info *
dst_entry.dirfd = dst_fd;
dst_entry.name = ent->d_name;
err = copy_entry(&src_entry, &dst_entry,
err = copy_entry(&src_entry, &dst_entry, reset_selinux,
old_uid, new_uid, old_gid, new_gid);
free(dst_name);
@ -360,6 +398,7 @@ skip:
* to -1.
*/
static int copy_entry (const struct path_info *src, const struct path_info *dst,
bool reset_selinux,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{
@ -381,7 +420,7 @@ static int copy_entry (const struct path_info *src, const struct path_info *dst,
mt[1].tv_nsec = sb.st_mtim.tv_nsec;
if (S_ISDIR (sb.st_mode)) {
err = copy_dir (src, dst, &sb, mt,
err = copy_dir (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
}
@ -398,7 +437,7 @@ static int copy_entry (const struct path_info *src, const struct path_info *dst,
*/
else if (S_ISLNK (sb.st_mode)) {
err = copy_symlink (src, dst, &sb, mt,
err = copy_symlink (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
}
@ -407,7 +446,7 @@ static int copy_entry (const struct path_info *src, const struct path_info *dst,
*/
else if ((lp = check_link (src->full_path, &sb)) != NULL) {
err = copy_hardlink (dst, lp);
err = copy_hardlink (dst, reset_selinux, lp);
}
/*
@ -417,7 +456,7 @@ static int copy_entry (const struct path_info *src, const struct path_info *dst,
*/
else if (!S_ISREG (sb.st_mode)) {
err = copy_special (src, dst, &sb, mt,
err = copy_special (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
}
@ -427,7 +466,7 @@ static int copy_entry (const struct path_info *src, const struct path_info *dst,
*/
else {
err = copy_file (src, dst, &sb, mt,
err = copy_file (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
}
@ -445,6 +484,7 @@ static int copy_entry (const struct path_info *src, const struct path_info *dst,
* Return 0 on success, -1 on error.
*/
static int copy_dir (const struct path_info *src, const struct path_info *dst,
bool reset_selinux,
const struct stat *statp, const struct timespec mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
@ -462,14 +502,14 @@ static int copy_dir (const struct path_info *src, const struct path_info *dst,
return -1;
}
#endif /* WITH_SELINUX */
/*
* If the destination is already a directory, don't change it
* but copy into it (recursively).
*/
if (fstatat(dst->dirfd, dst->name, &dst_sb, AT_SYMLINK_NOFOLLOW) == 0 && S_ISDIR(dst_sb.st_mode)) {
return (copy_tree_impl (src, dst, false,
old_uid, new_uid, old_gid, new_gid) != 0);
}
/*
* If the destination is already a directory, don't change it
* but copy into it (recursively).
*/
if (fstatat(dst->dirfd, dst->name, &dst_sb, AT_SYMLINK_NOFOLLOW) == 0 && S_ISDIR(dst_sb.st_mode)) {
return (copy_tree_impl (src, dst, false, reset_selinux,
old_uid, new_uid, old_gid, new_gid) != 0);
}
if ( (mkdirat (dst->dirfd, dst->name, 0700) != 0)
|| (chownat_if_needed (dst, statp,
@ -479,7 +519,19 @@ static int copy_dir (const struct path_info *src, const struct path_info *dst,
|| ( (perm_copy_path (src, dst, &ctx) != 0)
&& (errno != 0))
#endif /* WITH_ACL */
|| (copy_tree_impl (src, dst, false,
#ifdef WITH_ATTR
/*
* If the third parameter is NULL, all extended attributes
* except those that define Access Control Lists are copied.
* ACLs are excluded by default because copying them between
* file systems with and without ACL support needs some
* additional logic so that no unexpected permissions result.
*/
|| ( !reset_selinux
&& (attr_copy_path (src, dst, NULL, &ctx) != 0)
&& (errno != 0))
#endif /* WITH_ATTR */
|| (copy_tree_impl (src, dst, false, reset_selinux,
old_uid, new_uid, old_gid, new_gid) != 0)
|| (utimensat (dst->dirfd, dst->name, mt, AT_SYMLINK_NOFOLLOW) != 0)) {
err = -1;
@ -499,6 +551,7 @@ static int copy_dir (const struct path_info *src, const struct path_info *dst,
* Return 0 on success, -1 on error.
*/
static int copy_symlink (const struct path_info *src, const struct path_info *dst,
MAYBE_UNUSED bool reset_selinux,
const struct stat *statp, const struct timespec mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
@ -569,6 +622,7 @@ static int copy_symlink (const struct path_info *src, const struct path_info *ds
* Return 0 on success, -1 on error.
*/
static int copy_hardlink (const struct path_info *dst,
MAYBE_UNUSED bool reset_selinux,
struct link_name *lp)
{
/* FIXME: selinux, ACL, Extended Attributes needed? */
@ -599,7 +653,8 @@ static int copy_hardlink (const struct path_info *dst,
* Return 0 on success, -1 on error.
*/
static int
copy_special(MAYBE_UNUSED const struct path_info *src, const struct path_info *dst,
copy_special(const struct path_info *src, const struct path_info *dst,
bool reset_selinux,
const struct stat *statp, const struct timespec mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
@ -623,6 +678,20 @@ copy_special(MAYBE_UNUSED const struct path_info *src, const struct path_info *d
return -1;
#endif
#if defined(WITH_ATTR)
/*
* If the third parameter is NULL, all extended attributes
* except those that define Access Control Lists are copied.
* ACLs are excluded by default because copying them between
* file systems with and without ACL support needs some
* additional logic so that no unexpected permissions result.
*/
if (!reset_selinux) {
if (attr_copy_path(src, dst, NULL, &ctx) == -1 && errno != 0)
return -1;
}
#endif
if (utimensat(dst->dirfd, dst->name, mt, AT_SYMLINK_NOFOLLOW) == -1)
return -1;
@ -640,6 +709,7 @@ copy_special(MAYBE_UNUSED const struct path_info *src, const struct path_info *d
* Return 0 on success, -1 on error.
*/
static int copy_file (const struct path_info *src, const struct path_info *dst,
bool reset_selinux,
const struct stat *statp, const struct timespec mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
@ -667,6 +737,18 @@ static int copy_file (const struct path_info *src, const struct path_info *dst,
|| ( (perm_copy_fd (src->full_path, ifd, dst->full_path, ofd, &ctx) != 0)
&& (errno != 0))
#endif /* WITH_ACL */
#ifdef WITH_ATTR
/*
* If the third parameter is NULL, all extended attributes
* except those that define Access Control Lists are copied.
* ACLs are excluded by default because copying them between
* file systems with and without ACL support needs some
* additional logic so that no unexpected permissions result.
*/
|| ( !reset_selinux
&& (attr_copy_fd (src->full_path, ifd, dst->full_path, ofd, NULL, &ctx) != 0)
&& (errno != 0))
#endif /* WITH_ATTR */
) {
if (ofd >= 0) {
(void) close (ofd);
@ -679,7 +761,7 @@ static int copy_file (const struct path_info *src, const struct path_info *dst,
char buf[8192];
ssize_t cnt;
cnt = read(ifd, buf, sizeof(buf));
cnt = read (ifd, buf, sizeof buf);
if (cnt < 0) {
if (errno == EINTR) {
continue;
@ -719,7 +801,7 @@ static int chown_function ## _if_needed (type_dst dst, \
{ \
uid_t tmpuid = (uid_t) -1; \
gid_t tmpgid = (gid_t) -1; \
\
\
/* Use new_uid if old_uid is set to -1 or if the file was \
* owned by the user. */ \
if (((uid_t) -1 == old_uid) || (statp->st_uid == old_uid)) { \
@ -730,14 +812,14 @@ static int chown_function ## _if_needed (type_dst dst, \
if ((uid_t) -1 == tmpuid) { \
tmpuid = statp->st_uid; \
} \
\
\
if (((gid_t) -1 == old_gid) || (statp->st_gid == old_gid)) { \
tmpgid = new_gid; \
} \
if ((gid_t) -1 == tmpgid) { \
tmpgid = statp->st_gid; \
} \
\
\
return chown_function (dst, tmpuid, tmpgid); \
}
@ -778,6 +860,9 @@ static int chownat_if_needed (const struct path_info *dst,
* copy_tree() walks a directory tree and copies ordinary files
* as it goes.
*
* When reset_selinux is enabled, extended attributes (and thus
* SELinux attributes) are not copied.
*
* old_uid and new_uid are used to set the ownership of the copied
* files. Unless old_uid is set to -1, only the files owned by
* old_uid have their ownership changed to new_uid. In addition, if
@ -787,7 +872,7 @@ static int chownat_if_needed (const struct path_info *dst,
* old_gid/new_gid.
*/
int copy_tree (const char *src_root, const char *dst_root,
bool copy_root,
bool copy_root, bool reset_selinux,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{
@ -802,5 +887,6 @@ int copy_tree (const char *src_root, const char *dst_root,
.name = dst_root
};
return copy_tree_impl(&src, &dst, copy_root, old_uid, new_uid, old_gid, new_gid);
return copy_tree_impl(&src, &dst, copy_root, reset_selinux,
old_uid, new_uid, old_gid, new_gid);
}

View File

@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2022-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include "config.h"
#include <config.h>
#ident "$Id$"

View File

@ -51,9 +51,20 @@
#include <dirent.h>
#include <shadow.h>
#if defined(SHADOWGRP)
#include "gshadow_.h"
#endif
#include <limits.h>
#ifndef NGROUPS_MAX
#ifdef NGROUPS
#define NGROUPS_MAX NGROUPS
#else
#define NGROUPS_MAX 64
#endif
#endif
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
@ -68,6 +79,11 @@
#define LOG_WARN LOG_WARNING
#endif
/* LOG_NOWAIT is deprecated */
#ifndef LOG_NOWAIT
#define LOG_NOWAIT 0
#endif
/* LOG_AUTH is deprecated, use LOG_AUTHPRIV instead */
#ifndef LOG_AUTHPRIV
#define LOG_AUTHPRIV LOG_AUTH
@ -81,7 +97,7 @@
syslogd should log the current system time for each event, and not
trust the formatted time received from the unix domain (or worse,
UDP) socket. -MM */
/* Avoid translated PAM error messages: set LC_ALL to "C".
/* Avoid translated PAM error messages: Set LC_ALL to "C".
* --Nekral */
#define SYSLOG(x) \
do { \
@ -107,7 +123,7 @@
in just one place. */
#ifndef SYSLOG_OPTIONS
/* #define SYSLOG_OPTIONS (LOG_PID | LOG_CONS) */
/* #define SYSLOG_OPTIONS (LOG_PID | LOG_CONS | LOG_NOWAIT) */
#define SYSLOG_OPTIONS (LOG_PID)
#endif
@ -144,6 +160,10 @@
#define GROUP_FILE "/etc/group"
#endif
#ifndef SHADOW_FILE
#define SHADOW_FILE "/etc/shadow"
#endif
#ifndef SUBUID_FILE
#define SUBUID_FILE "/etc/subuid"
#endif
@ -152,6 +172,12 @@
#define SUBGID_FILE "/etc/subgid"
#endif
#ifdef SHADOWGRP
#ifndef SGROUP_FILE
#define SGROUP_FILE "/etc/gshadow"
#endif
#endif
/*
* string to use for the pw_passwd field in /etc/passwd when using
* shadow passwords - most systems use "x" but there are a few

View File

@ -7,7 +7,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "config.h"
#include <config.h>
#ident "$Id$"
@ -16,7 +16,7 @@
#include "prototypes.h"
#include "defines.h"
#include "shadowlog.h"
#include "shadowlog_internal.h"
#include "string/strcmp/strprefix.h"
@ -64,7 +64,7 @@
method = &nummethod[0];
}
}
(void) fprintf (log_get_logfd(),
(void) fprintf (shadow_logfd,
_("crypt method not supported by libcrypt? (%s)\n"),
method);
errno = EINVAL;

View File

@ -7,7 +7,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "config.h"
#include <config.h>
#ident "$Id$"
@ -16,16 +16,15 @@
#include <stdlib.h>
#include <string.h>
#include "alloc/malloc.h"
#include "alloc/realloc.h"
#include "alloc/x/xmalloc.h"
#include "alloc/x/xrealloc.h"
#include "prototypes.h"
#include "defines.h"
#include "shadowlog.h"
#include "string/sprintf/aprintf.h"
#include "string/sprintf/snprintf.h"
#include "string/sprintf/aprintf.h"
#include "string/sprintf/xaprintf.h"
#include "string/strcmp/strprefix.h"
#include "string/strdup/strdup.h"
#include "string/strdup/xstrdup.h"
/*
@ -68,7 +67,7 @@ static const char *const noslash[] = {
*/
void initenv (void)
{
newenvp = xmalloc_T(NEWENVP_STEP, char *);
newenvp = XMALLOC(NEWENVP_STEP, char *);
*newenvp = NULL;
}
@ -135,7 +134,7 @@ void addenv (const char *string, /*@null@*/const char *value)
update_environ = (environ == newenvp);
newenvp = xrealloc_T(newenvp, newenvc + NEWENVP_STEP, char *);
newenvp = XREALLOC(newenvp, newenvc + NEWENVP_STEP, char *);
/*
* If this is our current environment, update
@ -164,13 +163,13 @@ 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) {
assert(stprintf_a(variable, "L%d", noname) != -1);
assert(SNPRINTF(variable, "L%d", noname) != -1);
noname++;
addenv (variable, *argv);
} else {
@ -227,9 +226,9 @@ void sanitize_env (void)
if (!strprefix(*cur, *bad)) {
continue;
}
if (!strchr(*cur, '/'))
if (strchr (*cur, '/') == NULL) {
continue; /* OK */
}
for (move = cur; NULL != *move; move++) {
*move = *(move + 1);
}

View File

@ -1,10 +0,0 @@
// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include "config.h"
#include "exit_if_null.h"
extern inline void exit_if_null_(void *p);

View File

@ -1,48 +0,0 @@
// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_EXIT_IF_NULL_H_
#define SHADOW_INCLUDE_LIB_EXIT_IF_NULL_H_
#include "config.h"
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include "shadowlog.h"
#include "string/strerrno.h"
/*
* This macro is used for implementing x*() variants of functions that
* allocate memory, such as xstrdup() for wrapping strdup(3). The macro
* returns the input pointer transparently, with the same type, but
* calls exit(3) if the input is a null pointer (thus, if the allocation
* failed).
*/
#define exit_if_null(p) \
({ \
__auto_type p_ = p; \
\
exit_if_null_(p_); \
p_; \
})
inline void exit_if_null_(void *p);
inline void
exit_if_null_(void *p)
{
if (p == NULL) {
fprintf(log_get_logfd(), "%s: %s\n", log_get_progname(), strerrno());
exit(13);
}
}
#endif // include guard

View File

@ -7,7 +7,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "config.h"
#include <config.h>
#ident "$Id$"
@ -34,7 +34,7 @@
void failure (uid_t uid, const char *tty, struct faillog *fl)
{
int fd;
off_t offset_uid = (off_t) sizeof(*fl) * uid;
off_t offset_uid = (off_t) (sizeof *fl) * uid;
/*
* Don't do anything if failure logging isn't set up.
@ -59,7 +59,7 @@ void failure (uid_t uid, const char *tty, struct faillog *fl)
*/
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|| (read(fd, fl, sizeof(*fl)) != (ssize_t) sizeof(*fl))) {
|| (read (fd, fl, sizeof *fl) != (ssize_t) sizeof *fl)) {
/* This is not necessarily a failure. The file is
* initially zero length.
*
@ -67,7 +67,7 @@ void failure (uid_t uid, const char *tty, struct faillog *fl)
* might reset the counter. But the new failure will be
* logged.
*/
memzero(fl, sizeof(*fl));
memzero (fl, sizeof *fl);
}
/*
@ -81,7 +81,7 @@ void failure (uid_t uid, const char *tty, struct faillog *fl)
fl->fail_cnt++;
}
strtcpy_a(fl->fail_line, tty);
STRTCPY(fl->fail_line, tty);
fl->fail_time = time(NULL);
/*
@ -92,7 +92,7 @@ void failure (uid_t uid, const char *tty, struct faillog *fl)
*/
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|| (write_full(fd, fl, sizeof(*fl)) == -1)) {
|| (write_full(fd, fl, sizeof *fl) == -1)) {
goto err_write;
}
@ -150,7 +150,7 @@ int failcheck (uid_t uid, struct faillog *fl, bool failed)
{
int fd;
struct faillog fail;
off_t offset_uid = (off_t) sizeof(*fl) * uid;
off_t offset_uid = (off_t) (sizeof *fl) * uid;
/*
* Suppress the check if the log file isn't there.
@ -182,7 +182,7 @@ int failcheck (uid_t uid, struct faillog *fl, bool failed)
*/
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|| (read(fd, fl, sizeof(*fl)) != (ssize_t) sizeof(*fl))) {
|| (read (fd, fl, sizeof *fl) != (ssize_t) sizeof *fl)) {
(void) close (fd);
return 1;
}
@ -204,7 +204,7 @@ int failcheck (uid_t uid, struct faillog *fl, bool failed)
fail.fail_cnt = 0;
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|| (write_full(fd, &fail, sizeof(fail)) == -1)) {
|| (write_full(fd, &fail, sizeof fail) == -1)) {
goto err_write;
}
@ -252,7 +252,7 @@ void failprint (const struct faillog *fail)
/*
* Print all information we have.
*/
strftime_a(lasttimeb, "%c", tp);
STRFTIME(lasttimeb, "%c", tp);
/*@-formatconst@*/
(void) printf (ngettext ("%d failure since last login.\n"

View File

@ -7,14 +7,13 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "config.h"
#include <config.h>
#include "fields.h"
#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <stdio.h>
#include "prototypes.h"
#include "string/ctype/strisascii/strisprint.h"
@ -63,14 +62,15 @@ change_field(char *buf, size_t maxsize, const char *prompt)
char newf[200];
char *cp;
if (maxsize > sizeof(newf)) {
maxsize = sizeof(newf);
if (maxsize > sizeof (newf)) {
maxsize = sizeof (newf);
}
printf ("\t%s [%s]: ", prompt, buf);
(void) fflush (stdout);
if (fgets(newf, maxsize, stdin) == NULL)
if (fgets (newf, maxsize, stdin) != newf) {
return;
}
if (stpsep(newf, "\n") == NULL)
return;

View File

@ -5,7 +5,7 @@
#define _SHADOW_INCLUDE_LIB_FIELDS_H_
#include "config.h"
#include <config.h>
#include <stddef.h>

View File

@ -6,7 +6,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "config.h"
#include <config.h>
#include <assert.h>
#include <stdint.h>
@ -18,18 +18,16 @@
#include "groupio.h"
#include "getdef.h"
#include "shadowlog.h"
#include "string/strerrno.h"
/*
* get_ranges - Get the minimum and maximum ID ranges for the search
*
* This function will return the minimum and maximum ranges for IDs
*
* 0: the function completed successfully
* EINVAL: the provided ranges are impossible (such as maximum < minimum)
* 0: The function completed successfully
* EINVAL: The provided ranges are impossible (such as maximum < minimum)
*
* preferred_min: the special-case minimum value for a specifically-
* preferred_min: The special-case minimum value for a specifically-
* requested ID, which may be lower than the standard min_id
*/
static int get_ranges (bool sys_group, gid_t *min_id, gid_t *max_id,
@ -56,11 +54,11 @@ static int get_ranges (bool sys_group, gid_t *min_id, gid_t *max_id,
/* Check that the ranges make sense */
if (*max_id < *min_id) {
(void) fprintf (log_get_logfd(),
_("%s: Invalid configuration: SYS_GID_MIN (%lu), "
"GID_MIN (%lu), SYS_GID_MAX (%lu)\n"),
log_get_progname(), (unsigned long) *min_id,
getdef_ulong ("GID_MIN", 1000UL),
(unsigned long) *max_id);
_("%s: Invalid configuration: SYS_GID_MIN (%lu), "
"GID_MIN (%lu), SYS_GID_MAX (%lu)\n"),
log_get_progname(), (unsigned long) *min_id,
getdef_ulong ("GID_MIN", 1000UL),
(unsigned long) *max_id);
return EINVAL;
}
/*
@ -235,11 +233,11 @@ int find_new_gid (bool sys_group,
*/
/* Create an array to hold all of the discovered GIDs */
used_gids = calloc_T(gid_max + 1, bool);
used_gids = CALLOC (gid_max + 1, bool);
if (NULL == used_gids) {
fprintf (log_get_logfd(),
_("%s: failed to allocate memory: %s\n"),
log_get_progname(), strerrno());
log_get_progname(), strerror (errno));
return -1;
}
@ -247,7 +245,7 @@ int find_new_gid (bool sys_group,
(void) gr_rewind ();
highest_found = gid_min;
lowest_found = gid_max;
while (NULL != (grp = gr_next())) {
while ((grp = gr_next ()) != NULL) {
/*
* Does this entry have a lower GID than the lowest we've found
* so far?

View File

@ -4,7 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "config.h"
#include <config.h>
#ifdef ENABLE_SUBIDS

View File

@ -4,7 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "config.h"
#include <config.h>
#ifdef ENABLE_SUBIDS

View File

@ -6,7 +6,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "config.h"
#include <config.h>
#include <assert.h>
#include <stdint.h>
@ -18,17 +18,16 @@
#include "pwio.h"
#include "getdef.h"
#include "shadowlog.h"
#include "string/strerrno.h"
/*
* get_ranges - Get the minimum and maximum ID ranges for the search
*
* This function will return the minimum and maximum ranges for IDs
*
* 0: the function completed successfully
* EINVAL: the provided ranges are impossible (such as maximum < minimum)
* 0: The function completed successfully
* EINVAL: The provided ranges are impossible (such as maximum < minimum)
*
* preferred_min: the special-case minimum value for a specifically-
* preferred_min: The special-case minimum value for a specifically-
* requested ID, which may be lower than the standard min_id
*/
static int get_ranges (bool sys_user, uid_t *min_id, uid_t *max_id,
@ -55,11 +54,11 @@ static int get_ranges (bool sys_user, uid_t *min_id, uid_t *max_id,
/* Check that the ranges make sense */
if (*max_id < *min_id) {
(void) fprintf (log_get_logfd(),
_("%s: Invalid configuration: SYS_UID_MIN (%lu), "
"UID_MIN (%lu), SYS_UID_MAX (%lu)\n"),
log_get_progname(), (unsigned long) *min_id,
getdef_ulong ("UID_MIN", 1000UL),
(unsigned long) *max_id);
_("%s: Invalid configuration: SYS_UID_MIN (%lu), "
"UID_MIN (%lu), SYS_UID_MAX (%lu)\n"),
log_get_progname(), (unsigned long) *min_id,
getdef_ulong ("UID_MIN", 1000UL),
(unsigned long) *max_id);
return EINVAL;
}
/*
@ -234,11 +233,11 @@ int find_new_uid(bool sys_user,
*/
/* Create an array to hold all of the discovered UIDs */
used_uids = calloc_T(uid_max + 1, bool);
used_uids = CALLOC(uid_max + 1, bool);
if (NULL == used_uids) {
fprintf (log_get_logfd(),
_("%s: failed to allocate memory: %s\n"),
log_get_progname(), strerrno());
log_get_progname(), strerror (errno));
return -1;
}
@ -246,7 +245,7 @@ int find_new_uid(bool sys_user,
(void) pw_rewind ();
highest_found = uid_min;
lowest_found = uid_max;
while (NULL != (pwd = pw_next())) {
while ((pwd = pw_next ()) != NULL) {
/*
* Does this entry have a lower UID than the lowest we've found
* so far?

67
lib/fputsx.c Normal file
View File

@ -0,0 +1,67 @@
/*
* SPDX-FileCopyrightText: 1990 - 1994, Julianne Frances Haugh
* SPDX-FileCopyrightText: 1996 - 1999, Marek Michałkiewicz
* SPDX-FileCopyrightText: 2005 , Tomasz Kłoczko
* SPDX-FileCopyrightText: 2008 , Nicolas François
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <config.h>
#include <stdio.h>
#include <string.h>
#include "defines.h"
#include "prototypes.h"
#include "string/strcmp/streq.h"
/*@null@*/char *
fgetsx(/*@returned@*/char *restrict buf, int cnt, FILE *restrict f)
{
char *cp = buf;
char *ep;
while (cnt > 0) {
if (fgets (cp, cnt, f) != cp) {
if (cp == buf) {
return NULL;
} else {
break;
}
}
ep = strrchr (cp, '\\');
if ((NULL != ep) && (*(ep + 1) == '\n')) {
cnt -= ep - cp;
if (cnt > 0)
cp = stpcpy(ep, "");
} else {
break;
}
}
return buf;
}
int fputsx (const char *s, FILE * stream)
{
int i;
for (i = 0; !streq(s, ""); i++, s++) {
if (putc (*s, stream) == EOF) {
return EOF;
}
#if 0 /* The standard getgr*() can't handle that. --marekm */
if (i > (BUFSIZ / 2)) {
if (putc ('\\', stream) == EOF ||
putc ('\n', stream) == EOF)
return EOF;
i = 0;
}
#endif
}
return 0;
}

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: BSD-3-Clause
#include "config.h"
#include <config.h>
#include "fs/mkstemp/fmkomstemp.h"

View File

@ -6,7 +6,7 @@
#define SHADOW_INCLUDE_LIB_FS_MKSTEMP_FMKOMSTEMP_H_
#include "config.h"
#include <config.h>
#include <stdio.h>
#include <sys/types.h>

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: BSD-3-Clause
#include "config.h"
#include <config.h>
#include "fs/mkstemp/mkomstemp.h"

View File

@ -6,7 +6,7 @@
#define SHADOW_INCLUDE_LIB_FS_MKSTEMP_MKOMSTEMP_H_
#include "config.h"
#include <config.h>
#include <stdlib.h>
#include <sys/stat.h>

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: BSD-3-Clause
#include "config.h"
#include <config.h>
#include "fs/readlink/areadlink.h"

View File

@ -6,7 +6,7 @@
#define SHADOW_INCLUDE_LIB_FS_READLINK_AREADLINK_H_
#include "config.h"
#include <config.h>
#include <errno.h>
#include <stdbool.h>
@ -33,7 +33,7 @@ areadlink(const char *link)
int len;
char *buf;
buf = malloc_T(size, char);
buf = MALLOC(size, char);
if (NULL == buf)
return NULL;

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: BSD-3-Clause
#include "config.h"
#include <config.h>
#include "fs/readlink/readlinknul.h"

View File

@ -6,7 +6,7 @@
#define SHADOW_INCLUDE_LIB_FS_READLINK_READLINKNUL_H_
#include "config.h"
#include <config.h>
#include <errno.h>
#include <string.h>
@ -17,8 +17,7 @@
#include "sizeof.h"
// readlinknul_a - read link nul-terminate array
#define readlinknul_a(link, buf) readlinknul(link, buf, countof(buf))
#define READLINKNUL(link, buf) readlinknul(link, buf, countof(buf))
ATTR_STRING(1)
@ -26,7 +25,7 @@ inline ssize_t readlinknul(const char *restrict link, char *restrict buf,
ssize_t size);
// readlinknul - read link nul-terminate
// Similar to readlink(2), but terminate the string.
inline ssize_t
readlinknul(const char *restrict link, char *restrict buf, ssize_t size)
{

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