summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am42
-rw-r--r--src/Makefile.in117
-rw-r--r--src/chage.c185
-rw-r--r--src/check_subid_range.c12
-rw-r--r--src/chfn.c94
-rw-r--r--src/chgpasswd.c39
-rw-r--r--src/chpasswd.c51
-rw-r--r--src/chsh.c147
-rw-r--r--src/expiry.c24
-rw-r--r--src/faillog.c218
-rw-r--r--src/free_subid_range.c3
-rw-r--r--src/get_subid_owners.c3
-rw-r--r--src/getsubids.c4
-rw-r--r--src/gpasswd.c198
-rw-r--r--src/groupadd.c56
-rw-r--r--src/groupdel.c61
-rw-r--r--src/groupmems.c32
-rw-r--r--src/groupmod.c151
-rw-r--r--src/groups.c11
-rw-r--r--src/grpck.c14
-rw-r--r--src/grpconv.c12
-rw-r--r--src/grpunconv.c9
-rw-r--r--src/id.c15
-rw-r--r--src/lastlog.c49
-rw-r--r--src/login.c267
-rw-r--r--src/login_nopam.c68
-rw-r--r--src/logoutd.c92
-rw-r--r--src/new_subid_range.c3
-rw-r--r--src/newgidmap.c48
-rw-r--r--src/newgrp.c127
-rw-r--r--src/newuidmap.c47
-rw-r--r--src/newusers.c192
-rw-r--r--src/passwd.c425
-rw-r--r--src/pwck.c24
-rw-r--r--src/pwconv.c11
-rw-r--r--src/pwunconv.c6
-rw-r--r--src/su.c115
-rw-r--r--src/suauth.c9
-rw-r--r--src/sulogin.c182
-rw-r--r--src/useradd.c909
-rw-r--r--src/userdel.c156
-rw-r--r--src/usermod.c714
-rw-r--r--src/vipw.c113
43 files changed, 2477 insertions, 2578 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index a1a2e4e..b6cb09e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,9 +9,11 @@ sgidperms = 2755
AM_CPPFLAGS = \
-I${top_srcdir}/lib \
- -I$(top_srcdir)/libmisc \
-I$(top_srcdir) \
- -DLOCALEDIR=\"$(datadir)/locale\"
+ -DLOCALEDIR=\"$(datadir)/locale\" \
+ $(ECONF_CPPFLAGS)
+
+AM_CFLAGS = $(LIBBSD_CFLAGS)
# XXX why are login and su in /bin anyway (other than for
# historical reasons)?
@@ -26,10 +28,13 @@ AM_CPPFLAGS = \
bin_PROGRAMS = groups login
sbin_PROGRAMS = nologin
-ubin_PROGRAMS = faillog lastlog chage chfn chsh expiry gpasswd newgrp passwd
+ubin_PROGRAMS = faillog chage chfn chsh expiry gpasswd newgrp passwd
if ENABLE_SUBIDS
ubin_PROGRAMS += newgidmap newuidmap
endif
+if ENABLE_LASTLOG
+ubin_PROGRAMS += lastlog
+endif
if WITH_SU
bin_PROGRAMS += su
endif
@@ -79,7 +84,6 @@ shadowsgidubins = passwd
endif
LDADD = $(INTLLIBS) \
- $(top_builddir)/libmisc/libmisc.la \
$(top_builddir)/lib/libshadow.la \
$(LIBTCB)
@@ -95,13 +99,13 @@ else
LIBCRYPT_NOPAM = $(LIBCRYPT)
endif
-chage_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
+chage_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) -ldl
newuidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) $(LIBECONF) -ldl
newgidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) $(LIBECONF) -ldl
chfn_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF)
chgpasswd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF)
chsh_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF)
-chpasswd_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF)
+chpasswd_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) -ldl
expiry_LDADD = $(LDADD) $(LIBECONF)
gpasswd_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF)
groupadd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) -ldl
@@ -115,18 +119,18 @@ lastlog_LDADD = $(LDADD) $(LIBAUDIT) $(LIBECONF)
login_SOURCES = \
login.c \
login_nopam.c
-login_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF)
+login_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF) $(LIBSELINUX)
newgrp_LDADD = $(LDADD) $(LIBAUDIT) $(LIBCRYPT) $(LIBECONF)
newusers_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) -ldl
nologin_LDADD =
-passwd_LDADD = $(LDADD) $(LIBPAM) $(LIBCRACK) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBECONF)
+passwd_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBECONF) -ldl
pwck_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
pwconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
pwunconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
su_SOURCES = \
su.c \
suauth.c
-su_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF)
+su_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF) $(LIBSELINUX)
sulogin_LDADD = $(LDADD) $(LIBCRYPT) $(LIBECONF)
useradd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBACL) $(LIBATTR) $(LIBECONF) -ldl
userdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBECONF) -ldl
@@ -177,59 +181,49 @@ MISCLIBS = \
getsubids_LDADD = \
$(top_builddir)/lib/libshadow.la \
- $(top_builddir)/libmisc/libmisc.la \
$(top_builddir)/libsubid/libsubid.la \
$(MISCLIBS) -ldl
getsubids_CPPFLAGS = \
-I$(top_srcdir)/lib \
- -I$(top_srcdir)/libmisc \
-I$(top_srcdir) \
- -I$(top_srcdir)/libsubid
+ -I$(top_builddir)/libsubid
get_subid_owners_LDADD = \
$(top_builddir)/lib/libshadow.la \
- $(top_builddir)/libmisc/libmisc.la \
$(top_builddir)/libsubid/libsubid.la \
$(MISCLIBS) -ldl
get_subid_owners_CPPFLAGS = \
-I$(top_srcdir)/lib \
- -I$(top_srcdir)/libmisc \
-I$(top_srcdir) \
- -I$(top_srcdir)/libsubid
+ -I$(top_builddir)/libsubid
new_subid_range_CPPFLAGS = \
-I$(top_srcdir)/lib \
- -I$(top_srcdir)/libmisc \
-I$(top_srcdir) \
- -I$(top_srcdir)/libsubid
+ -I$(top_builddir)/libsubid
new_subid_range_LDADD = \
$(top_builddir)/lib/libshadow.la \
- $(top_builddir)/libmisc/libmisc.la \
$(top_builddir)/libsubid/libsubid.la \
$(MISCLIBS) -ldl
free_subid_range_CPPFLAGS = \
-I$(top_srcdir)/lib \
- -I$(top_srcdir)/libmisc \
-I$(top_srcdir) \
- -I$(top_srcdir)/libsubid
+ -I$(top_builddir)/libsubid
free_subid_range_LDADD = \
$(top_builddir)/lib/libshadow.la \
- $(top_builddir)/libmisc/libmisc.la \
$(top_builddir)/libsubid/libsubid.la \
$(MISCLIBS) -ldl
check_subid_range_CPPFLAGS = \
-I$(top_srcdir)/lib \
- -I$(top_srcdir) \
- -I$(top_srcdir)/libmisc
+ -I$(top_srcdir)
check_subid_range_LDADD = \
$(top_builddir)/lib/libshadow.la \
- $(top_builddir)/libmisc/libmisc.la \
$(MISCLIBS) -ldl
endif
diff --git a/src/Makefile.in b/src/Makefile.in
index da31572..f62a5cf 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -91,11 +91,12 @@ host_triplet = @host@
bin_PROGRAMS = groups$(EXEEXT) login$(EXEEXT) $(am__EXEEXT_1) \
$(am__EXEEXT_2)
sbin_PROGRAMS = nologin$(EXEEXT)
-ubin_PROGRAMS = faillog$(EXEEXT) lastlog$(EXEEXT) chage$(EXEEXT) \
- chfn$(EXEEXT) chsh$(EXEEXT) expiry$(EXEEXT) gpasswd$(EXEEXT) \
- newgrp$(EXEEXT) passwd$(EXEEXT) $(am__EXEEXT_4)
+ubin_PROGRAMS = faillog$(EXEEXT) chage$(EXEEXT) chfn$(EXEEXT) \
+ chsh$(EXEEXT) expiry$(EXEEXT) gpasswd$(EXEEXT) newgrp$(EXEEXT) \
+ passwd$(EXEEXT) $(am__EXEEXT_4) $(am__EXEEXT_5)
@ENABLE_SUBIDS_TRUE@am__append_1 = newgidmap newuidmap
-@WITH_SU_TRUE@am__append_2 = su
+@ENABLE_LASTLOG_TRUE@am__append_2 = lastlog
+@WITH_SU_TRUE@am__append_3 = su
usbin_PROGRAMS = chgpasswd$(EXEEXT) chpasswd$(EXEEXT) \
groupadd$(EXEEXT) groupdel$(EXEEXT) groupmems$(EXEEXT) \
groupmod$(EXEEXT) grpck$(EXEEXT) grpconv$(EXEEXT) \
@@ -104,12 +105,12 @@ usbin_PROGRAMS = chgpasswd$(EXEEXT) chpasswd$(EXEEXT) \
useradd$(EXEEXT) userdel$(EXEEXT) usermod$(EXEEXT) \
vipw$(EXEEXT)
noinst_PROGRAMS = id$(EXEEXT) sulogin$(EXEEXT) $(am__EXEEXT_3)
-@WITH_SU_TRUE@am__append_3 = su
-@WITH_TCB_FALSE@am__append_4 = passwd
-@ACCT_TOOLS_SETUID_TRUE@am__append_5 = chgpasswd chpasswd groupadd groupdel groupmod newusers useradd userdel usermod
-@ENABLE_SUBIDS_TRUE@@FCAPS_FALSE@am__append_6 = newgidmap newuidmap
-@ENABLE_SUBIDS_TRUE@am__append_7 = getsubids
-@ENABLE_SUBIDS_TRUE@am__append_8 = get_subid_owners \
+@WITH_SU_TRUE@am__append_4 = su
+@WITH_TCB_FALSE@am__append_5 = passwd
+@ACCT_TOOLS_SETUID_TRUE@am__append_6 = chgpasswd chpasswd groupadd groupdel groupmod newusers useradd userdel usermod
+@ENABLE_SUBIDS_TRUE@@FCAPS_FALSE@am__append_7 = newgidmap newuidmap
+@ENABLE_SUBIDS_TRUE@am__append_8 = getsubids
+@ENABLE_SUBIDS_TRUE@am__append_9 = get_subid_owners \
@ENABLE_SUBIDS_TRUE@ new_subid_range \
@ENABLE_SUBIDS_TRUE@ free_subid_range \
@ENABLE_SUBIDS_TRUE@ check_subid_range
@@ -142,13 +143,13 @@ am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" \
@ENABLE_SUBIDS_TRUE@ check_subid_range$(EXEEXT)
@ENABLE_SUBIDS_TRUE@am__EXEEXT_4 = newgidmap$(EXEEXT) \
@ENABLE_SUBIDS_TRUE@ newuidmap$(EXEEXT)
+@ENABLE_LASTLOG_TRUE@am__EXEEXT_5 = lastlog$(EXEEXT)
PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) $(sbin_PROGRAMS) \
$(ubin_PROGRAMS) $(usbin_PROGRAMS)
chage_SOURCES = chage.c
chage_OBJECTS = chage.$(OBJEXT)
am__DEPENDENCIES_1 =
am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \
- $(top_builddir)/libmisc/libmisc.la \
$(top_builddir)/lib/libshadow.la $(am__DEPENDENCIES_1)
@ACCT_TOOLS_SETUID_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1)
chage_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3) \
@@ -173,7 +174,6 @@ check_subid_range_OBJECTS = \
@ENABLE_SUBIDS_TRUE@ $(am__DEPENDENCIES_1)
@ENABLE_SUBIDS_TRUE@check_subid_range_DEPENDENCIES = \
@ENABLE_SUBIDS_TRUE@ $(top_builddir)/lib/libshadow.la \
-@ENABLE_SUBIDS_TRUE@ $(top_builddir)/libmisc/libmisc.la \
@ENABLE_SUBIDS_TRUE@ $(am__DEPENDENCIES_5)
chfn_SOURCES = chfn.c
chfn_OBJECTS = chfn.$(OBJEXT)
@@ -204,14 +204,12 @@ faillog_SOURCES = faillog.c
faillog_OBJECTS = faillog.$(OBJEXT)
faillog_LDADD = $(LDADD)
faillog_DEPENDENCIES = $(am__DEPENDENCIES_1) \
- $(top_builddir)/libmisc/libmisc.la \
$(top_builddir)/lib/libshadow.la $(am__DEPENDENCIES_1)
free_subid_range_SOURCES = free_subid_range.c
free_subid_range_OBJECTS = \
free_subid_range-free_subid_range.$(OBJEXT)
@ENABLE_SUBIDS_TRUE@free_subid_range_DEPENDENCIES = \
@ENABLE_SUBIDS_TRUE@ $(top_builddir)/lib/libshadow.la \
-@ENABLE_SUBIDS_TRUE@ $(top_builddir)/libmisc/libmisc.la \
@ENABLE_SUBIDS_TRUE@ $(top_builddir)/libsubid/libsubid.la \
@ENABLE_SUBIDS_TRUE@ $(am__DEPENDENCIES_5)
get_subid_owners_SOURCES = get_subid_owners.c
@@ -219,14 +217,12 @@ get_subid_owners_OBJECTS = \
get_subid_owners-get_subid_owners.$(OBJEXT)
@ENABLE_SUBIDS_TRUE@get_subid_owners_DEPENDENCIES = \
@ENABLE_SUBIDS_TRUE@ $(top_builddir)/lib/libshadow.la \
-@ENABLE_SUBIDS_TRUE@ $(top_builddir)/libmisc/libmisc.la \
@ENABLE_SUBIDS_TRUE@ $(top_builddir)/libsubid/libsubid.la \
@ENABLE_SUBIDS_TRUE@ $(am__DEPENDENCIES_5)
getsubids_SOURCES = getsubids.c
getsubids_OBJECTS = getsubids-getsubids.$(OBJEXT)
@ENABLE_SUBIDS_TRUE@getsubids_DEPENDENCIES = \
@ENABLE_SUBIDS_TRUE@ $(top_builddir)/lib/libshadow.la \
-@ENABLE_SUBIDS_TRUE@ $(top_builddir)/libmisc/libmisc.la \
@ENABLE_SUBIDS_TRUE@ $(top_builddir)/libsubid/libsubid.la \
@ENABLE_SUBIDS_TRUE@ $(am__DEPENDENCIES_5)
gpasswd_SOURCES = gpasswd.c
@@ -258,7 +254,6 @@ groups_SOURCES = groups.c
groups_OBJECTS = groups.$(OBJEXT)
groups_LDADD = $(LDADD)
groups_DEPENDENCIES = $(am__DEPENDENCIES_1) \
- $(top_builddir)/libmisc/libmisc.la \
$(top_builddir)/lib/libshadow.la $(am__DEPENDENCIES_1)
grpck_SOURCES = grpck.c
grpck_OBJECTS = grpck.$(OBJEXT)
@@ -276,7 +271,6 @@ id_SOURCES = id.c
id_OBJECTS = id.$(OBJEXT)
id_LDADD = $(LDADD)
id_DEPENDENCIES = $(am__DEPENDENCIES_1) \
- $(top_builddir)/libmisc/libmisc.la \
$(top_builddir)/lib/libshadow.la $(am__DEPENDENCIES_1)
lastlog_SOURCES = lastlog.c
lastlog_OBJECTS = lastlog.$(OBJEXT)
@@ -287,18 +281,16 @@ login_OBJECTS = $(am_login_OBJECTS)
login_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_4) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
logoutd_SOURCES = logoutd.c
logoutd_OBJECTS = logoutd.$(OBJEXT)
logoutd_LDADD = $(LDADD)
logoutd_DEPENDENCIES = $(am__DEPENDENCIES_1) \
- $(top_builddir)/libmisc/libmisc.la \
$(top_builddir)/lib/libshadow.la $(am__DEPENDENCIES_1)
new_subid_range_SOURCES = new_subid_range.c
new_subid_range_OBJECTS = new_subid_range-new_subid_range.$(OBJEXT)
@ENABLE_SUBIDS_TRUE@new_subid_range_DEPENDENCIES = \
@ENABLE_SUBIDS_TRUE@ $(top_builddir)/lib/libshadow.la \
-@ENABLE_SUBIDS_TRUE@ $(top_builddir)/libmisc/libmisc.la \
@ENABLE_SUBIDS_TRUE@ $(top_builddir)/libsubid/libsubid.la \
@ENABLE_SUBIDS_TRUE@ $(am__DEPENDENCIES_5)
newgidmap_SOURCES = newgidmap.c
@@ -325,8 +317,7 @@ passwd_SOURCES = passwd.c
passwd_OBJECTS = passwd.$(OBJEXT)
passwd_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_4) \
- $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_4) $(am__DEPENDENCIES_1)
pwck_SOURCES = pwck.c
pwck_OBJECTS = pwck.$(OBJEXT)
pwck_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
@@ -344,7 +335,7 @@ su_OBJECTS = $(am_su_OBJECTS)
su_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_4) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
sulogin_SOURCES = sulogin.c
sulogin_OBJECTS = sulogin.$(OBJEXT)
sulogin_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
@@ -478,6 +469,8 @@ AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
+CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
+CMOCKA_LIBS = @CMOCKA_LIBS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
@@ -496,6 +489,7 @@ EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+FILECMD = @FILECMD@
GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
GMSGFMT = @GMSGFMT@
GMSGFMT_015 = @GMSGFMT_015@
@@ -511,9 +505,15 @@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBACL = @LIBACL@
+LIBADD_DL = @LIBADD_DL@
+LIBADD_DLD_LINK = @LIBADD_DLD_LINK@
+LIBADD_DLOPEN = @LIBADD_DLOPEN@
+LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@
LIBATTR = @LIBATTR@
LIBAUDIT = @LIBAUDIT@
-LIBCRACK = @LIBCRACK@
+LIBBSD = @LIBBSD@
+LIBBSD_CFLAGS = @LIBBSD_CFLAGS@
+LIBBSD_LIBS = @LIBBSD_LIBS@
LIBCRYPT = @LIBCRYPT@
LIBECONF = @LIBECONF@
LIBICONV = @LIBICONV@
@@ -529,6 +529,7 @@ LIBSUBID_ABI = @LIBSUBID_ABI@
LIBSUBID_ABI_MAJOR = @LIBSUBID_ABI_MAJOR@
LIBSUBID_ABI_MICRO = @LIBSUBID_ABI_MICRO@
LIBSUBID_ABI_MINOR = @LIBSUBID_ABI_MINOR@
+LIBSYSTEMD = @LIBSYSTEMD@
LIBTCB = @LIBTCB@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
@@ -537,6 +538,8 @@ LN_S = @LN_S@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
+LT_DLLOADERS = @LT_DLLOADERS@
+LT_DLPREOPEN = @LT_DLPREOPEN@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
@@ -559,6 +562,9 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
POSUB = @POSUB@
RANLIB = @RANLIB@
SED = @SED@
@@ -639,17 +645,17 @@ suidperms = 4755
sgidperms = 2755
AM_CPPFLAGS = \
-I${top_srcdir}/lib \
- -I$(top_srcdir)/libmisc \
-I$(top_srcdir) \
- -DLOCALEDIR=\"$(datadir)/locale\"
-
-suidusbins = $(am__append_5)
-suidbins = $(am__append_3)
-suidubins = chage chfn chsh expiry gpasswd newgrp $(am__append_4) \
- $(am__append_6)
+ -DLOCALEDIR=\"$(datadir)/locale\" \
+ $(ECONF_CPPFLAGS)
+
+AM_CFLAGS = $(LIBBSD_CFLAGS)
+suidusbins = $(am__append_6)
+suidbins = $(am__append_4)
+suidubins = chage chfn chsh expiry gpasswd newgrp $(am__append_5) \
+ $(am__append_7)
@WITH_TCB_TRUE@shadowsgidubins = passwd
LDADD = $(INTLLIBS) \
- $(top_builddir)/libmisc/libmisc.la \
$(top_builddir)/lib/libshadow.la \
$(LIBTCB)
@@ -657,13 +663,13 @@ LDADD = $(INTLLIBS) \
@ACCT_TOOLS_SETUID_TRUE@LIBPAM_SUID = $(LIBPAM)
@USE_PAM_FALSE@LIBCRYPT_NOPAM = $(LIBCRYPT)
@USE_PAM_TRUE@LIBCRYPT_NOPAM =
-chage_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
+chage_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) -ldl
newuidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) $(LIBECONF) -ldl
newgidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) $(LIBECONF) -ldl
chfn_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF)
chgpasswd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF)
chsh_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF)
-chpasswd_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF)
+chpasswd_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) -ldl
expiry_LDADD = $(LDADD) $(LIBECONF)
gpasswd_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF)
groupadd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) -ldl
@@ -678,11 +684,11 @@ login_SOURCES = \
login.c \
login_nopam.c
-login_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF)
+login_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF) $(LIBSELINUX)
newgrp_LDADD = $(LDADD) $(LIBAUDIT) $(LIBCRYPT) $(LIBECONF)
newusers_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) -ldl
nologin_LDADD =
-passwd_LDADD = $(LDADD) $(LIBPAM) $(LIBCRACK) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBECONF)
+passwd_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBECONF) -ldl
pwck_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
pwconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
pwunconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
@@ -690,7 +696,7 @@ su_SOURCES = \
su.c \
suauth.c
-su_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF)
+su_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF) $(LIBSELINUX)
sulogin_LDADD = $(LDADD) $(LIBCRYPT) $(LIBECONF)
useradd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBACL) $(LIBATTR) $(LIBECONF) -ldl
userdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBECONF) -ldl
@@ -709,60 +715,50 @@ vipw_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
@ENABLE_SUBIDS_TRUE@getsubids_LDADD = \
@ENABLE_SUBIDS_TRUE@ $(top_builddir)/lib/libshadow.la \
-@ENABLE_SUBIDS_TRUE@ $(top_builddir)/libmisc/libmisc.la \
@ENABLE_SUBIDS_TRUE@ $(top_builddir)/libsubid/libsubid.la \
@ENABLE_SUBIDS_TRUE@ $(MISCLIBS) -ldl
@ENABLE_SUBIDS_TRUE@getsubids_CPPFLAGS = \
@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir)/lib \
-@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir)/libmisc \
@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir) \
-@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir)/libsubid
+@ENABLE_SUBIDS_TRUE@ -I$(top_builddir)/libsubid
@ENABLE_SUBIDS_TRUE@get_subid_owners_LDADD = \
@ENABLE_SUBIDS_TRUE@ $(top_builddir)/lib/libshadow.la \
-@ENABLE_SUBIDS_TRUE@ $(top_builddir)/libmisc/libmisc.la \
@ENABLE_SUBIDS_TRUE@ $(top_builddir)/libsubid/libsubid.la \
@ENABLE_SUBIDS_TRUE@ $(MISCLIBS) -ldl
@ENABLE_SUBIDS_TRUE@get_subid_owners_CPPFLAGS = \
@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir)/lib \
-@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir)/libmisc \
@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir) \
-@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir)/libsubid
+@ENABLE_SUBIDS_TRUE@ -I$(top_builddir)/libsubid
@ENABLE_SUBIDS_TRUE@new_subid_range_CPPFLAGS = \
@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir)/lib \
-@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir)/libmisc \
@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir) \
-@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir)/libsubid
+@ENABLE_SUBIDS_TRUE@ -I$(top_builddir)/libsubid
@ENABLE_SUBIDS_TRUE@new_subid_range_LDADD = \
@ENABLE_SUBIDS_TRUE@ $(top_builddir)/lib/libshadow.la \
-@ENABLE_SUBIDS_TRUE@ $(top_builddir)/libmisc/libmisc.la \
@ENABLE_SUBIDS_TRUE@ $(top_builddir)/libsubid/libsubid.la \
@ENABLE_SUBIDS_TRUE@ $(MISCLIBS) -ldl
@ENABLE_SUBIDS_TRUE@free_subid_range_CPPFLAGS = \
@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir)/lib \
-@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir)/libmisc \
@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir) \
-@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir)/libsubid
+@ENABLE_SUBIDS_TRUE@ -I$(top_builddir)/libsubid
@ENABLE_SUBIDS_TRUE@free_subid_range_LDADD = \
@ENABLE_SUBIDS_TRUE@ $(top_builddir)/lib/libshadow.la \
-@ENABLE_SUBIDS_TRUE@ $(top_builddir)/libmisc/libmisc.la \
@ENABLE_SUBIDS_TRUE@ $(top_builddir)/libsubid/libsubid.la \
@ENABLE_SUBIDS_TRUE@ $(MISCLIBS) -ldl
@ENABLE_SUBIDS_TRUE@check_subid_range_CPPFLAGS = \
@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir)/lib \
-@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir) \
-@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir)/libmisc
+@ENABLE_SUBIDS_TRUE@ -I$(top_srcdir)
@ENABLE_SUBIDS_TRUE@check_subid_range_LDADD = \
@ENABLE_SUBIDS_TRUE@ $(top_builddir)/lib/libshadow.la \
-@ENABLE_SUBIDS_TRUE@ $(top_builddir)/libmisc/libmisc.la \
@ENABLE_SUBIDS_TRUE@ $(MISCLIBS) -ldl
all: all-am
@@ -1220,22 +1216,25 @@ $(am__depfiles_remade):
am--depfiles: $(am__depfiles_remade)
.c.o:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
diff --git a/src/chage.c b/src/chage.c
index 01570d7..1edab47 100644
--- a/src/chage.c
+++ b/src/chage.c
@@ -25,21 +25,31 @@
#endif /* USE_PAM */
#endif /* ACCT_TOOLS_SETUID */
#include <pwd.h>
-#include "prototypes.h"
+
+#include "alloc.h"
+#include "atoi/str2i.h"
#include "defines.h"
+#include "memzero.h"
+#include "prototypes.h"
#include "pwio.h"
#include "shadowio.h"
#include "shadowlog.h"
+#include "string/sprintf.h"
+#include "string/strftime.h"
+#include "string/strtcpy.h"
+#include "time/day_to_str.h"
+/*@-exitarg@*/
+#include "exitcodes.h"
+
#ifdef WITH_TCB
#include "tcbfuncs.h"
#endif
-/*@-exitarg@*/
-#include "exitcodes.h"
+
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "chage";
static bool
dflg = false, /* set last password change date */
@@ -52,6 +62,8 @@ static bool
Wflg = false; /* set expiration warning days */
static bool amroot = false;
+static const char *prefix = "";
+
static bool pw_locked = false; /* Indicate if the password file is locked */
static bool spw_locked = false; /* Indicate if the shadow file is locked */
/* The name and UID of the user being worked on */
@@ -66,21 +78,23 @@ static long inactdays;
static long expdate;
/* local function prototypes */
-static /*@noreturn@*/void usage (int status);
+NORETURN static void usage (int status);
static int new_fields (void);
-static void print_date (time_t date);
+static void print_day_as_date (long day);
static void list_fields (void);
static void process_flags (int argc, char **argv);
static void check_flags (int argc, int opt_index);
static void check_perms (void);
static void open_files (bool readonly);
static void close_files (void);
-static /*@noreturn@*/void fail_exit (int code);
+NORETURN static void fail_exit (int code);
/*
* fail_exit - do some cleanup and exit with the given error code
*/
-static /*@noreturn@*/void fail_exit (int code)
+NORETURN
+static void
+fail_exit (int code)
{
if (spw_locked) {
if (spw_unlock () == 0) {
@@ -101,8 +115,7 @@ static /*@noreturn@*/void fail_exit (int code)
#ifdef WITH_AUDIT
if (E_SUCCESS != code) {
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
- "change age",
- user_name, (unsigned int) user_uid, 0);
+ "change age", user_name, user_uid, 0);
}
#endif
@@ -112,7 +125,9 @@ static /*@noreturn@*/void fail_exit (int code)
/*
* usage - print command line syntax and exit
*/
-static /*@noreturn@*/void usage (int status)
+NORETURN
+static void
+usage (int status)
{
FILE *usageout = (E_SUCCESS != status) ? stderr : stdout;
(void) fprintf (usageout,
@@ -132,6 +147,7 @@ static /*@noreturn@*/void usage (int status)
(void) fputs (_(" -M, --maxdays MAX_DAYS set maximum number of days before password\n"
" change to MAX_DAYS\n"), usageout);
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
+ (void) fputs (_(" -P, --prefix PREFIX_DIR directory prefix\n"), usageout);
(void) fputs (_(" -W, --warndays WARN_DAYS set expiration warning days to WARN_DAYS\n"), usageout);
(void) fputs ("\n", usageout);
exit (status);
@@ -148,30 +164,29 @@ static /*@noreturn@*/void usage (int status)
*/
static int new_fields (void)
{
- char buf[200];
+ char buf[200];
(void) puts (_("Enter the new value, or press ENTER for the default"));
(void) puts ("");
- (void) snprintf (buf, sizeof buf, "%ld", mindays);
+ SNPRINTF(buf, "%ld", mindays);
change_field (buf, sizeof buf, _("Minimum Password Age"));
- if ( (getlong (buf, &mindays) == 0)
+ if ( (str2sl(&mindays, buf) == -1)
|| (mindays < -1)) {
return 0;
}
- (void) snprintf (buf, sizeof buf, "%ld", maxdays);
+ SNPRINTF(buf, "%ld", maxdays);
change_field (buf, sizeof buf, _("Maximum Password Age"));
- if ( (getlong (buf, &maxdays) == 0)
+ if ( (str2sl(&maxdays, buf) == -1)
|| (maxdays < -1)) {
return 0;
}
- if (-1 == lstchgdate || lstchgdate > LONG_MAX / SCALE) {
- strcpy (buf, "-1");
- } else {
- date_to_str (sizeof(buf), buf, lstchgdate * SCALE);
- }
+ if (-1 == lstchgdate || lstchgdate > LONG_MAX / DAY)
+ strcpy(buf, "-1");
+ else
+ DAY_TO_STR(buf, lstchgdate);
change_field (buf, sizeof buf, _("Last Password Change (YYYY-MM-DD)"));
@@ -184,25 +199,24 @@ static int new_fields (void)
}
}
- (void) snprintf (buf, sizeof buf, "%ld", warndays);
+ SNPRINTF(buf, "%ld", warndays);
change_field (buf, sizeof buf, _("Password Expiration Warning"));
- if ( (getlong (buf, &warndays) == 0)
+ if ( (str2sl(&warndays, buf) == -1)
|| (warndays < -1)) {
return 0;
}
- (void) snprintf (buf, sizeof buf, "%ld", inactdays);
+ SNPRINTF(buf, "%ld", inactdays);
change_field (buf, sizeof buf, _("Password Inactive"));
- if ( (getlong (buf, &inactdays) == 0)
+ if ( (str2sl(&inactdays, buf) == -1)
|| (inactdays < -1)) {
return 0;
}
- if (-1 == expdate || LONG_MAX / SCALE < expdate) {
- strcpy (buf, "-1");
- } else {
- date_to_str (sizeof(buf), buf, expdate * SCALE);
- }
+ if (-1 == expdate || LONG_MAX / DAY < expdate)
+ strcpy(buf, "-1");
+ else
+ DAY_TO_STR(buf, expdate);
change_field (buf, sizeof buf,
_("Account Expiration Date (YYYY-MM-DD)"));
@@ -219,20 +233,33 @@ static int new_fields (void)
return 1;
}
-static void print_date (time_t date)
+
+static void
+print_day_as_date(long day)
{
- struct tm *tp;
- char buf[80];
+ char buf[80];
+ time_t date;
+ struct tm tm;
- tp = gmtime (&date);
- if (NULL == tp) {
+ if (day < 0) {
+ puts(_("never"));
+ return;
+ }
+ if (__builtin_mul_overflow(day, DAY, &date)) {
+ puts(_("future"));
+ return;
+ }
+
+ if (gmtime_r(&date, &tm) == NULL) {
(void) printf ("time_t: %lu\n", (unsigned long)date);
- } else {
- (void) strftime (buf, sizeof buf, iflg ? "%Y-%m-%d" : "%b %d, %Y", tp);
- (void) puts (buf);
+ return;
}
+
+ STRFTIME(buf, iflg ? "%Y-%m-%d" : "%b %d, %Y", &tm);
+ (void) puts (buf);
}
+
/*
* list_fields - display the current values of the expiration fields
*
@@ -242,21 +269,15 @@ static void print_date (time_t date)
*/
static void list_fields (void)
{
- long changed = 0;
- long expires;
-
/*
* The "last change" date is either "never" or the date the password
* was last modified. The date is the number of days since 1/1/1970.
*/
(void) fputs (_("Last password change\t\t\t\t\t: "), stdout);
- if (lstchgdate < 0 || lstchgdate > LONG_MAX / SCALE) {
- (void) puts (_("never"));
- } else if (lstchgdate == 0) {
+ if (lstchgdate == 0) {
(void) puts (_("password must be changed"));
} else {
- changed = lstchgdate * SCALE;
- print_date ((time_t) changed);
+ print_day_as_date(lstchgdate);
}
/*
@@ -267,13 +288,13 @@ static void list_fields (void)
if (lstchgdate == 0) {
(void) puts (_("password must be changed"));
} else if ( (lstchgdate < 0)
- || (maxdays >= (10000 * (DAY / SCALE)))
+ || (maxdays >= 10000)
|| (maxdays < 0)
- || ((LONG_MAX - changed) / SCALE < maxdays)) {
+ || (LONG_MAX - lstchgdate < maxdays))
+ {
(void) puts (_("never"));
} else {
- expires = changed + maxdays * SCALE;
- print_date ((time_t) expires);
+ print_day_as_date(lstchgdate + maxdays);
}
/*
@@ -287,14 +308,14 @@ static void list_fields (void)
(void) puts (_("password must be changed"));
} else if ( (lstchgdate < 0)
|| (inactdays < 0)
- || (maxdays >= (10000 * (DAY / SCALE)))
+ || (maxdays >= 10000)
|| (maxdays < 0)
- || (maxdays > LONG_MAX - inactdays)
- || ((LONG_MAX - changed) / SCALE < maxdays + inactdays)) {
+ || (LONG_MAX - inactdays < maxdays)
+ || (LONG_MAX - lstchgdate < maxdays + inactdays))
+ {
(void) puts (_("never"));
} else {
- expires = changed + (maxdays + inactdays) * SCALE;
- print_date ((time_t) expires);
+ print_day_as_date(lstchgdate + maxdays + inactdays);
}
/*
@@ -302,12 +323,7 @@ static void list_fields (void)
* password expiring or not.
*/
(void) fputs (_("Account expires\t\t\t\t\t\t: "), stdout);
- if (expdate < 0 || LONG_MAX / SCALE < expdate) {
- (void) puts (_("never"));
- } else {
- expires = expdate * SCALE;
- print_date ((time_t) expires);
- }
+ print_day_as_date(expdate);
/*
* Start with the easy numbers - the number of days before the
@@ -344,12 +360,13 @@ static void process_flags (int argc, char **argv)
{"mindays", required_argument, NULL, 'm'},
{"maxdays", required_argument, NULL, 'M'},
{"root", required_argument, NULL, 'R'},
+ {"prefix", required_argument, NULL, 'P'},
{"warndays", required_argument, NULL, 'W'},
{"iso8601", no_argument, NULL, 'i'},
{NULL, 0, NULL, '\0'}
};
- while ((c = getopt_long (argc, argv, "d:E:hiI:lm:M:R:W:",
+ while ((c = getopt_long (argc, argv, "d:E:hiI:lm:M:R:P:W:",
long_options, NULL)) != -1) {
switch (c) {
case 'd':
@@ -380,7 +397,7 @@ static void process_flags (int argc, char **argv)
break;
case 'I':
Iflg = true;
- if ( (getlong (optarg, &inactdays) == 0)
+ if ( (str2sl(&inactdays, optarg) == -1)
|| (inactdays < -1)) {
fprintf (stderr,
_("%s: invalid numeric argument '%s'\n"),
@@ -393,7 +410,7 @@ static void process_flags (int argc, char **argv)
break;
case 'm':
mflg = true;
- if ( (getlong (optarg, &mindays) == 0)
+ if ( (str2sl(&mindays, optarg) == -1)
|| (mindays < -1)) {
fprintf (stderr,
_("%s: invalid numeric argument '%s'\n"),
@@ -403,7 +420,7 @@ static void process_flags (int argc, char **argv)
break;
case 'M':
Mflg = true;
- if ( (getlong (optarg, &maxdays) == 0)
+ if ( (str2sl(&maxdays, optarg) == -1)
|| (maxdays < -1)) {
fprintf (stderr,
_("%s: invalid numeric argument '%s'\n"),
@@ -413,9 +430,11 @@ static void process_flags (int argc, char **argv)
break;
case 'R': /* no-op, handled in process_root_flag () */
break;
+ case 'P': /* no-op, handled in process_prefix_flag () */
+ break;
case 'W':
Wflg = true;
- if ( (getlong (optarg, &warndays) == 0)
+ if ( (str2sl(&warndays, optarg) == -1)
|| (warndays < -1)) {
fprintf (stderr,
_("%s: invalid numeric argument '%s'\n"),
@@ -500,7 +519,7 @@ static void check_perms (void)
exit (E_NOPERM);
}
- retval = pam_start ("chage", pampw->pw_name, &conv, &pamh);
+ retval = pam_start (Prog, pampw->pw_name, &conv, &pamh);
if (PAM_SUCCESS == retval) {
retval = pam_authenticate (pamh, 0);
@@ -751,24 +770,23 @@ int main (int argc, char **argv)
gid_t rgid;
const struct passwd *pw;
- /*
- * Get the program name so that error messages can use it.
- */
- Prog = Basename (argv[0]);
+ sanitize_env ();
+ check_fds ();
+
log_set_progname(Prog);
log_set_logfd(stderr);
- sanitize_env ();
(void) setlocale (LC_ALL, "");
(void) bindtextdomain (PACKAGE, LOCALEDIR);
(void) textdomain (PACKAGE);
process_root_flag ("-R", argc, argv);
+ prefix = process_prefix_flag ("-P", argc, argv);
#ifdef WITH_AUDIT
audit_help_open ();
#endif
- OPENLOG ("chage");
+ OPENLOG (Prog);
ruid = getuid ();
rgid = getgid ();
@@ -809,7 +827,7 @@ int main (int argc, char **argv)
fail_exit (E_NOPERM);
}
- STRFCPY (user_name, pw->pw_name);
+ STRTCPY(user_name, pw->pw_name);
#ifdef WITH_TCB
if (shadowtcb_set_user (pw->pw_name) == SHADOWTCB_FAILURE) {
fail_exit (E_NOPERM);
@@ -831,8 +849,7 @@ int main (int argc, char **argv)
}
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
- "display aging info",
- user_name, (unsigned int) user_uid, 1);
+ "display aging info", user_name, user_uid, 1);
#endif
list_fields ();
fail_exit (E_SUCCESS);
@@ -854,40 +871,38 @@ int main (int argc, char **argv)
else {
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
"change all aging information",
- user_name, (unsigned int) user_uid, 1);
+ user_name, user_uid, 1);
}
#endif
} else {
#ifdef WITH_AUDIT
if (Mflg) {
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
- "change max age",
- user_name, (unsigned int) user_uid, 1);
+ "change max age", user_name, user_uid, 1);
}
if (mflg) {
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
- "change min age",
- user_name, (unsigned int) user_uid, 1);
+ "change min age", user_name, user_uid, 1);
}
if (dflg) {
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
"change last change date",
- user_name, (unsigned int) user_uid, 1);
+ user_name, user_uid, 1);
}
if (Wflg) {
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
"change passwd warning",
- user_name, (unsigned int) user_uid, 1);
+ user_name, user_uid, 1);
}
if (Iflg) {
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
"change inactive days",
- user_name, (unsigned int) user_uid, 1);
+ user_name, user_uid, 1);
}
if (Eflg) {
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
"change passwd expiration",
- user_name, (unsigned int) user_uid, 1);
+ user_name, user_uid, 1);
}
#endif
}
diff --git a/src/check_subid_range.c b/src/check_subid_range.c
index 38703b6..68266f5 100644
--- a/src/check_subid_range.c
+++ b/src/check_subid_range.c
@@ -12,20 +12,21 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+
+#include "atoi/str2i.h"
#include "defines.h"
#include "prototypes.h"
#include "subordinateio.h"
#include "idmapping.h"
#include "shadowlog.h"
-const char *Prog;
+static const char Prog[] = "check_subid_range";
int main(int argc, char **argv)
{
char *owner;
unsigned long start, count;
bool check_uids;
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -34,11 +35,10 @@ int main(int argc, char **argv)
owner = argv[1];
check_uids = argv[2][0] == 'u';
- start = strtoul(argv[3], NULL, 10);
- if (start == ULONG_MAX && errno == ERANGE)
+ errno = 0;
+ if (str2ul(&start, argv[3]) == -1)
exit(1);
- count = strtoul(argv[4], NULL, 10);
- if (count == ULONG_MAX && errno == ERANGE)
+ if (str2ul(&count, argv[4]) == -1)
exit(1);
if (check_uids) {
if (have_sub_uids(owner, start, count))
diff --git a/src/chfn.c b/src/chfn.c
index 1c2f1cc..9043212 100644
--- a/src/chfn.c
+++ b/src/chfn.c
@@ -17,6 +17,8 @@
#include <stdio.h>
#include <sys/types.h>
#include <getopt.h>
+
+#include "alloc.h"
#include "defines.h"
#include "getdef.h"
#include "nscd.h"
@@ -30,11 +32,14 @@
/*@-exitarg@*/
#include "exitcodes.h"
#include "shadowlog.h"
+#include "string/sprintf.h"
+#include "string/strtcpy.h"
+
/*
* Global variables.
*/
-const char *Prog;
+static const char Prog[] = "chfn";
static char fullnm[BUFSIZ];
static char roomno[BUFSIZ];
static char workph[BUFSIZ];
@@ -54,8 +59,8 @@ static bool pw_locked = false;
*/
/* local function prototypes */
-static void fail_exit (int code);
-static /*@noreturn@*/void usage (int status);
+NORETURN static void fail_exit (int code);
+NORETURN static void usage (int status);
static bool may_change_field (int);
static void new_fields (void);
static char *copy_field (char *, char *, char *);
@@ -86,7 +91,9 @@ static void fail_exit (int code)
/*
* usage - print command line syntax and exit
*/
-static /*@noreturn@*/void usage (int status)
+NORETURN
+static void
+usage (int status)
{
FILE *usageout = (E_SUCCESS != status) ? stderr : stdout;
(void) fprintf (usageout,
@@ -175,19 +182,19 @@ static void new_fields (void)
if (may_change_field ('r')) {
change_field (roomno, sizeof roomno, _("Room Number"));
} else {
- printf (_("\t%s: %s\n"), _("Room Number"), fullnm);
+ printf (_("\t%s: %s\n"), _("Room Number"), roomno);
}
if (may_change_field ('w')) {
change_field (workph, sizeof workph, _("Work Phone"));
} else {
- printf (_("\t%s: %s\n"), _("Work Phone"), fullnm);
+ printf (_("\t%s: %s\n"), _("Work Phone"), workph);
}
if (may_change_field ('h')) {
change_field (homeph, sizeof homeph, _("Home Phone"));
} else {
- printf (_("\t%s: %s\n"), _("Home Phone"), fullnm);
+ printf (_("\t%s: %s\n"), _("Home Phone"), homeph);
}
if (amroot) {
@@ -271,7 +278,7 @@ static void process_flags (int argc, char **argv)
exit (E_NOPERM);
}
fflg = true;
- STRFCPY (fullnm, optarg);
+ STRTCPY(fullnm, optarg);
break;
case 'h':
if (!may_change_field ('h')) {
@@ -280,7 +287,7 @@ static void process_flags (int argc, char **argv)
exit (E_NOPERM);
}
hflg = true;
- STRFCPY (homeph, optarg);
+ STRTCPY(homeph, optarg);
break;
case 'o':
if (!amroot) {
@@ -294,7 +301,7 @@ static void process_flags (int argc, char **argv)
_("%s: fields too long\n"), Prog);
exit (E_NOPERM);
}
- STRFCPY (slop, optarg);
+ STRTCPY(slop, optarg);
break;
case 'r':
if (!may_change_field ('r')) {
@@ -303,7 +310,7 @@ static void process_flags (int argc, char **argv)
exit (E_NOPERM);
}
rflg = true;
- STRFCPY (roomno, optarg);
+ STRTCPY(roomno, optarg);
break;
case 'R': /* no-op, handled in process_root_flag () */
break;
@@ -317,7 +324,7 @@ static void process_flags (int argc, char **argv)
exit (E_NOPERM);
}
wflg = true;
- STRFCPY (workph, optarg);
+ STRTCPY(workph, optarg);
break;
default:
usage (E_USAGE);
@@ -358,7 +365,7 @@ static void check_perms (const struct passwd *pw)
* check if the change is allowed by SELinux policy.
*/
if ((pw->pw_uid != getuid ())
- && (check_selinux_permit ("chfn") != 0)) {
+ && (check_selinux_permit (Prog) != 0)) {
fprintf (stderr, _("%s: Permission denied.\n"), Prog);
closelog ();
exit (E_NOPERM);
@@ -373,7 +380,7 @@ static void check_perms (const struct passwd *pw)
* --marekm
*/
if (!amroot && getdef_bool ("CHFN_AUTH")) {
- passwd_check (pw->pw_name, pw->pw_passwd, "chfn");
+ passwd_check (pw->pw_name, pw->pw_passwd, Prog);
}
#else /* !USE_PAM */
@@ -385,7 +392,7 @@ static void check_perms (const struct passwd *pw)
exit (E_NOPERM);
}
- retval = pam_start ("chfn", pampw->pw_name, &conv, &pamh);
+ retval = pam_start (Prog, pampw->pw_name, &conv, &pamh);
if (PAM_SUCCESS == retval) {
retval = pam_authenticate (pamh, 0);
@@ -504,34 +511,35 @@ static void get_old_fields (const char *gecos)
{
char *cp; /* temporary character pointer */
char old_gecos[BUFSIZ]; /* buffer for old GECOS fields */
- STRFCPY (old_gecos, gecos);
+
+ STRTCPY(old_gecos, gecos);
/*
* Now get the full name. It is the first comma separated field in
* the GECOS field.
*/
- cp = copy_field (old_gecos, fflg ? (char *) 0 : fullnm, slop);
+ cp = copy_field (old_gecos, fflg ? NULL : fullnm, slop);
/*
* Now get the room number. It is the next comma separated field,
* if there is indeed one.
*/
if (NULL != cp) {
- cp = copy_field (cp, rflg ? (char *) 0 : roomno, slop);
+ cp = copy_field (cp, rflg ? NULL : roomno, slop);
}
/*
* Now get the work phone number. It is the third field.
*/
if (NULL != cp) {
- cp = copy_field (cp, wflg ? (char *) 0 : workph, slop);
+ cp = copy_field (cp, wflg ? NULL : workph, slop);
}
/*
* Now get the home phone number. It is the fourth field.
*/
if (NULL != cp) {
- cp = copy_field (cp, hflg ? (char *) 0 : homeph, slop);
+ cp = copy_field (cp, hflg ? NULL : homeph, slop);
}
/*
@@ -608,19 +616,16 @@ static void check_fields (void)
*/
int main (int argc, char **argv)
{
- const struct passwd *pw; /* password file entry */
- char new_gecos[BUFSIZ]; /* buffer for new GECOS fields */
- char *user;
+ char new_gecos[BUFSIZ];
+ char *user;
+ const struct passwd *pw;
+
+ sanitize_env ();
+ check_fds ();
- /*
- * Get the program name. The program name is used as a
- * prefix to most error messages.
- */
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
- sanitize_env ();
(void) setlocale (LC_ALL, "");
(void) bindtextdomain (PACKAGE, LOCALEDIR);
(void) textdomain (PACKAGE);
@@ -633,7 +638,7 @@ int main (int argc, char **argv)
*/
amroot = (getuid () == 0);
- OPENLOG ("chfn");
+ OPENLOG (Prog);
/* parse the command line options */
process_flags (argc, argv);
@@ -663,29 +668,6 @@ int main (int argc, char **argv)
user = xstrdup (pw->pw_name);
}
-#ifdef USE_NIS
- /*
- * Now we make sure this is a LOCAL password entry for this user ...
- */
- if (__ispwNIS ()) {
- char *nis_domain;
- char *nis_master;
-
- fprintf (stderr,
- _("%s: cannot change user '%s' on NIS client.\n"),
- Prog, user);
-
- if (!yp_get_default_domain (&nis_domain) &&
- !yp_master (nis_domain, "passwd.byname", &nis_master)) {
- fprintf (stderr,
- _
- ("%s: '%s' is the NIS master for this client.\n"),
- Prog, nis_master);
- }
- fail_exit (E_NOPERM);
- }
-#endif
-
/* Check that the caller is allowed to change the gecos of the
* specified user */
check_perms (pw);
@@ -717,9 +699,9 @@ int main (int argc, char **argv)
fprintf (stderr, _("%s: fields too long\n"), Prog);
fail_exit (E_NOPERM);
}
- snprintf (new_gecos, sizeof new_gecos, "%s,%s,%s,%s%s%s",
- fullnm, roomno, workph, homeph,
- ('\0' != slop[0]) ? "," : "", slop);
+ SNPRINTF(new_gecos, "%s,%s,%s,%s%s%s",
+ fullnm, roomno, workph, homeph,
+ ('\0' != slop[0]) ? "," : "", slop);
/* Rewrite the user's gecos in the passwd file */
update_gecos (user, new_gecos);
diff --git a/src/chgpasswd.c b/src/chgpasswd.c
index d17acb6..1ff6776 100644
--- a/src/chgpasswd.c
+++ b/src/chgpasswd.c
@@ -16,11 +16,13 @@
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
+
#ifdef ACCT_TOOLS_SETUID
#ifdef USE_PAM
#include "pam_defs.h"
#endif /* USE_PAM */
#endif /* ACCT_TOOLS_SETUID */
+#include "atoi/str2i.h"
#include "defines.h"
#include "nscd.h"
#include "sssd.h"
@@ -33,10 +35,11 @@
#include "exitcodes.h"
#include "shadowlog.h"
+
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "chgpasswd";
static bool eflg = false;
static bool md5flg = false;
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT)
@@ -62,8 +65,8 @@ static bool sgr_locked = false;
static bool gr_locked = false;
/* local function prototypes */
-static void fail_exit (int code);
-static /*@noreturn@*/void usage (int status);
+NORETURN static void fail_exit (int code);
+NORETURN static void usage (int status);
static void process_flags (int argc, char **argv);
static void check_flags (void);
static void check_perms (void);
@@ -99,7 +102,9 @@ static void fail_exit (int code)
/*
* usage - display usage message and exit
*/
-static /*@noreturn@*/void usage (int status)
+NORETURN
+static void
+usage (int status)
{
FILE *usageout = (E_SUCCESS != status) ? stderr : stdout;
(void) fprintf (usageout,
@@ -184,21 +189,28 @@ static void process_flags (int argc, char **argv)
case 's':
sflg = true;
bad_s = 0;
+
+ if (!crypt_method) {
+ fprintf (stderr,
+ _("%s: no crypt method defined\n"),
+ Prog);
+ usage (E_USAGE);
+ }
#if defined(USE_SHA_CRYPT)
if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512")))
- && (0 == getlong(optarg, &sha_rounds)))) {
+ && (-1 == str2sl(&sha_rounds, optarg)))) {
bad_s = 1;
}
#endif /* USE_SHA_CRYPT */
#if defined(USE_BCRYPT)
if (( (0 == strcmp (crypt_method, "BCRYPT"))
- && (0 == getlong(optarg, &bcrypt_rounds)))) {
+ && (-1 == str2sl(&bcrypt_rounds, optarg)))) {
bad_s = 1;
}
#endif /* USE_BCRYPT */
#if defined(USE_YESCRYPT)
if (( (0 == strcmp (crypt_method, "YESCRYPT"))
- && (0 == getlong(optarg, &yescrypt_cost)))) {
+ && (-1 == str2sl(&yescrypt_cost, optarg)))) {
bad_s = 1;
}
#endif /* USE_YESCRYPT */
@@ -294,7 +306,7 @@ static void check_perms (void)
exit (1);
}
- retval = pam_start ("chgpasswd", pampw->pw_name, &conv, &pamh);
+ retval = pam_start (Prog, pampw->pw_name, &conv, &pamh);
if (PAM_SUCCESS == retval) {
retval = pam_authenticate (pamh, 0);
@@ -414,7 +426,6 @@ int main (int argc, char **argv)
int errors = 0;
int line = 0;
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -422,11 +433,17 @@ int main (int argc, char **argv)
(void) bindtextdomain (PACKAGE, LOCALEDIR);
(void) textdomain (PACKAGE);
+#ifdef WITH_SELINUX
+ if (check_selinux_permit ("passwd") != 0) {
+ return (E_NOPERM);
+ }
+#endif /* WITH_SELINUX */
+
process_root_flag ("-R", argc, argv);
process_flags (argc, argv);
- OPENLOG ("chgpasswd");
+ OPENLOG (Prog);
check_perms ();
@@ -441,7 +458,7 @@ int main (int argc, char **argv)
* group entry for each group will be looked up in the appropriate
* file (gshadow or group) and the password changed.
*/
- while (fgets (buf, (int) sizeof buf, stdin) != (char *) 0) {
+ while (fgets (buf, (int) sizeof buf, stdin) != NULL) {
line++;
cp = strrchr (buf, '\n');
if (NULL != cp) {
diff --git a/src/chpasswd.c b/src/chpasswd.c
index 48d5178..79880f5 100644
--- a/src/chpasswd.c
+++ b/src/chpasswd.c
@@ -16,9 +16,11 @@
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
+
#ifdef USE_PAM
#include "pam_defs.h"
#endif /* USE_PAM */
+#include "atoi/str2i.h"
#include "defines.h"
#include "nscd.h"
#include "sssd.h"
@@ -30,12 +32,13 @@
#include "exitcodes.h"
#include "shadowlog.h"
+
#define IS_CRYPT_METHOD(str) ((crypt_method != NULL && strcmp(crypt_method, str) == 0) ? true : false)
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "chpasswd";
static bool eflg = false;
static bool md5flg = false;
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT)
@@ -54,13 +57,15 @@ static long bcrypt_rounds = 13;
static long yescrypt_cost = 5;
#endif
+static const char *prefix = "";
+
static bool is_shadow_pwd;
static bool pw_locked = false;
static bool spw_locked = false;
/* local function prototypes */
-static void fail_exit (int code);
-static /*@noreturn@*/void usage (int status);
+NORETURN static void fail_exit (int code);
+NORETURN static void usage (int status);
static void process_flags (int argc, char **argv);
static void check_flags (void);
static void check_perms (void);
@@ -94,7 +99,9 @@ static void fail_exit (int code)
/*
* usage - display usage message and exit
*/
-static /*@noreturn@*/void usage (int status)
+NORETURN
+static void
+usage (int status)
{
FILE *usageout = (E_SUCCESS != status) ? stderr : stdout;
(void) fprintf (usageout,
@@ -121,6 +128,7 @@ static /*@noreturn@*/void usage (int status)
" the MD5 algorithm\n"),
usageout);
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
+ (void) fputs (_(" -P, --prefix PREFIX_DIR directory prefix\n"), usageout);
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT)
(void) fputs (_(" -s, --sha-rounds number of rounds for the SHA, BCRYPT\n"
" or YESCRYPT crypt algorithms\n"),
@@ -148,6 +156,7 @@ static void process_flags (int argc, char **argv)
{"help", no_argument, NULL, 'h'},
{"md5", no_argument, NULL, 'm'},
{"root", required_argument, NULL, 'R'},
+ {"prefix", required_argument, NULL, 'P'},
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT)
{"sha-rounds", required_argument, NULL, 's'},
#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */
@@ -156,9 +165,9 @@ static void process_flags (int argc, char **argv)
while ((c = getopt_long (argc, argv,
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT)
- "c:ehmR:s:",
+ "c:ehmR:P:s:",
#else
- "c:ehmR:",
+ "c:ehmR:P:",
#endif
long_options, NULL)) != -1) {
switch (c) {
@@ -176,25 +185,27 @@ static void process_flags (int argc, char **argv)
break;
case 'R': /* no-op, handled in process_root_flag () */
break;
+ case 'P': /* no-op, handled in process_prefix_flag () */
+ break;
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT)
case 's':
sflg = true;
bad_s = 0;
#if defined(USE_SHA_CRYPT)
if ((IS_CRYPT_METHOD("SHA256") || IS_CRYPT_METHOD("SHA512"))
- && (0 == getlong(optarg, &sha_rounds))) {
+ && (-1 == str2sl(&sha_rounds, optarg))) {
bad_s = 1;
}
#endif /* USE_SHA_CRYPT */
#if defined(USE_BCRYPT)
if (IS_CRYPT_METHOD("BCRYPT")
- && (0 == getlong(optarg, &bcrypt_rounds))) {
+ && (-1 == str2sl(&bcrypt_rounds, optarg))) {
bad_s = 1;
}
#endif /* USE_BCRYPT */
#if defined(USE_YESCRYPT)
if (IS_CRYPT_METHOD("YESCRYPT")
- && (0 == getlong(optarg, &yescrypt_cost))) {
+ && (-1 == str2sl(&yescrypt_cost, optarg))) {
bad_s = 1;
}
#endif /* USE_YESCRYPT */
@@ -294,7 +305,7 @@ static void check_perms (void)
exit (1);
}
- retval = pam_start ("chpasswd", pampw->pw_name, &conv, &pamh);
+ retval = pam_start (Prog, pampw->pw_name, &conv, &pamh);
if (PAM_SUCCESS == retval) {
retval = pam_authenticate (pamh, 0);
@@ -442,7 +453,6 @@ int main (int argc, char **argv)
int errors = 0;
int line = 0;
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -450,18 +460,25 @@ int main (int argc, char **argv)
(void) bindtextdomain (PACKAGE, LOCALEDIR);
(void) textdomain (PACKAGE);
+#ifdef WITH_SELINUX
+ if (check_selinux_permit ("passwd") != 0) {
+ return (E_NOPERM);
+ }
+#endif /* WITH_SELINUX */
+
process_flags (argc, argv);
salt = get_salt();
process_root_flag ("-R", argc, argv);
+ prefix = process_prefix_flag ("-P", argc, argv);
#ifdef USE_PAM
- if (md5flg || eflg || cflg) {
+ if (md5flg || eflg || cflg || prefix[0]) {
use_pam = false;
}
#endif /* USE_PAM */
- OPENLOG ("chpasswd");
+ OPENLOG (Prog);
check_perms ();
@@ -482,7 +499,7 @@ int main (int argc, char **argv)
* last change date is set in the age only if aging information is
* present.
*/
- while (fgets (buf, (int) sizeof buf, stdin) != (char *) 0) {
+ while (fgets (buf, sizeof buf, stdin) != NULL) {
line++;
cp = strrchr (buf, '\n');
if (NULL != cp) {
@@ -491,7 +508,7 @@ int main (int argc, char **argv)
if (feof (stdin) == 0) {
// Drop all remaining characters on this line.
- while (fgets (buf, (int) sizeof buf, stdin) != (char *) 0) {
+ while (fgets (buf, sizeof buf, stdin) != NULL) {
cp = strchr (buf, '\n');
if (cp != NULL) {
break;
@@ -531,7 +548,7 @@ int main (int argc, char **argv)
#ifdef USE_PAM
if (use_pam) {
- if (do_pam_passwd_non_interactive ("chpasswd", name, newpwd) != 0) {
+ if (do_pam_passwd_non_interactive (Prog, name, newpwd) != 0) {
fprintf (stderr,
_("%s: (line %d, user %s) password not changed\n"),
Prog, line, name);
@@ -606,7 +623,7 @@ int main (int argc, char **argv)
if (NULL != sp) {
newsp = *sp;
newsp.sp_pwdp = cp;
- newsp.sp_lstchg = (long) gettime () / SCALE;
+ newsp.sp_lstchg = gettime () / DAY;
if (0 == newsp.sp_lstchg) {
/* Better disable aging than requiring a
* password change */
diff --git a/src/chsh.c b/src/chsh.c
index 21d1c3e..c4918c1 100644
--- a/src/chsh.c
+++ b/src/chsh.c
@@ -16,6 +16,8 @@
#include <pwd.h>
#include <stdio.h>
#include <sys/types.h>
+
+#include "alloc.h"
#include "defines.h"
#include "getdef.h"
#include "nscd.h"
@@ -29,14 +31,22 @@
/*@-exitarg@*/
#include "exitcodes.h"
#include "shadowlog.h"
+#include "string/strtcpy.h"
#ifndef SHELLS_FILE
#define SHELLS_FILE "/etc/shells"
#endif
+
+#ifdef HAVE_VENDORDIR
+#include <libeconf.h>
+#define SHELLS "shells"
+#define ETCDIR "/etc"
+#endif
+
/*
* Global variables
*/
-const char *Prog; /* Program name */
+static const char Prog[] = "chsh"; /* Program name */
static bool amroot; /* Real UID is root */
static char loginsh[BUFSIZ]; /* Name of new login shell */
/* command line options */
@@ -46,8 +56,8 @@ static bool pw_locked = false;
/* external identifiers */
/* local function prototypes */
-static /*@noreturn@*/void fail_exit (int code);
-static /*@noreturn@*/void usage (int status);
+NORETURN static void fail_exit (int code);
+NORETURN static void usage (int status);
static void new_fields (void);
static bool shell_is_listed (const char *);
static bool is_restricted_shell (const char *);
@@ -58,7 +68,9 @@ static void update_shell (const char *user, char *loginsh);
/*
* fail_exit - do some cleanup and exit with the given error code
*/
-static /*@noreturn@*/void fail_exit (int code)
+NORETURN
+static void
+fail_exit (int code)
{
if (pw_locked) {
if (pw_unlock () == 0) {
@@ -76,7 +88,9 @@ static /*@noreturn@*/void fail_exit (int code)
/*
* usage - print command line syntax and exit
*/
-static /*@noreturn@*/void usage (int status)
+NORETURN
+static void
+usage (int status)
{
FILE *usageout = (E_SUCCESS != status) ? stderr : stdout;
(void) fprintf (usageout,
@@ -127,17 +141,60 @@ static bool is_restricted_shell (const char *sh)
* If getusershell() is available (Linux, *BSD, possibly others), use it
* instead of re-implementing it.
*/
+
+#ifdef HAVE_VENDORDIR
static bool shell_is_listed (const char *sh)
{
- char *cp;
bool found = false;
-#ifndef HAVE_GETUSERSHELL
- char buf[BUFSIZ];
- FILE *fp;
-#endif
+ size_t size = 0;
+ econf_err error;
+ char **keys;
+ econf_file *key_file;
+
+ error = econf_readDirs(&key_file,
+ VENDORDIR,
+ ETCDIR,
+ SHELLS,
+ NULL,
+ "", /* key only */
+ "#" /* comment */);
+ if (error) {
+ fprintf (stderr,
+ _("Cannot parse shell files: %s"),
+ econf_errString(error));
+ fail_exit (1);
+ }
+
+ error = econf_getKeys(key_file, NULL, &size, &keys);
+ if (error) {
+ fprintf (stderr,
+ _("Cannot evaluate entries in shell files: %s"),
+ econf_errString(error));
+ econf_free (key_file);
+ fail_exit (1);
+ }
+
+ for (size_t i = 0; i < size; i++) {
+ if (strcmp (keys[i], sh) == 0) {
+ found = true;
+ break;
+ }
+ }
+ econf_free (keys);
+ econf_free (key_file);
+
+ return found;
+}
+
+#else /* without HAVE_VENDORDIR */
+
+static bool shell_is_listed (const char *sh)
+{
+ bool found = false;
#ifdef HAVE_GETUSERSHELL
+ char *cp;
setusershell ();
while ((cp = getusershell ())) {
if (strcmp (cp, sh) == 0) {
@@ -147,18 +204,17 @@ static bool shell_is_listed (const char *sh)
}
endusershell ();
#else
+ char *buf = NULL;
+ FILE *fp;
+ size_t n = 0;
+
fp = fopen (SHELLS_FILE, "r");
if (NULL == fp) {
return false;
}
- while (fgets (buf, sizeof (buf), fp) == buf) {
- cp = strrchr (buf, '\n');
- if (NULL != cp) {
- *cp = '\0';
- }
-
- if (buf[0] == '#') {
+ while (getline (&buf, &n, fp) != -1) {
+ if (buf[0] != '/') {
continue;
}
@@ -167,10 +223,13 @@ static bool shell_is_listed (const char *sh)
break;
}
}
+
+ free(buf);
fclose (fp);
#endif
return found;
}
+#endif /* with HAVE_VENDORDIR */
/*
* process_flags - parse the command line options
@@ -197,7 +256,7 @@ static void process_flags (int argc, char **argv)
break;
case 's':
sflg = true;
- STRFCPY (loginsh, optarg);
+ STRTCPY(loginsh, optarg);
break;
default:
usage (E_USAGE);
@@ -260,7 +319,7 @@ static void check_perms (const struct passwd *pw)
* check if the change is allowed by SELinux policy.
*/
if ((pw->pw_uid != getuid ())
- && (check_selinux_permit("chsh") != 0)) {
+ && (check_selinux_permit(Prog) != 0)) {
SYSLOG ((LOG_WARN, "can't change shell for '%s'", pw->pw_name));
fprintf (stderr,
_("You may not change the shell for '%s'.\n"),
@@ -277,7 +336,7 @@ static void check_perms (const struct passwd *pw)
* chfn/chsh. --marekm
*/
if (!amroot && getdef_bool ("CHSH_AUTH")) {
- passwd_check (pw->pw_name, pw->pw_passwd, "chsh");
+ passwd_check (pw->pw_name, pw->pw_passwd, Prog);
}
#else /* !USE_PAM */
@@ -289,7 +348,7 @@ static void check_perms (const struct passwd *pw)
exit (E_NOPERM);
}
- retval = pam_start ("chsh", pampw->pw_name, &conv, &pamh);
+ retval = pam_start (Prog, pampw->pw_name, &conv, &pamh);
if (PAM_SUCCESS == retval) {
retval = pam_authenticate (pamh, 0);
@@ -413,12 +472,8 @@ int main (int argc, char **argv)
const struct passwd *pw; /* Password entry from /etc/passwd */
sanitize_env ();
+ check_fds ();
- /*
- * Get the program name. The program name is used as a prefix to
- * most error messages.
- */
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -433,7 +488,7 @@ int main (int argc, char **argv)
*/
amroot = (getuid () == 0);
- OPENLOG ("chsh");
+ OPENLOG (Prog);
/* parse the command line options */
process_flags (argc, argv);
@@ -463,28 +518,6 @@ int main (int argc, char **argv)
user = xstrdup (pw->pw_name);
}
-#ifdef USE_NIS
- /*
- * Now we make sure this is a LOCAL password entry for this user ...
- */
- if (__ispwNIS ()) {
- char *nis_domain;
- char *nis_master;
-
- fprintf (stderr,
- _("%s: cannot change user '%s' on NIS client.\n"),
- Prog, user);
-
- if (!yp_get_default_domain (&nis_domain) &&
- !yp_master (nis_domain, "passwd.byname", &nis_master)) {
- fprintf (stderr,
- _("%s: '%s' is the NIS master for this client.\n"),
- Prog, nis_master);
- }
- fail_exit (1);
- }
-#endif
-
check_perms (pw);
/*
@@ -492,7 +525,7 @@ int main (int argc, char **argv)
* file, or use the value from the command line.
*/
if (!sflg) {
- STRFCPY (loginsh, pw->pw_shell);
+ STRTCPY(loginsh, pw->pw_shell);
}
/*
@@ -514,11 +547,15 @@ int main (int argc, char **argv)
fprintf (stderr, _("%s: Invalid entry: %s\n"), Prog, loginsh);
fail_exit (1);
}
- if ( !amroot
- && ( is_restricted_shell (loginsh)
- || (access (loginsh, X_OK) != 0))) {
- fprintf (stderr, _("%s: %s is an invalid shell\n"), Prog, loginsh);
- fail_exit (1);
+ if (loginsh[0] != '/'
+ || is_restricted_shell (loginsh)
+ || (access (loginsh, X_OK) != 0)) {
+ if (amroot) {
+ fprintf (stderr, _("%s: Warning: %s is an invalid shell\n"), Prog, loginsh);
+ } else {
+ fprintf (stderr, _("%s: %s is an invalid shell\n"), Prog, loginsh);
+ fail_exit (1);
+ }
}
/* Even for root, warn if an invalid shell is specified. */
diff --git a/src/expiry.c b/src/expiry.c
index dc20b90..12647a2 100644
--- a/src/expiry.c
+++ b/src/expiry.c
@@ -16,6 +16,8 @@
#include <stdio.h>
#include <sys/types.h>
#include <getopt.h>
+
+#include "attr.h"
#include "defines.h"
#include "prototypes.h"
/*@-exitarg@*/
@@ -23,18 +25,18 @@
#include "shadowlog.h"
/* Global variables */
-const char *Prog;
+static const char Prog[] = "expiry";
static bool cflg = false;
/* local function prototypes */
-static void catch_signals (unused int sig);
-static /*@noreturn@*/void usage (int status);
+static void catch_signals (MAYBE_UNUSED int sig);
+NORETURN static void usage (int status);
static void process_flags (int argc, char **argv);
/*
* catch_signals - signal catcher
*/
-static void catch_signals (unused int sig)
+static void catch_signals (MAYBE_UNUSED int sig)
{
_exit (10);
}
@@ -42,7 +44,9 @@ static void catch_signals (unused int sig)
/*
* usage - print syntax message and exit
*/
-static /*@noreturn@*/void usage (int status)
+NORETURN
+static void
+usage (int status)
{
FILE *usageout = (E_SUCCESS != status) ? stderr : stdout;
(void) fprintf (usageout,
@@ -121,21 +125,19 @@ int main (int argc, char **argv)
struct passwd *pwd;
struct spwd *spwd;
- Prog = Basename (argv[0]);
+ sanitize_env ();
+ check_fds ();
+
log_set_progname(Prog);
log_set_logfd(stderr);
- sanitize_env ();
-
/*
* Start by disabling all of the keyboard signals.
*/
(void) signal (SIGHUP, catch_signals);
(void) signal (SIGINT, catch_signals);
(void) signal (SIGQUIT, catch_signals);
-#ifdef SIGTSTP
(void) signal (SIGTSTP, catch_signals);
-#endif
/*
* expiry takes one of two arguments. The default action is to give
@@ -145,7 +147,7 @@ int main (int argc, char **argv)
(void) bindtextdomain (PACKAGE, LOCALEDIR);
(void) textdomain (PACKAGE);
- OPENLOG ("expiry");
+ OPENLOG (Prog);
process_flags (argc, argv);
diff --git a/src/faillog.c b/src/faillog.c
index 0f94836..77c25b8 100644
--- a/src/faillog.c
+++ b/src/faillog.c
@@ -18,15 +18,21 @@
#include <sys/types.h>
#include <time.h>
#include <assert.h>
+
+#include "atoi/str2i.h"
#include "defines.h"
#include "faillog.h"
+#include "memzero.h"
#include "prototypes.h"
/*@-exitarg@*/
#include "exitcodes.h"
#include "shadowlog.h"
+#include "string/strftime.h"
+
+
/* local function prototypes */
-static /*@noreturn@*/void usage (int status);
+NORETURN static void usage (int status);
static void print_one (/*@null@*/const struct passwd *pw, bool force);
static void set_locktime (long locktime);
static bool set_locktime_one (uid_t uid, long locktime);
@@ -39,7 +45,7 @@ static void reset (void);
/*
* Global variables
*/
-const char *Prog; /* Program name */
+static const char Prog[] = "faillog"; /* Program name */
static FILE *fail; /* failure file stream */
static time_t seconds; /* that number of days in seconds */
static unsigned long umin; /* if uflg and has_umin, only display users with uid >= umin */
@@ -57,9 +63,11 @@ static bool rflg = false; /* reset the counters of login failures */
static struct stat statbuf; /* fstat buffer for file size */
-#define NOW (time((time_t *) 0))
+#define NOW time(NULL)
-static /*@noreturn@*/void usage (int status)
+NORETURN
+static void
+usage (int status)
{
FILE *usageout = (E_SUCCESS != status) ? stderr : stdout;
(void) fprintf (usageout,
@@ -81,34 +89,36 @@ static /*@noreturn@*/void usage (int status)
exit (status);
}
-static void print_one (/*@null@*/const struct passwd *pw, bool force)
+/*
+ * Looks up the offset in the faillog file for the given uid.
+ * Returns -1 on error.
+ */
+static off_t lookup_faillog(struct faillog *fl, uid_t uid)
{
- static bool once = false;
- struct tm *tm;
- off_t offset;
- struct faillog fl;
- time_t now;
- char *cp;
- char ptime[80];
-
- if (NULL == pw) {
- return;
+ off_t offset, size;
+
+ /* Ensure multiplication does not overflow and retrieving a wrong entry */
+ if (__builtin_mul_overflow(uid, sizeof(*fl), &offset)) {
+ fprintf(stderr,
+ _("%s: Failed to get the entry for UID %lu\n"),
+ Prog, (unsigned long)uid);
+ return -1;
}
- offset = (off_t) pw->pw_uid * sizeof (fl);
- if (offset + sizeof (fl) <= statbuf.st_size) {
+ if (!__builtin_add_overflow(offset, sizeof(*fl), &size)
+ && size <= statbuf.st_size) {
/* fseeko errors are not really relevant for us. */
- int err = fseeko (fail, offset, SEEK_SET);
- assert (0 == err);
+ int err = fseeko(fail, offset, SEEK_SET);
+ assert(0 == err);
/* faillog is a sparse file. Even if no entries were
* entered for this user, which should be able to get the
* empty entry in this case.
*/
- if (fread ((char *) &fl, sizeof (fl), 1, fail) != 1) {
- fprintf (stderr,
- _("%s: Failed to get the entry for UID %lu\n"),
- Prog, (unsigned long int)pw->pw_uid);
- return;
+ if (fread(fl, sizeof(*fl), 1, fail) != 1) {
+ fprintf(stderr,
+ _("%s: Failed to get the entry for UID %lu\n"),
+ Prog, (unsigned long)uid);
+ return -1;
}
} else {
/* Outsize of the faillog file.
@@ -116,7 +126,27 @@ static void print_one (/*@null@*/const struct passwd *pw, bool force)
* as if we were reading an non existing entry in the
* sparse faillog file).
*/
- memzero (&fl, sizeof (fl));
+ memzero(fl, sizeof(*fl));
+ }
+
+ return offset;
+}
+
+static void print_one (/*@null@*/const struct passwd *pw, bool force)
+{
+ static bool once = false;
+ struct tm *tm;
+ struct faillog fl;
+ time_t now;
+ char *cp;
+ char ptime[80];
+
+ if (NULL == pw) {
+ return;
+ }
+
+ if (lookup_faillog(&fl, pw->pw_uid) < 0) {
+ return;
}
/* Nothing to report */
@@ -142,7 +172,7 @@ static void print_one (/*@null@*/const struct passwd *pw, bool force)
fprintf (stderr, "Cannot read time from faillog.\n");
return;
}
- strftime (ptime, sizeof (ptime), "%D %H:%M:%S %z", tm);
+ STRFTIME(ptime, "%D %H:%M:%S %z", tm);
cp = ptime;
printf ("%-9s %5d %5d ",
@@ -164,7 +194,7 @@ static void print_one (/*@null@*/const struct passwd *pw, bool force)
static void print (void)
{
if (uflg && has_umin && has_umax && (umin==umax)) {
- print_one (getpwuid ((uid_t)umin), true);
+ print_one (getpwuid (umin), true);
} else {
/* We only print records for existing users.
* Loop based on the user database instead of reading the
@@ -197,28 +227,10 @@ static bool reset_one (uid_t uid)
off_t offset;
struct faillog fl;
- offset = (off_t) uid * sizeof (fl);
- if (offset + sizeof (fl) <= statbuf.st_size) {
- /* fseeko errors are not really relevant for us. */
- int err = fseeko (fail, offset, SEEK_SET);
- assert (0 == err);
- /* faillog is a sparse file. Even if no entries were
- * entered for this user, which should be able to get the
- * empty entry in this case.
- */
- if (fread ((char *) &fl, sizeof (fl), 1, fail) != 1) {
- fprintf (stderr,
- _("%s: Failed to get the entry for UID %lu\n"),
- Prog, (unsigned long int)uid);
- return true;
- }
- } else {
- /* Outsize of the faillog file.
- * Behave as if there were a missing entry (same behavior
- * as if we were reading an non existing entry in the
- * sparse faillog file).
- */
- memzero (&fl, sizeof (fl));
+ offset = lookup_faillog(&fl, uid);
+ if (offset < 0) {
+ /* failure */
+ return true;
}
if (0 == fl.fail_cnt) {
@@ -232,21 +244,21 @@ static bool reset_one (uid_t uid)
fl.fail_cnt = 0;
if ( (fseeko (fail, offset, SEEK_SET) == 0)
- && (fwrite ((char *) &fl, sizeof (fl), 1, fail) == 1)) {
+ && (fwrite (&fl, sizeof (fl), 1, fail) == 1)) {
(void) fflush (fail);
return false;
}
fprintf (stderr,
_("%s: Failed to reset fail count for UID %lu\n"),
- Prog, (unsigned long int)uid);
+ Prog, (unsigned long)uid);
return true;
}
static void reset (void)
{
if (uflg && has_umin && has_umax && (umin==umax)) {
- if (reset_one ((uid_t)umin)) {
+ if (reset_one (umin)) {
errors = true;
}
} else {
@@ -258,7 +270,7 @@ static void reset (void)
uidmax--;
}
if (has_umax && (uid_t)umax < uidmax) {
- uidmax = (uid_t)umax;
+ uidmax = umax;
}
/* Reset all entries in the specified range.
@@ -271,7 +283,7 @@ static void reset (void)
/* Make sure we stay in the umin-umax range if specified */
if (has_umin) {
- uid = (uid_t)umin;
+ uid = umin;
}
while (uid <= uidmax) {
@@ -289,7 +301,7 @@ static void reset (void)
while ( (pwent = getpwent ()) != NULL ) {
if ( uflg
&& ( (has_umin && (pwent->pw_uid < (uid_t)umin))
- || (pwent->pw_uid > (uid_t)uidmax))) {
+ || (pwent->pw_uid > uidmax))) {
continue;
}
if (reset_one (pwent->pw_uid)) {
@@ -311,28 +323,9 @@ static bool setmax_one (uid_t uid, short max)
off_t offset;
struct faillog fl;
- offset = (off_t) uid * sizeof (fl);
- if (offset + sizeof (fl) <= statbuf.st_size) {
- /* fseeko errors are not really relevant for us. */
- int err = fseeko (fail, offset, SEEK_SET);
- assert (0 == err);
- /* faillog is a sparse file. Even if no entries were
- * entered for this user, which should be able to get the
- * empty entry in this case.
- */
- if (fread ((char *) &fl, sizeof (fl), 1, fail) != 1) {
- fprintf (stderr,
- _("%s: Failed to get the entry for UID %lu\n"),
- Prog, (unsigned long int)uid);
- return true;
- }
- } else {
- /* Outsize of the faillog file.
- * Behave as if there were a missing entry (same behavior
- * as if we were reading an non existing entry in the
- * sparse faillog file).
- */
- memzero (&fl, sizeof (fl));
+ offset = lookup_faillog(&fl, uid);
+ if (offset < 0) {
+ return true;
}
if (max == fl.fail_max) {
@@ -347,21 +340,21 @@ static bool setmax_one (uid_t uid, short max)
fl.fail_max = max;
if ( (fseeko (fail, offset, SEEK_SET) == 0)
- && (fwrite ((char *) &fl, sizeof (fl), 1, fail) == 1)) {
+ && (fwrite (&fl, sizeof (fl), 1, fail) == 1)) {
(void) fflush (fail);
return false;
}
fprintf (stderr,
_("%s: Failed to set max for UID %lu\n"),
- Prog, (unsigned long int)uid);
+ Prog, (unsigned long)uid);
return true;
}
static void setmax (short max)
{
if (uflg && has_umin && has_umax && (umin==umax)) {
- if (setmax_one ((uid_t)umin, max)) {
+ if (setmax_one (umin, max)) {
errors = true;
}
} else {
@@ -385,10 +378,10 @@ static void setmax (short max)
/* Make sure we stay in the umin-umax range if specified */
if (has_umin) {
- uid = (uid_t)umin;
+ uid = umin;
}
if (has_umax) {
- uidmax = (uid_t)umax;
+ uidmax = umax;
}
while (uid <= uidmax) {
@@ -428,28 +421,9 @@ static bool set_locktime_one (uid_t uid, long locktime)
off_t offset;
struct faillog fl;
- offset = (off_t) uid * sizeof (fl);
- if (offset + sizeof (fl) <= statbuf.st_size) {
- /* fseeko errors are not really relevant for us. */
- int err = fseeko (fail, offset, SEEK_SET);
- assert (0 == err);
- /* faillog is a sparse file. Even if no entries were
- * entered for this user, which should be able to get the
- * empty entry in this case.
- */
- if (fread ((char *) &fl, sizeof (fl), 1, fail) != 1) {
- fprintf (stderr,
- _("%s: Failed to get the entry for UID %lu\n"),
- Prog, (unsigned long int)uid);
- return true;
- }
- } else {
- /* Outsize of the faillog file.
- * Behave as if there were a missing entry (same behavior
- * as if we were reading an non existing entry in the
- * sparse faillog file).
- */
- memzero (&fl, sizeof (fl));
+ offset = lookup_faillog(&fl, uid);
+ if (offset < 0) {
+ return true;
}
if (locktime == fl.fail_locktime) {
@@ -464,21 +438,21 @@ static bool set_locktime_one (uid_t uid, long locktime)
fl.fail_locktime = locktime;
if ( (fseeko (fail, offset, SEEK_SET) == 0)
- && (fwrite ((char *) &fl, sizeof (fl), 1, fail) == 1)) {
+ && (fwrite (&fl, sizeof (fl), 1, fail) == 1)) {
(void) fflush (fail);
return false;
}
fprintf (stderr,
_("%s: Failed to set locktime for UID %lu\n"),
- Prog, (unsigned long int)uid);
+ Prog, (unsigned long)uid);
return true;
}
static void set_locktime (long locktime)
{
if (uflg && has_umin && has_umax && (umin==umax)) {
- if (set_locktime_one ((uid_t)umin, locktime)) {
+ if (set_locktime_one (umin, locktime)) {
errors = true;
}
} else {
@@ -502,10 +476,10 @@ static void set_locktime (long locktime)
/* Make sure we stay in the umin-umax range if specified */
if (has_umin) {
- uid = (uid_t)umin;
+ uid = umin;
}
if (has_umax) {
- uidmax = (uid_t)umax;
+ uidmax = umax;
}
while (uid <= uidmax) {
@@ -541,11 +515,6 @@ int main (int argc, char **argv)
short fail_max = 0; // initialize to silence compiler warning
long days = 0;
- /*
- * Get the program name. The program name is used as a prefix to
- * most error messages.
- */
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -578,7 +547,7 @@ int main (int argc, char **argv)
usage (E_SUCCESS);
/*@notreached@*/break;
case 'l':
- if (getlong (optarg, &fail_locktime) == 0) {
+ if (str2sl(&fail_locktime, optarg) == -1) {
fprintf (stderr,
_("%s: invalid numeric argument '%s'\n"),
Prog, optarg);
@@ -588,15 +557,16 @@ int main (int argc, char **argv)
break;
case 'm':
{
- long int lmax;
- if ( (getlong (optarg, &lmax) == 0)
- || ((long int)(short) lmax != lmax)) {
+ long lmax;
+
+ if ( (str2sl(&lmax, optarg) == -1)
+ || ((long)(short) lmax != lmax)) {
fprintf (stderr,
_("%s: invalid numeric argument '%s'\n"),
Prog, optarg);
exit (E_BAD_ARG);
}
- fail_max = (short) lmax;
+ fail_max = lmax;
mflg = true;
break;
}
@@ -606,7 +576,7 @@ int main (int argc, char **argv)
case 'R': /* no-op, handled in process_root_flag () */
break;
case 't':
- if (getlong (optarg, &days) == 0) {
+ if (str2sl(&days, optarg) == -1) {
fprintf (stderr,
_("%s: invalid numeric argument '%s'\n"),
Prog, optarg);
@@ -630,14 +600,14 @@ int main (int argc, char **argv)
/* local, no need for xgetpwnam */
pwent = getpwnam (optarg);
if (NULL != pwent) {
- umin = (unsigned long) pwent->pw_uid;
+ umin = pwent->pw_uid;
has_umin = true;
umax = umin;
has_umax = true;
} else {
- if (getrange (optarg,
- &umin, &has_umin,
- &umax, &has_umax) == 0) {
+ if (getrange(optarg,
+ &umin, &has_umin,
+ &umax, &has_umax) == -1) {
fprintf (stderr,
_("%s: Unknown user or range: %s\n"),
Prog, optarg);
diff --git a/src/free_subid_range.c b/src/free_subid_range.c
index d9a2cd8..441c227 100644
--- a/src/free_subid_range.c
+++ b/src/free_subid_range.c
@@ -9,7 +9,7 @@
/* Test program for the subid freeing routine */
-const char *Prog;
+static const char Prog[] = "free_subid_range";
static void usage(void)
{
@@ -25,7 +25,6 @@ int main(int argc, char *argv[])
struct subordinate_range range;
bool group = false; // get subuids by default
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
while ((c = getopt(argc, argv, "g")) != EOF) {
diff --git a/src/get_subid_owners.c b/src/get_subid_owners.c
index 36974b8..e1c1e79 100644
--- a/src/get_subid_owners.c
+++ b/src/get_subid_owners.c
@@ -6,7 +6,7 @@
#include "prototypes.h"
#include "shadowlog.h"
-const char *Prog;
+static const char Prog[] = "get_subid_owners";
static void usage(void)
{
@@ -21,7 +21,6 @@ int main(int argc, char *argv[])
int i, n;
uid_t *uids;
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
if (argc < 2) {
diff --git a/src/getsubids.c b/src/getsubids.c
index c91ae39..0753abd 100644
--- a/src/getsubids.c
+++ b/src/getsubids.c
@@ -7,7 +7,7 @@
#include "prototypes.h"
#include "shadowlog.h"
-const char *Prog;
+static const char Prog[] = "getsubids";
static void usage(void)
{
@@ -23,7 +23,6 @@ int main(int argc, char *argv[])
struct subid_range *ranges;
const char *owner;
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
if (argc < 2)
@@ -45,5 +44,6 @@ int main(int argc, char *argv[])
printf("%d: %s %lu %lu\n", i, owner,
ranges[i].start, ranges[i].count);
}
+ free(ranges);
return 0;
}
diff --git a/src/gpasswd.c b/src/gpasswd.c
index 5983f78..de6b1c4 100644
--- a/src/gpasswd.c
+++ b/src/gpasswd.c
@@ -19,8 +19,13 @@
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
+
+#include "agetpass.h"
+#include "alloc.h"
+#include "attr.h"
#include "defines.h"
#include "groupio.h"
+#include "memzero.h"
#include "nscd.h"
#include "sssd.h"
#include "prototypes.h"
@@ -29,13 +34,16 @@
#endif
/*@-exitarg@*/
#include "exitcodes.h"
-
#include "shadowlog.h"
+#include "string/sprintf.h"
+#include "string/strtcpy.h"
+
+
/*
* Global variables
*/
/* The name of this command, as it is invoked */
-const char *Prog;
+static const char Prog[] = "gpasswd";
#ifdef SHADOWGRP
/* Indicate if shadow groups are enabled on the system
@@ -73,6 +81,7 @@ static uid_t bywho;
#endif
/* local function prototypes */
+NORETURN static void failure(void);
static void usage (int status);
static void catch_signals (int killed);
static bool is_valid_user_list (const char *users);
@@ -92,14 +101,14 @@ static void update_group (struct group *gr);
static void change_passwd (struct group *gr);
#endif
static void log_gpasswd_failure (const char *suffix);
-static void log_gpasswd_failure_system (/*@null@*/unused void *arg);
-static void log_gpasswd_failure_group (/*@null@*/unused void *arg);
+static void log_gpasswd_failure_system (/*@null@*/MAYBE_UNUSED void *arg);
+static void log_gpasswd_failure_group (/*@null@*/MAYBE_UNUSED void *arg);
#ifdef SHADOWGRP
-static void log_gpasswd_failure_gshadow (/*@null@*/unused void *arg);
+static void log_gpasswd_failure_gshadow (/*@null@*/MAYBE_UNUSED void *arg);
#endif
static void log_gpasswd_success (const char *suffix);
-static void log_gpasswd_success_system (/*@null@*/unused void *arg);
-static void log_gpasswd_success_group (/*@null@*/unused void *arg);
+static void log_gpasswd_success_system (/*@null@*/MAYBE_UNUSED void *arg);
+static void log_gpasswd_success_group (/*@null@*/MAYBE_UNUSED void *arg);
/*
* usage - display usage message
@@ -194,11 +203,11 @@ static bool is_valid_user_list (const char *users)
return is_valid;
}
-static void failure (void)
+static void failure(void)
{
- fprintf (stderr, _("%s: Permission denied.\n"), Prog);
- log_gpasswd_failure (": Permission denied");
- exit (E_NOPERM);
+ fprintf(stderr, _("%s: Permission denied.\n"), Prog);
+ log_gpasswd_failure(": Permission denied");
+ exit(E_NOPERM);
}
/*
@@ -376,17 +385,16 @@ static void open_files (void)
static void log_gpasswd_failure (const char *suffix)
{
#ifdef WITH_AUDIT
- char buf[1024];
+ char buf[1024];
#endif
+
if (aflg) {
SYSLOG ((LOG_ERR,
"%s failed to add user %s to group %s%s",
myname, user, group, suffix));
#ifdef WITH_AUDIT
- snprintf (buf, 1023,
- "%s failed to add user %s to group %s%s",
- myname, user, group, suffix);
- buf[1023] = '\0';
+ SNPRINTF(buf, "%s failed to add user %s to group %s%s",
+ myname, user, group, suffix);
audit_logger (AUDIT_USER_ACCT, Prog,
buf,
group, AUDIT_NO_ID,
@@ -397,10 +405,8 @@ static void log_gpasswd_failure (const char *suffix)
"%s failed to remove user %s from group %s%s",
myname, user, group, suffix));
#ifdef WITH_AUDIT
- snprintf (buf, 1023,
- "%s failed to remove user %s from group %s%s",
- myname, user, group, suffix);
- buf[1023] = '\0';
+ SNPRINTF(buf, "%s failed to remove user %s from group %s%s",
+ myname, user, group, suffix);
audit_logger (AUDIT_USER_ACCT, Prog,
buf,
group, AUDIT_NO_ID,
@@ -411,10 +417,8 @@ static void log_gpasswd_failure (const char *suffix)
"%s failed to remove password of group %s%s",
myname, group, suffix));
#ifdef WITH_AUDIT
- snprintf (buf, 1023,
- "%s failed to remove password of group %s%s",
- myname, group, suffix);
- buf[1023] = '\0';
+ SNPRINTF(buf, "%s failed to remove password of group %s%s",
+ myname, group, suffix);
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
buf,
group, AUDIT_NO_ID,
@@ -425,10 +429,8 @@ static void log_gpasswd_failure (const char *suffix)
"%s failed to restrict access to group %s%s",
myname, group, suffix));
#ifdef WITH_AUDIT
- snprintf (buf, 1023,
- "%s failed to restrict access to group %s%s",
- myname, group, suffix);
- buf[1023] = '\0';
+ SNPRINTF(buf, "%s failed to restrict access to group %s%s",
+ myname, group, suffix);
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
buf,
group, AUDIT_NO_ID,
@@ -441,10 +443,8 @@ static void log_gpasswd_failure (const char *suffix)
"%s failed to set the administrators of group %s to %s%s",
myname, group, admins, suffix));
#ifdef WITH_AUDIT
- snprintf (buf, 1023,
- "%s failed to set the administrators of group %s to %s%s",
- myname, group, admins, suffix);
- buf[1023] = '\0';
+ SNPRINTF(buf, "%s failed to set the administrators of group %s to %s%s",
+ myname, group, admins, suffix);
audit_logger (AUDIT_USER_ACCT, Prog,
buf,
group, AUDIT_NO_ID,
@@ -457,10 +457,8 @@ static void log_gpasswd_failure (const char *suffix)
"%s failed to set the members of group %s to %s%s",
myname, group, members, suffix));
#ifdef WITH_AUDIT
- snprintf (buf, 1023,
- "%s failed to set the members of group %s to %s%s",
- myname, group, members, suffix);
- buf[1023] = '\0';
+ SNPRINTF(buf, "%s failed to set the members of group %s to %s%s",
+ myname, group, members, suffix);
audit_logger (AUDIT_USER_ACCT, Prog,
buf,
group, AUDIT_NO_ID,
@@ -472,10 +470,8 @@ static void log_gpasswd_failure (const char *suffix)
"%s failed to change password of group %s%s",
myname, group, suffix));
#ifdef WITH_AUDIT
- snprintf (buf, 1023,
- "%s failed to change password of group %s%s",
- myname, group, suffix);
- buf[1023] = '\0';
+ SNPRINTF(buf, "%s failed to change password of group %s%s",
+ myname, group, suffix);
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
buf,
group, AUDIT_NO_ID,
@@ -484,25 +480,25 @@ static void log_gpasswd_failure (const char *suffix)
}
}
-static void log_gpasswd_failure_system (unused void *arg)
+static void log_gpasswd_failure_system (MAYBE_UNUSED void *arg)
{
log_gpasswd_failure ("");
}
-static void log_gpasswd_failure_group (unused void *arg)
+static void log_gpasswd_failure_group (MAYBE_UNUSED void *arg)
{
- char buf[1024];
- snprintf (buf, 1023, " in %s", gr_dbname ());
- buf[1023] = '\0';
+ char buf[1024];
+
+ SNPRINTF(buf, " in %s", gr_dbname());
log_gpasswd_failure (buf);
}
#ifdef SHADOWGRP
-static void log_gpasswd_failure_gshadow (unused void *arg)
+static void log_gpasswd_failure_gshadow (MAYBE_UNUSED void *arg)
{
- char buf[1024];
- snprintf (buf, 1023, " in %s", sgr_dbname ());
- buf[1023] = '\0';
+ char buf[1024];
+
+ SNPRINTF(buf, " in %s", sgr_dbname());
log_gpasswd_failure (buf);
}
#endif /* SHADOWGRP */
@@ -510,17 +506,16 @@ static void log_gpasswd_failure_gshadow (unused void *arg)
static void log_gpasswd_success (const char *suffix)
{
#ifdef WITH_AUDIT
- char buf[1024];
+ char buf[1024];
#endif
+
if (aflg) {
SYSLOG ((LOG_INFO,
"user %s added by %s to group %s%s",
user, myname, group, suffix));
#ifdef WITH_AUDIT
- snprintf (buf, 1023,
- "user %s added by %s to group %s%s",
- user, myname, group, suffix);
- buf[1023] = '\0';
+ SNPRINTF(buf, "user %s added by %s to group %s%s",
+ user, myname, group, suffix);
audit_logger (AUDIT_USER_ACCT, Prog,
buf,
group, AUDIT_NO_ID,
@@ -531,10 +526,8 @@ static void log_gpasswd_success (const char *suffix)
"user %s removed by %s from group %s%s",
user, myname, group, suffix));
#ifdef WITH_AUDIT
- snprintf (buf, 1023,
- "user %s removed by %s from group %s%s",
- user, myname, group, suffix);
- buf[1023] = '\0';
+ SNPRINTF(buf, "user %s removed by %s from group %s%s",
+ user, myname, group, suffix);
audit_logger (AUDIT_USER_ACCT, Prog,
buf,
group, AUDIT_NO_ID,
@@ -545,10 +538,8 @@ static void log_gpasswd_success (const char *suffix)
"password of group %s removed by %s%s",
group, myname, suffix));
#ifdef WITH_AUDIT
- snprintf (buf, 1023,
- "password of group %s removed by %s%s",
- group, myname, suffix);
- buf[1023] = '\0';
+ SNPRINTF(buf, "password of group %s removed by %s%s",
+ group, myname, suffix);
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
buf,
group, AUDIT_NO_ID,
@@ -559,10 +550,8 @@ static void log_gpasswd_success (const char *suffix)
"access to group %s restricted by %s%s",
group, myname, suffix));
#ifdef WITH_AUDIT
- snprintf (buf, 1023,
- "access to group %s restricted by %s%s",
- group, myname, suffix);
- buf[1023] = '\0';
+ SNPRINTF(buf, "access to group %s restricted by %s%s",
+ group, myname, suffix);
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
buf,
group, AUDIT_NO_ID,
@@ -575,10 +564,8 @@ static void log_gpasswd_success (const char *suffix)
"administrators of group %s set by %s to %s%s",
group, myname, admins, suffix));
#ifdef WITH_AUDIT
- snprintf (buf, 1023,
- "administrators of group %s set by %s to %s%s",
- group, myname, admins, suffix);
- buf[1023] = '\0';
+ SNPRINTF(buf, "administrators of group %s set by %s to %s%s",
+ group, myname, admins, suffix);
audit_logger (AUDIT_USER_ACCT, Prog,
buf,
group, AUDIT_NO_ID,
@@ -591,10 +578,8 @@ static void log_gpasswd_success (const char *suffix)
"members of group %s set by %s to %s%s",
group, myname, members, suffix));
#ifdef WITH_AUDIT
- snprintf (buf, 1023,
- "members of group %s set by %s to %s%s",
- group, myname, members, suffix);
- buf[1023] = '\0';
+ SNPRINTF(buf, "members of group %s set by %s to %s%s",
+ group, myname, members, suffix);
audit_logger (AUDIT_USER_ACCT, Prog,
buf,
group, AUDIT_NO_ID,
@@ -606,10 +591,8 @@ static void log_gpasswd_success (const char *suffix)
"password of group %s changed by %s%s",
group, myname, suffix));
#ifdef WITH_AUDIT
- snprintf (buf, 1023,
- "password of group %s changed by %s%s",
- group, myname, suffix);
- buf[1023] = '\0';
+ SNPRINTF(buf, "password of group %s changed by %s%s",
+ group, myname, suffix);
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
buf,
group, AUDIT_NO_ID,
@@ -618,16 +601,16 @@ static void log_gpasswd_success (const char *suffix)
}
}
-static void log_gpasswd_success_system (unused void *arg)
+static void log_gpasswd_success_system (MAYBE_UNUSED void *arg)
{
log_gpasswd_success ("");
}
-static void log_gpasswd_success_group (unused void *arg)
+static void log_gpasswd_success_group (MAYBE_UNUSED void *arg)
{
- char buf[1024];
- snprintf (buf, 1023, " in %s", gr_dbname ());
- buf[1023] = '\0';
+ char buf[1024];
+
+ SNPRINTF(buf, " in %s", gr_dbname());
log_gpasswd_success (buf);
}
@@ -704,8 +687,7 @@ static void check_perms (const struct group *gr)
}
} else
#endif /* SHADOWGRP */
- {
-#ifdef FIRST_MEMBER_IS_ADMIN
+ if (!amroot) {
/*
* The policy here for changing a group is that
* 1) you must be root or
@@ -720,20 +702,14 @@ static void check_perms (const struct group *gr)
* first group member might be just a normal user.
* --marekm
*/
- if (!amroot) {
- if (gr->gr_mem[0] == (char *) 0) {
- failure ();
- }
-
- if (strcmp (gr->gr_mem[0], myname) != 0) {
- failure ();
- }
- }
-#else /* ! FIRST_MEMBER_IS_ADMIN */
- if (!amroot) {
- failure ();
- }
+#if !defined(FIRST_MEMBER_IS_ADMIN)
+ failure();
#endif
+ if (gr->gr_mem[0] == NULL)
+ failure();
+
+ if (strcmp(gr->gr_mem[0], myname) != 0)
+ failure();
}
}
@@ -834,7 +810,7 @@ static void get_group (struct group *gr)
sg->sg_mem = dup_list (gr->gr_mem);
- sg->sg_adm = (char **) xmalloc (sizeof (char *) * 2);
+ sg->sg_adm = XMALLOC(2, char *);
#ifdef FIRST_MEMBER_IS_ADMIN
if (sg->sg_mem[0]) {
sg->sg_adm[0] = xstrdup (sg->sg_mem[0]);
@@ -887,25 +863,26 @@ static void change_passwd (struct group *gr)
printf (_("Changing the password for group %s\n"), group);
for (retries = 0; retries < RETRIES; retries++) {
- cp = getpass (_("New Password: "));
+ cp = agetpass (_("New Password: "));
if (NULL == cp) {
exit (1);
}
- STRFCPY (pass, cp);
- strzero (cp);
- cp = getpass (_("Re-enter new password: "));
+ STRTCPY(pass, cp);
+ erase_pass (cp);
+ cp = agetpass (_("Re-enter new password: "));
if (NULL == cp) {
+ MEMZERO(pass);
exit (1);
}
if (strcmp (pass, cp) == 0) {
- strzero (cp);
+ erase_pass (cp);
break;
}
- strzero (cp);
- memzero (pass, sizeof pass);
+ erase_pass (cp);
+ MEMZERO(pass);
if (retries + 1 < RETRIES) {
puts (_("They don't match; try again"));
@@ -925,7 +902,7 @@ static void change_passwd (struct group *gr)
Prog, salt, strerror (errno));
exit (1);
}
- memzero (pass, sizeof pass);
+ MEMZERO(pass);
#ifdef SHADOWGRP
if (is_shadowgrp) {
gr->gr_passwd = SHADOW_PASSWD_STRING;
@@ -953,6 +930,8 @@ int main (int argc, char **argv)
#endif
sanitize_env ();
+ check_fds ();
+
(void) setlocale (LC_ALL, "");
(void) bindtextdomain (PACKAGE, LOCALEDIR);
(void) textdomain (PACKAGE);
@@ -965,11 +944,10 @@ int main (int argc, char **argv)
* with this command.
*/
bywho = getuid ();
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
- OPENLOG ("gpasswd");
+ OPENLOG (Prog);
setbuf (stdout, NULL);
setbuf (stderr, NULL);
@@ -1145,9 +1123,7 @@ int main (int argc, char **argv)
(void) signal (SIGINT, catch_signals);
(void) signal (SIGQUIT, catch_signals);
(void) signal (SIGTERM, catch_signals);
-#ifdef SIGTSTP
(void) signal (SIGTSTP, catch_signals);
-#endif
/* Prompt for the new password */
#ifdef SHADOWGRP
diff --git a/src/groupadd.c b/src/groupadd.c
index 66ccb53..46e6550 100644
--- a/src/groupadd.c
+++ b/src/groupadd.c
@@ -27,6 +27,7 @@
#include "defines.h"
#include "getdef.h"
#include "groupio.h"
+#include "memzero.h"
#include "nscd.h"
#include "sssd.h"
#include "prototypes.h"
@@ -34,6 +35,7 @@
#include "sgroupio.h"
#endif
#include "shadowlog.h"
+#include "run_part.h"
/*
* exit status values
@@ -49,7 +51,7 @@
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "groupadd";
static /*@null@*/char *group_name;
static gid_t group_id;
@@ -70,7 +72,7 @@ static bool is_shadow_grp;
#endif
/* local function prototypes */
-static /*@noreturn@*/void usage (int status);
+NORETURN static void usage (int status);
static void new_grent (struct group *grent);
#ifdef SHADOWGRP
@@ -87,7 +89,9 @@ static void check_perms (void);
/*
* usage - display usage message and exit
*/
-static /*@noreturn@*/void usage (int status)
+NORETURN
+static void
+usage (int status)
{
FILE *usageout = (E_SUCCESS != status) ? stderr : stdout;
(void) fprintf (usageout,
@@ -105,7 +109,7 @@ static /*@noreturn@*/void usage (int status)
(void) fputs (_(" -p, --password PASSWORD use this encrypted password for the new group\n"), usageout);
(void) fputs (_(" -r, --system create a system account\n"), usageout);
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
- (void) fputs (_(" -P, --prefix PREFIX_DI directory prefix\n"), usageout);
+ (void) fputs (_(" -P, --prefix PREFIX_DIR directory prefix\n"), usageout);
(void) fputs (_(" -U, --users USERS list of user members of this group\n"), usageout);
(void) fputs ("\n", usageout);
exit (status);
@@ -262,8 +266,7 @@ static void close_files (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_GROUP, Prog,
"adding group to /etc/group",
- group_name, (unsigned int) group_id,
- SHADOW_AUDIT_SUCCESS);
+ group_name, group_id, SHADOW_AUDIT_SUCCESS);
#endif
SYSLOG ((LOG_INFO, "group added to %s: name=%s, GID=%u",
gr_dbname (), group_name, (unsigned int) group_id));
@@ -284,8 +287,7 @@ static void close_files (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_GROUP, Prog,
"adding group to /etc/gshadow",
- group_name, (unsigned int) group_id,
- SHADOW_AUDIT_SUCCESS);
+ group_name, group_id, SHADOW_AUDIT_SUCCESS);
#endif
SYSLOG ((LOG_INFO, "group added to %s: name=%s",
sgr_dbname (), group_name));
@@ -299,9 +301,7 @@ static void close_files (void)
/* Report success at the system level */
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_GROUP, Prog,
- "",
- group_name, (unsigned int) group_id,
- SHADOW_AUDIT_SUCCESS);
+ "", group_name, group_id, SHADOW_AUDIT_SUCCESS);
#endif
SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u",
group_name, (unsigned int) group_id));
@@ -344,8 +344,8 @@ static void open_files (void)
/* And now open the databases */
if (gr_open (O_CREAT | O_RDWR) == 0) {
- fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
- SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ()));
+ fprintf (stderr, _("%s: cannot open %s: %s\n"), Prog, gr_dbname (), strerror(errno));
+ SYSLOG ((LOG_WARN, "cannot open %s: %s", gr_dbname (), strerror(errno)));
exit (E_GRP_UPDATE);
}
@@ -353,9 +353,9 @@ static void open_files (void)
if (is_shadow_grp) {
if (sgr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
- _("%s: cannot open %s\n"),
- Prog, sgr_dbname ());
- SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ()));
+ _("%s: cannot open %s: %s\n"),
+ Prog, sgr_dbname (), strerror(errno));
+ SYSLOG ((LOG_WARN, "cannot open %s: %s", sgr_dbname (), strerror(errno)));
exit (E_GRP_UPDATE);
}
}
@@ -403,7 +403,7 @@ static void process_flags (int argc, char **argv)
break;
case 'g':
gflg = true;
- if ( (get_gid (optarg, &group_id) == 0)
+ if ( (get_gid(optarg, &group_id) == -1)
|| (group_id == (gid_t)-1)) {
fprintf (stderr,
_("%s: invalid group ID '%s'\n"),
@@ -429,7 +429,7 @@ static void process_flags (int argc, char **argv)
}
/* terminate name, point to value */
*cp++ = '\0';
- if (putdef_str (optarg, cp) < 0) {
+ if (putdef_str (optarg, cp, NULL) < 0) {
exit (E_BAD_ARG);
}
break;
@@ -511,7 +511,7 @@ static void check_flags (void)
} else {
fprintf (stderr,
_("%s: GID '%lu' already exists\n"),
- Prog, (unsigned long int) group_id);
+ Prog, (unsigned long) group_id);
exit (E_GID_IN_USE);
}
}
@@ -543,7 +543,7 @@ static void check_perms (void)
exit (1);
}
- retval = pam_start ("groupadd", pampw->pw_name, &conv, &pamh);
+ retval = pam_start (Prog, pampw->pw_name, &conv, &pamh);
if (PAM_SUCCESS == retval) {
retval = pam_authenticate (pamh, 0);
@@ -572,10 +572,6 @@ static void check_perms (void)
*/
int main (int argc, char **argv)
{
- /*
- * Get my name so that I can use it to report errors.
- */
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -586,7 +582,7 @@ int main (int argc, char **argv)
process_root_flag ("-R", argc, argv);
prefix = process_prefix_flag ("-P", argc, argv);
- OPENLOG ("groupadd");
+ OPENLOG (Prog);
#ifdef WITH_AUDIT
audit_help_open ();
#endif
@@ -605,6 +601,11 @@ int main (int argc, char **argv)
check_perms ();
+ if (run_parts ("/etc/shadow-maint/groupadd-pre.d", group_name,
+ Prog)) {
+ exit(1);
+ }
+
#ifdef SHADOWGRP
is_shadow_grp = sgr_file_present ();
#endif
@@ -623,6 +624,11 @@ int main (int argc, char **argv)
grp_update ();
close_files ();
+ if (run_parts ("/etc/shadow-maint/groupadd-post.d", group_name,
+ Prog)) {
+ exit(1);
+ }
+
nscd_flush_cache ("group");
sssd_flush_cache (SSSD_DB_GROUP);
diff --git a/src/groupdel.c b/src/groupdel.c
index c84faa7..4bc58aa 100644
--- a/src/groupdel.c
+++ b/src/groupdel.c
@@ -32,10 +32,11 @@
#include "sgroupio.h"
#endif
#include "shadowlog.h"
+#include "run_part.h"
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "groupdel";
static char *group_name;
static gid_t group_id = -1;
@@ -58,7 +59,7 @@ static bool is_shadow_grp;
#define E_GRP_UPDATE 10 /* can't update group file */
/* local function prototypes */
-static /*@noreturn@*/void usage (int status);
+NORETURN static void usage (int status);
static void grp_update (void);
static void close_files (void);
static void open_files (void);
@@ -68,7 +69,9 @@ static void process_flags (int argc, char **argv);
/*
* usage - display usage message and exit
*/
-static /*@noreturn@*/void usage (int status)
+NORETURN
+static void
+usage (int status)
{
FILE *usageout = (E_SUCCESS != status) ? stderr : stdout;
(void) fprintf (usageout,
@@ -147,8 +150,7 @@ static void close_files (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_GROUP, Prog,
"removing group from /etc/group",
- group_name, (unsigned int) group_id,
- SHADOW_AUDIT_SUCCESS);
+ group_name, group_id, SHADOW_AUDIT_SUCCESS);
#endif
SYSLOG ((LOG_INFO,
"group '%s' removed from %s",
@@ -172,8 +174,7 @@ static void close_files (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_GROUP, Prog,
"removing group from /etc/gshadow",
- group_name, (unsigned int) group_id,
- SHADOW_AUDIT_SUCCESS);
+ group_name, group_id, SHADOW_AUDIT_SUCCESS);
#endif
SYSLOG ((LOG_INFO,
"group '%s' removed from %s",
@@ -188,9 +189,7 @@ static void close_files (void)
/* Report success at the system level */
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_GROUP, Prog,
- "",
- group_name, (unsigned int) group_id,
- SHADOW_AUDIT_SUCCESS);
+ "", group_name, group_id, SHADOW_AUDIT_SUCCESS);
#endif
SYSLOG ((LOG_INFO, "group '%s' removed\n", group_name));
del_cleanup (cleanup_report_del_group);
@@ -275,7 +274,7 @@ static void group_busy (gid_t gid)
* If pwd isn't NULL, it stopped because the gid's matched.
*/
- if (pwd == (struct passwd *) 0) {
+ if (pwd == NULL) {
return;
}
@@ -350,10 +349,6 @@ int main (int argc, char **argv)
#endif /* USE_PAM */
#endif /* ACCT_TOOLS_SETUID */
- /*
- * Get my name so that I can use it to report errors.
- */
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -364,7 +359,7 @@ int main (int argc, char **argv)
process_root_flag ("-R", argc, argv);
prefix = process_prefix_flag ("-P", argc, argv);
- OPENLOG ("groupdel");
+ OPENLOG (Prog);
#ifdef WITH_AUDIT
audit_help_open ();
#endif
@@ -390,7 +385,7 @@ int main (int argc, char **argv)
exit (1);
}
- retval = pam_start ("groupdel", pampw->pw_name, &conv, &pamh);
+ retval = pam_start (Prog, pampw->pw_name, &conv, &pamh);
}
if (PAM_SUCCESS == retval) {
@@ -434,28 +429,6 @@ int main (int argc, char **argv)
group_id = grp->gr_gid;
}
-#ifdef USE_NIS
- /*
- * Make sure this isn't a NIS group
- */
- if (__isgrNIS ()) {
- char *nis_domain;
- char *nis_master;
-
- fprintf (stderr,
- _("%s: group '%s' is a NIS group\n"),
- Prog, group_name);
-
- if (!yp_get_default_domain (&nis_domain) &&
- !yp_master (nis_domain, "group.byname", &nis_master)) {
- fprintf (stderr,
- _("%s: %s is the NIS master\n"),
- Prog, nis_master);
- }
- exit (E_NOTFOUND);
- }
-#endif
-
/*
* Make sure this isn't the primary group of anyone.
*/
@@ -463,6 +436,11 @@ int main (int argc, char **argv)
group_busy (group_id);
}
+ if (run_parts ("/etc/shadow-maint/groupdel-pre.d", group_name,
+ Prog)) {
+ exit(1);
+ }
+
/*
* Do the hard stuff - open the files, delete the group entries,
* then close and update the files.
@@ -473,6 +451,11 @@ int main (int argc, char **argv)
close_files ();
+ if (run_parts ("/etc/shadow-maint/groupdel-post.d", group_name,
+ Prog)) {
+ exit(1);
+ }
+
nscd_flush_cache ("group");
sssd_flush_cache (SSSD_DB_GROUP);
diff --git a/src/groupmems.c b/src/groupmems.c
index a0e3266..a369a61 100644
--- a/src/groupmems.c
+++ b/src/groupmems.c
@@ -18,6 +18,8 @@
#include "pam_defs.h"
#endif /* USE_PAM */
#include <pwd.h>
+
+#include "alloc.h"
#include "defines.h"
#include "prototypes.h"
#include "groupio.h"
@@ -42,7 +44,7 @@
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "groupmems";
static char *adduser = NULL;
static char *deluser = NULL;
@@ -66,10 +68,10 @@ static void remove_user (const char *user,
const struct group *grp);
static void purge_members (const struct group *grp);
static void display_members (const char *const *members);
-static /*@noreturn@*/void usage (int status);
+NORETURN static void usage (int status);
static void process_flags (int argc, char **argv);
static void check_perms (void);
-static void fail_exit (int code);
+NORETURN static void fail_exit (int code);
#define isroot() (getuid () == 0)
static char *whoami (void)
@@ -89,7 +91,7 @@ static char *whoami (void)
}
/*
- * add_user - Add an user to the specified group
+ * add_user - Add a user to the specified group
*/
static void add_user (const char *user,
const struct group *grp)
@@ -125,7 +127,7 @@ static void add_user (const char *user,
static struct sgrp sgrent;
sgrent.sg_name = xstrdup (newgrp->gr_name);
sgrent.sg_mem = dup_list (newgrp->gr_mem);
- sgrent.sg_adm = (char **) xmalloc (sizeof (char *));
+ sgrent.sg_adm = XMALLOC(1, char *);
#ifdef FIRST_MEMBER_IS_ADMIN
if (sgrent.sg_mem[0]) {
sgrent.sg_adm[0] = xstrdup (sgrent.sg_mem[0]);
@@ -172,7 +174,7 @@ static void add_user (const char *user,
}
/*
- * remove_user - Remove an user from a given group
+ * remove_user - Remove a user from a given group
*/
static void remove_user (const char *user,
const struct group *grp)
@@ -208,7 +210,7 @@ static void remove_user (const char *user,
static struct sgrp sgrent;
sgrent.sg_name = xstrdup (newgrp->gr_name);
sgrent.sg_mem = dup_list (newgrp->gr_mem);
- sgrent.sg_adm = (char **) xmalloc (sizeof (char *));
+ sgrent.sg_adm = XMALLOC(1, char *);
#ifdef FIRST_MEMBER_IS_ADMIN
if (sgrent.sg_mem[0]) {
sgrent.sg_adm[0] = xstrdup (sgrent.sg_mem[0]);
@@ -281,9 +283,9 @@ static void purge_members (const struct group *grp)
/* Create a shadow group based on this group */
static struct sgrp sgrent;
sgrent.sg_name = xstrdup (newgrp->gr_name);
- sgrent.sg_mem = (char **) xmalloc (sizeof (char *));
+ sgrent.sg_mem = XMALLOC(1, char *);
sgrent.sg_mem[0] = NULL;
- sgrent.sg_adm = (char **) xmalloc (sizeof (char *));
+ sgrent.sg_adm = XMALLOC(1, char *);
sgrent.sg_adm[0] = NULL;
/* Move any password to gshadow */
@@ -339,7 +341,9 @@ static void display_members (const char *const *members)
}
}
-static /*@noreturn@*/void usage (int status)
+NORETURN
+static void
+usage (int status)
{
FILE *usageout = (EXIT_SUCCESS != status) ? stderr : stdout;
(void) fprintf (usageout,
@@ -439,7 +443,7 @@ static void check_perms (void)
fail_exit (1);
}
- retval = pam_start ("groupmems", pampw->pw_name, &conv, &pamh);
+ retval = pam_start (Prog, pampw->pw_name, &conv, &pamh);
if (PAM_SUCCESS == retval) {
retval = pam_authenticate (pamh, 0);
@@ -569,10 +573,6 @@ int main (int argc, char **argv)
char *name;
const struct group *grp;
- /*
- * Get my name so that I can use it to report errors.
- */
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -582,7 +582,7 @@ int main (int argc, char **argv)
process_root_flag ("-R", argc, argv);
- OPENLOG ("groupmems");
+ OPENLOG (Prog);
#ifdef SHADOWGRP
is_shadowgrp = sgr_file_present ();
diff --git a/src/groupmod.c b/src/groupmod.c
index 006eca1..989d7ea 100644
--- a/src/groupmod.c
+++ b/src/groupmod.c
@@ -15,7 +15,9 @@
#include <fcntl.h>
#include <getopt.h>
#include <grp.h>
+#include <stdint.h>
#include <stdio.h>
+#include <strings.h>
#include <sys/types.h>
#ifdef ACCT_TOOLS_SETUID
#ifdef USE_PAM
@@ -23,6 +25,8 @@
#include <pwd.h>
#endif /* USE_PAM */
#endif /* ACCT_TOOLS_SETUID */
+
+#include "alloc.h"
#include "chkname.h"
#include "defines.h"
#include "groupio.h"
@@ -34,6 +38,8 @@
#include "sgroupio.h"
#endif
#include "shadowlog.h"
+#include "string/stpecpy.h"
+#include "string/stpeprintf.h"
/*
* exit status values
*/
@@ -53,7 +59,7 @@
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "groupmod";
#ifdef SHADOWGRP
static bool is_shadow_grp;
@@ -224,7 +230,7 @@ static void grp_update (void)
* shadowed password, we force the creation of a
* gshadow entry when a new password is requested.
*/
- memset (&sgrp, 0, sizeof sgrp);
+ bzero(&sgrp, sizeof sgrp);
sgrp.sg_name = xstrdup (grp.gr_name);
sgrp.sg_passwd = xstrdup (grp.gr_passwd);
sgrp.sg_adm = &empty;
@@ -244,10 +250,8 @@ static void grp_update (void)
if (!aflg) {
// requested to replace the existing groups
- if (NULL != grp.gr_mem[0])
- gr_free_members(&grp);
- grp.gr_mem = (char **)xmalloc(sizeof(char *));
- grp.gr_mem[0] = (char *)0;
+ grp.gr_mem = XMALLOC(1, char *);
+ grp.gr_mem[0] = NULL;
} else {
// append to existing groups
if (NULL != grp.gr_mem[0])
@@ -333,7 +337,7 @@ static void check_new_gid (void)
*/
fprintf (stderr,
_("%s: GID '%lu' already exists\n"),
- Prog, (unsigned long int) group_newid);
+ Prog, (unsigned long) group_newid);
exit (E_GID_IN_USE);
}
@@ -408,7 +412,7 @@ static void process_flags (int argc, char **argv)
break;
case 'g':
gflg = true;
- if ( (get_gid (optarg, &group_newid) == 0)
+ if ( (get_gid(optarg, &group_newid) == -1)
|| (group_newid == (gid_t)-1)) {
fprintf (stderr,
_("%s: invalid group ID '%s'\n"),
@@ -542,95 +546,74 @@ static void close_files (void)
*/
static void prepare_failure_reports (void)
{
+ char *gr, *gr_end;
+#ifdef SHADOWGRP
+ char *sgr, *sgr_end;
+#endif
+ char *pw, *pw_end;
+
info_group.name = group_name;
#ifdef SHADOWGRP
info_gshadow.name = group_name;
#endif
info_passwd.name = group_name;
- info_group.audit_msg = xmalloc (512);
+ gr = XMALLOC(512, char);
+ info_group.audit_msg = gr;
+ gr_end = gr + 512;
#ifdef SHADOWGRP
- info_gshadow.audit_msg = xmalloc (512);
+ sgr = XMALLOC(512, char);
+ info_gshadow.audit_msg = sgr;
+ sgr_end = sgr + 512;
#endif
- info_passwd.audit_msg = xmalloc (512);
+ pw = XMALLOC(512, char);
+ info_passwd.audit_msg = pw;
+ pw_end = pw + 512;
- (void) snprintf (info_group.audit_msg, 511,
- "changing %s; ", gr_dbname ());
+ gr = stpeprintf(gr, gr_end, "changing %s; ", gr_dbname ());
#ifdef SHADOWGRP
- (void) snprintf (info_gshadow.audit_msg, 511,
- "changing %s; ", sgr_dbname ());
+ sgr = stpeprintf(sgr, sgr_end, "changing %s; ", sgr_dbname ());
#endif
- (void) snprintf (info_passwd.audit_msg, 511,
- "changing %s; ", pw_dbname ());
+ pw = stpeprintf(pw, pw_end, "changing %s; ", pw_dbname ());
- info_group.action = info_group.audit_msg
- + strlen (info_group.audit_msg);
+ info_group.action = gr;
#ifdef SHADOWGRP
- info_gshadow.action = info_gshadow.audit_msg
- + strlen (info_gshadow.audit_msg);
+ info_gshadow.action = sgr;
#endif
- info_passwd.action = info_passwd.audit_msg
- + strlen (info_passwd.audit_msg);
+ info_passwd.action = pw;
- (void) snprintf (info_group.action,
- 511 - strlen (info_group.audit_msg),
- "group %s/%lu",
- group_name, (unsigned long int) group_id);
+ gr = stpeprintf(gr, gr_end,
+ "group %s/%ju", group_name, (uintmax_t) group_id);
#ifdef SHADOWGRP
- (void) snprintf (info_gshadow.action,
- 511 - strlen (info_group.audit_msg),
+ sgr = stpeprintf(sgr, sgr_end,
"group %s", group_name);
#endif
- (void) snprintf (info_passwd.action,
- 511 - strlen (info_group.audit_msg),
- "group %s/%lu",
- group_name, (unsigned long int) group_id);
+ pw = stpeprintf(pw, pw_end,
+ "group %s/%ju", group_name, (uintmax_t) group_id);
if (nflg) {
- strncat (info_group.action, ", new name: ",
- 511 - strlen (info_group.audit_msg));
- strncat (info_group.action, group_newname,
- 511 - strlen (info_group.audit_msg));
-
+ gr = stpecpy(gr, gr_end, ", new name: ");
+ gr = stpecpy(gr, gr_end, group_newname);
#ifdef SHADOWGRP
- strncat (info_gshadow.action, ", new name: ",
- 511 - strlen (info_gshadow.audit_msg));
- strncat (info_gshadow.action, group_newname,
- 511 - strlen (info_gshadow.audit_msg));
+ sgr = stpecpy(sgr, sgr_end, ", new name: ");
+ sgr = stpecpy(sgr, sgr_end, group_newname);
#endif
-
- strncat (info_passwd.action, ", new name: ",
- 511 - strlen (info_passwd.audit_msg));
- strncat (info_passwd.action, group_newname,
- 511 - strlen (info_passwd.audit_msg));
+ pw = stpecpy(pw, pw_end, ", new name: ");
+ pw = stpecpy(pw, pw_end, group_newname);
}
if (pflg) {
- strncat (info_group.action, ", new password",
- 511 - strlen (info_group.audit_msg));
-
+ gr = stpecpy(gr, gr_end, ", new password");
#ifdef SHADOWGRP
- strncat (info_gshadow.action, ", new password",
- 511 - strlen (info_gshadow.audit_msg));
+ sgr = stpecpy(sgr, sgr_end, ", new password");
#endif
}
if (gflg) {
- strncat (info_group.action, ", new gid: ",
- 511 - strlen (info_group.audit_msg));
- (void) snprintf (info_group.action+strlen (info_group.action),
- 511 - strlen (info_group.audit_msg),
- "%lu", (unsigned long int) group_newid);
-
- strncat (info_passwd.action, ", new gid: ",
- 511 - strlen (info_passwd.audit_msg));
- (void) snprintf (info_passwd.action+strlen (info_passwd.action),
- 511 - strlen (info_passwd.audit_msg),
- "%lu", (unsigned long int) group_newid);
- }
- info_group.audit_msg[511] = '\0';
-#ifdef SHADOWGRP
- info_gshadow.audit_msg[511] = '\0';
-#endif
- info_passwd.audit_msg[511] = '\0';
+ gr = stpecpy(gr, gr_end, ", new gid: ");
+ stpeprintf(gr, gr_end, "%ju", (uintmax_t) group_newid);
+
+ pw = stpecpy(pw, pw_end, ", new gid: ");
+ stpeprintf(pw, pw_end, "%ju", (uintmax_t) group_newid);
+ }
// FIXME: add a system cleanup
add_cleanup (cleanup_report_mod_group, &info_group);
@@ -766,10 +749,6 @@ int main (int argc, char **argv)
#endif /* USE_PAM */
#endif /* ACCT_TOOLS_SETUID */
- /*
- * Get my name so that I can use it to report errors.
- */
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -780,7 +759,7 @@ int main (int argc, char **argv)
process_root_flag ("-R", argc, argv);
prefix = process_prefix_flag ("-P", argc, argv);
- OPENLOG ("groupmod");
+ OPENLOG (Prog);
#ifdef WITH_AUDIT
audit_help_open ();
#endif
@@ -806,7 +785,7 @@ int main (int argc, char **argv)
exit (E_PAM_USERNAME);
}
- retval = pam_start ("groupmod", pampw->pw_name, &conv, &pamh);
+ retval = pam_start (Prog, pampw->pw_name, &conv, &pamh);
}
if (PAM_SUCCESS == retval) {
@@ -849,28 +828,6 @@ int main (int argc, char **argv)
}
}
-#ifdef USE_NIS
- /*
- * Now make sure it isn't an NIS group.
- */
- if (__isgrNIS ()) {
- char *nis_domain;
- char *nis_master;
-
- fprintf (stderr,
- _("%s: group %s is a NIS group\n"),
- Prog, group_name);
-
- if (!yp_get_default_domain (&nis_domain) &&
- !yp_master (nis_domain, "group.byname", &nis_master)) {
- fprintf (stderr,
- _("%s: %s is the NIS master\n"),
- Prog, nis_master);
- }
- exit (E_NOTFOUND);
- }
-#endif
-
if (gflg) {
check_new_gid ();
}
diff --git a/src/groups.c b/src/groups.c
index 12bd224..d19a80a 100644
--- a/src/groups.c
+++ b/src/groups.c
@@ -14,13 +14,16 @@
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
+
+#include "alloc.h"
#include "defines.h"
#include "prototypes.h"
#include "shadowlog.h"
+
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "groups";
/* local function prototypes */
static void print_groups (const char *member);
@@ -88,16 +91,12 @@ int main (int argc, char **argv)
GETGROUPS_T *groups;
sys_ngroups = sysconf (_SC_NGROUPS_MAX);
- groups = (GETGROUPS_T *) malloc (sizeof (GETGROUPS_T) * sys_ngroups);
+ groups = XMALLOC(sys_ngroups, GETGROUPS_T);
(void) setlocale (LC_ALL, "");
(void) bindtextdomain (PACKAGE, LOCALEDIR);
(void) textdomain (PACKAGE);
- /*
- * Get the program name so that error messages can use it.
- */
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
diff --git a/src/grpck.c b/src/grpck.c
index 881fb4d..4ef1b15 100644
--- a/src/grpck.c
+++ b/src/grpck.c
@@ -43,7 +43,7 @@
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "grpck";
static const char *grp_file = GROUP_FILE;
static bool use_system_grp_file = true;
@@ -62,7 +62,7 @@ static bool silence_warnings = false;
/* local function prototypes */
static void fail_exit (int status);
-static /*@noreturn@*/void usage (int status);
+NORETURN static void usage (int status);
static void delete_member (char **, const char *);
static void process_flags (int argc, char **argv);
static void open_files (void);
@@ -114,7 +114,9 @@ static void fail_exit (int status)
/*
* usage - print syntax message and exit
*/
-static /*@noreturn@*/void usage (int status)
+NORETURN
+static void
+usage (int status)
{
FILE *usageout = (E_SUCCESS != status) ? stderr : stdout;
#ifdef SHADOWGRP
@@ -814,10 +816,6 @@ int main (int argc, char **argv)
int errors = 0;
bool changed = false;
- /*
- * Get my name so that I can use it to report errors.
- */
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -827,7 +825,7 @@ int main (int argc, char **argv)
process_root_flag ("-R", argc, argv);
- OPENLOG ("grpck");
+ OPENLOG (Prog);
/* Parse the command line arguments */
process_flags (argc, argv);
diff --git a/src/grpconv.c b/src/grpconv.c
index 57d8d58..4d941cd 100644
--- a/src/grpconv.c
+++ b/src/grpconv.c
@@ -21,9 +21,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
#include <time.h>
#include <unistd.h>
#include <getopt.h>
+
+#include "attr.h"
#include "nscd.h"
#include "sssd.h"
#include "prototypes.h"
@@ -36,7 +39,7 @@
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "grpconv";
static bool gr_locked = false;
static bool sgr_locked = false;
@@ -123,7 +126,6 @@ int main (int argc, char **argv)
const struct sgrp *sg;
struct sgrp sgent;
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -133,7 +135,7 @@ int main (int argc, char **argv)
process_root_flag ("-R", argc, argv);
- OPENLOG ("grpconv");
+ OPENLOG (Prog);
process_flags (argc, argv);
@@ -198,7 +200,7 @@ int main (int argc, char **argv)
static char *empty = 0;
/* add new shadow group entry */
- memset (&sgent, 0, sizeof sgent);
+ bzero(&sgent, sizeof sgent);
sgent.sg_name = gr->gr_name;
sgent.sg_passwd = gr->gr_passwd;
sgent.sg_adm = &empty;
@@ -259,7 +261,7 @@ int main (int argc, char **argv)
return 0;
}
#else /* !SHADOWGRP */
-int main (int unused(argc), char **argv)
+int main (MAYBE_UNUSED int argc, char **argv)
{
fprintf (stderr,
"%s: not configured for shadow group support.\n", argv[0]);
diff --git a/src/grpunconv.c b/src/grpunconv.c
index fc6cecf..d001ece 100644
--- a/src/grpunconv.c
+++ b/src/grpunconv.c
@@ -24,6 +24,8 @@
#include <unistd.h>
#include <grp.h>
#include <getopt.h>
+
+#include "attr.h"
#include "nscd.h"
#include "sssd.h"
#include "prototypes.h"
@@ -36,7 +38,7 @@
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "grpunconv";
static bool gr_locked = false;
static bool sgr_locked = false;
@@ -122,7 +124,6 @@ int main (int argc, char **argv)
struct group grent;
const struct sgrp *sg;
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -132,7 +133,7 @@ int main (int argc, char **argv)
process_root_flag ("-R", argc, argv);
- OPENLOG ("grpunconv");
+ OPENLOG (Prog);
process_flags (argc, argv);
@@ -222,7 +223,7 @@ int main (int argc, char **argv)
return 0;
}
#else /* !SHADOWGRP */
-int main (int unused(argc), char **argv)
+int main (MAYBE_UNUSED int argc, char **argv)
{
fprintf (stderr,
"%s: not configured for shadow group support.\n", argv[0]);
diff --git a/src/id.c b/src/id.c
index 4952109..673693e 100644
--- a/src/id.c
+++ b/src/id.c
@@ -23,7 +23,10 @@
#include <pwd.h>
#include <stdio.h>
#include <sys/types.h>
+
+#include "alloc.h"
#include "defines.h"
+
/* local function prototypes */
static void usage (void);
@@ -33,7 +36,8 @@ static void usage (void)
exit (EXIT_FAILURE);
}
- /*ARGSUSED*/ int main (int argc, char **argv)
+int
+main(int argc, char *argv[])
{
uid_t ruid, euid;
gid_t rgid, egid;
@@ -63,7 +67,7 @@ static void usage (void)
* work if the system library is recompiled.
*/
sys_ngroups = sysconf (_SC_NGROUPS_MAX);
- groups = (GETGROUPS_T *) malloc (sizeof (GETGROUPS_T) * sys_ngroups);
+ groups = MALLOC(sys_ngroups, GETGROUPS_T);
/*
* See if the -a flag has been given to print out the concurrent
@@ -71,11 +75,10 @@ static void usage (void)
*/
if (argc > 1) {
- if ((argc > 2) || (strcmp (argv[1], "-a") != 0)) {
- usage ();
- } else {
+ if (argc > 2 || strcmp(argv[1], "-a") != 0)
+ usage();
+ else
aflg = true;
- }
}
ruid = getuid ();
diff --git a/src/lastlog.c b/src/lastlog.c
index f5c0a5c..3914b72 100644
--- a/src/lastlog.c
+++ b/src/lastlog.c
@@ -22,12 +22,18 @@
#ifdef HAVE_LL_HOST
#include <net/if.h>
#endif
+
+#include "atoi/str2i.h"
#include "defines.h"
#include "prototypes.h"
#include "getdef.h"
+#include "memzero.h"
/*@-exitarg@*/
#include "exitcodes.h"
#include "shadowlog.h"
+#include "string/strftime.h"
+
+
/*
* Needed for MkLinux DR1/2/2.1 - J.
@@ -39,7 +45,7 @@
/*
* Global variables
*/
-const char *Prog; /* Program name */
+static const char Prog[] = "lastlog"; /* Program name */
static FILE *lastlogfile; /* lastlog file stream */
static unsigned long umin; /* if uflg and has_umin, only display users with uid >= umin */
static bool has_umin = false;
@@ -50,15 +56,17 @@ static time_t inverse_seconds; /* that number of days in seconds */
static struct stat statbuf; /* fstat buffer for file size */
-static bool uflg = false; /* print only an user of range of users */
+static bool uflg = false; /* print only a user of range of users */
static bool tflg = false; /* print is restricted to most recent days */
static bool bflg = false; /* print excludes most recent days */
static bool Cflg = false; /* clear record for user */
static bool Sflg = false; /* set record for user */
-#define NOW (time ((time_t *) 0))
+#define NOW time(NULL)
-static /*@noreturn@*/void usage (int status)
+NORETURN
+static void
+usage (int status)
{
FILE *usageout = (E_SUCCESS != status) ? stderr : stdout;
(void) fprintf (usageout,
@@ -67,7 +75,7 @@ static /*@noreturn@*/void usage (int status)
"Options:\n"),
Prog);
(void) fputs (_(" -b, --before DAYS print only lastlog records older than DAYS\n"), usageout);
- (void) fputs (_(" -C, --clear clear lastlog record of an user (usable only with -u)\n"), usageout);
+ (void) fputs (_(" -C, --clear clear lastlog record of a user (usable only with -u)\n"), usageout);
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
(void) fputs (_(" -S, --set set lastlog record to current time (usable only with -u)\n"), usageout);
@@ -114,10 +122,10 @@ static void print_one (/*@null@*/const struct passwd *pw)
* entered for this user, which should be able to get the
* empty entry in this case.
*/
- if (fread ((char *) &ll, sizeof (ll), 1, lastlogfile) != 1) {
+ if (fread (&ll, sizeof (ll), 1, lastlogfile) != 1) {
fprintf (stderr,
_("%s: Failed to get the entry for UID %lu\n"),
- Prog, (unsigned long int)pw->pw_uid);
+ Prog, (unsigned long)pw->pw_uid);
exit (EXIT_FAILURE);
}
} else {
@@ -141,7 +149,7 @@ static void print_one (/*@null@*/const struct passwd *pw)
/* Print the header only once */
if (!once) {
#ifdef HAVE_LL_HOST
- printf (_("Username Port From%*sLatest\n"), maxIPv6Addrlen-3, " ");
+ printf (_("Username Port From%*sLatest\n"), maxIPv6Addrlen-4, " ");
#else
puts (_("Username Port Latest"));
#endif
@@ -153,7 +161,7 @@ static void print_one (/*@null@*/const struct passwd *pw)
if (tm == NULL) {
cp = "(unknown)";
} else {
- strftime (ptime, sizeof (ptime), "%a %b %e %H:%M:%S %z %Y", tm);
+ STRFTIME(ptime, "%a %b %e %H:%M:%S %z %Y", tm);
cp = ptime;
}
if (ll.ll_time == (time_t) 0) {
@@ -182,7 +190,7 @@ static void print (void)
}
if (uflg && has_umin && has_umax && (umin == umax)) {
- print_one (getpwuid ((uid_t)umin));
+ print_one (getpwuid (umin));
} else {
setpwent ();
while ( (pwent = getpwent ()) != NULL ) {
@@ -225,21 +233,21 @@ static void update_one (/*@null@*/const struct passwd *pw)
#ifdef WITH_AUDIT
audit_logger (AUDIT_ACCT_UNLOCK, Prog,
"clearing-lastlog",
- pw->pw_name, (unsigned int) pw->pw_uid, SHADOW_AUDIT_SUCCESS);
+ pw->pw_name, pw->pw_uid, SHADOW_AUDIT_SUCCESS);
#endif
}
#ifdef WITH_AUDIT
else {
audit_logger (AUDIT_ACCT_UNLOCK, Prog,
"refreshing-lastlog",
- pw->pw_name, (unsigned int) pw->pw_uid, SHADOW_AUDIT_SUCCESS);
+ pw->pw_name, pw->pw_uid, SHADOW_AUDIT_SUCCESS);
}
#endif
if (fwrite (&ll, sizeof(ll), 1, lastlogfile) != 1) {
fprintf (stderr,
_("%s: Failed to update the entry for UID %lu\n"),
- Prog, (unsigned long int)pw->pw_uid);
+ Prog, (unsigned long)pw->pw_uid);
exit (EXIT_FAILURE);
}
}
@@ -261,7 +269,7 @@ static void update (void)
}
if (has_umin && has_umax && (umin == umax)) {
- update_one (getpwuid ((uid_t)umin));
+ update_one (getpwuid (umin));
} else {
setpwent ();
while ( (pwent = getpwent ()) != NULL ) {
@@ -288,7 +296,6 @@ int main (int argc, char **argv)
* Get the program name. The program name is used as a prefix to
* most error messages.
*/
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -321,7 +328,7 @@ int main (int argc, char **argv)
case 'b':
{
unsigned long inverse_days;
- if (getulong (optarg, &inverse_days) == 0) {
+ if (str2ul(&inverse_days, optarg) == -1) {
fprintf (stderr,
_("%s: invalid numeric argument '%s'\n"),
Prog, optarg);
@@ -349,7 +356,7 @@ int main (int argc, char **argv)
case 't':
{
unsigned long days;
- if (getulong (optarg, &days) == 0) {
+ if (str2ul(&days, optarg) == -1) {
fprintf (stderr,
_("%s: invalid numeric argument '%s'\n"),
Prog, optarg);
@@ -373,14 +380,14 @@ int main (int argc, char **argv)
/* local, no need for xgetpwnam */
pwent = getpwnam (optarg);
if (NULL != pwent) {
- umin = (unsigned long) pwent->pw_uid;
+ umin = pwent->pw_uid;
has_umin = true;
umax = umin;
has_umax = true;
} else {
- if (getrange (optarg,
- &umin, &has_umin,
- &umax, &has_umax) == 0) {
+ if (getrange(optarg,
+ &umin, &has_umin,
+ &umax, &has_umax) == -1) {
fprintf (stderr,
_("%s: Unknown user or range: %s\n"),
Prog, optarg);
diff --git a/src/login.c b/src/login.c
index 0048281..9fed7b3 100644
--- a/src/login.c
+++ b/src/login.c
@@ -14,7 +14,9 @@
#include <errno.h>
#include <grp.h>
#ifndef USE_PAM
+#ifdef ENABLE_LASTLOG
#include <lastlog.h>
+#endif /* ENABLE_LASTLOG */
#endif /* !USE_PAM */
#include <pwd.h>
#include <signal.h>
@@ -22,15 +24,24 @@
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <assert.h>
+
+#include "alloc.h"
+#include "attr.h"
+#include "chkname.h"
#include "defines.h"
#include "faillog.h"
#include "failure.h"
#include "getdef.h"
+#include "memzero.h"
#include "prototypes.h"
#include "pwauth.h"
/*@-exitarg@*/
#include "exitcodes.h"
#include "shadowlog.h"
+#include "string/sprintf.h"
+#include "string/strftime.h"
+#include "string/strtcpy.h"
+
#ifdef USE_PAM
#include "pam_defs.h"
@@ -60,14 +71,16 @@ static pam_handle_t *pamh = NULL;
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "login";
static const char *hostname = "";
static /*@null@*/ /*@only@*/char *username = NULL;
static int reason = PW_LOGIN;
#ifndef USE_PAM
+#ifdef ENABLE_LASTLOG
static struct lastlog ll;
+#endif /* ENABLE_LASTLOG */
#endif /* !USE_PAM */
static bool pflg = false;
static bool fflg = false;
@@ -89,7 +102,6 @@ static char tmsg[256];
extern char **newenvp;
extern size_t newenvc;
-extern char **environ;
#ifndef ALARM
#define ALARM 60
@@ -104,15 +116,6 @@ static void usage (void);
static void setup_tty (void);
static void process_flags (int argc, char *const *argv);
static /*@observer@*/const char *get_failent_user (/*@returned@*/const char *user);
-static void update_utmp (const char *user,
- const char *tty,
- const char *host,
-#ifdef USE_UTMPX
- /*@null@*/const struct utmpx *utent
-#else
- /*@null@*/const struct utmp *utent
-#endif
- );
#ifndef USE_PAM
static struct faillog faillog;
@@ -125,6 +128,7 @@ static void get_pam_user (char **ptr_pam_user);
static void init_env (void);
static void alarm_handler (int);
+static void exit_handler (int);
/*
* usage - print login command usage and exit
@@ -172,10 +176,10 @@ static void setup_tty (void)
#endif
/* leave these values unchanged if not specified in login.defs */
- erasechar = getdef_num ("ERASECHAR", (int) termio.c_cc[VERASE]);
- killchar = getdef_num ("KILLCHAR", (int) termio.c_cc[VKILL]);
- termio.c_cc[VERASE] = (cc_t) erasechar;
- termio.c_cc[VKILL] = (cc_t) killchar;
+ erasechar = getdef_num ("ERASECHAR", termio.c_cc[VERASE]);
+ killchar = getdef_num ("KILLCHAR", termio.c_cc[VKILL]);
+ termio.c_cc[VERASE] = erasechar;
+ termio.c_cc[VKILL] = killchar;
/* Make sure the values were valid.
* getdef_num cannot validate this.
*/
@@ -396,13 +400,18 @@ static void init_env (void)
#endif /* !USE_PAM */
}
-
-static void alarm_handler (unused int sig)
+static void exit_handler (MAYBE_UNUSED int sig)
{
- write (STDERR_FILENO, tmsg, strlen (tmsg));
_exit (0);
}
+static void alarm_handler (MAYBE_UNUSED int sig)
+{
+ write_full(STDERR_FILENO, tmsg, strlen(tmsg));
+ signal(SIGALRM, exit_handler);
+ alarm(2);
+}
+
#ifdef USE_PAM
/*
* get_pam_user - Get the username according to PAM
@@ -411,17 +420,17 @@ static void alarm_handler (unused int sig)
*/
static void get_pam_user (char **ptr_pam_user)
{
- int retcode;
- void *ptr_user;
+ int retcode;
+ const void *ptr_user;
assert (NULL != ptr_pam_user);
- retcode = pam_get_item (pamh, PAM_USER, (const void **)&ptr_user);
+ retcode = pam_get_item (pamh, PAM_USER, &ptr_user);
PAM_FAIL_CHECK;
free (*ptr_pam_user);
if (NULL != ptr_user) {
- *ptr_pam_user = xstrdup ((const char *)ptr_user);
+ *ptr_pam_user = xstrdup (ptr_user);
} else {
*ptr_pam_user = NULL;
}
@@ -430,7 +439,7 @@ static void get_pam_user (char **ptr_pam_user)
/*
* get_failent_user - Return a string that can be used to log failure
- * from an user.
+ * from a user.
*
* This will be either the user argument, or "UNKNOWN".
*
@@ -453,38 +462,6 @@ static /*@observer@*/const char *get_failent_user (/*@returned@*/const char *use
}
/*
- * update_utmp - Update or create an utmp entry in utmp, wtmp, utmpw, and
- * wtmpx
- *
- * utent should be the utmp entry returned by get_current_utmp (or
- * NULL).
- */
-static void update_utmp (const char *user,
- const char *tty,
- const char *host,
-#ifdef USE_UTMPX
- /*@null@*/const struct utmpx *utent
-#else
- /*@null@*/const struct utmp *utent
-#endif
- )
-{
-#ifdef USE_UTMPX
- struct utmpx *utx = prepare_utmpx (user, tty, host, utent);
-#else
- struct utmp *ut = prepare_utmp (user, tty, host, utent);
-#endif /* USE_UTMPX */
-
-#ifndef USE_UTMPX
- (void) setutmp (ut); /* make entry in the utmp & wtmp files */
- free (ut);
-#else
- (void) setutmpx (utx); /* make entry in the utmpx & wtmpx files */
- free (utx);
-#endif /* USE_UTMPX */
-}
-
-/*
* login - create a new login session for a user
*
* login is typically called by getty as the second step of a
@@ -503,42 +480,36 @@ static void update_utmp (const char *user,
*/
int main (int argc, char **argv)
{
- const char *tmptty;
- char tty[BUFSIZ];
-
-#ifdef RLOGIN
- char term[128] = "";
-#endif /* RLOGIN */
-#if !defined(USE_PAM)
- char ptime[80];
-#endif
- unsigned int delay;
- unsigned int retries;
- bool subroot = false;
-#ifndef USE_PAM
+ int err;
+ bool subroot = false;
+ char **envp = environ;
+ char *host = NULL;
+ char tty[BUFSIZ];
+ char fromhost[512];
+ const char *failent_user;
+ const char *tmptty;
+ const char *cp;
+ const char *tmp;
+ unsigned int delay;
+ unsigned int retries;
+ unsigned int timeout;
+ struct passwd *pwd = NULL;
+
+#if defined(USE_PAM)
+ int retcode;
+ char *pam_user = NULL;
+ pid_t child;
+#else
bool is_console;
+ struct spwd *spwd = NULL;
+# if defined(ENABLE_LASTLOG)
+ char ptime[80];
+# endif
#endif
- int err;
- unsigned int timeout;
- const char *cp;
- const char *tmp;
- char fromhost[512];
- struct passwd *pwd = NULL;
- char **envp = environ;
- const char *failent_user;
-#ifdef USE_UTMPX
- /*@null@*/struct utmpx *utent;
-#else
- /*@null@*/struct utmp *utent;
+#if defined(RLOGIN)
+ char term[128] = "";
#endif
-#ifdef USE_PAM
- int retcode;
- pid_t child;
- char *pam_user = NULL;
-#else
- struct spwd *spwd = NULL;
-#endif
/*
* Some quick initialization.
*/
@@ -552,7 +523,6 @@ int main (int argc, char **argv)
initenv ();
amroot = (getuid () == 0);
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -567,25 +537,23 @@ int main (int argc, char **argv)
exit (1); /* must be a terminal */
}
- utent = get_current_utmp ();
+ err = get_session_host(&host);
/*
* Be picky if run by normal users (possible if installed setuid
- * root), but not if run by root. This way it still allows logins
- * even if your getty is broken, or if something corrupts utmp,
- * but users must "exec login" which will use the existing utmp
- * entry (will not overwrite remote hostname). --marekm
+ * root), but not if run by root.
*/
- if (!amroot && (NULL == utent)) {
- (void) puts (_("No utmp entry. You must exec \"login\" from the lowest level \"sh\""));
+ if (!amroot && (err != 0)) {
+ SYSLOG ((LOG_ERR,
+ "No session entry, error %d. You must exec \"login\" from the lowest level \"sh\"",
+ err));
exit (1);
}
- /* NOTE: utent might be NULL afterwards */
tmptty = ttyname (0);
if (NULL == tmptty) {
tmptty = "UNKNOWN";
}
- STRFCPY (tty, tmptty);
+ STRTCPY(tty, tmptty);
#ifndef USE_PAM
is_console = console (tty);
@@ -606,10 +574,14 @@ int main (int argc, char **argv)
}
#ifdef RLOGIN
if (rflg) {
+ size_t max_size;
+
+ max_size = login_name_max_size();
assert (NULL == username);
- username = xmalloc (USER_NAME_MAX_LENGTH + 1);
- username[USER_NAME_MAX_LENGTH] = '\0';
- if (do_rlogin (hostname, username, USER_NAME_MAX_LENGTH, term, sizeof term)) {
+ username = XMALLOC(max_size, char);
+ username[max_size - 1] = '\0';
+ if (do_rlogin(hostname, username, max_size, term, sizeof(term)))
+ {
preauth_flag = true;
} else {
free (username);
@@ -618,7 +590,7 @@ int main (int argc, char **argv)
}
#endif /* RLOGIN */
- OPENLOG ("login");
+ OPENLOG (Prog);
setup_tty ();
@@ -674,27 +646,23 @@ int main (int argc, char **argv)
if (rflg || hflg) {
cp = hostname;
-#if defined(HAVE_STRUCT_UTMP_UT_HOST) || defined(USE_UTMPX)
- } else if ((NULL != utent) && ('\0' != utent->ut_host[0])) {
- cp = utent->ut_host;
-#endif /* HAVE_STRUCT_UTMP_UT_HOST */
+ } else if ((host != NULL) && (host[0] != '\0')) {
+ cp = host;
} else {
cp = "";
}
if ('\0' != *cp) {
- snprintf (fromhost, sizeof fromhost,
- " on '%.100s' from '%.200s'", tty, cp);
+ SNPRINTF(fromhost, " on '%.100s' from '%.200s'", tty, cp);
} else {
- snprintf (fromhost, sizeof fromhost,
- " on '%.100s'", tty);
+ SNPRINTF(fromhost, " on '%.100s'", tty);
}
+ free(host);
top:
/* only allow ALARM sec. for login */
timeout = getdef_unum ("LOGIN_TIMEOUT", ALARM);
- snprintf (tmsg, sizeof tmsg,
- _("\nLogin timed out after %u seconds.\n"), timeout);
+ SNPRINTF(tmsg, _("\nLogin timed out after %u seconds.\n"), timeout);
(void) signal (SIGALRM, alarm_handler);
if (timeout > 0) {
(void) alarm (timeout);
@@ -705,7 +673,7 @@ int main (int argc, char **argv)
retries = getdef_unum ("LOGIN_RETRIES", RETRIES);
#ifdef USE_PAM
- retcode = pam_start ("login", username, &conv, &pamh);
+ retcode = pam_start (Prog, username, &conv, &pamh);
if (retcode != PAM_SUCCESS) {
fprintf (stderr,
_("login: PAM Failure, aborting: %s\n"),
@@ -733,18 +701,15 @@ int main (int argc, char **argv)
#endif
/* if fflg, then the user has already been authenticated */
if (!fflg) {
- unsigned int failcount = 0;
- char hostn[256];
- char loginprompt[256]; /* That's one hell of a prompt :) */
+ char hostn[256];
+ char loginprompt[256]; //That's one hell of a prompt :)
+ unsigned int failcount = 0;
/* Make the login prompt look like we want it */
if (gethostname (hostn, sizeof (hostn)) == 0) {
- snprintf (loginprompt,
- sizeof (loginprompt),
- _("%s login: "), hostn);
+ SNPRINTF(loginprompt, _("%s login: "), hostn);
} else {
- strncpy (loginprompt, _("login: "),
- sizeof (loginprompt));
+ STRTCPY(loginprompt, _("login: "));
}
retcode = pam_set_item (pamh, PAM_USER_PROMPT, loginprompt);
@@ -919,14 +884,17 @@ int main (int argc, char **argv)
failed = false; /* haven't failed authentication yet */
if (NULL == username) { /* need to get a login id */
+ size_t max_size;
+
+ max_size = login_name_max_size();
if (subroot) {
closelog ();
exit (1);
}
preauth_flag = false;
- username = xmalloc (USER_NAME_MAX_LENGTH + 1);
- username[USER_NAME_MAX_LENGTH] = '\0';
- login_prompt (_("\n%s login: "), username, USER_NAME_MAX_LENGTH);
+ username = XMALLOC(max_size, char);
+ username[max_size - 1] = '\0';
+ login_prompt(username, max_size);
if ('\0' == username[0]) {
/* Prompt for a new login */
@@ -956,7 +924,8 @@ int main (int argc, char **argv)
}
if (strcmp (user_passwd, "") == 0) {
- char *prevent_no_auth = getdef_str("PREVENT_NO_AUTH");
+ const char *prevent_no_auth = getdef_str("PREVENT_NO_AUTH");
+
if (prevent_no_auth == NULL) {
prevent_no_auth = "superuser";
}
@@ -992,7 +961,7 @@ int main (int argc, char **argv)
goto auth_ok;
}
- if (pw_auth (user_passwd, username, reason, (char *) 0) == 0) {
+ if (pw_auth (user_passwd, username, reason, NULL) == 0) {
goto auth_ok;
}
@@ -1035,23 +1004,9 @@ int main (int argc, char **argv)
if ((NULL != pwd) && getdef_bool ("FAILLOG_ENAB")) {
failure (pwd->pw_uid, tty, &faillog);
}
- if (getdef_str ("FTMP_FILE") != NULL) {
-#ifdef USE_UTMPX
- struct utmpx *failent =
- prepare_utmpx (failent_user,
- tty,
- /* FIXME: or fromhost? */hostname,
- utent);
-#else /* !USE_UTMPX */
- struct utmp *failent =
- prepare_utmp (failent_user,
- tty,
- hostname,
- utent);
-#endif /* !USE_UTMPX */
- failtmp (failent_user, failent);
- free (failent);
- }
+#ifndef ENABLE_LOGIND
+ record_failure(failent_user, tty, hostname);
+#endif /* ENABLE_LOGIND */
retries--;
if (retries <= 0) {
@@ -1067,7 +1022,7 @@ int main (int argc, char **argv)
* all). --marekm
*/
if (user_passwd[0] == '\0') {
- pw_auth ("!", username, reason, (char *) 0);
+ pw_auth ("!", username, reason, NULL);
}
/*
@@ -1107,7 +1062,7 @@ int main (int argc, char **argv)
* by Ivan Nejgebauer <ian@unsux.ns.ac.yu>. --marekm
*/
if ( getdef_bool ("PORTTIME_CHECKS_ENAB")
- && !isttytime (username, tty, time ((time_t *) 0))) {
+ && !isttytime (username, tty, time (NULL))) {
SYSLOG ((LOG_WARN, "invalid login time for '%s'%s",
username, fromhost));
closelog ();
@@ -1151,11 +1106,13 @@ int main (int argc, char **argv)
#endif /* WITH_AUDIT */
#ifndef USE_PAM /* pam_lastlog handles this */
+#ifdef ENABLE_LASTLOG
if ( getdef_bool ("LASTLOG_ENAB")
&& pwd->pw_uid <= (uid_t) getdef_ulong ("LASTLOG_UID_MAX", 0xFFFFFFFFUL)) {
/* give last login and log this one */
dolastlog (&ll, pwd, tty, hostname);
}
+#endif /* ENABLE_LASTLOG */
#endif
#ifndef USE_PAM /* PAM handles this as well */
@@ -1220,11 +1177,16 @@ int main (int argc, char **argv)
}
}
+#ifndef ENABLE_LOGIND
/*
* The utmp entry needs to be updated to indicate the new status
* of the session, the new PID and SID.
*/
- update_utmp (username, tty, hostname, utent);
+ err = update_utmp (username, tty, hostname);
+ if (err != 0) {
+ SYSLOG ((LOG_WARN, "Unable to update utmp entry for %s", username));
+ }
+#endif /* ENABLE_LOGIND */
/* The pwd and spwd entries for the user have been copied.
*
@@ -1289,14 +1251,16 @@ int main (int argc, char **argv)
username, (int) faillog.fail_cnt));
}
}
+#ifdef ENABLE_LASTLOG
if ( getdef_bool ("LASTLOG_ENAB")
&& pwd->pw_uid <= (uid_t) getdef_ulong ("LASTLOG_UID_MAX", 0xFFFFFFFFUL)
- && (ll.ll_time != 0)) {
- time_t ll_time = ll.ll_time;
+ && (ll.ll_time != 0))
+ {
+ time_t ll_time = ll.ll_time;
+ struct tm tm;
- (void) strftime (ptime, sizeof (ptime),
- "%a %b %e %H:%M:%S %z %Y",
- localtime (&ll_time));
+ localtime_r(&ll_time, &tm);
+ STRFTIME(ptime, "%a %b %e %H:%M:%S %z %Y", &tm);
printf (_("Last login: %s on %s"),
ptime, ll.ll_line);
#ifdef HAVE_LL_HOST /* __linux__ || SUN4 */
@@ -1307,6 +1271,7 @@ int main (int argc, char **argv)
#endif
printf (".\n");
}
+#endif /* ENABLE_LASTLOG */
agecheck (spwd);
mailcheck (); /* report on the status of mail */
@@ -1334,7 +1299,7 @@ int main (int argc, char **argv)
err = shell (tmp, pwd->pw_shell, newenvp); /* fake shell */
} else {
/* exec the shell finally */
- err = shell (pwd->pw_shell, (char *) 0, newenvp);
+ err = shell (pwd->pw_shell, NULL, newenvp);
}
return ((err == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
diff --git a/src/login_nopam.c b/src/login_nopam.c
index df6ba88..e6f77d1 100644
--- a/src/login_nopam.c
+++ b/src/login_nopam.c
@@ -39,12 +39,11 @@
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
*/
#include <sys/types.h>
+#include <stddef.h>
#include <stdio.h>
#include <syslog.h>
#include <ctype.h>
-#ifdef HAVE_NETDB_H
#include <netdb.h>
-#endif
#include <grp.h>
#ifdef PRIMARY_GROUP_MATCH
#include <pwd.h>
@@ -57,6 +56,8 @@
#include <netinet/in.h>
#include <arpa/inet.h> /* for inet_ntoa() */
+#include "sizeof.h"
+
#if !defined(MAXHOSTNAMELEN) || (MAXHOSTNAMELEN < 64)
#undef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 256
@@ -98,11 +99,11 @@ int login_access (const char *user, const char *from)
if (NULL != fp) {
int lineno = 0; /* for diagnostics */
while ( !match
- && (fgets (line, (int) sizeof (line), fp) == line)) {
- int end;
+ && (fgets (line, sizeof (line), fp) == line)) {
+ ptrdiff_t end;
lineno++;
- end = (int) strlen (line) - 1;
- if (line[end] != '\n') {
+ end = strlen (line) - 1;
+ if (line[0] == '\0' || line[end] != '\n') {
SYSLOG ((LOG_ERR,
"%s: line %d: missing newline or line too long",
TABLE, lineno));
@@ -119,9 +120,9 @@ int login_access (const char *user, const char *from)
continue;
}
if ( ((perm = strtok (line, fs)) == NULL)
- || ((users = strtok ((char *) 0, fs)) == NULL)
- || ((froms = strtok ((char *) 0, fs)) == NULL)
- || (strtok ((char *) 0, fs) != NULL)) {
+ || ((users = strtok (NULL, fs)) == NULL)
+ || ((froms = strtok (NULL, fs)) == NULL)
+ || (strtok (NULL, fs) != NULL)) {
SYSLOG ((LOG_ERR,
"%s: line %d: bad field count",
TABLE, lineno));
@@ -156,7 +157,7 @@ static bool list_match (char *list, const char *item, bool (*match_fn) (const ch
* a match, look for an "EXCEPT" list and recurse to determine whether
* the match is affected by any exceptions.
*/
- for (tok = strtok (list, sep); tok != NULL; tok = strtok ((char *) 0, sep)) {
+ for (tok = strtok (list, sep); tok != NULL; tok = strtok (NULL, sep)) {
if (strcasecmp (tok, "EXCEPT") == 0) { /* EXCEPT: give up */
break;
}
@@ -168,10 +169,10 @@ static bool list_match (char *list, const char *item, bool (*match_fn) (const ch
/* Process exceptions to matches. */
if (match) {
- while ( ((tok = strtok ((char *) 0, sep)) != NULL)
+ while ( ((tok = strtok (NULL, sep)) != NULL)
&& (strcasecmp (tok, "EXCEPT") != 0))
/* VOID */ ;
- if (tok == 0 || !list_match ((char *) 0, item, match_fn)) {
+ if (tok == 0 || !list_match (NULL, item, match_fn)) {
return (match);
}
}
@@ -195,9 +196,9 @@ static char *myhostname (void)
static bool
netgroup_match (const char *group, const char *machine, const char *user)
{
- static char *mydomain = (char *)0;
+ static char *mydomain = NULL;
- if (mydomain == (char *)0) {
+ if (mydomain == NULL) {
static char domain[MAXHOSTNAMELEN + 1];
getdomainname (domain, MAXHOSTNAMELEN);
@@ -230,7 +231,7 @@ static bool user_match (const char *tok, const char *string)
&& from_match (at + 1, myhostname ()));
#if HAVE_INNETGR
} else if (tok[0] == '@') { /* netgroup */
- return (netgroup_match (tok + 1, (char *) 0, string));
+ return (netgroup_match (tok + 1, NULL, string));
#endif
} else if (string_match (tok, string)) { /* ALL or exact match */
return true;
@@ -244,7 +245,7 @@ static bool user_match (const char *tok, const char *string)
}
#ifdef PRIMARY_GROUP_MATCH
/*
- * If the string is an user whose initial GID matches the token,
+ * If the string is a user whose initial GID matches the token,
* accept it. May avoid excessively long lines in /etc/group.
* Radu-Adrian Feurdean <raf@licj.soroscj.ro>
*
@@ -265,19 +266,28 @@ static bool user_match (const char *tok, const char *string)
static const char *resolve_hostname (const char *string)
{
- /*
- * Resolve hostname to numeric IP address, as suggested
- * by Dave Hagewood <admin@arrowweb.com>. --marekm
- */
- struct hostent *hp;
+ int gai_err;
+ const char *addr_str;
+ struct addrinfo *addrs;
+
+ static char host[MAXHOSTNAMELEN];
+
+ gai_err = getaddrinfo(string, NULL, NULL, &addrs);
+ if (gai_err != 0) {
+ SYSLOG ((LOG_ERR, "getaddrinfo(%s): %s", string, gai_strerror(gai_err)));
+ return string;
+ }
- hp = gethostbyname (string);
- if (NULL != hp) {
- return inet_ntoa (*((struct in_addr *) *(hp->h_addr_list)));
+ addr_str = host;
+ gai_err = getnameinfo(addrs[0].ai_addr, addrs[0].ai_addrlen,
+ host, NITEMS(host), NULL, 0, NI_NUMERICHOST);
+ if (gai_err != 0) {
+ SYSLOG ((LOG_ERR, "getnameinfo(%s): %s", string, gai_strerror(gai_err)));
+ addr_str = string;
}
- SYSLOG ((LOG_ERR, "%s - unknown host", string));
- return string;
+ freeaddrinfo(addrs);
+ return addr_str;
}
/* from_match - match a host or tty against a list of tokens */
@@ -296,7 +306,7 @@ static bool from_match (const char *tok, const char *string)
*/
#if HAVE_INNETGR
if (tok[0] == '@') { /* netgroup */
- return (netgroup_match (tok + 1, string, (char *) 0));
+ return (netgroup_match (tok + 1, string, NULL));
} else
#endif
if (string_match (tok, string)) { /* ALL or exact match */
@@ -313,7 +323,7 @@ static bool from_match (const char *tok, const char *string)
if (strchr (string, '.') == NULL) {
return true;
}
- } else if ( (tok[(tok_len = strlen (tok)) - 1] == '.') /* network */
+ } else if ( (tok[0] != '\0' && tok[(tok_len = strlen (tok)) - 1] == '.') /* network */
&& (strncmp (tok, resolve_hostname (string), tok_len) == 0)) {
return true;
}
@@ -337,5 +347,5 @@ static bool string_match (const char *tok, const char *string)
}
#else /* !USE_PAM */
-extern int errno; /* warning: ANSI C forbids an empty source file */
+extern int ISO_C_forbids_an_empty_translation_unit;
#endif /* !USE_PAM */
diff --git a/src/logoutd.c b/src/logoutd.c
index 03680f3..c870510 100644
--- a/src/logoutd.c
+++ b/src/logoutd.c
@@ -15,13 +15,16 @@
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <utmpx.h>
#include "defines.h"
#include "prototypes.h"
#include "shadowlog.h"
+#include "sizeof.h"
+#include "string/zustr2stp.h"
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "logoutd";
#ifndef DEFAULT_HUP_MESG
#define DEFAULT_HUP_MESG _("login time exceeded\n\n")
@@ -31,38 +34,31 @@ const char *Prog;
#define HUP_MESG_FILE "/etc/logoutd.mesg"
#endif
+
/* local function prototypes */
-#ifdef USE_UTMPX
static int check_login (const struct utmpx *ut);
-#else /* !USE_UTMPX */
-static int check_login (const struct utmp *ut);
-#endif /* !USE_UTMPX */
static void send_mesg_to_tty (int tty_fd);
+
/*
- * check_login - check if user (struct utmpx/utmp) allowed to stay logged in
+ * check_login - check if user (struct utmpx) allowed to stay logged in
*/
-#ifdef USE_UTMPX
-static int check_login (const struct utmpx *ut)
-#else /* !USE_UTMPX */
-static int check_login (const struct utmp *ut)
-#endif /* !USE_UTMPX */
+static int
+check_login(const struct utmpx *ut)
{
- char user[sizeof (ut->ut_user) + 1];
- time_t now;
+ char user[sizeof(ut->ut_user) + 1];
+ char line[sizeof(ut->ut_line) + 1];
+ time_t now;
- /*
- * ut_user may not have the terminating NUL.
- */
- strncpy (user, ut->ut_user, sizeof (ut->ut_user));
- user[sizeof (ut->ut_user)] = '\0';
+ ZUSTR2STP(user, ut->ut_user);
+ ZUSTR2STP(line, ut->ut_line);
(void) time (&now);
/*
* Check if they are allowed to be logged in right now.
*/
- if (!isttytime (user, ut->ut_line, now)) {
+ if (!isttytime(user, line, now)) {
return 0;
}
return 1;
@@ -116,23 +112,20 @@ static void send_mesg_to_tty (int tty_fd)
*
* logoutd is started at system boot time and enforces the login
* time and port restrictions specified in /etc/porttime. The
- * utmpx/utmp file is periodically scanned and offending users are logged
+ * utmp file is periodically scanned and offending users are logged
* off from the system.
*/
-int main (int argc, char **argv)
+int
+main(int argc, char **argv)
{
- int i;
- int status;
- pid_t pid;
-
-#ifdef USE_UTMPX
- struct utmpx *ut;
-#else /* !USE_UTMPX */
- struct utmp *ut;
-#endif /* !USE_UTMPX */
- char user[sizeof (ut->ut_user) + 1]; /* terminating NUL */
- char tty_name[sizeof (ut->ut_line) + 6]; /* /dev/ + NUL */
- int tty_fd;
+ int i;
+ int status;
+ pid_t pid;
+
+ struct utmpx *ut;
+ char user[sizeof (ut->ut_user) + 1]; /* terminating NUL */
+ char tty_name[sizeof (ut->ut_line) + 6]; /* /dev/ + NUL */
+ int tty_fd;
if (1 != argc) {
(void) fputs (_("Usage: logoutd\n"), stderr);
@@ -164,39 +157,29 @@ int main (int argc, char **argv)
/*
* Start syslogging everything
*/
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
- OPENLOG ("logoutd");
+ OPENLOG (Prog);
/*
- * Scan the utmpx/utmp file once per minute looking for users that
+ * Scan the utmp file once per minute looking for users that
* are not supposed to still be logged in.
*/
while (true) {
/*
- * Attempt to re-open the utmpx/utmp file. The file is only
+ * Attempt to re-open the utmp file. The file is only
* open while it is being used.
*/
-#ifdef USE_UTMPX
- setutxent ();
-#else /* !USE_UTMPX */
- setutent ();
-#endif /* !USE_UTMPX */
+ setutxent();
/*
- * Read all of the entries in the utmpx/utmp file. The entries
+ * Read all of the entries in the utmp file. The entries
* for login sessions will be checked to see if the user
* is permitted to be signed on at this time.
*/
-#ifdef USE_UTMPX
- while ((ut = getutxent ()) != NULL)
-#else /* !USE_UTMPX */
- while ((ut = getutent ()) != NULL)
-#endif /* !USE_UTMPX */
- {
+ while ((ut = getutxent()) != NULL) {
if (ut->ut_type != USER_PROCESS) {
continue;
}
@@ -228,7 +211,7 @@ int main (int argc, char **argv)
tty_name[0] = '\0';
}
- strncat (tty_name, ut->ut_line, UT_LINESIZE);
+ strncat(tty_name, ut->ut_line, NITEMS(ut->ut_line));
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif
@@ -246,8 +229,7 @@ int main (int argc, char **argv)
kill (-ut->ut_pid, SIGKILL);
}
- strncpy (user, ut->ut_user, sizeof (user) - 1);
- user[sizeof (user) - 1] = '\0';
+ ZUSTR2STP(user, ut->ut_user);
SYSLOG ((LOG_NOTICE,
"logged off user '%s' on '%s'", user,
@@ -259,11 +241,7 @@ int main (int argc, char **argv)
exit (EXIT_SUCCESS);
}
-#ifdef USE_UTMPX
- endutxent ();
-#else /* !USE_UTMPX */
- endutent ();
-#endif /* !USE_UTMPX */
+ endutxent();
#ifndef DEBUG
sleep (60);
diff --git a/src/new_subid_range.c b/src/new_subid_range.c
index 523d480..1ef71f3 100644
--- a/src/new_subid_range.c
+++ b/src/new_subid_range.c
@@ -9,7 +9,7 @@
/* Test program for the subid creation routine */
-const char *Prog;
+static const char Prog[] = "new_subid_range";
static void usage(void)
{
@@ -28,7 +28,6 @@ int main(int argc, char *argv[])
bool group = false; // get subuids by default
bool ok;
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
while ((c = getopt(argc, argv, "gn")) != EOF) {
diff --git a/src/newgidmap.c b/src/newgidmap.c
index 5b42431..96a89de 100644
--- a/src/newgidmap.c
+++ b/src/newgidmap.c
@@ -23,7 +23,7 @@
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "newgidmap";
static bool verify_range(struct passwd *pw, struct map_range *range, bool *allow_setgroups)
@@ -69,7 +69,7 @@ static void verify_ranges(struct passwd *pw, int ranges,
static void usage(void)
{
- fprintf(stderr, _("usage: %s <pid> <gid> <lowergid> <count> [ <gid> <lowergid> <count> ] ... \n"), Prog);
+ fprintf(stderr, _("usage: %s [<pid|fd:<pidfd>] <gid> <lowergid> <count> [ <gid> <lowergid> <count> ] ... \n"), Prog);
exit(EXIT_FAILURE);
}
@@ -143,18 +143,14 @@ out:
*/
int main(int argc, char **argv)
{
- char proc_dir_name[32];
char *target_str;
- pid_t target;
int proc_dir_fd;
int ranges;
struct map_range *mappings;
struct stat st;
struct passwd *pw;
- int written;
bool allow_setgroups = false;
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -168,25 +164,19 @@ int main(int argc, char **argv)
/* Find the process that needs its user namespace
* gid mapping set.
*/
- target_str = argv[1];
- if (!get_pid(target_str, &target))
- usage();
- /* max string length is 6 + 10 + 1 + 1 = 18, allocate 32 bytes */
- written = snprintf(proc_dir_name, sizeof(proc_dir_name), "/proc/%u/",
- target);
- if ((written <= 0) || (written >= sizeof(proc_dir_name))) {
- fprintf(stderr, "%s: snprintf of proc path failed: %s\n",
- Prog, strerror(errno));
- }
-
- proc_dir_fd = open(proc_dir_name, O_DIRECTORY);
- if (proc_dir_fd < 0) {
- fprintf(stderr, _("%s: Could not open proc directory for target %u\n"),
- Prog, target);
- return EXIT_FAILURE;
+ target_str = argv[1];
+ if (strlen(target_str) > 3 && strncmp(target_str, "fd:", 3) == 0) {
+ /* the user passed in a /proc/pid fd for the process */
+ target_str = &target_str[3];
+ proc_dir_fd = get_pidfd_from_fd(target_str);
+ if (proc_dir_fd < 0)
+ usage();
+ } else {
+ proc_dir_fd = open_pidfd(target_str);
+ if (proc_dir_fd < 0)
+ usage();
}
-
/* Who am i? */
pw = get_my_pwent ();
if (NULL == pw) {
@@ -200,8 +190,8 @@ int main(int argc, char **argv)
/* Get the effective uid and effective gid of the target process */
if (fstat(proc_dir_fd, &st) < 0) {
- fprintf(stderr, _("%s: Could not stat directory for target %u\n"),
- Prog, target);
+ fprintf(stderr, _("%s: Could not stat directory for process\n"),
+ Prog);
return EXIT_FAILURE;
}
@@ -213,10 +203,10 @@ int main(int argc, char **argv)
(!getdef_bool("GRANT_AUX_GROUP_SUBIDS") && (getgid() != pw->pw_gid)) ||
(pw->pw_uid != st.st_uid) ||
(getgid() != st.st_gid)) {
- fprintf(stderr, _( "%s: Target %u is owned by a different user: uid:%lu pw_uid:%lu st_uid:%lu, gid:%lu pw_gid:%lu st_gid:%lu\n" ),
- Prog, target,
- (unsigned long int)getuid(), (unsigned long int)pw->pw_uid, (unsigned long int)st.st_uid,
- (unsigned long int)getgid(), (unsigned long int)pw->pw_gid, (unsigned long int)st.st_gid);
+ fprintf(stderr, _( "%s: Target process is owned by a different user: uid:%lu pw_uid:%lu st_uid:%lu, gid:%lu pw_gid:%lu st_gid:%lu\n" ),
+ Prog,
+ (unsigned long)getuid(), (unsigned long)pw->pw_uid, (unsigned long)st.st_uid,
+ (unsigned long)getgid(), (unsigned long)pw->pw_gid, (unsigned long)st.st_gid);
return EXIT_FAILURE;
}
diff --git a/src/newgrp.c b/src/newgrp.c
index 9982083..1b3d76b 100644
--- a/src/newgrp.c
+++ b/src/newgrp.c
@@ -16,20 +16,24 @@
#include <pwd.h>
#include <stdio.h>
#include <assert.h>
+
+#include "agetpass.h"
+#include "alloc.h"
#include "defines.h"
#include "getdef.h"
#include "prototypes.h"
/*@-exitarg@*/
#include "exitcodes.h"
#include "shadowlog.h"
+#include "string/sprintf.h"
+
/*
* Global variables
*/
-const char *Prog;
+static const char *Prog;
extern char **newenvp;
-extern char **environ;
#ifdef HAVE_SETGROUPS
static int ngroups;
@@ -158,7 +162,7 @@ static void check_perms (const struct group *grp,
* get the password from her, and set the salt for
* the decryption from the group file.
*/
- cp = getpass (_("Password: "));
+ cp = agetpass (_("Password: "));
if (NULL == cp) {
goto failure;
}
@@ -169,7 +173,7 @@ static void check_perms (const struct group *grp,
* must match the previously encrypted value in the file.
*/
cpasswd = pw_encrypt (cp, grp->gr_passwd);
- strzero (cp);
+ erase_pass (cp);
if (NULL == cpasswd) {
fprintf (stderr,
@@ -184,12 +188,10 @@ static void check_perms (const struct group *grp,
if (grp->gr_passwd[0] == '\0' ||
strcmp (cpasswd, grp->gr_passwd) != 0) {
#ifdef WITH_AUDIT
- snprintf (audit_buf, sizeof(audit_buf),
- "authentication new-gid=%lu",
- (unsigned long) grp->gr_gid);
+ SNPRINTF(audit_buf, "authentication new-gid=%lu",
+ (unsigned long) grp->gr_gid);
audit_logger (AUDIT_GRP_AUTH, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 0);
+ audit_buf, NULL, getuid (), 0);
#endif
SYSLOG ((LOG_INFO,
"Invalid password for group '%s' from '%s'",
@@ -199,12 +201,10 @@ static void check_perms (const struct group *grp,
goto failure;
}
#ifdef WITH_AUDIT
- snprintf (audit_buf, sizeof(audit_buf),
- "authentication new-gid=%lu",
- (unsigned long) grp->gr_gid);
+ SNPRINTF(audit_buf, "authentication new-gid=%lu",
+ (unsigned long) grp->gr_gid);
audit_logger (AUDIT_GRP_AUTH, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 1);
+ audit_buf, NULL, getuid (), 1);
#endif
}
@@ -217,21 +217,17 @@ failure:
closelog ();
#ifdef WITH_AUDIT
if (groupname) {
- snprintf (audit_buf, sizeof(audit_buf),
- "changing new-group=%s", groupname);
+ SNPRINTF(audit_buf, "changing new-group=%s", groupname);
audit_logger (AUDIT_CHGRP_ID, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 0);
+ audit_buf, NULL, getuid (), 0);
} else {
audit_logger (AUDIT_CHGRP_ID, Prog,
- "changing", NULL,
- (unsigned int) getuid (), 0);
+ "changing", NULL, getuid (), 0);
}
#endif
exit (EXIT_FAILURE);
}
-#ifdef USE_SYSLOG
/*
* syslog_sg - log the change of group to syslog
*
@@ -292,6 +288,9 @@ static void syslog_sg (const char *name, const char *group)
(void) signal (SIGTSTP, SIG_IGN);
(void) signal (SIGTTIN, SIG_IGN);
(void) signal (SIGTTOU, SIG_IGN);
+ /* set SIGCHLD to default for waitpid */
+ (void) signal(SIGCHLD, SIG_DFL);
+
child = fork ();
if ((pid_t)-1 == child) {
/* error in fork() */
@@ -299,15 +298,13 @@ static void syslog_sg (const char *name, const char *group)
is_newgrp ? "newgrp" : "sg", strerror (errno));
#ifdef WITH_AUDIT
if (group) {
- snprintf (audit_buf, sizeof(audit_buf),
- "changing new-group=%s", group);
+ SNPRINTF(audit_buf,
+ "changing new-group=%s", group);
audit_logger (AUDIT_CHGRP_ID, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 0);
+ audit_buf, NULL, getuid (), 0);
} else {
audit_logger (AUDIT_CHGRP_ID, Prog,
- "changing", NULL,
- (unsigned int) getuid (), 0);
+ "changing", NULL, getuid (), 0);
}
#endif
exit (EXIT_FAILURE);
@@ -365,7 +362,6 @@ static void syslog_sg (const char *name, const char *group)
free(free_login);
free(free_tty);
}
-#endif /* USE_SYSLOG */
/*
* newgrp - change the invokers current real and effective group id
@@ -394,12 +390,15 @@ int main (int argc, char **argv)
#ifdef WITH_AUDIT
audit_help_open ();
#endif
+
+ check_fds ();
+
(void) setlocale (LC_ALL, "");
(void) bindtextdomain (PACKAGE, LOCALEDIR);
(void) textdomain (PACKAGE);
/*
- * Save my name for error messages and save my real gid incase of
+ * Save my name for error messages and save my real gid in case of
* errors. If there is an error i have to exec a new login shell for
* the user since her old shell won't have fork'd to create the
* process. Skip over the program name to the next command line
@@ -421,11 +420,18 @@ int main (int argc, char **argv)
* but we do not need to restore the previous process persona and we
* don't need to re-exec anything. -- JWP
*/
- Prog = Basename (argv[0]);
+
+ /*
+ * Ensure that "Prog" is always either "newgrp" or "sg" to avoid
+ * injecting arbitrary strings into our stderr/stdout, as this can
+ * be an exploit vector.
+ */
+ is_newgrp = (strcmp (Basename (argv[0]), "newgrp") == 0);
+ Prog = is_newgrp ? "newgrp" : "sg";
+
log_set_progname(Prog);
log_set_logfd(stderr);
- is_newgrp = (strcmp (Prog, "newgrp") == 0);
- OPENLOG (is_newgrp ? "newgrp" : "sg");
+ OPENLOG (Prog);
argc--;
argv++;
@@ -437,8 +443,7 @@ int main (int argc, char **argv)
Prog);
#ifdef WITH_AUDIT
audit_logger (AUDIT_CHGRP_ID, Prog,
- "changing", NULL,
- (unsigned int) getuid (), 0);
+ "changing", NULL, getuid (), 0);
#endif
SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)",
(unsigned long) getuid ()));
@@ -507,7 +512,7 @@ int main (int argc, char **argv)
if ((argc > 0) && (argv[0][0] == '-')) {
usage ();
goto failure;
- } else if (argv[0] != (char *) 0) {
+ } else if (argv[0] != NULL) {
group = argv[0];
} else {
/*
@@ -541,7 +546,7 @@ int main (int argc, char **argv)
/* don't use getgroups(0, 0) - it doesn't work on some systems */
i = 16;
for (;;) {
- grouplist = (GETGROUPS_T *) xmalloc (i * sizeof (GETGROUPS_T));
+ grouplist = XMALLOC(i, GETGROUPS_T);
ngroups = getgroups (i, grouplist);
if (i > ngroups && !(ngroups == -1 && errno == EINVAL)) {
break;
@@ -554,15 +559,12 @@ int main (int argc, char **argv)
perror ("getgroups");
#ifdef WITH_AUDIT
if (group) {
- snprintf (audit_buf, sizeof(audit_buf),
- "changing new-group=%s", group);
+ SNPRINTF(audit_buf, "changing new-group=%s", group);
audit_logger (AUDIT_CHGRP_ID, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 0);
+ audit_buf, NULL, getuid (), 0);
} else {
audit_logger (AUDIT_CHGRP_ID, Prog,
- "changing", NULL,
- (unsigned int) getuid (), 0);
+ "changing", NULL, getuid (), 0);
}
#endif
exit (EXIT_FAILURE);
@@ -628,7 +630,7 @@ int main (int argc, char **argv)
}
#endif /* HAVE_SETGROUPS */
/*
- * For splitted groups (due to limitations of NIS), check all
+ * For split groups (due to limitations of NIS), check all
* groups of the same GID like the requested group for
* membership of the current user.
*/
@@ -665,11 +667,9 @@ int main (int argc, char **argv)
* all successful validations pass through this point. The group id
* will be set, and the group added to the concurrent groupset.
*/
-#ifdef USE_SYSLOG
if (getdef_bool ("SYSLOG_SG_ENAB")) {
syslog_sg (name, group);
}
-#endif /* USE_SYSLOG */
gid = grp->gr_gid;
@@ -718,11 +718,9 @@ int main (int argc, char **argv)
if (setgid (gid) != 0) {
perror ("setgid");
#ifdef WITH_AUDIT
- snprintf (audit_buf, sizeof(audit_buf),
- "changing new-gid=%lu", (unsigned long) gid);
+ SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid);
audit_logger (AUDIT_CHGRP_ID, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 0);
+ audit_buf, NULL, getuid (), 0);
#endif
exit (EXIT_FAILURE);
}
@@ -730,11 +728,9 @@ int main (int argc, char **argv)
if (setuid (getuid ()) != 0) {
perror ("setuid");
#ifdef WITH_AUDIT
- snprintf (audit_buf, sizeof(audit_buf),
- "changing new-gid=%lu", (unsigned long) gid);
+ SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid);
audit_logger (AUDIT_CHGRP_ID, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 0);
+ audit_buf, NULL, getuid (), 0);
#endif
exit (EXIT_FAILURE);
}
@@ -745,13 +741,11 @@ int main (int argc, char **argv)
*/
if (cflag) {
closelog ();
- execl (SHELL, "sh", "-c", command, (char *) 0);
+ execl (SHELL, "sh", "-c", command, (char *) NULL);
#ifdef WITH_AUDIT
- snprintf (audit_buf, sizeof(audit_buf),
- "changing new-gid=%lu", (unsigned long) gid);
+ SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid);
audit_logger (AUDIT_CHGRP_ID, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 0);
+ audit_buf, NULL, getuid (), 0);
#endif
perror (SHELL);
exit ((errno == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
@@ -815,17 +809,15 @@ int main (int argc, char **argv)
}
#ifdef WITH_AUDIT
- snprintf (audit_buf, sizeof(audit_buf), "changing new-gid=%lu",
- (unsigned long) gid);
+ SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid);
audit_logger (AUDIT_CHGRP_ID, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 1);
+ audit_buf, NULL, getuid (), 1);
#endif
/*
* Exec the login shell and go away. We are trying to get back to
* the previous environment which should be the user's login shell.
*/
- err = shell (prog, initflag ? (char *) 0 : progbase, newenvp);
+ err = shell (prog, initflag ? NULL : progbase, newenvp);
exit ((err == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
/*@notreached@*/
failure:
@@ -843,15 +835,12 @@ int main (int argc, char **argv)
closelog ();
#ifdef WITH_AUDIT
if (NULL != group) {
- snprintf (audit_buf, sizeof(audit_buf),
- "changing new-group=%s", group);
+ SNPRINTF(audit_buf, "changing new-group=%s", group);
audit_logger (AUDIT_CHGRP_ID, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 0);
+ audit_buf, NULL, getuid (), 0);
} else {
audit_logger (AUDIT_CHGRP_ID, Prog,
- "changing", NULL,
- (unsigned int) getuid (), 0);
+ "changing", NULL, getuid (), 0);
}
#endif
exit (EXIT_FAILURE);
diff --git a/src/newuidmap.c b/src/newuidmap.c
index 546856a..e2652b5 100644
--- a/src/newuidmap.c
+++ b/src/newuidmap.c
@@ -23,7 +23,7 @@
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "newuidmap";
static bool verify_range(struct passwd *pw, struct map_range *range)
{
@@ -64,7 +64,7 @@ static void verify_ranges(struct passwd *pw, int ranges,
static void usage(void)
{
- fprintf(stderr, _("usage: %s <pid> <uid> <loweruid> <count> [ <uid> <loweruid> <count> ] ... \n"), Prog);
+ fprintf(stderr, _("usage: %s [<pid>|fd:<pidfd>] <uid> <loweruid> <count> [ <uid> <loweruid> <count> ] ... \n"), Prog);
exit(EXIT_FAILURE);
}
@@ -73,17 +73,13 @@ static void usage(void)
*/
int main(int argc, char **argv)
{
- char proc_dir_name[32];
char *target_str;
- pid_t target;
int proc_dir_fd;
int ranges;
struct map_range *mappings;
struct stat st;
struct passwd *pw;
- int written;
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -94,26 +90,20 @@ int main(int argc, char **argv)
if (argc < 2)
usage();
+ target_str = argv[1];
/* Find the process that needs its user namespace
* uid mapping set.
*/
- target_str = argv[1];
- if (!get_pid(target_str, &target))
- usage();
-
- /* max string length is 6 + 10 + 1 + 1 = 18, allocate 32 bytes */
- written = snprintf(proc_dir_name, sizeof(proc_dir_name), "/proc/%u/",
- target);
- if ((written <= 0) || (written >= sizeof(proc_dir_name))) {
- fprintf(stderr, "%s: snprintf of proc path failed: %s\n",
- Prog, strerror(errno));
- }
-
- proc_dir_fd = open(proc_dir_name, O_DIRECTORY);
- if (proc_dir_fd < 0) {
- fprintf(stderr, _("%s: Could not open proc directory for target %u\n"),
- Prog, target);
- return EXIT_FAILURE;
+ if (strlen(target_str) > 3 && strncmp(target_str, "fd:", 3) == 0) {
+ /* the user passed in a /proc/pid fd for the process */
+ target_str = &target_str[3];
+ proc_dir_fd = get_pidfd_from_fd(target_str);
+ if (proc_dir_fd < 0)
+ usage();
+ } else {
+ proc_dir_fd = open_pidfd(target_str);
+ if (proc_dir_fd < 0)
+ usage();
}
/* Who am i? */
@@ -129,8 +119,7 @@ int main(int argc, char **argv)
/* Get the effective uid and effective gid of the target process */
if (fstat(proc_dir_fd, &st) < 0) {
- fprintf(stderr, _("%s: Could not stat directory for target %u\n"),
- Prog, target);
+ fprintf(stderr, _("%s: Could not stat directory for target process\n"), Prog);
return EXIT_FAILURE;
}
@@ -142,10 +131,10 @@ int main(int argc, char **argv)
(!getdef_bool("GRANT_AUX_GROUP_SUBIDS") && (getgid() != pw->pw_gid)) ||
(pw->pw_uid != st.st_uid) ||
(getgid() != st.st_gid)) {
- fprintf(stderr, _( "%s: Target process %u is owned by a different user: uid:%lu pw_uid:%lu st_uid:%lu, gid:%lu pw_gid:%lu st_gid:%lu\n" ),
- Prog, target,
- (unsigned long int)getuid(), (unsigned long int)pw->pw_uid, (unsigned long int)st.st_uid,
- (unsigned long int)getgid(), (unsigned long int)pw->pw_gid, (unsigned long int)st.st_gid);
+ fprintf(stderr, _( "%s: Target process is owned by a different user: uid:%lu pw_uid:%lu st_uid:%lu, gid:%lu pw_gid:%lu st_gid:%lu\n" ),
+ Prog,
+ (unsigned long)getuid(), (unsigned long)pw->pw_uid, (unsigned long)st.st_uid,
+ (unsigned long)getgid(), (unsigned long)pw->pw_gid, (unsigned long)st.st_gid);
return EXIT_FAILURE;
}
diff --git a/src/newusers.c b/src/newusers.c
index deeb361..0705b57 100644
--- a/src/newusers.c
+++ b/src/newusers.c
@@ -29,6 +29,9 @@
#include <ctype.h>
#include <errno.h>
#include <string.h>
+
+#include "alloc.h"
+#include "atoi/str2i.h"
#ifdef ACCT_TOOLS_SETUID
#ifdef USE_PAM
#include "pam_defs.h"
@@ -48,17 +51,19 @@
#endif /* ENABLE_SUBIDS */
#include "chkname.h"
#include "shadowlog.h"
+#include "string/sprintf.h"
+
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "newusers";
static bool rflg = false; /* create a system account */
#ifndef USE_PAM
static /*@null@*//*@observer@*/char *crypt_method = NULL;
#define cflg (NULL != crypt_method)
-#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT)
static bool sflg = false;
#endif
#ifdef USE_SHA_CRYPT
@@ -88,8 +93,8 @@ static bool sub_gid_locked = false;
#endif /* ENABLE_SUBIDS */
/* local function prototypes */
-static void usage (int status);
-static void fail_exit (int);
+NORETURN static void usage (int status);
+NORETURN static void fail_exit (int);
static int add_group (const char *, const char *, gid_t *, gid_t);
static int get_user_id (const char *, uid_t *);
static int add_user (const char *, uid_t, gid_t);
@@ -235,7 +240,7 @@ static int add_group (const char *name, const char *gid, gid_t *ngid, uid_t uid)
* new group, or an existing group.
*/
- if (get_gid (gid, &grent.gr_gid) == 0) {
+ if (get_gid(gid, &grent.gr_gid) == -1) {
fprintf (stderr,
_("%s: invalid group ID '%s'\n"),
Prog, gid);
@@ -245,11 +250,11 @@ static int add_group (const char *name, const char *gid, gid_t *ngid, uid_t uid)
/* Look in both the system database (getgrgid) and in the
* internal database (gr_locate_gid), which may contain
* uncommitted changes */
- if ( (getgrgid ((gid_t) grent.gr_gid) != NULL)
- || (gr_locate_gid ((gid_t) grent.gr_gid) != NULL)) {
+ if ( (getgrgid (grent.gr_gid) != NULL)
+ || (gr_locate_gid (grent.gr_gid) != NULL)) {
/* The user will use this ID for her
* primary group */
- *ngid = (gid_t) grent.gr_gid;
+ *ngid = grent.gr_gid;
return 0;
}
@@ -339,7 +344,7 @@ static int get_user_id (const char *uid, uid_t *nuid) {
* caller provided, or the next available UID.
*/
if (isdigit (uid[0])) {
- if ((get_uid (uid, nuid) == 0) || (*nuid == (uid_t)-1)) {
+ if ((get_uid(uid, nuid) == -1) || (*nuid == (uid_t)-1)) {
fprintf (stderr,
_("%s: invalid user ID '%s'\n"),
Prog, uid);
@@ -350,22 +355,20 @@ static int get_user_id (const char *uid, uid_t *nuid) {
const struct passwd *pwd;
/* local, no need for xgetpwnam */
pwd = getpwnam (uid);
- if (NULL == pwd) {
+ if (pwd == NULL)
pwd = pw_locate (uid);
- }
- if (NULL != pwd) {
- *nuid = pwd->pw_uid;
- } else {
+ if (pwd == NULL) {
fprintf (stderr,
_("%s: user '%s' does not exist\n"),
Prog, uid);
return -1;
}
+
+ *nuid = pwd->pw_uid;
} else {
- if (find_new_uid (rflg, nuid, NULL) < 0) {
+ if (find_new_uid (rflg, nuid, NULL) < 0)
return -1;
- }
}
}
@@ -527,7 +530,7 @@ static int add_passwd (struct passwd *pwd, const char *password)
}
spent.sp_pwdp = cp;
}
- spent.sp_lstchg = (long) gettime () / SCALE;
+ spent.sp_lstchg = gettime () / DAY;
if (0 == spent.sp_lstchg) {
/* Better disable aging than requiring a password
* change */
@@ -584,7 +587,7 @@ static int add_passwd (struct passwd *pwd, const char *password)
*/
spent.sp_pwdp = "!";
#endif
- spent.sp_lstchg = (long) gettime () / SCALE;
+ spent.sp_lstchg = gettime () / DAY;
if (0 == spent.sp_lstchg) {
/* Better disable aging than requiring a password change */
spent.sp_lstchg = -1;
@@ -662,21 +665,28 @@ static void process_flags (int argc, char **argv)
case 's':
sflg = true;
bad_s = 0;
+
+ if (!crypt_method){
+ fprintf(stderr,
+ _("%s: Provide '--crypt-method' before number of rounds\n"),
+ Prog);
+ usage (EXIT_FAILURE);
+ }
#if defined(USE_SHA_CRYPT)
if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512")))
- && (0 == getlong(optarg, &sha_rounds)))) {
+ && (-1 == str2sl(&sha_rounds, optarg)))) {
bad_s = 1;
}
#endif /* USE_SHA_CRYPT */
#if defined(USE_BCRYPT)
if (( (0 == strcmp (crypt_method, "BCRYPT"))
- && (0 == getlong(optarg, &bcrypt_rounds)))) {
+ && (-1 == str2sl(&bcrypt_rounds, optarg)))) {
bad_s = 1;
}
#endif /* USE_BCRYPT */
#if defined(USE_YESCRYPT)
if (( (0 == strcmp (crypt_method, "YESCRYPT"))
- && (0 == getlong(optarg, &yescrypt_cost)))) {
+ && (-1 == str2sl(&yescrypt_cost, optarg)))) {
bad_s = 1;
}
#endif /* USE_YESCRYPT */
@@ -702,8 +712,9 @@ static void process_flags (int argc, char **argv)
if (argv[optind] != NULL) {
if (freopen (argv[optind], "r", stdin) == NULL) {
- char buf[BUFSIZ];
- snprintf (buf, sizeof buf, "%s: %s", Prog, argv[1]);
+ char buf[BUFSIZ];
+
+ SNPRINTF(buf, "%s: %s", Prog, argv[1]);
perror (buf);
fail_exit (EXIT_FAILURE);
}
@@ -1039,7 +1050,6 @@ int main (int argc, char **argv)
char *cp;
const struct passwd *pw;
struct passwd newpw;
- int errors = 0;
int line = 0;
uid_t uid;
gid_t gid;
@@ -1050,7 +1060,6 @@ int main (int argc, char **argv)
unsigned int nusers = 0;
#endif /* USE_PAM */
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -1088,19 +1097,16 @@ int main (int argc, char **argv)
* over 100 is allocated. The pw_gid field will be updated with that
* value.
*/
- while (fgets (buf, (int) sizeof buf, stdin) != (char *) 0) {
+ while (fgets (buf, sizeof buf, stdin) != NULL) {
line++;
cp = strrchr (buf, '\n');
- if (NULL != cp) {
+ if (cp == NULL && feof (stdin) == 0) {
+ fprintf (stderr, _("%s: line %d: line too long\n"),
+ Prog, line);
+ fail_exit (EXIT_FAILURE);
+ }
+ if (cp != NULL) {
*cp = '\0';
- } else {
- if (feof (stdin) == 0) {
- fprintf (stderr,
- _("%s: line %d: line too long\n"),
- Prog, line);
- errors++;
- continue;
- }
}
/*
@@ -1111,39 +1117,35 @@ int main (int argc, char **argv)
for (cp = buf, nfields = 0; nfields < 7; nfields++) {
fields[nfields] = cp;
cp = strchr (cp, ':');
- if (NULL != cp) {
- *cp = '\0';
- cp++;
- } else {
+ if (cp == NULL)
break;
- }
+
+ *cp = '\0';
+ cp++;
}
if (nfields != 6) {
fprintf (stderr, _("%s: line %d: invalid line\n"),
Prog, line);
- errors++;
- continue;
+ fail_exit (EXIT_FAILURE);
}
/*
- * First check if we have to create or update an user
+ * First check if we have to create or update a user
*/
pw = pw_locate (fields[0]);
/* local, no need for xgetpwnam */
- if ( (NULL == pw)
- && (getpwnam (fields[0]) != NULL)) {
- fprintf (stderr, _("%s: cannot update the entry of user %s (not in the passwd database)\n"), Prog, fields[0]);
- errors++;
- continue;
+ if (NULL == pw && getpwnam(fields[0]) != NULL) {
+ fprintf (stderr,
+ _("%s: cannot update the entry of user %s (not in the passwd database)\n"),
+ Prog, fields[0]);
+ fail_exit (EXIT_FAILURE);
}
- if ( (NULL == pw)
- && (get_user_id (fields[2], &uid) != 0)) {
+ if (NULL == pw && get_user_id(fields[2], &uid) != 0) {
fprintf (stderr,
_("%s: line %d: can't create user\n"),
Prog, line);
- errors++;
- continue;
+ fail_exit (EXIT_FAILURE);
}
/*
@@ -1163,8 +1165,7 @@ int main (int argc, char **argv)
fprintf (stderr,
_("%s: line %d: can't create group\n"),
Prog, line);
- errors++;
- continue;
+ fail_exit (EXIT_FAILURE);
}
/*
@@ -1179,8 +1180,7 @@ int main (int argc, char **argv)
fprintf (stderr,
_("%s: line %d: can't create user\n"),
Prog, line);
- errors++;
- continue;
+ fail_exit (EXIT_FAILURE);
}
/*
@@ -1192,17 +1192,22 @@ int main (int argc, char **argv)
fprintf (stderr,
_("%s: line %d: user '%s' does not exist in %s\n"),
Prog, line, fields[0], pw_dbname ());
- errors++;
- continue;
+ fail_exit (EXIT_FAILURE);
}
newpw = *pw;
#ifdef USE_PAM
/* keep the list of user/password for later update by PAM */
nusers++;
- lines = realloc (lines, sizeof (lines[0]) * nusers);
- usernames = realloc (usernames, sizeof (usernames[0]) * nusers);
- passwords = realloc (passwords, sizeof (passwords[0]) * nusers);
+ lines = REALLOCF(lines, nusers, int);
+ usernames = REALLOCF(usernames, nusers, char *);
+ passwords = REALLOCF(passwords, nusers, char *);
+ if (lines == NULL || usernames == NULL || passwords == NULL) {
+ fprintf (stderr,
+ _("%s: line %d: %s\n"),
+ Prog, line, strerror(errno));
+ fail_exit (EXIT_FAILURE);
+ }
lines[nusers-1] = line;
usernames[nusers-1] = strdup (fields[0]);
passwords[nusers-1] = strdup (fields[1]);
@@ -1211,8 +1216,7 @@ int main (int argc, char **argv)
fprintf (stderr,
_("%s: line %d: can't update password\n"),
Prog, line);
- errors++;
- continue;
+ fail_exit (EXIT_FAILURE);
}
if ('\0' != fields[4][0]) {
newpw.pw_gecos = fields[4];
@@ -1235,21 +1239,24 @@ int main (int argc, char **argv)
fprintf(stderr,
_("%s: line %d: homedir must be an absolute path\n"),
Prog, line);
- errors++;
- continue;
- };
+ fail_exit (EXIT_FAILURE);
+ }
if (mkdir (newpw.pw_dir, mode) != 0) {
fprintf (stderr,
_("%s: line %d: mkdir %s failed: %s\n"),
Prog, line, newpw.pw_dir,
strerror (errno));
- } else if (chown (newpw.pw_dir,
- newpw.pw_uid,
- newpw.pw_gid) != 0) {
+ if (errno != EEXIST) {
+ fail_exit (EXIT_FAILURE);
+ }
+ }
+ if (chown(newpw.pw_dir, newpw.pw_uid, newpw.pw_gid) != 0)
+ {
fprintf (stderr,
_("%s: line %d: chown %s failed: %s\n"),
Prog, line, newpw.pw_dir,
strerror (errno));
+ fail_exit (EXIT_FAILURE);
}
}
@@ -1260,8 +1267,7 @@ int main (int argc, char **argv)
fprintf (stderr,
_("%s: line %d: can't update entry\n"),
Prog, line);
- errors++;
- continue;
+ fail_exit (EXIT_FAILURE);
}
#ifdef ENABLE_SUBIDS
@@ -1271,17 +1277,19 @@ int main (int argc, char **argv)
if (is_sub_uid && want_subuids() && !local_sub_uid_assigned(fields[0])) {
uid_t sub_uid_start = 0;
unsigned long sub_uid_count = 0;
- if (find_new_sub_uids(&sub_uid_start, &sub_uid_count) == 0) {
- if (sub_uid_add(fields[0], sub_uid_start, sub_uid_count) == 0) {
- fprintf (stderr,
- _("%s: failed to prepare new %s entry\n"),
- Prog, sub_uid_dbname ());
- }
- } else {
+ if (find_new_sub_uids(&sub_uid_start, &sub_uid_count) != 0)
+ {
fprintf (stderr,
_("%s: can't find subordinate user range\n"),
Prog);
- errors++;
+ fail_exit (EXIT_FAILURE);
+ }
+ if (sub_uid_add(fields[0], sub_uid_start, sub_uid_count) == 0)
+ {
+ fprintf (stderr,
+ _("%s: failed to prepare new %s entry\n"),
+ Prog, sub_uid_dbname ());
+ fail_exit (EXIT_FAILURE);
}
}
@@ -1291,17 +1299,17 @@ int main (int argc, char **argv)
if (is_sub_gid && want_subgids() && !local_sub_gid_assigned(fields[0])) {
gid_t sub_gid_start = 0;
unsigned long sub_gid_count = 0;
- if (find_new_sub_gids(&sub_gid_start, &sub_gid_count) == 0) {
- if (sub_gid_add(fields[0], sub_gid_start, sub_gid_count) == 0) {
- fprintf (stderr,
- _("%s: failed to prepare new %s entry\n"),
- Prog, sub_uid_dbname ());
- }
- } else {
+ if (find_new_sub_gids(&sub_gid_start, &sub_gid_count) != 0) {
fprintf (stderr,
_("%s: can't find subordinate group range\n"),
Prog);
- errors++;
+ fail_exit (EXIT_FAILURE);
+ }
+ if (sub_gid_add(fields[0], sub_gid_start, sub_gid_count) == 0) {
+ fprintf (stderr,
+ _("%s: failed to prepare new %s entry\n"),
+ Prog, sub_uid_dbname ());
+ fail_exit (EXIT_FAILURE);
}
}
#endif /* ENABLE_SUBIDS */
@@ -1314,12 +1322,6 @@ int main (int argc, char **argv)
* changes to be written out all at once, and then unlocked
* afterwards.
*/
- if (0 != errors) {
- fprintf (stderr,
- _("%s: error detected, changes ignored\n"), Prog);
- fail_exit (EXIT_FAILURE);
- }
-
close_files ();
nscd_flush_cache ("passwd");
@@ -1334,11 +1336,11 @@ int main (int argc, char **argv)
fprintf (stderr,
_("%s: (line %d, user %s) password not changed\n"),
Prog, lines[i], usernames[i]);
- errors++;
+ exit (EXIT_FAILURE);
}
}
#endif /* USE_PAM */
- return ((0 == errors) ? EXIT_SUCCESS : EXIT_FAILURE);
+ exit (EXIT_SUCCESS);
}
diff --git a/src/passwd.c b/src/passwd.c
index 8c6f81a..2999a3c 100644
--- a/src/passwd.c
+++ b/src/passwd.c
@@ -19,8 +19,13 @@
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
+
+#include "agetpass.h"
+#include "alloc.h"
+#include "atoi/str2i.h"
#include "defines.h"
#include "getdef.h"
+#include "memzero.h"
#include "nscd.h"
#include "sssd.h"
#include "prototypes.h"
@@ -28,6 +33,10 @@
#include "pwio.h"
#include "shadowio.h"
#include "shadowlog.h"
+#include "string/strtcpy.h"
+#include "time/day_to_str.h"
+
+
/*
* exit status values
@@ -43,12 +52,14 @@
/*
* Global variables
*/
-const char *Prog; /* Program name */
+static const char Prog[] = "passwd"; /* Program name */
static char *name; /* The name of user whose password is being changed */
static char *myname; /* The current user's name */
static bool amroot; /* The caller's real UID was 0 */
+static const char *prefix = "";
+
static bool
aflg = false, /* -a - show status for all users */
dflg = false, /* -d - delete password */
@@ -61,7 +72,8 @@ static bool
Sflg = false, /* -S - show password status */
uflg = false, /* -u - unlock the user's password */
wflg = false, /* -w - set warning days */
- xflg = false; /* -x - set maximum days */
+ xflg = false, /* -x - set maximum days */
+ sflg = false; /* -s - read passwd from stdin */
/*
* set to 1 if there are any flags which require root privileges,
@@ -74,14 +86,16 @@ static long age_max = 0; /* Maximum days until change */
static long warn = 0; /* Warning days before change */
static long inact = 0; /* Days without change before locked */
-#ifndef USE_PAM
static bool do_update_age = false;
-#endif /* ! USE_PAM */
+#ifdef USE_PAM
+static bool use_pam = true;
+#else
+static bool use_pam = false;
+#endif /* USE_PAM */
static bool pw_locked = false;
static bool spw_locked = false;
-#ifndef USE_PAM
/*
* Size of the biggest passwd:
* $6$ 3
@@ -97,25 +111,21 @@ static bool spw_locked = false;
*/
static char crypt_passwd[256];
static bool do_update_pwd = false;
-#endif /* !USE_PAM */
/*
* External identifiers
*/
/* local function prototypes */
-static /*@noreturn@*/void usage (int);
+NORETURN static void usage (int);
-#ifndef USE_PAM
-static bool reuse (const char *, const struct passwd *);
static int new_password (const struct passwd *);
static void check_password (const struct passwd *, const struct spwd *);
-#endif /* !USE_PAM */
static /*@observer@*/const char *pw_status (const char *);
static void print_status (const struct passwd *);
-static /*@noreturn@*/void fail_exit (int);
-static /*@noreturn@*/void oom (void);
+NORETURN static void fail_exit (int);
+NORETURN static void oom (void);
static char *update_crypt_pw (char *);
static void update_noshadow (void);
@@ -124,7 +134,9 @@ static void update_shadow (void);
/*
* usage - print command usage and exit
*/
-static /*@noreturn@*/void usage (int status)
+NORETURN
+static void
+usage (int status)
{
FILE *usageout = (E_SUCCESS != status) ? stderr : stdout;
(void) fprintf (usageout,
@@ -145,37 +157,17 @@ static /*@noreturn@*/void usage (int status)
(void) fputs (_(" -q, --quiet quiet mode\n"), usageout);
(void) fputs (_(" -r, --repository REPOSITORY change password in REPOSITORY repository\n"), usageout);
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
+ (void) fputs (_(" -P, --prefix PREFIX_DIR directory prefix\n"), usageout);
(void) fputs (_(" -S, --status report password status on the named account\n"), usageout);
(void) fputs (_(" -u, --unlock unlock the password of the named account\n"), usageout);
(void) fputs (_(" -w, --warndays WARN_DAYS set expiration warning days to WARN_DAYS\n"), usageout);
(void) fputs (_(" -x, --maxdays MAX_DAYS set maximum number of days before password\n"
" change to MAX_DAYS\n"), usageout);
+ (void) fputs (_(" -s, --stdin read new token from stdin\n"), usageout);
(void) fputs ("\n", usageout);
exit (status);
}
-#ifndef USE_PAM
-static bool reuse (const char *pass, const struct passwd *pw)
-{
-#ifdef HAVE_LIBCRACK_HIST
- const char *reason;
-
-#ifdef HAVE_LIBCRACK_PW
- const char *FascistHistoryPw (const char *, const struct passwd *);
-
- reason = FascistHistory (pass, pw);
-#else /* !HAVE_LIBCRACK_PW */
- const char *FascistHistory (const char *, int);
-
- reason = FascistHistory (pass, pw->pw_uid);
-#endif /* !HAVE_LIBCRACK_PW */
- if (NULL != reason) {
- (void) printf (_("Bad password: %s. "), reason);
- return true;
- }
-#endif /* HAVE_LIBCRACK_HIST */
- return false;
-}
/*
* new_password - validate old password and replace with new (both old and
@@ -186,25 +178,22 @@ static int new_password (const struct passwd *pw)
char *clear; /* Pointer to clear text */
char *cipher; /* Pointer to cipher text */
const char *salt; /* Pointer to new salt */
- char *cp; /* Pointer to getpass() response */
- char orig[200]; /* Original password */
- char pass[200]; /* New password */
+ char *cp; /* Pointer to agetpass() response */
+ char orig[PASS_MAX + 1]; /* Original password */
+ char pass[PASS_MAX + 1]; /* New password */
int i; /* Counter for retries */
+ int ret;
bool warned;
int pass_max_len = -1;
const char *method;
-#ifdef HAVE_LIBCRACK_HIST
- int HistUpdate (const char *, const char *);
-#endif /* HAVE_LIBCRACK_HIST */
-
/*
* Authenticate the user. The user will be prompted for their own
* password.
*/
if (!amroot && ('\0' != crypt_passwd[0])) {
- clear = getpass (_("Old password: "));
+ clear = agetpass (_("Old password: "));
if (NULL == clear) {
return -1;
}
@@ -212,7 +201,7 @@ static int new_password (const struct passwd *pw)
cipher = pw_encrypt (clear, crypt_passwd);
if (NULL == cipher) {
- strzero (clear);
+ erase_pass (clear);
fprintf (stderr,
_("%s: failed to crypt password with previous salt: %s\n"),
Prog, strerror (errno));
@@ -223,7 +212,7 @@ static int new_password (const struct passwd *pw)
}
if (strcmp (cipher, crypt_passwd) != 0) {
- strzero (clear);
+ erase_pass (clear);
strzero (cipher);
SYSLOG ((LOG_WARN, "incorrect password for %s",
pw->pw_name));
@@ -233,8 +222,8 @@ static int new_password (const struct passwd *pw)
pw->pw_name);
return -1;
}
- STRFCPY (orig, clear);
- strzero (clear);
+ STRTCPY(orig, clear);
+ erase_pass (clear);
strzero (cipher);
} else {
orig[0] = '\0';
@@ -270,7 +259,7 @@ static int new_password (const struct passwd *pw)
pass_max_len = getdef_num ("PASS_MAX_LEN", 8);
}
}
- if (!qflg) {
+ if (!qflg && !sflg) {
if (pass_max_len == -1) {
(void) printf (_(
"Enter the new password (minimum of %d characters)\n"
@@ -284,62 +273,87 @@ static int new_password (const struct passwd *pw)
}
}
- warned = false;
- for (i = getdef_num ("PASS_CHANGE_TRIES", 5); i > 0; i--) {
- cp = getpass (_("New password: "));
+ if (sflg) {
+ /*
+ * root is setting the passphrase from stdin
+ */
+ cp = agetpass_stdin ();
if (NULL == cp) {
- memzero (orig, sizeof orig);
- memzero (pass, sizeof pass);
return -1;
}
- if (warned && (strcmp (pass, cp) != 0)) {
- warned = false;
+ ret = STRTCPY (pass, cp);
+ erase_pass (cp);
+ if (ret == -1) {
+ (void) fputs (_("Password is too long.\n"), stderr);
+ MEMZERO(pass);
+ return -1;
}
- STRFCPY (pass, cp);
- strzero (cp);
+ } else {
+ warned = false;
+ for (i = getdef_num ("PASS_CHANGE_TRIES", 5); i > 0; i--) {
+ cp = agetpass (_("New password: "));
+ if (NULL == cp) {
+ MEMZERO(orig);
+ MEMZERO(pass);
+ return -1;
+ }
+ if (warned && (strcmp (pass, cp) != 0)) {
+ warned = false;
+ }
+ ret = STRTCPY (pass, cp);
+ erase_pass (cp);
+ if (ret == -1) {
+ (void) fputs (_("Password is too long.\n"), stderr);
+ MEMZERO(orig);
+ MEMZERO(pass);
+ return -1;
+ }
- if (!amroot && (!obscure (orig, pass, pw) || reuse (pass, pw))) {
- (void) puts (_("Try again."));
- continue;
- }
+ if (!amroot && !obscure(orig, pass, pw)) {
+ (void) puts (_("Try again."));
+ continue;
+ }
- /*
- * If enabled, warn about weak passwords even if you are
- * root (enter this password again to use it anyway).
- * --marekm
- */
- if (amroot && !warned && getdef_bool ("PASS_ALWAYS_WARN")
- && (!obscure (orig, pass, pw) || reuse (pass, pw))) {
- (void) puts (_("\nWarning: weak password (enter it again to use it anyway)."));
- warned = true;
- continue;
+ /*
+ * If enabled, warn about weak passwords even if you are
+ * root (enter this password again to use it anyway).
+ * --marekm
+ */
+ if (amroot && !warned && getdef_bool ("PASS_ALWAYS_WARN")
+ && !obscure(orig, pass, pw)) {
+ (void) puts (_("\nWarning: weak password (enter it again to use it anyway)."));
+ warned = true;
+ continue;
+ }
+ cp = agetpass (_("Re-enter new password: "));
+ if (NULL == cp) {
+ MEMZERO(orig);
+ MEMZERO(pass);
+ return -1;
+ }
+ if (strcmp (cp, pass) != 0) {
+ erase_pass (cp);
+ (void) fputs (_("They don't match; try again.\n"), stderr);
+ } else {
+ erase_pass (cp);
+ break;
+ }
}
- cp = getpass (_("Re-enter new password: "));
- if (NULL == cp) {
- memzero (orig, sizeof orig);
- memzero (pass, sizeof pass);
+ MEMZERO(orig);
+
+ if (i == 0) {
+ MEMZERO(pass);
return -1;
}
- if (strcmp (cp, pass) != 0) {
- (void) fputs (_("They don't match; try again.\n"), stderr);
- } else {
- strzero (cp);
- break;
- }
}
- memzero (orig, sizeof orig);
- if (i == 0) {
- memzero (pass, sizeof pass);
- return -1;
- }
/*
* Encrypt the password, then wipe the cleartext password.
*/
salt = crypt_make_salt (NULL, NULL);
cp = pw_encrypt (pass, salt);
- memzero (pass, sizeof pass);
+ MEMZERO(pass);
if (NULL == cp) {
fprintf (stderr,
@@ -348,10 +362,7 @@ static int new_password (const struct passwd *pw)
return -1;
}
-#ifdef HAVE_LIBCRACK_HIST
- HistUpdate (pw->pw_name, crypt_passwd);
-#endif /* HAVE_LIBCRACK_HIST */
- STRFCPY (crypt_passwd, cp);
+ STRTCPY(crypt_passwd, cp);
return 0;
}
@@ -363,7 +374,6 @@ static int new_password (const struct passwd *pw)
*/
static void check_password (const struct passwd *pw, const struct spwd *sp)
{
- time_t now;
int exp_status;
exp_status = isexpired (pw, sp);
@@ -383,8 +393,6 @@ static void check_password (const struct passwd *pw, const struct spwd *sp)
return;
}
- (void) time (&now);
-
/*
* Expired accounts cannot be changed ever. Passwords which are
* locked may not be changed. Passwords where min > max may not be
@@ -407,10 +415,12 @@ static void check_password (const struct passwd *pw, const struct spwd *sp)
* Passwords may only be changed after sp_min time is up.
*/
if (sp->sp_lstchg > 0) {
- time_t ok;
- ok = (time_t) sp->sp_lstchg * SCALE;
- if (sp->sp_min > 0) {
- ok += (time_t) sp->sp_min * SCALE;
+ long now, ok;
+ now = time(NULL) / DAY;
+ ok = sp->sp_lstchg;
+ if ( (sp->sp_min > 0)
+ && __builtin_add_overflow(ok, sp->sp_min, &ok)) {
+ ok = LONG_MAX;
}
if (now < ok) {
@@ -423,7 +433,6 @@ static void check_password (const struct passwd *pw, const struct spwd *sp)
}
}
}
-#endif /* !USE_PAM */
static /*@observer@*/const char *pw_status (const char *pass)
{
@@ -444,17 +453,17 @@ static void print_status (const struct passwd *pw)
char date[80];
struct spwd *sp;
- sp = getspnam (pw->pw_name); /* local, no need for xgetspnam */
+ sp = prefix_getspnam (pw->pw_name); /* local, no need for xprefix_getspnam */
if (NULL != sp) {
- date_to_str (sizeof(date), date, sp->sp_lstchg * SCALE),
- (void) printf ("%s %s %s %lld %lld %lld %lld\n",
+ DAY_TO_STR(date, sp->sp_lstchg);
+ (void) printf ("%s %s %s %ld %ld %ld %ld\n",
pw->pw_name,
pw_status (sp->sp_pwdp),
date,
- ((long long)sp->sp_min * SCALE) / DAY,
- ((long long)sp->sp_max * SCALE) / DAY,
- ((long long)sp->sp_warn * SCALE) / DAY,
- ((long long)sp->sp_inact * SCALE) / DAY);
+ sp->sp_min,
+ sp->sp_max,
+ sp->sp_warn,
+ sp->sp_inact);
} else if (NULL != pw->pw_passwd) {
(void) printf ("%s %s\n",
pw->pw_name, pw_status (pw->pw_passwd));
@@ -465,7 +474,9 @@ static void print_status (const struct passwd *pw)
}
-static /*@noreturn@*/void fail_exit (int status)
+NORETURN
+static void
+fail_exit (int status)
{
if (pw_locked) {
if (pw_unlock () == 0) {
@@ -486,7 +497,9 @@ static /*@noreturn@*/void fail_exit (int status)
exit (status);
}
-static /*@noreturn@*/void oom (void)
+NORETURN
+static void
+oom (void)
{
(void) fprintf (stderr, _("%s: out of memory\n"), Prog);
fail_exit (E_FAILURE);
@@ -494,11 +507,12 @@ static /*@noreturn@*/void oom (void)
static char *update_crypt_pw (char *cp)
{
-#ifndef USE_PAM
- if (do_update_pwd) {
- cp = xstrdup (crypt_passwd);
+ if (!use_pam)
+ {
+ if (do_update_pwd) {
+ cp = xstrdup (crypt_passwd);
+ }
}
-#endif /* !USE_PAM */
if (dflg) {
*cp = '\0';
@@ -517,15 +531,16 @@ static char *update_crypt_pw (char *cp)
}
if (lflg && *cp != '!') {
- char *newpw = xmalloc (strlen (cp) + 2);
+ char *newpw = XMALLOC(strlen(cp) + 2, char);
strcpy (newpw, "!");
strcat (newpw, cp);
-#ifndef USE_PAM
- if (do_update_pwd) {
- free (cp);
+ if (!use_pam)
+ {
+ if (do_update_pwd) {
+ free (cp);
+ }
}
-#endif /* USE_PAM */
cp = newpw;
}
return cp;
@@ -626,27 +641,28 @@ static void update_shadow (void)
}
nsp->sp_pwdp = update_crypt_pw (nsp->sp_pwdp);
if (xflg) {
- nsp->sp_max = (age_max * DAY) / SCALE;
+ nsp->sp_max = age_max;
}
if (nflg) {
- nsp->sp_min = (age_min * DAY) / SCALE;
+ nsp->sp_min = age_min;
}
if (wflg) {
- nsp->sp_warn = (warn * DAY) / SCALE;
+ nsp->sp_warn = warn;
}
if (iflg) {
- nsp->sp_inact = (inact * DAY) / SCALE;
+ nsp->sp_inact = inact;
}
-#ifndef USE_PAM
- if (do_update_age) {
- nsp->sp_lstchg = (long) gettime () / SCALE;
- if (0 == nsp->sp_lstchg) {
- /* Better disable aging than requiring a password
- * change */
- nsp->sp_lstchg = -1;
+ if (!use_pam)
+ {
+ if (do_update_age) {
+ nsp->sp_lstchg = gettime () / DAY;
+ if (0 == nsp->sp_lstchg) {
+ /* Better disable aging than requiring a password
+ * change */
+ nsp->sp_lstchg = -1;
+ }
}
}
-#endif /* !USE_PAM */
/*
* Force change on next login, like SunOS 4.x passwd -e or Solaris
@@ -690,18 +706,16 @@ static void update_shadow (void)
*
* -d delete the password for the named account (*)
* -e expire the password for the named account (*)
- * -f execute chfn command to interpret flags
- * -g execute gpasswd command to interpret flags
* -i # set sp_inact to # days (*)
* -k change password only if expired
* -l lock the password of the named account (*)
* -n # set sp_min to # days (*)
* -r # change password in # repository
- * -s execute chsh command to interpret flags
* -S show password status of named account
* -u unlock the password of the named account (*)
* -w # set sp_warn to # days (*)
* -x # set sp_max to # days (*)
+ * -s read password from stdin (*)
*
* (*) requires root permission to execute.
*
@@ -713,19 +727,13 @@ int main (int argc, char **argv)
{
const struct passwd *pw; /* Password file entry for user */
-#ifndef USE_PAM
char *cp; /* Miscellaneous character pointing */
const struct spwd *sp; /* Shadow file entry for user */
-#endif /* !USE_PAM */
sanitize_env ();
+ check_fds ();
- /*
- * Get the program name. The program name is used as a prefix to
- * most error messages.
- */
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -734,6 +742,12 @@ int main (int argc, char **argv)
(void) textdomain (PACKAGE);
process_root_flag ("-R", argc, argv);
+ prefix = process_prefix_flag ("-P", argc, argv);
+
+ if (prefix[0]) {
+ use_pam = false;
+ do_update_age = true;
+ }
/*
* The program behaves differently when executed by root than when
@@ -741,7 +755,7 @@ int main (int argc, char **argv)
*/
amroot = (getuid () == 0);
- OPENLOG ("passwd");
+ OPENLOG (Prog);
{
/*
@@ -760,14 +774,16 @@ int main (int argc, char **argv)
{"quiet", no_argument, NULL, 'q'},
{"repository", required_argument, NULL, 'r'},
{"root", required_argument, NULL, 'R'},
+ {"prefix", required_argument, NULL, 'P'},
{"status", no_argument, NULL, 'S'},
{"unlock", no_argument, NULL, 'u'},
{"warndays", required_argument, NULL, 'w'},
{"maxdays", required_argument, NULL, 'x'},
+ {"stdin", no_argument, NULL, 's'},
{NULL, 0, NULL, '\0'}
};
- while ((c = getopt_long (argc, argv, "adehi:kln:qr:R:Suw:x:",
+ while ((c = getopt_long (argc, argv, "adehi:kln:qr:R:P:Suw:x:s",
long_options, NULL)) != -1) {
switch (c) {
case 'a':
@@ -785,7 +801,7 @@ int main (int argc, char **argv)
usage (E_SUCCESS);
/*@notreached@*/break;
case 'i':
- if ( (getlong (optarg, &inact) == 0)
+ if ( (str2sl(&inact, optarg) == -1)
|| (inact < -1)) {
fprintf (stderr,
_("%s: invalid numeric argument '%s'\n"),
@@ -804,7 +820,7 @@ int main (int argc, char **argv)
anyflag = true;
break;
case 'n':
- if ( (getlong (optarg, &age_min) == 0)
+ if ( (str2sl(&age_min, optarg) == -1)
|| (age_min < -1)) {
fprintf (stderr,
_("%s: invalid numeric argument '%s'\n"),
@@ -829,6 +845,8 @@ int main (int argc, char **argv)
break;
case 'R': /* no-op, handled in process_root_flag () */
break;
+ case 'P': /* no-op, handled in process_prefix_flag () */
+ break;
case 'S':
Sflg = true; /* ok for users */
break;
@@ -837,7 +855,7 @@ int main (int argc, char **argv)
anyflag = true;
break;
case 'w':
- if ( (getlong (optarg, &warn) == 0)
+ if ( (str2sl(&warn, optarg) == -1)
|| (warn < -1)) {
(void) fprintf (stderr,
_("%s: invalid numeric argument '%s'\n"),
@@ -848,7 +866,7 @@ int main (int argc, char **argv)
anyflag = true;
break;
case 'x':
- if ( (getlong (optarg, &age_max) == 0)
+ if ( (str2sl(&age_max, optarg) == -1)
|| (age_max < -1)) {
(void) fprintf (stderr,
_("%s: invalid numeric argument '%s'\n"),
@@ -858,6 +876,15 @@ int main (int argc, char **argv)
xflg = true;
anyflag = true;
break;
+ case 's':
+ if (!amroot) {
+ (void) fprintf (stderr,
+ _("%s: only root can use --stdin/-s option\n"),
+ Prog);
+ usage (E_BAD_ARG);
+ }
+ sflg = true;
+ break;
default:
usage (E_BAD_ARG);
}
@@ -906,11 +933,11 @@ int main (int argc, char **argv)
Prog);
exit (E_NOPERM);
}
- setpwent ();
- while ( (pw = getpwent ()) != NULL ) {
+ prefix_setpwent ();
+ while ( (pw = prefix_getpwent ()) != NULL ) {
print_status (pw);
}
- endpwent ();
+ prefix_endpwent ();
exit (E_SUCCESS);
}
#if 0
@@ -947,7 +974,7 @@ int main (int argc, char **argv)
exit (E_NOPERM);
}
- pw = xgetpwnam (name);
+ pw = xprefix_getpwnam (name);
if (NULL == pw) {
(void) fprintf (stderr,
_("%s: user '%s' does not exist\n"),
@@ -957,7 +984,7 @@ int main (int argc, char **argv)
#ifdef WITH_SELINUX
/* only do this check when getuid()==0 because it's a pre-condition for
changing a password without entering the old one */
- if (amroot && (check_selinux_permit ("passwd") != 0)) {
+ if (amroot && (check_selinux_permit (Prog) != 0)) {
SYSLOG ((LOG_ALERT,
"root is not authorized by SELinux to change the password of %s",
name));
@@ -977,8 +1004,8 @@ int main (int argc, char **argv)
_("%s: You may not view or modify password information for %s.\n"),
Prog, name);
SYSLOG ((LOG_WARN,
- "%s: can't view or modify password information for %s",
- Prog, name));
+ "can't view or modify password information for %s",
+ name));
closelog ();
exit (E_NOPERM);
}
@@ -987,53 +1014,55 @@ int main (int argc, char **argv)
print_status (pw);
exit (E_SUCCESS);
}
-#ifndef USE_PAM
- /*
- * The user name is valid, so let's get the shadow file entry.
- */
- sp = getspnam (name); /* !USE_PAM, no need for xgetspnam */
- if (NULL == sp) {
- if (errno == EACCES) {
- (void) fprintf (stderr,
- _("%s: Permission denied.\n"),
- Prog);
- exit (E_NOPERM);
- }
- sp = pwd_to_spwd (pw);
- }
-
- cp = sp->sp_pwdp;
-
- /*
- * If there are no other flags, just change the password.
- */
- if (!anyflag) {
- STRFCPY (crypt_passwd, cp);
-
+ if (!use_pam)
+ {
/*
- * See if the user is permitted to change the password.
- * Otherwise, go ahead and set a new password.
+ * The user name is valid, so let's get the shadow file entry.
*/
- check_password (pw, sp);
+ sp = prefix_getspnam (name); /* !use_pam, no need for xprefix_getspnam */
+ if (NULL == sp) {
+ if (errno == EACCES) {
+ (void) fprintf (stderr,
+ _("%s: Permission denied.\n"),
+ Prog);
+ exit (E_NOPERM);
+ }
+ sp = pwd_to_spwd (pw);
+ }
+
+ cp = sp->sp_pwdp;
/*
- * Let the user know whose password is being changed.
+ * If there are no other flags, just change the password.
*/
- if (!qflg) {
- (void) printf (_("Changing password for %s\n"), name);
- }
+ if (!anyflag) {
+ STRTCPY(crypt_passwd, cp);
+
+ /*
+ * See if the user is permitted to change the password.
+ * Otherwise, go ahead and set a new password.
+ */
+ check_password (pw, sp);
+
+ /*
+ * Let the user know whose password is being changed.
+ */
+ if (!qflg) {
+ (void) printf (_("Changing password for %s\n"), name);
+ }
- if (new_password (pw) != 0) {
- (void) fprintf (stderr,
- _("The password for %s is unchanged.\n"),
- name);
- closelog ();
- exit (E_NOPERM);
+ if (new_password (pw) != 0) {
+ (void) fprintf (stderr,
+ _("The password for %s is unchanged.\n"),
+ name);
+ closelog ();
+ exit (E_NOPERM);
+ }
+ do_update_pwd = true;
+ do_update_age = true;
}
- do_update_pwd = true;
- do_update_age = true;
}
-#endif /* !USE_PAM */
+
/*
* Before going any further, raise the ulimit to prevent colliding
* into a lowered ulimit, and set the real UID to root to protect
@@ -1046,8 +1075,17 @@ int main (int argc, char **argv)
/*
* Don't set the real UID for PAM...
*/
- if (!anyflag) {
- do_pam_passwd (name, qflg, kflg);
+ if (!anyflag && use_pam) {
+ if (sflg) {
+ cp = agetpass_stdin ();
+ if (cp == NULL) {
+ exit (E_FAILURE);
+ }
+ do_pam_passwd_non_interactive ("passwd", name, cp);
+ erase_pass (cp);
+ } else {
+ do_pam_passwd (name, qflg, kflg);
+ }
exit (E_SUCCESS);
}
#endif /* USE_PAM */
@@ -1081,4 +1119,3 @@ int main (int argc, char **argv)
return E_SUCCESS;
}
-
diff --git a/src/pwck.c b/src/pwck.c
index eaa4163..70ff5e6 100644
--- a/src/pwck.c
+++ b/src/pwck.c
@@ -47,7 +47,7 @@
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "pwck";
static bool use_system_pw_file = true;
static bool use_system_spw_file = true;
@@ -66,7 +66,7 @@ static bool quiet = false; /* don't report warnings, only errors */
/* local function prototypes */
static void fail_exit (int code);
-static /*@noreturn@*/void usage (int status);
+NORETURN static void usage (int status);
static void process_flags (int argc, char **argv);
static void open_files (void);
static void close_files (bool changed);
@@ -109,7 +109,9 @@ static void fail_exit (int code)
/*
* usage - print syntax message and exit
*/
-static /*@noreturn@*/void usage (int status)
+NORETURN
+static void
+usage (int status)
{
FILE *usageout = (E_SUCCESS != status) ? stderr : stdout;
#ifdef WITH_TCB
@@ -367,8 +369,8 @@ static void check_pw_file (int *errors, bool *changed)
struct commonio_entry *pfe, *tpfe;
struct passwd *pwd;
const struct spwd *spw;
- uid_t min_sys_id = (uid_t) getdef_ulong ("SYS_UID_MIN", 101UL);
- uid_t max_sys_id = (uid_t) getdef_ulong ("SYS_UID_MAX", 999UL);
+ uid_t min_sys_id = getdef_ulong ("SYS_UID_MIN", 101UL);
+ uid_t max_sys_id = getdef_ulong ("SYS_UID_MAX", 999UL);
/*
* Loop through the entire password file.
@@ -607,7 +609,7 @@ static void check_pw_file (int *errors, bool *changed)
sp.sp_inact = -1;
sp.sp_expire = -1;
sp.sp_flag = SHADOW_SP_FLAG_UNSET;
- sp.sp_lstchg = (long) gettime () / SCALE;
+ sp.sp_lstchg = gettime () / DAY;
if (0 == sp.sp_lstchg) {
/* Better disable aging than
* requiring a password change
@@ -812,9 +814,9 @@ static void check_spw_file (int *errors, bool *changed)
* Warn if last password change in the future. --marekm
*/
if (!quiet) {
- time_t t = time ((time_t *) 0);
+ time_t t = time (NULL);
if ( (t != 0)
- && (spw->sp_lstchg > (long) t / SCALE)) {
+ && (spw->sp_lstchg > t / DAY)) {
printf (_("user %s: last password change in the future\n"),
spw->sp_namp);
*errors += 1;
@@ -831,10 +833,6 @@ int main (int argc, char **argv)
int errors = 0;
bool changed = false;
- /*
- * Get my name so that I can use it to report errors.
- */
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -844,7 +842,7 @@ int main (int argc, char **argv)
process_root_flag ("-R", argc, argv);
- OPENLOG ("pwck");
+ OPENLOG (Prog);
/* Parse the command line arguments */
process_flags (argc, argv);
diff --git a/src/pwconv.c b/src/pwconv.c
index 21d36e7..7dd327a 100644
--- a/src/pwconv.c
+++ b/src/pwconv.c
@@ -40,9 +40,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
#include <time.h>
#include <unistd.h>
#include <getopt.h>
+
#include "defines.h"
#include "getdef.h"
#include "prototypes.h"
@@ -66,7 +68,7 @@
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "pwconv";
static bool spw_locked = false;
static bool pw_locked = false;
@@ -153,7 +155,6 @@ int main (int argc, char **argv)
const struct spwd *sp;
struct spwd spent;
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -163,7 +164,7 @@ int main (int argc, char **argv)
process_root_flag ("-R", argc, argv);
- OPENLOG ("pwconv");
+ OPENLOG (Prog);
process_flags (argc, argv);
@@ -237,7 +238,7 @@ int main (int argc, char **argv)
spent = *sp;
} else {
/* add new shadow entry */
- memset (&spent, 0, sizeof spent);
+ bzero(&spent, sizeof spent);
spent.sp_namp = pw->pw_name;
spent.sp_min = getdef_num ("PASS_MIN_DAYS", -1);
spent.sp_max = getdef_num ("PASS_MAX_DAYS", -1);
@@ -247,7 +248,7 @@ int main (int argc, char **argv)
spent.sp_flag = SHADOW_SP_FLAG_UNSET;
}
spent.sp_pwdp = pw->pw_passwd;
- spent.sp_lstchg = (long) gettime () / SCALE;
+ spent.sp_lstchg = gettime () / DAY;
if (0 == spent.sp_lstchg) {
/* Better disable aging than requiring a password
* change */
diff --git a/src/pwunconv.c b/src/pwunconv.c
index b862435..fe18113 100644
--- a/src/pwunconv.c
+++ b/src/pwunconv.c
@@ -18,6 +18,7 @@
#include <unistd.h>
#include <getopt.h>
#include "defines.h"
+#include "getdef.h"
#include "nscd.h"
#include "sssd.h"
#include "prototypes.h"
@@ -30,7 +31,7 @@
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "pwunconv";
static bool spw_locked = false;
static bool pw_locked = false;
@@ -114,7 +115,6 @@ int main (int argc, char **argv)
struct passwd pwent;
const struct spwd *spwd;
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -124,7 +124,7 @@ int main (int argc, char **argv)
process_root_flag ("-R", argc, argv);
- OPENLOG ("pwunconv");
+ OPENLOG (Prog);
process_flags (argc, argv);
diff --git a/src/su.c b/src/su.c
index 6cd82fc..80c0859 100644
--- a/src/su.c
+++ b/src/su.c
@@ -45,6 +45,10 @@
#include <sys/stat.h>
#include <fcntl.h>
#endif /* !USE_PAM */
+
+#include "alloc.h"
+#include "attr.h"
+#include "cast.h"
#include "prototypes.h"
#include "defines.h"
#include "pwauth.h"
@@ -55,11 +59,14 @@
/*@-exitarg@*/
#include "exitcodes.h"
#include "shadowlog.h"
+#include "string/sprintf.h"
+#include "string/strtcpy.h"
+
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "su";
static /*@observer@*/const char *caller_tty = NULL; /* Name of tty SU is run from */
static bool caller_is_root = false;
static uid_t caller_uid;
@@ -95,8 +102,8 @@ static pid_t pid_child = 0;
* External identifiers
*/
-extern char **newenvp; /* libmisc/env.c */
-extern size_t newenvc; /* libmisc/env.c */
+extern char **newenvp; /* lib/env.c */
+extern size_t newenvc; /* lib/env.c */
/* local function prototypes */
@@ -104,15 +111,16 @@ static void execve_shell (const char *shellname,
char *args[],
char *const envp[]);
#ifdef USE_PAM
-static void kill_child (int unused(s));
+static void kill_child (MAYBE_UNUSED int s);
static void prepare_pam_close_session (void);
#else /* !USE_PAM */
static void die (int);
static bool iswheel (const char *);
#endif /* !USE_PAM */
static bool restricted_shell (const char *shellname);
-static /*@noreturn@*/void su_failure (const char *tty, bool su_to_root);
+NORETURN static void su_failure (const char *tty, bool su_to_root);
static /*@only@*/struct passwd * check_perms (void);
+static /*@only@*/struct passwd * do_check_perms (void);
#ifdef USE_PAM
static void check_perms_pam (const struct passwd *pw);
#else /* !USE_PAM */
@@ -157,13 +165,13 @@ static bool iswheel (const char *username)
return is_on_list (grp->gr_mem, username);
}
#else /* USE_PAM */
-static void kill_child (int unused(s))
+static void kill_child (MAYBE_UNUSED int s)
{
if (0 != pid_child) {
(void) kill (-pid_child, SIGKILL);
- (void) write (STDERR_FILENO, kill_msg, strlen (kill_msg));
+ (void) write_full(STDERR_FILENO, kill_msg, strlen(kill_msg));
} else {
- (void) write (STDERR_FILENO, wait_msg, strlen (wait_msg));
+ (void) write_full(STDERR_FILENO, wait_msg, strlen(wait_msg));
}
_exit (255);
}
@@ -185,10 +193,11 @@ static bool restricted_shell (const char *shellname)
return true;
}
-static /*@noreturn@*/void su_failure (const char *tty, bool su_to_root)
+NORETURN
+static void
+su_failure (const char *tty, bool su_to_root)
{
sulog (tty, false, caller_name, name); /* log failed attempt */
-#ifdef USE_SYSLOG
if (getdef_bool ("SYSLOG_SU_ENAB")) {
SYSLOG ((su_to_root ? LOG_NOTICE : LOG_INFO,
"- %s %s:%s", tty,
@@ -196,7 +205,6 @@ static /*@noreturn@*/void su_failure (const char *tty, bool su_to_root)
('\0' != name[0]) ? name : "???"));
}
closelog ();
-#endif
#ifdef WITH_AUDIT
audit_fd = audit_open ();
@@ -225,7 +233,7 @@ static void execve_shell (const char *shellname,
char *const envp[])
{
int err;
- (void) execve (shellname, (char **) args, envp);
+ (void) execve (shellname, args, envp);
err = errno;
if (access (shellname, R_OK|X_OK) == 0) {
@@ -238,7 +246,7 @@ static void execve_shell (const char *shellname,
while (NULL != args[n_args]) {
n_args++;
}
- targs = (char **) xmalloc ((n_args + 3) * sizeof (args[0]));
+ targs = XMALLOC(n_args + 3, char *);
targs[0] = "sh";
targs[1] = "-";
targs[2] = xstrdup (shellname);
@@ -382,8 +390,8 @@ static void prepare_pam_close_session (void)
stderr);
(void) kill (-pid_child, caught);
- snprintf (kill_msg, sizeof kill_msg, _(" ...killed.\n"));
- snprintf (wait_msg, sizeof wait_msg, _(" ...waiting for child to terminate.\n"));
+ SNPRINTF(kill_msg, _(" ...killed.\n"));
+ SNPRINTF(wait_msg, _(" ...waiting for child to terminate.\n"));
/* Any signals other than SIGCHLD and SIGALRM will no longer have any effect,
* so it's time to block all of them. */
@@ -430,6 +438,7 @@ static void prepare_pam_close_session (void)
/*
* usage - print command line syntax and exit
*/
+NORETURN
static void usage (int status)
{
(void)
@@ -501,7 +510,8 @@ static void check_perms_nopam (const struct passwd *pw)
}
if (strcmp (pw->pw_passwd, "") == 0) {
- char *prevent_no_auth = getdef_str("PREVENT_NO_AUTH");
+ const char *prevent_no_auth = getdef_str("PREVENT_NO_AUTH");
+
if (prevent_no_auth == NULL) {
prevent_no_auth = "superuser";
}
@@ -577,7 +587,7 @@ static void check_perms_nopam (const struct passwd *pw)
* The first character of an administrator defined method is an '@'
* character.
*/
- if (pw_auth (password, name, PW_SU, (char *) 0) != 0) {
+ if (pw_auth (password, name, PW_SU, NULL) != 0) {
SYSLOG (((pw->pw_uid != 0)? LOG_NOTICE : LOG_WARN,
"Authentication failed for %s", name));
fprintf(stderr, _("%s: Authentication failure\n"), Prog);
@@ -600,7 +610,7 @@ static void check_perms_nopam (const struct passwd *pw)
* there is a "SU" entry in the /etc/porttime file denying access to
* the account.
*/
- if (!isttytime (name, "SU", time ((time_t *) 0))) {
+ if (!isttytime (name, "SU", time (NULL))) {
SYSLOG (((0 != pw->pw_uid) ? LOG_WARN : LOG_CRIT,
"SU by %s to restricted account %s",
caller_name, name));
@@ -615,14 +625,30 @@ static void check_perms_nopam (const struct passwd *pw)
/*
* check_perms - check permissions to switch to the user 'name'
*
- * In case of subsystem login, the user is first authenticated in the
- * caller's root subsystem, and then in the user's target subsystem.
+ * The user is authenticated in all subsystems iterately.
*/
static /*@only@*/struct passwd * check_perms (void)
{
+ struct passwd *pw = NULL;
+
+ while (pw == NULL)
+ pw = do_check_perms();
+ return pw;
+}
+
+/*
+ * do_check_perms - check permissions to switch to the user 'name'
+ *
+ * The user is authenticated in current subsystem, if any. Returns
+ * NULL if permissions have to be checked in next subsystem, in
+ * which case the subsystem has already been entered.
+ */
+static /*@only@*/struct passwd * do_check_perms (void)
+{
#ifdef USE_PAM
- const char *tmp_name;
- int ret;
+ int ret;
+ const char *tmp_name;
+ const void *item;
#endif /* !USE_PAM */
/*
* The password file entries for the user is gotten and the account
@@ -642,7 +668,7 @@ static /*@only@*/struct passwd * check_perms (void)
#ifdef USE_PAM
check_perms_pam (pw);
/* PAM authentication can request a change of account */
- ret = pam_get_item(pamh, PAM_USER, (const void **) &tmp_name);
+ ret = pam_get_item(pamh, PAM_USER, &item);
if (ret != PAM_SUCCESS) {
SYSLOG((LOG_ERR, "pam_get_item: internal PAM error\n"));
(void) fprintf (stderr,
@@ -651,12 +677,18 @@ static /*@only@*/struct passwd * check_perms (void)
(void) pam_end (pamh, ret);
su_failure (caller_tty, 0 == pw->pw_uid);
}
+ tmp_name = item;
if (strcmp (name, tmp_name) != 0) {
SYSLOG ((LOG_INFO,
"Change user from '%s' to '%s' as requested by PAM",
name, tmp_name));
- strncpy (name, tmp_name, sizeof(name) - 1);
- name[sizeof(name) - 1] = '\0';
+ if (STRTCPY(name, tmp_name) == -1) {
+ fprintf (stderr, _("Overlong user name '%s'\n"),
+ tmp_name);
+ SYSLOG ((LOG_NOTICE, "Overlong user name '%s'",
+ tmp_name));
+ su_failure (caller_tty, true);
+ }
pw = xgetpwnam (name);
if (NULL == pw) {
(void) fprintf (stderr,
@@ -684,7 +716,7 @@ static /*@only@*/struct passwd * check_perms (void)
endpwent (); /* close the old password databases */
endspent ();
pw_free (pw);
- return check_perms (); /* authenticate in the subsystem */
+ return NULL; /* authenticate in the subsystem */
}
return pw;
@@ -706,11 +738,6 @@ static void save_caller_context (char **argv)
const char *password = NULL;
#endif /* SU_ACCESS */
#endif /* !USE_PAM */
- /*
- * Get the program name. The program name is used as a prefix to
- * most error messages.
- */
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -752,7 +779,7 @@ static void save_caller_context (char **argv)
(unsigned long) caller_uid));
su_failure (caller_tty, true); /* unknown target UID*/
}
- STRFCPY (caller_name, pw->pw_name);
+ STRTCPY(caller_name, pw->pw_name);
#ifndef USE_PAM
#ifdef SU_ACCESS
@@ -808,7 +835,7 @@ static void process_flags (int argc, char **argv)
case 'm':
case 'p':
/* This will only have an effect if the target
- * user do not have a restricted shell, or if
+ * user does not have a restricted shell, or if
* su is called by root.
*/
change_environment = false;
@@ -827,7 +854,7 @@ static void process_flags (int argc, char **argv)
}
if (optind < argc) {
- STRFCPY (name, argv[optind++]); /* use this login id */
+ STRTCPY(name, argv[optind++]); /* use this login id */
}
if ('\0' == name[0]) { /* use default user */
struct passwd *root_pw = getpwnam ("root");
@@ -980,20 +1007,22 @@ int main (int argc, char **argv)
int ret;
#endif /* USE_PAM */
+ check_fds ();
+
(void) setlocale (LC_ALL, "");
(void) bindtextdomain (PACKAGE, LOCALEDIR);
(void) textdomain (PACKAGE);
save_caller_context (argv);
- OPENLOG ("su");
+ OPENLOG (Prog);
process_flags (argc, argv);
initenv ();
#ifdef USE_PAM
- ret = pam_start ("su", name, &conv, &pamh);
+ ret = pam_start (Prog, name, &conv, &pamh);
if (PAM_SUCCESS != ret) {
SYSLOG ((LOG_ERR, "pam_start: error %d", ret);
fprintf (stderr,
@@ -1002,9 +1031,9 @@ int main (int argc, char **argv)
exit (1);
}
- ret = pam_set_item (pamh, PAM_TTY, (const void *) caller_tty);
+ ret = pam_set_item (pamh, PAM_TTY, caller_tty);
if (PAM_SUCCESS == ret) {
- ret = pam_set_item (pamh, PAM_RUSER, (const void *) caller_name);
+ ret = pam_set_item (pamh, PAM_RUSER, caller_name);
}
if (PAM_SUCCESS != ret) {
SYSLOG ((LOG_ERR, "pam_set_item: %s",
@@ -1017,7 +1046,7 @@ int main (int argc, char **argv)
pw = check_perms ();
- /* If the user do not want to change the environment,
+ /* If the user does not want to change the environment,
* use the current SHELL.
* (unless another shell is required by the command line)
*/
@@ -1050,13 +1079,11 @@ int main (int argc, char **argv)
}
sulog (caller_tty, true, caller_name, name); /* save SU information */
-#ifdef USE_SYSLOG
if (getdef_bool ("SYSLOG_SU_ENAB")) {
SYSLOG ((LOG_INFO, "+ %s %s:%s", caller_tty,
('\0' != caller_name[0]) ? caller_name : "???",
('\0' != name[0]) ? name : "???"));
}
-#endif
#ifdef USE_PAM
/* set primary group id and supplementary groups */
@@ -1135,7 +1162,7 @@ int main (int argc, char **argv)
int fd = open ("/dev/tty", O_RDWR);
if (fd >= 0) {
- err = ioctl (fd, TIOCNOTTY, (char *) 0);
+ err = ioctl (fd, TIOCNOTTY, (char *) NULL);
(void) close (fd);
} else if (ENXIO == errno) {
/* There are no controlling terminal already */
@@ -1178,7 +1205,7 @@ int main (int argc, char **argv)
cp = Basename (shellstr);
}
- arg0 = xmalloc (strlen (cp) + 2);
+ arg0 = XMALLOC(strlen(cp) + 2, char);
arg0[0] = '-';
strcpy (arg0 + 1, cp);
cp = arg0;
@@ -1199,7 +1226,7 @@ int main (int argc, char **argv)
* Use the shell and create an argv
* with the rest of the command line included.
*/
- argv[-1] = cp;
+ argv[-1] = const_cast(char *, cp);
execve_shell (shellstr, &argv[-1], environ);
err = errno;
(void) fprintf (stderr,
diff --git a/src/suauth.c b/src/suauth.c
index 2641d33..4d63190 100644
--- a/src/suauth.c
+++ b/src/suauth.c
@@ -68,8 +68,9 @@ int check_su_auth (const char *actual_id,
while (fgets (temp, sizeof (temp), authfile_fd) != NULL) {
lines++;
+ endline = strlen(temp) - 1;
- if (temp[endline = strlen (temp) - 1] != '\n') {
+ if (temp[0] == '\0' || temp[endline] != '\n') {
SYSLOG ((LOG_ERR,
"%s, line %d: line too long or missing newline",
SUAUTHFILE, lines));
@@ -91,9 +92,9 @@ int check_su_auth (const char *actual_id,
continue;
}
if (!(to_users = strtok (temp + posn, field))
- || !(from_users = strtok ((char *) NULL, field))
- || !(action = strtok ((char *) NULL, field))
- || strtok ((char *) NULL, field)) {
+ || !(from_users = strtok (NULL, field))
+ || !(action = strtok (NULL, field))
+ || strtok (NULL, field)) {
SYSLOG ((LOG_ERR,
"%s, line %d. Bad number of fields.\n",
SUAUTHFILE, lines));
diff --git a/src/sulogin.c b/src/sulogin.c
index 2c5e094..2097174 100644
--- a/src/sulogin.c
+++ b/src/sulogin.c
@@ -16,6 +16,11 @@
#include <signal.h>
#include <stdio.h>
#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include "agetpass.h"
+#include "alloc.h"
+#include "attr.h"
#include "defines.h"
#include "getdef.h"
#include "prototypes.h"
@@ -24,113 +29,76 @@
#include "exitcodes.h"
#include "shadowlog.h"
+
/*
* Global variables
*/
-const char *Prog;
-
-static char name[BUFSIZ];
-static char pass[BUFSIZ];
+static const char Prog[] = "sulogin";
-static struct passwd pwent;
extern char **newenvp;
-extern size_t newenvc;
-
-extern char **environ;
#ifndef ALARM
#define ALARM 60
#endif
-/* local function prototypes */
+
static void catch_signals (int);
+static int pw_entry(const char *name, struct passwd *pwent);
-static void catch_signals (unused int sig)
+
+static void catch_signals (MAYBE_UNUSED int sig)
{
_exit (1);
}
-/*
- * syslogd is usually not running at the time when sulogin is typically
- * called, cluttering the screen with unnecessary messages. Suggested by
- * Ivan Nejgebauer <ian@unsux.ns.ac.yu>. --marekm
- */
-#undef USE_SYSLOG
- /*ARGSUSED*/ int main (int argc, char **argv)
+int
+main(int argc, char *argv[])
{
+ int err = 0;
+ char **envp = environ;
+ TERMIO termio;
+ struct passwd pwent = {};
+ bool done;
#ifndef USE_PAM
- const char *env;
-#endif /* !USE_PAM */
- char **envp = environ;
- TERMIO termio;
- int err = 0;
-
-#ifdef USE_TERMIO
- ioctl (0, TCGETA, &termio);
- termio.c_iflag |= (ICRNL | IXON);
- termio.c_oflag |= (OPOST | ONLCR);
- termio.c_cflag |= (CREAD);
- termio.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK);
- ioctl (0, TCSETAF, &termio);
+ const char *env;
#endif
-#ifdef USE_TERMIOS
+
+
tcgetattr (0, &termio);
termio.c_iflag |= (ICRNL | IXON);
termio.c_oflag |= (CREAD);
termio.c_lflag |= (ECHO | ECHOE | ECHOK | ICANON | ISIG);
tcsetattr (0, TCSANOW, &termio);
-#endif
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
(void) setlocale (LC_ALL, "");
(void) bindtextdomain (PACKAGE, LOCALEDIR);
(void) textdomain (PACKAGE);
-#ifdef USE_SYSLOG
- OPENLOG ("sulogin");
-#endif
- initenv ();
+ initenv();
if (argc > 1) {
- close (0);
- close (1);
- close (2);
-
- if (open (argv[1], O_RDWR) >= 0) {
- dup (0);
- dup (0);
- } else {
-#ifdef USE_SYSLOG
- SYSLOG (LOG_WARN, "cannot open %s\n", argv[1]);
- closelog ();
-#endif
- exit (1);
- }
+ close(0);
+ close(1);
+ close(2);
+
+ if (open(argv[1], O_RDWR) == -1)
+ exit(1);
+ dup(0);
+ dup(0);
}
if (access (PASSWD_FILE, F_OK) == -1) { /* must be a password file! */
(void) puts (_("No password file"));
-#ifdef USE_SYSLOG
- SYSLOG (LOG_WARN, "No password file\n");
- closelog ();
-#endif
exit (1);
}
#if !defined(DEBUG) && defined(SULOGIN_ONLY_INIT)
if (getppid () != 1) { /* parent must be INIT */
-#ifdef USE_SYSLOG
- SYSLOG (LOG_WARN, "Pid == %d, not 1\n", getppid ());
- closelog ();
-#endif
exit (1);
}
#endif
if ((isatty (0) == 0) || (isatty (1) == 0) || (isatty (2) == 0)) {
-#ifdef USE_SYSLOG
- closelog ();
-#endif
exit (1); /* must be a terminal */
}
/* If we were init, we need to start a new session */
@@ -156,24 +124,17 @@ static void catch_signals (unused int sig)
}
#endif /* !USE_PAM */
- (void) strcpy (name, "root"); /* KLUDGE!!! */
-
(void) signal (SIGALRM, catch_signals); /* exit if the timer expires */
(void) alarm (ALARM); /* only wait so long ... */
- while (true) { /* repeatedly get login/password pairs */
- char *cp;
- pw_entry (name, &pwent); /* get entry from password file */
- if (pwent.pw_name == (char *) 0) {
+ do { /* repeatedly get login/password pairs */
+ char *pass;
+ if (pw_entry("root", &pwent) == -1) { /* get entry from password file */
/*
* Fail secure
*/
- (void) puts (_("No password entry for 'root'"));
-#ifdef USE_SYSLOG
- SYSLOG (LOG_WARN, "No password entry for 'root'\n");
- closelog ();
-#endif
- exit (1);
+ (void) puts(_("No password entry for 'root'"));
+ exit(1);
}
/*
@@ -182,7 +143,7 @@ static void catch_signals (unused int sig)
*/
/* get a password for root */
- cp = getpass (_(
+ pass = agetpass (_(
"\n"
"Type control-d to proceed with normal startup,\n"
"(or give root password for system maintenance):"));
@@ -192,46 +153,65 @@ static void catch_signals (unused int sig)
* it will work with standard getpass() (no NULL on EOF).
* --marekm
*/
- if ((NULL == cp) || ('\0' == *cp)) {
-#ifdef USE_SYSLOG
- SYSLOG (LOG_INFO, "Normal startup\n");
- closelog ();
-#endif
+ if ((NULL == pass) || ('\0' == *pass)) {
+ erase_pass (pass);
(void) puts ("");
#ifdef TELINIT
- execl (PATH_TELINIT, "telinit", RUNLEVEL, (char *) 0);
+ execl (PATH_TELINIT, "telinit", RUNLEVEL, (char *) NULL);
#endif
exit (0);
- } else {
- STRFCPY (pass, cp);
- strzero (cp);
- }
- if (valid (pass, &pwent)) { /* check encrypted passwords ... */
- break; /* ... encrypted passwords matched */
}
-#ifdef USE_SYSLOG
- SYSLOG (LOG_WARN, "Incorrect root password\n");
-#endif
- sleep (2);
- (void) puts (_("Login incorrect"));
- }
- memzero (pass, sizeof pass);
+ done = valid(pass, &pwent);
+ erase_pass (pass);
+
+ if (!done) { /* check encrypted passwords ... */
+ /* ... encrypted passwords did not match */
+ sleep (2);
+ (void) puts (_("Login incorrect"));
+ }
+ } while (!done);
(void) alarm (0);
(void) signal (SIGALRM, SIG_DFL);
environ = newenvp; /* make new environment active */
(void) puts (_("Entering System Maintenance Mode"));
-#ifdef USE_SYSLOG
- SYSLOG (LOG_INFO, "System Maintenance Mode\n");
-#endif
-#ifdef USE_SYSLOG
- closelog ();
-#endif
/* exec the shell finally. */
- err = shell (pwent.pw_shell, (char *) 0, environ);
+ err = shell (pwent.pw_shell, NULL, environ);
return ((err == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
}
+
+static int
+pw_entry(const char *name, struct passwd *pwent)
+{
+ struct spwd *spwd;
+ struct passwd *passwd;
+
+ if (!(passwd = getpwnam(name))) /* local, no need for xgetpwnam */
+ return -1;
+
+ free(pwent->pw_name);
+ pwent->pw_name = xstrdup(passwd->pw_name);
+ pwent->pw_uid = passwd->pw_uid;
+ pwent->pw_gid = passwd->pw_gid;
+ free(pwent->pw_gecos);
+ pwent->pw_gecos = xstrdup(passwd->pw_gecos);
+ free(pwent->pw_dir);
+ pwent->pw_dir = xstrdup(passwd->pw_dir);
+ free(pwent->pw_shell);
+ pwent->pw_shell = xstrdup(passwd->pw_shell);
+#if !defined(AUTOSHADOW)
+ /* local, no need for xgetspnam */
+ if ((spwd = getspnam(name))) {
+ free(pwent->pw_passwd);
+ pwent->pw_passwd = xstrdup(spwd->sp_pwdp);
+ return 0;
+ }
+#endif
+ free(pwent->pw_passwd);
+ pwent->pw_passwd = xstrdup(passwd->pw_passwd);
+ return 0;
+}
diff --git a/src/useradd.c b/src/useradd.c
index 7ea0a9c..347334a 100644
--- a/src/useradd.c
+++ b/src/useradd.c
@@ -17,9 +17,12 @@
#include <fcntl.h>
#include <getopt.h>
#include <grp.h>
+#ifdef ENABLE_LASTLOG
#include <lastlog.h>
+#endif /* ENABLE_LASTLOG */
#include <libgen.h>
#include <pwd.h>
+#include <signal.h>
#ifdef ACCT_TOOLS_SETUID
#ifdef USE_PAM
#include "pam_defs.h"
@@ -32,11 +35,15 @@
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
+
+#include "alloc.h"
+#include "atoi/str2i.h"
#include "chkname.h"
#include "defines.h"
#include "faillog.h"
#include "getdef.h"
#include "groupio.h"
+#include "memzero.h"
#include "nscd.h"
#include "sssd.h"
#include "prototypes.h"
@@ -57,10 +64,15 @@
#include "tcbfuncs.h"
#endif
#include "shadowlog.h"
+#include "string/sprintf.h"
+
#ifndef SKEL_DIR
#define SKEL_DIR "/etc/skel"
#endif
+#ifndef USRSKELDIR
+#define USRSKELDIR "/usr/etc/skel"
+#endif
#ifndef USER_DEFAULTS_FILE
#define USER_DEFAULTS_FILE "/etc/default/useradd"
#define NEW_USER_FILE "/etc/default/nuaddXXXXXX"
@@ -74,16 +86,18 @@
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "useradd";
/*
* These defaults are used if there is no defaults file.
*/
static gid_t def_group = 1000;
+static const char *def_groups = "";
static const char *def_gname = "other";
static const char *def_home = "/home";
static const char *def_shell = "/bin/bash";
static const char *def_template = SKEL_DIR;
+static const char *def_usrtemplate = USRSKELDIR;
static const char *def_create_mail_spool = "yes";
static const char *def_log_init = "yes";
@@ -106,6 +120,7 @@ static const char *prefix_user_home = NULL;
#ifdef WITH_SELINUX
static /*@notnull@*/const char *user_selinux = "";
+static const char *user_selinux_range = NULL;
#endif /* WITH_SELINUX */
static long user_expire = -1;
@@ -183,25 +198,26 @@ static bool home_added = false;
#endif /* ENABLE_SUBIDS */
#define DGROUP "GROUP="
+#define DGROUPS "GROUPS="
#define DHOME "HOME="
#define DSHELL "SHELL="
#define DINACT "INACTIVE="
#define DEXPIRE "EXPIRE="
#define DSKEL "SKEL="
+#define DUSRSKEL "USRSKEL="
#define DCREATE_MAIL_SPOOL "CREATE_MAIL_SPOOL="
#define DLOG_INIT "LOG_INIT="
/* local function prototypes */
-static void fail_exit (int);
+NORETURN static void fail_exit (int);
static void get_defaults (void);
static void show_defaults (void);
static int set_defaults (void);
static int get_groups (char *);
static struct group * get_local_group (char * grp_name);
-static void usage (int status);
+NORETURN static void usage (int status);
static void new_pwent (struct passwd *);
-static long scale_age (long);
static void new_spent (struct spwd *);
static void grp_update (void);
@@ -213,118 +229,97 @@ static void open_files (void);
static void open_group_files (void);
static void open_shadow (void);
static void faillog_reset (uid_t);
+#ifdef ENABLE_LASTLOG
static void lastlog_reset (uid_t);
+#endif /* ENABLE_LASTLOG */
static void tallylog_reset (const char *);
static void usr_update (unsigned long subuid_count, unsigned long subgid_count);
static void create_home (void);
static void create_mail (void);
static void check_uid_range(int rflg, uid_t user_id);
+static FILE *fmkstemp(char *template);
+
+
/*
* fail_exit - undo as much as possible
*/
static void fail_exit (int code)
{
- if (home_added) {
- if (rmdir (prefix_user_home) != 0) {
- fprintf (stderr,
- _("%s: %s was created, but could not be removed\n"),
- Prog, prefix_user_home);
- SYSLOG ((LOG_ERR, "failed to remove %s", prefix_user_home));
- }
+ if (home_added && rmdir(prefix_user_home) != 0) {
+ fprintf(stderr,
+ _("%s: %s was created, but could not be removed\n"),
+ Prog, prefix_user_home);
+ SYSLOG((LOG_ERR, "failed to remove %s", prefix_user_home));
}
- if (spw_locked) {
- if (spw_unlock () == 0) {
- fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ());
- SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
+ if (spw_locked && spw_unlock() == 0) {
+ fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname());
+ SYSLOG((LOG_ERR, "failed to unlock %s", spw_dbname()));
#ifdef WITH_AUDIT
- audit_logger (AUDIT_ADD_USER, Prog,
- "unlocking shadow file",
- user_name, AUDIT_NO_ID,
- SHADOW_AUDIT_FAILURE);
+ audit_logger(AUDIT_ADD_USER, Prog, "unlocking shadow file",
+ user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE);
#endif
- /* continue */
- }
+ /* continue */
}
- if (pw_locked) {
- if (pw_unlock () == 0) {
- fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
- SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
+ if (pw_locked && pw_unlock() == 0) {
+ fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname());
+ SYSLOG((LOG_ERR, "failed to unlock %s", pw_dbname()));
#ifdef WITH_AUDIT
- audit_logger (AUDIT_ADD_USER, Prog,
- "unlocking passwd file",
- user_name, AUDIT_NO_ID,
- SHADOW_AUDIT_FAILURE);
+ audit_logger(AUDIT_ADD_USER, Prog, "unlocking passwd file",
+ user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE);
#endif
- /* continue */
- }
+ /* continue */
}
- if (gr_locked) {
- if (gr_unlock () == 0) {
- fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ());
- SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
+ if (gr_locked && gr_unlock() == 0) {
+ fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname());
+ SYSLOG((LOG_ERR, "failed to unlock %s", gr_dbname()));
#ifdef WITH_AUDIT
- audit_logger (AUDIT_ADD_USER, Prog,
- "unlocking group file",
- user_name, AUDIT_NO_ID,
- SHADOW_AUDIT_FAILURE);
+ audit_logger(AUDIT_ADD_USER, Prog, "unlocking group file",
+ user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE);
#endif
- /* continue */
- }
+ /* continue */
}
-#ifdef SHADOWGRP
- if (sgr_locked) {
- if (sgr_unlock () == 0) {
- fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ());
- SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
-#ifdef WITH_AUDIT
- audit_logger (AUDIT_ADD_USER, Prog,
- "unlocking gshadow file",
- user_name, AUDIT_NO_ID,
- SHADOW_AUDIT_FAILURE);
-#endif
- /* continue */
- }
+#ifdef SHADOWGRP
+ if (sgr_locked && sgr_unlock() == 0) {
+ fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname());
+ SYSLOG((LOG_ERR, "failed to unlock %s", sgr_dbname()));
+# ifdef WITH_AUDIT
+ audit_logger(AUDIT_ADD_USER, Prog, "unlocking gshadow file",
+ user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE);
+# endif
+ /* continue */
}
#endif
#ifdef ENABLE_SUBIDS
- if (sub_uid_locked) {
- if (sub_uid_unlock () == 0) {
- fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ());
- SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ()));
-#ifdef WITH_AUDIT
- audit_logger (AUDIT_ADD_USER, Prog,
- "unlocking subordinate user file",
- user_name, AUDIT_NO_ID,
- SHADOW_AUDIT_FAILURE);
-#endif
- /* continue */
- }
+ if (sub_uid_locked && sub_uid_unlock() == 0) {
+ fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname());
+ SYSLOG((LOG_ERR, "failed to unlock %s", sub_uid_dbname()));
+# ifdef WITH_AUDIT
+ audit_logger(AUDIT_ADD_USER, Prog,
+ "unlocking subordinate user file",
+ user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE);
+# endif
+ /* continue */
}
- if (sub_gid_locked) {
- if (sub_gid_unlock () == 0) {
- fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ());
- SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ()));
-#ifdef WITH_AUDIT
- audit_logger (AUDIT_ADD_USER, Prog,
- "unlocking subordinate group file",
- user_name, AUDIT_NO_ID,
- SHADOW_AUDIT_FAILURE);
-#endif
- /* continue */
- }
+ if (sub_gid_locked && sub_gid_unlock() == 0) {
+ fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname());
+ SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname()));
+# ifdef WITH_AUDIT
+ audit_logger(AUDIT_ADD_USER, Prog,
+ "unlocking subordinate group file",
+ user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE);
+# endif
+ /* continue */
}
-#endif /* ENABLE_SUBIDS */
+#endif /* ENABLE_SUBIDS */
#ifdef WITH_AUDIT
- audit_logger (AUDIT_ADD_USER, Prog,
- "adding user",
- user_name, AUDIT_NO_ID,
- SHADOW_AUDIT_FAILURE);
+ audit_logger(AUDIT_ADD_USER, Prog, "adding user",
+ user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE);
#endif
- SYSLOG ((LOG_INFO, "failed adding user '%s', exit code: %d", user_name, code));
- exit (code);
+ SYSLOG((LOG_INFO, "failed adding user '%s', exit code: %d", user_name, code));
+ exit(code);
}
#define MATCH(x,y) (strncmp((x),(y),strlen(y)) == 0)
@@ -338,21 +333,15 @@ static void fail_exit (int code)
*/
static void get_defaults (void)
{
- FILE *fp;
- char *default_file = USER_DEFAULTS_FILE;
- char buf[1024];
- char *cp;
+ FILE *fp;
+ char *default_file = USER_DEFAULTS_FILE;
+ char buf[1024];
+ char *cp;
+ const char *ccp;
if (prefix[0]) {
- size_t len;
- int wlen;
-
- len = strlen(prefix) + strlen(USER_DEFAULTS_FILE) + 2;
- default_file = malloc(len);
- if (default_file == NULL)
- return;
- wlen = snprintf(default_file, len, "%s/%s", prefix, USER_DEFAULTS_FILE);
- assert (wlen == (int) len -1);
+ if (asprintf(&default_file, "%s/%s", prefix, USER_DEFAULTS_FILE) == -1)
+ return;
}
/*
@@ -368,7 +357,7 @@ static void get_defaults (void)
* Read the file a line at a time. Only the lines that have relevant
* values are used, everything else can be ignored.
*/
- while (fgets (buf, (int) sizeof buf, fp) == buf) {
+ while (fgets (buf, sizeof buf, fp) == buf) {
cp = strrchr (buf, '\n');
if (NULL != cp) {
*cp = '\0';
@@ -399,29 +388,42 @@ static void get_defaults (void)
}
}
+ ccp = cp;
+
+ if (MATCH (buf, DGROUPS)) {
+ if (get_groups (cp) != 0) {
+ fprintf (stderr,
+ _("%s: the '%s' configuration in %s has an invalid group, ignoring the bad group\n"),
+ Prog, DGROUPS, default_file);
+ }
+ if (user_groups[0] != NULL) {
+ do_grp_update = true;
+ def_groups = xstrdup (cp);
+ }
+ }
/*
* Default HOME filesystem
*/
else if (MATCH (buf, DHOME)) {
- def_home = xstrdup (cp);
+ def_home = xstrdup(ccp);
}
/*
* Default Login Shell command
*/
else if (MATCH (buf, DSHELL)) {
- def_shell = xstrdup (cp);
+ def_shell = xstrdup(ccp);
}
/*
* Default Password Inactive value
*/
else if (MATCH (buf, DINACT)) {
- if ( (getlong (cp, &def_inactive) == 0)
+ if ( (str2sl(&def_inactive, ccp) == -1)
|| (def_inactive < -1)) {
fprintf (stderr,
_("%s: invalid numeric argument '%s'\n"),
- Prog, cp);
+ Prog, ccp);
fprintf (stderr,
_("%s: the %s configuration in %s will be ignored\n"),
Prog, DINACT, default_file);
@@ -433,52 +435,60 @@ static void get_defaults (void)
* Default account expiration date
*/
else if (MATCH (buf, DEXPIRE)) {
- def_expire = xstrdup (cp);
+ def_expire = xstrdup(ccp);
}
/*
* Default Skeleton information
*/
else if (MATCH (buf, DSKEL)) {
- if ('\0' == *cp) {
- cp = SKEL_DIR; /* XXX warning: const */
- }
+ if ('\0' == *ccp)
+ ccp = SKEL_DIR;
if (prefix[0]) {
- size_t len;
- int wlen;
- char* _def_template; /* avoid const warning */
-
- len = strlen(prefix) + strlen(cp) + 2;
- _def_template = xmalloc(len);
- wlen = snprintf(_def_template, len, "%s/%s", prefix, cp);
- assert (wlen == (int) len -1);
- def_template = _def_template;
- }
- else {
- def_template = xstrdup (cp);
+ char *dt;
+
+ xasprintf(&dt, "%s/%s", prefix, ccp);
+ def_template = dt;
+ } else {
+ def_template = xstrdup(ccp);
}
}
/*
+ * Default Usr Skeleton information
+ */
+ else if (MATCH (buf, DUSRSKEL)) {
+ if ('\0' == *ccp)
+ ccp = USRSKELDIR;
+
+ if (prefix[0]) {
+ char *dut;
+
+ xasprintf(&dut, "%s/%s", prefix, ccp);
+ def_usrtemplate = dut;
+ } else {
+ def_usrtemplate = xstrdup(ccp);
+ }
+ }
+ /*
* Create by default user mail spool or not ?
*/
else if (MATCH (buf, DCREATE_MAIL_SPOOL)) {
- if (*cp == '\0') {
- cp = "no"; /* XXX warning: const */
- }
+ if (*ccp == '\0')
+ ccp = "no";
- def_create_mail_spool = xstrdup (cp);
+ def_create_mail_spool = xstrdup(ccp);
}
/*
* By default do we add the user to the lastlog and faillog databases ?
*/
else if (MATCH (buf, DLOG_INIT)) {
- if (*cp == '\0') {
- cp = def_log_init; /* XXX warning: const */
- }
- def_log_init = xstrdup (cp);
+ if (*ccp == '\0')
+ ccp = def_log_init;
+
+ def_log_init = xstrdup(ccp);
}
}
(void) fclose (fp);
@@ -497,11 +507,13 @@ static void get_defaults (void)
static void show_defaults (void)
{
printf ("GROUP=%u\n", (unsigned int) def_group);
+ printf ("GROUPS=%s\n", def_groups);
printf ("HOME=%s\n", def_home);
printf ("INACTIVE=%ld\n", def_inactive);
printf ("EXPIRE=%s\n", def_expire);
printf ("SHELL=%s\n", def_shell);
printf ("SKEL=%s\n", def_template);
+ printf ("USRSKEL=%s\n", def_usrtemplate);
printf ("CREATE_MAIL_SPOOL=%s\n", def_create_mail_spool);
printf ("LOG_INIT=%s\n", def_log_init);
}
@@ -515,49 +527,41 @@ static void show_defaults (void)
*/
static int set_defaults (void)
{
- FILE *ifp;
- FILE *ofp;
- char buf[1024];
- char *new_file = NULL;
- char *new_file_dup = NULL;
- char *default_file = USER_DEFAULTS_FILE;
- char *cp;
- int ofd;
- int wlen;
- bool out_group = false;
- bool out_home = false;
- bool out_inactive = false;
- bool out_expire = false;
- bool out_shell = false;
- bool out_skel = false;
- bool out_create_mail_spool = false;
- bool out_log_init = false;
- size_t len;
- int ret = -1;
-
-
- len = strlen(prefix) + strlen(NEW_USER_FILE) + 2;
- new_file = malloc(len);
- if (new_file == NULL) {
- fprintf (stderr,
- _("%s: cannot create new defaults file: %s\n"),
- Prog, strerror(errno));
+ int ret = -1;
+ bool out_group = false;
+ bool out_groups = false;
+ bool out_home = false;
+ bool out_inactive = false;
+ bool out_expire = false;
+ bool out_shell = false;
+ bool out_skel = false;
+ bool out_usrskel = false;
+ bool out_create_mail_spool = false;
+ bool out_log_init = false;
+ char buf[1024];
+ char *new_file = NULL;
+ char *new_file_dup = NULL;
+ char *default_file = USER_DEFAULTS_FILE;
+ char *cp;
+ FILE *ifp;
+ FILE *ofp;
+
+
+ if (asprintf(&new_file, "%s%s%s", prefix, prefix[0]?"/":"", NEW_USER_FILE) == -1)
+ {
+ fprintf(stderr, _("%s: cannot create new defaults file: %s\n"),
+ Prog, strerror(errno));
return -1;
}
- wlen = snprintf(new_file, len, "%s%s%s", prefix, prefix[0]?"/":"", NEW_USER_FILE);
- assert (wlen <= (int) len -1);
if (prefix[0]) {
- len = strlen(prefix) + strlen(USER_DEFAULTS_FILE) + 2;
- default_file = malloc(len);
- if (default_file == NULL) {
- fprintf (stderr,
- _("%s: cannot create new defaults file: %s\n"),
- Prog, strerror(errno));
- goto setdef_err;
+ if (asprintf(&default_file, "%s/%s", prefix, USER_DEFAULTS_FILE) == -1)
+ {
+ fprintf(stderr,
+ _("%s: cannot create new defaults file: %s\n"),
+ Prog, strerror(errno));
+ goto err_free_new;
}
- wlen = snprintf(default_file, len, "%s/%s", prefix, USER_DEFAULTS_FILE);
- assert (wlen == (int) len -1);
}
new_file_dup = strdup(new_file);
@@ -565,36 +569,27 @@ static int set_defaults (void)
fprintf (stderr,
_("%s: cannot create directory for defaults file\n"),
Prog);
- goto setdef_err;
+ goto err_free_def;
}
ret = mkdir(dirname(new_file_dup), 0755);
+ free(new_file_dup);
if (-1 == ret && EEXIST != errno) {
fprintf (stderr,
_("%s: cannot create directory for defaults file\n"),
Prog);
- free(new_file_dup);
- goto setdef_err;
+ goto err_free_def;
}
- free(new_file_dup);
/*
* Create a temporary file to copy the new output to.
*/
- ofd = mkstemp (new_file);
- if (-1 == ofd) {
- fprintf (stderr,
- _("%s: cannot create new defaults file\n"),
- Prog);
- goto setdef_err;
- }
-
- ofp = fdopen (ofd, "w");
+ ofp = fmkstemp(new_file);
if (NULL == ofp) {
fprintf (stderr,
_("%s: cannot open new defaults file\n"),
Prog);
- goto setdef_err;
+ goto err_free_def;
}
/*
@@ -608,7 +603,7 @@ static int set_defaults (void)
goto skip;
}
- while (fgets (buf, (int) sizeof buf, ifp) == buf) {
+ while (fgets (buf, sizeof buf, ifp) == buf) {
cp = strrchr (buf, '\n');
if (NULL != cp) {
*cp = '\0';
@@ -620,14 +615,18 @@ static int set_defaults (void)
fprintf (stderr,
_("%s: line too long in %s: %s..."),
Prog, default_file, buf);
- (void) fclose (ifp);
- goto setdef_err;
+ fclose(ifp);
+ fclose(ofp);
+ goto err_free_def;
}
}
if (!out_group && MATCH (buf, DGROUP)) {
fprintf (ofp, DGROUP "%u\n", (unsigned int) def_group);
out_group = true;
+ } else if (!out_groups && MATCH (buf, DGROUPS)) {
+ fprintf (ofp, DGROUPS "%s\n", def_groups);
+ out_groups = true;
} else if (!out_home && MATCH (buf, DHOME)) {
fprintf (ofp, DHOME "%s\n", def_home);
out_home = true;
@@ -643,6 +642,9 @@ static int set_defaults (void)
} else if (!out_skel && MATCH (buf, DSKEL)) {
fprintf (ofp, DSKEL "%s\n", def_template);
out_skel = true;
+ } else if (!out_usrskel && MATCH (buf, DUSRSKEL)) {
+ fprintf (ofp, DUSRSKEL "%s\n", def_usrtemplate);
+ out_usrskel = true;
} else if (!out_create_mail_spool
&& MATCH (buf, DCREATE_MAIL_SPOOL)) {
fprintf (ofp,
@@ -668,6 +670,8 @@ static int set_defaults (void)
*/
if (!out_group)
fprintf (ofp, DGROUP "%u\n", (unsigned int) def_group);
+ if (!out_groups)
+ fprintf (ofp, DGROUPS "%s\n", def_groups);
if (!out_home)
fprintf (ofp, DHOME "%s\n", def_home);
if (!out_inactive)
@@ -678,6 +682,8 @@ static int set_defaults (void)
fprintf (ofp, DSHELL "%s\n", def_shell);
if (!out_skel)
fprintf (ofp, DSKEL "%s\n", def_template);
+ if (!out_usrskel)
+ fprintf (ofp, DUSRSKEL "%s\n", def_usrtemplate);
if (!out_create_mail_spool)
fprintf (ofp, DCREATE_MAIL_SPOOL "%s\n", def_create_mail_spool);
@@ -690,16 +696,16 @@ static int set_defaults (void)
(void) fflush (ofp);
if ( (ferror (ofp) != 0)
|| (fsync (fileno (ofp)) != 0)
- || (fclose (ofp) != 0)) {
+ || (fclose (ofp) != 0))
+ {
unlink (new_file);
- goto setdef_err;
+ goto err_free_def;
}
/*
* Rename the current default file to its backup name.
*/
- wlen = snprintf (buf, sizeof buf, "%s-", default_file);
- assert (wlen < (int) sizeof buf);
+ assert(SNPRINTF(buf, "%s-", default_file) != -1);
unlink (buf);
if ((link (default_file, buf) != 0) && (ENOENT != errno)) {
int err = errno;
@@ -707,7 +713,7 @@ static int set_defaults (void)
_("%s: Cannot create backup file (%s): %s\n"),
Prog, buf, strerror (err));
unlink (new_file);
- goto setdef_err;
+ goto err_free_def;
}
/*
@@ -718,7 +724,7 @@ static int set_defaults (void)
fprintf (stderr,
_("%s: rename: %s: %s\n"),
Prog, new_file, strerror (err));
- goto setdef_err;
+ goto err_free_def;
}
#ifdef WITH_AUDIT
audit_logger (AUDIT_USYS_CONFIG, Prog,
@@ -733,11 +739,12 @@ static int set_defaults (void)
def_inactive, def_expire, def_template,
def_create_mail_spool, def_log_init));
ret = 0;
- setdef_err:
- free(new_file);
- if (prefix[0]) {
+
+err_free_def:
+ if (prefix[0])
free(default_file);
- }
+err_free_new:
+ free(new_file);
return ret;
}
@@ -807,20 +814,6 @@ static int get_groups (char *list)
continue;
}
-#ifdef USE_NIS
- /*
- * Don't add this group if they are an NIS group. Tell
- * the user to go to the server for this group.
- */
- if (__isgrNIS ()) {
- fprintf (stderr,
- _("%s: group '%s' is a NIS group.\n"),
- Prog, grp->gr_name);
- gr_free(grp);
- continue;
- }
-#endif
-
if (ngroups == sys_ngroups) {
fprintf (stderr,
_("%s: too many groups specified (max %d).\n"),
@@ -839,7 +832,7 @@ static int get_groups (char *list)
close_group_files ();
unlock_group_files ();
- user_groups[ngroups] = (char *) 0;
+ user_groups[ngroups] = NULL;
/*
* Any errors in finding group names are fatal
@@ -860,17 +853,17 @@ static int get_groups (char *list)
*/
static struct group * get_local_group(char * grp_name)
{
+ char *end;
const struct group *grp;
struct group *result_grp = NULL;
- long long int gid;
- char *endptr;
+ long long gid;
- gid = strtoll (grp_name, &endptr, 10);
+ gid = strtoll(grp_name, &end, 10);
if ( ('\0' != *grp_name)
- && ('\0' == *endptr)
+ && ('\0' == *end)
&& (ERANGE != errno)
&& (gid == (gid_t)gid)) {
- grp = gr_locate_gid ((gid_t) gid);
+ grp = gr_locate_gid (gid);
}
else {
grp = gr_locate(grp_name);
@@ -923,8 +916,10 @@ static void usage (int status)
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
(void) fputs (_(" -k, --skel SKEL_DIR use this alternative skeleton directory\n"), usageout);
(void) fputs (_(" -K, --key KEY=VALUE override /etc/login.defs defaults\n"), usageout);
+#ifdef ENABLE_LASTLOG
(void) fputs (_(" -l, --no-log-init do not add the user to the lastlog and\n"
" faillog databases\n"), usageout);
+#endif /* ENABLE_LASTLOG */
(void) fputs (_(" -m, --create-home create the user's home directory\n"), usageout);
(void) fputs (_(" -M, --no-create-home do not create the user's home directory\n"), usageout);
(void) fputs (_(" -N, --no-user-group do not create a group with the same name as\n"
@@ -940,6 +935,7 @@ static void usage (int status)
(void) fputs (_(" -U, --user-group create a group with the same name as the user\n"), usageout);
#ifdef WITH_SELINUX
(void) fputs (_(" -Z, --selinux-user SEUSER use a specific SEUSER for the SELinux user mapping\n"), usageout);
+ (void) fputs (_(" --selinux-range SERANGE use a specific MLS range for the SELinux user mapping\n"), usageout);
#endif /* WITH_SELINUX */
(void) fputs ("\n", usageout);
exit (status);
@@ -968,15 +964,6 @@ static void new_pwent (struct passwd *pwent)
pwent->pw_shell = (char *) user_shell;
}
-static long scale_age (long x)
-{
- if (x <= 0) {
- return x;
- }
-
- return x * (DAY / SCALE);
-}
-
/*
* new_spent - initialize the values in a shadow password file entry
*
@@ -988,17 +975,17 @@ static void new_spent (struct spwd *spent)
memzero (spent, sizeof *spent);
spent->sp_namp = (char *) user_name;
spent->sp_pwdp = (char *) user_pass;
- spent->sp_lstchg = (long) gettime () / SCALE;
+ spent->sp_lstchg = gettime () / DAY;
if (0 == spent->sp_lstchg) {
/* Better disable aging than requiring a password change */
spent->sp_lstchg = -1;
}
if (!rflg) {
- spent->sp_min = scale_age (getdef_num ("PASS_MIN_DAYS", -1));
- spent->sp_max = scale_age (getdef_num ("PASS_MAX_DAYS", -1));
- spent->sp_warn = scale_age (getdef_num ("PASS_WARN_AGE", -1));
- spent->sp_inact = scale_age (def_inactive);
- spent->sp_expire = scale_age (user_expire);
+ spent->sp_min = getdef_num ("PASS_MIN_DAYS", -1);
+ spent->sp_max = getdef_num ("PASS_MAX_DAYS", -1);
+ spent->sp_warn = getdef_num ("PASS_WARN_AGE", -1);
+ spent->sp_inact = def_inactive;
+ spent->sp_expire = user_expire;
} else {
spent->sp_min = -1;
spent->sp_max = -1;
@@ -1223,6 +1210,7 @@ static void process_flags (int argc, char **argv)
{"user-group", no_argument, NULL, 'U'},
#ifdef WITH_SELINUX
{"selinux-user", required_argument, NULL, 'Z'},
+ {"selinux-range", required_argument, NULL, 202},
#endif /* WITH_SELINUX */
{NULL, 0, NULL, '\0'}
};
@@ -1310,7 +1298,7 @@ static void process_flags (int argc, char **argv)
eflg = true;
break;
case 'f':
- if ( (getlong (optarg, &def_inactive) == 0)
+ if ( (str2sl(&def_inactive, optarg) == -1)
|| (def_inactive < -1)) {
fprintf (stderr,
_("%s: invalid numeric argument '%s'\n"),
@@ -1382,7 +1370,7 @@ static void process_flags (int argc, char **argv)
/* terminate name, point to value */
*cp = '\0';
cp++;
- if (putdef_str (optarg, cp) < 0) {
+ if (putdef_str (optarg, cp, NULL) < 0) {
exit (E_BAD_ARG);
}
break;
@@ -1442,7 +1430,7 @@ static void process_flags (int argc, char **argv)
sflg = true;
break;
case 'u':
- if ( (get_uid (optarg, &user_id) == 0)
+ if ( (get_uid(optarg, &user_id) == -1)
|| (user_id == (gid_t)-1)) {
fprintf (stderr,
_("%s: invalid user ID '%s'\n"),
@@ -1472,6 +1460,9 @@ static void process_flags (int argc, char **argv)
exit (E_BAD_ARG);
}
break;
+ case 202:
+ user_selinux_range = optarg;
+ break;
#endif /* WITH_SELINUX */
default:
usage (E_USAGE);
@@ -1519,6 +1510,14 @@ static void process_flags (int argc, char **argv)
Prog, "-m", "-M");
usage (E_USAGE);
}
+#ifdef WITH_SELINUX
+ if (user_selinux_range && !Zflg) {
+ fprintf (stderr,
+ _("%s: %s flag is only allowed with the %s flag\n"),
+ Prog, "--selinux-range", "--selinux-user");
+ usage (E_USAGE);
+ }
+#endif /* WITH_SELINUX */
/*
* Either -D or username is required. Defaults can be set with -D
@@ -1551,26 +1550,17 @@ static void process_flags (int argc, char **argv)
exit (E_BAD_ARG);
}
if (!dflg) {
- char *uh;
- size_t len = strlen (def_home) + strlen (user_name) + 2;
- int wlen;
-
- uh = xmalloc (len);
- wlen = snprintf (uh, len, "%s/%s", def_home, user_name);
- assert (wlen == (int) len -1);
+ char *uh;
+ xasprintf(&uh, "%s/%s", def_home, user_name);
user_home = uh;
}
if (prefix[0]) {
- size_t len = strlen(prefix) + strlen(user_home) + 2;
- int wlen;
- char* _prefix_user_home; /* to avoid const warning */
- _prefix_user_home = xmalloc(len);
- wlen = snprintf(_prefix_user_home, len, "%s/%s", prefix, user_home);
- assert (wlen == (int) len -1);
- prefix_user_home = _prefix_user_home;
- }
- else {
+ char *puh; /* to avoid const warning */
+
+ xasprintf(&puh, "%s/%s", prefix, user_home);
+ prefix_user_home = puh;
+ } else {
prefix_user_home = user_home;
}
}
@@ -1716,23 +1706,25 @@ static void close_files (void)
*/
static void close_group_files (void)
{
- if (do_grp_update) {
- if (gr_close () == 0) {
- fprintf (stderr,
- _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ());
- SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ()));
- fail_exit (E_GRP_UPDATE);
- }
+ if (!do_grp_update)
+ return;
+
+ if (gr_close() == 0) {
+ fprintf(stderr,
+ _("%s: failure while writing changes to %s\n"),
+ Prog, gr_dbname());
+ SYSLOG((LOG_ERR, "failure while writing changes to %s", gr_dbname()));
+ fail_exit(E_GRP_UPDATE);
+ }
#ifdef SHADOWGRP
- if (is_shadow_grp && (sgr_close () == 0)) {
- fprintf (stderr,
- _("%s: failure while writing changes to %s\n"),
- Prog, sgr_dbname ());
- SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ()));
- fail_exit (E_GRP_UPDATE);
- }
-#endif /* SHADOWGRP */
+ if (is_shadow_grp && sgr_close() == 0) {
+ fprintf(stderr,
+ _("%s: failure while writing changes to %s\n"),
+ Prog, sgr_dbname());
+ SYSLOG((LOG_ERR, "failure while writing changes to %s", sgr_dbname()));
+ fail_exit(E_GRP_UPDATE);
}
+#endif /* SHADOWGRP */
}
/*
@@ -2013,14 +2005,14 @@ static void faillog_reset (uid_t uid)
return;
}
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
- || (write (fd, &fl, sizeof (fl)) != (ssize_t) sizeof (fl))
+ || (write_full(fd, &fl, sizeof (fl)) == -1)
|| (fsync (fd) != 0)) {
fprintf (stderr,
_("%s: failed to reset the faillog entry of UID %lu: %s\n"),
Prog, (unsigned long) uid, strerror (errno));
SYSLOG ((LOG_WARN, "failed to reset the faillog entry of UID %lu", (unsigned long) uid));
}
- if (close (fd) != 0) {
+ if (close (fd) != 0 && errno != EINTR) {
fprintf (stderr,
_("%s: failed to close the faillog file for UID %lu: %s\n"),
Prog, (unsigned long) uid, strerror (errno));
@@ -2028,6 +2020,7 @@ static void faillog_reset (uid_t uid)
}
}
+#ifdef ENABLE_LASTLOG
static void lastlog_reset (uid_t uid)
{
struct lastlog ll;
@@ -2040,7 +2033,7 @@ static void lastlog_reset (uid_t uid)
return;
}
- max_uid = (uid_t) getdef_ulong ("LASTLOG_UID_MAX", 0xFFFFFFFFUL);
+ max_uid = getdef_ulong ("LASTLOG_UID_MAX", 0xFFFFFFFFUL);
if (uid > max_uid) {
/* do not touch lastlog for large uids */
return;
@@ -2057,7 +2050,7 @@ static void lastlog_reset (uid_t uid)
return;
}
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
- || (write (fd, &ll, sizeof (ll)) != (ssize_t) sizeof (ll))
+ || (write_full (fd, &ll, sizeof (ll)) != (ssize_t) sizeof (ll))
|| (fsync (fd) != 0)) {
fprintf (stderr,
_("%s: failed to reset the lastlog entry of UID %lu: %s\n"),
@@ -2065,7 +2058,7 @@ static void lastlog_reset (uid_t uid)
SYSLOG ((LOG_WARN, "failed to reset the lastlog entry of UID %lu", (unsigned long) uid));
/* continue */
}
- if (close (fd) != 0) {
+ if (close (fd) != 0 && errno != EINTR) {
fprintf (stderr,
_("%s: failed to close the lastlog file for UID %lu: %s\n"),
Prog, (unsigned long) uid, strerror (errno));
@@ -2073,6 +2066,7 @@ static void lastlog_reset (uid_t uid)
/* continue */
}
}
+#endif /* ENABLE_LASTLOG */
static void tallylog_reset (const char *user_name)
{
@@ -2085,6 +2079,9 @@ static void tallylog_reset (const char *user_name)
if (access(pam_tally2, X_OK) == -1)
return;
+ /* set SIGCHLD to default for waitpid */
+ signal(SIGCHLD, SIG_DFL);
+
failed = 0;
switch (childpid = fork())
{
@@ -2159,7 +2156,9 @@ static void usr_update (unsigned long subuid_count, unsigned long subgid_count)
/* local, no need for xgetpwuid */
if ((!lflg) && (prefix_getpwuid (user_id) == NULL)) {
faillog_reset (user_id);
+#ifdef ENABLE_LASTLOG
lastlog_reset (user_id);
+#endif /* ENABLE_LASTLOG */
}
/*
@@ -2182,20 +2181,19 @@ static void usr_update (unsigned long subuid_count, unsigned long subgid_count)
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
"adding shadow password",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif
fail_exit (E_PW_UPDATE);
}
#ifdef ENABLE_SUBIDS
- if (is_sub_uid &&
+ if (is_sub_uid && !local_sub_uid_assigned(user_name) &&
(sub_uid_add(user_name, sub_uid_start, subuid_count) == 0)) {
fprintf (stderr,
_("%s: failed to prepare the new %s entry\n"),
Prog, sub_uid_dbname ());
fail_exit (E_SUB_UID_UPDATE);
}
- if (is_sub_gid &&
+ if (is_sub_gid && !local_sub_gid_assigned(user_name) &&
(sub_gid_add(user_name, sub_gid_start, subgid_count) == 0)) {
fprintf (stderr,
_("%s: failed to prepare the new %s entry\n"),
@@ -2205,9 +2203,14 @@ static void usr_update (unsigned long subuid_count, unsigned long subgid_count)
#endif /* ENABLE_SUBIDS */
#ifdef WITH_AUDIT
+ /*
+ * Even though we have the ID of the user, we won't send it now
+ * because its not written to disk yet. After close_files it is
+ * and we can use the real ID thereafter.
+ */
audit_logger (AUDIT_ADD_USER, Prog,
"adding user",
- user_name, (unsigned int) user_id,
+ user_name, AUDIT_NO_ID,
SHADOW_AUDIT_SUCCESS);
#endif
/*
@@ -2227,123 +2230,120 @@ static void usr_update (unsigned long subuid_count, unsigned long subgid_count)
*/
static void create_home (void)
{
- if (access (prefix_user_home, F_OK) != 0) {
- char path[strlen (prefix_user_home) + 2];
- char *bhome, *cp;
+ char path[strlen(prefix_user_home) + 2];
+ char *bhome, *cp;
+ mode_t mode;
- path[0] = '\0';
- bhome = strdup (prefix_user_home);
- if (!bhome) {
- fprintf (stderr,
- _("%s: error while duplicating string %s\n"),
- Prog, user_home);
- fail_exit (E_HOMEDIR);
- }
+ if (access (prefix_user_home, F_OK) == 0)
+ return;
+
+ path[0] = '\0';
+ bhome = strdup(prefix_user_home);
+ if (!bhome) {
+ fprintf(stderr,
+ _("%s: error while duplicating string %s\n"),
+ Prog, user_home);
+ fail_exit(E_HOMEDIR);
+ }
#ifdef WITH_SELINUX
- if (set_selinux_file_context (prefix_user_home, S_IFDIR) != 0) {
- fprintf (stderr,
- _("%s: cannot set SELinux context for home directory %s\n"),
- Prog, user_home);
- fail_exit (E_HOMEDIR);
- }
+ if (set_selinux_file_context(prefix_user_home, S_IFDIR) != 0) {
+ fprintf(stderr,
+ _("%s: cannot set SELinux context for home directory %s\n"),
+ Prog, user_home);
+ fail_exit(E_HOMEDIR);
+ }
#endif
- /* Check for every part of the path, if the directory
- exists. If not, create it with permissions 755 and
- owner root:root.
+ /* Check for every part of the path, if the directory
+ exists. If not, create it with permissions 755 and
+ owner root:root.
+ */
+ for (cp = strtok(bhome, "/"); cp != NULL; cp = strtok(NULL, "/")) {
+ /* Avoid turning a relative path into an absolute path. */
+ if (bhome[0] == '/' || strlen(path) != 0) {
+ strcat(path, "/");
+ }
+ strcat(path, cp);
+ if (access(path, F_OK) == 0) {
+ continue;
+ }
+
+ /* Check if parent directory is BTRFS, fail if requesting
+ subvolume but no BTRFS. The paths could be different by the
+ trailing slash
*/
- cp = strtok (bhome, "/");
- while (cp) {
- /* Avoid turning a relative path into an absolute path.
- */
- if (bhome[0] == '/' || strlen (path) != 0) {
- strcat (path, "/");
- }
- strcat (path, cp);
- if (access (path, F_OK) != 0) {
- /* Check if parent directory is BTRFS, fail if requesting
- subvolume but no BTRFS. The paths cound be different by the
- trailing slash
- */
#if WITH_BTRFS
- if (subvolflg && (strlen(prefix_user_home) - (int)strlen(path)) <= 1) {
- char *btrfs_check = strdup(path);
-
- if (!btrfs_check) {
- fprintf (stderr,
- _("%s: error while duplicating string in BTRFS check %s\n"),
- Prog, path);
- fail_exit (E_HOMEDIR);
- }
- btrfs_check[strlen(path) - strlen(cp) - 1] = '\0';
- if (is_btrfs(btrfs_check) <= 0) {
- fprintf (stderr,
- _("%s: home directory \"%s\" must be mounted on BTRFS\n"),
- Prog, path);
- fail_exit (E_HOMEDIR);
- }
- // make subvolume to mount for user instead of directory
- if (btrfs_create_subvolume(path)) {
- fprintf (stderr,
- _("%s: failed to create BTRFS subvolume: %s\n"),
- Prog, path);
- fail_exit (E_HOMEDIR);
- }
- }
- else
+ if (subvolflg && (strlen(prefix_user_home) - (int)strlen(path)) <= 1) {
+ char *btrfs_check = strdup(path);
+
+ if (!btrfs_check) {
+ fprintf(stderr,
+ _("%s: error while duplicating string in BTRFS check %s\n"),
+ Prog, path);
+ fail_exit(E_HOMEDIR);
+ }
+ btrfs_check[strlen(path) - strlen(cp) - 1] = '\0';
+ if (is_btrfs(btrfs_check) <= 0) {
+ fprintf(stderr,
+ _("%s: home directory \"%s\" must be mounted on BTRFS\n"),
+ Prog, path);
+ fail_exit(E_HOMEDIR);
+ }
+ free(btrfs_check);
+ // make subvolume to mount for user instead of directory
+ if (btrfs_create_subvolume(path)) {
+ fprintf(stderr,
+ _("%s: failed to create BTRFS subvolume: %s\n"),
+ Prog, path);
+ fail_exit(E_HOMEDIR);
+ }
+ }
+ else
#endif
- if (mkdir (path, 0) != 0) {
- fprintf (stderr,
- _("%s: cannot create directory %s\n"),
- Prog, path);
+ if (mkdir(path, 0) != 0) {
+ fprintf(stderr, _("%s: cannot create directory %s\n"),
+ Prog, path);
#ifdef WITH_AUDIT
- audit_logger (AUDIT_ADD_USER, Prog,
- "adding home directory",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ audit_logger(AUDIT_ADD_USER, Prog, "adding home directory",
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif
- fail_exit (E_HOMEDIR);
+ fail_exit(E_HOMEDIR);
}
- if (chown (path, 0, 0) < 0) {
- fprintf (stderr,
- _("%s: warning: chown on `%s' failed: %m\n"),
- Prog, path);
- }
- if (chmod (path, 0755) < 0) {
- fprintf (stderr,
- _("%s: warning: chmod on `%s' failed: %m\n"),
- Prog, path);
- }
- }
- cp = strtok (NULL, "/");
+ if (chown(path, 0, 0) < 0) {
+ fprintf(stderr,
+ _("%s: warning: chown on `%s' failed: %m\n"),
+ Prog, path);
}
- free (bhome);
-
- (void) chown (prefix_user_home, user_id, user_gid);
- mode_t mode = getdef_num ("HOME_MODE",
- 0777 & ~getdef_num ("UMASK", GETDEF_DEFAULT_UMASK));
- if (chmod (prefix_user_home, mode)) {
- fprintf (stderr, _("%s: warning: chown on '%s' failed: %m\n"),
- Prog, path);
+ if (chmod(path, 0755) < 0) {
+ fprintf(stderr,
+ _("%s: warning: chmod on `%s' failed: %m\n"),
+ Prog, path);
}
- home_added = true;
+ }
+ free(bhome);
+
+ (void) chown(prefix_user_home, user_id, user_gid);
+ mode = getdef_num("HOME_MODE",
+ 0777 & ~getdef_num("UMASK", GETDEF_DEFAULT_UMASK));
+ if (chmod(prefix_user_home, mode)) {
+ fprintf(stderr, _("%s: warning: chown on '%s' failed: %m\n"),
+ Prog, path);
+ }
+ home_added = true;
#ifdef WITH_AUDIT
- audit_logger (AUDIT_ADD_USER, Prog,
- "adding home directory",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_SUCCESS);
+ audit_logger(AUDIT_ADD_USER, Prog, "adding home directory",
+ user_name, user_id, SHADOW_AUDIT_SUCCESS);
#endif
#ifdef WITH_SELINUX
- /* Reset SELinux to create files with default contexts */
- if (reset_selinux_file_context () != 0) {
- fprintf (stderr,
- _("%s: cannot reset SELinux file creation context\n"),
- Prog);
- fail_exit (E_HOMEDIR);
- }
-#endif
+ /* Reset SELinux to create files with default contexts */
+ if (reset_selinux_file_context() != 0) {
+ fprintf(stderr,
+ _("%s: cannot reset SELinux file creation context\n"),
+ Prog);
+ fail_exit(E_HOMEDIR);
}
+#endif
}
/*
@@ -2355,72 +2355,79 @@ static void create_home (void)
*/
static void create_mail (void)
{
- if (strcasecmp (create_mail_spool, "yes") == 0) {
- const char *spool;
- char *file;
- int fd;
- struct group *gr;
- gid_t gid;
- mode_t mode;
-
- spool = getdef_str ("MAIL_DIR");
+ int fd;
+ char *file;
+ gid_t gid;
+ mode_t mode;
+ const char *spool;
+ struct group *gr;
+
+ if (strcasecmp(create_mail_spool, "yes") != 0)
+ return;
+
+ spool = getdef_str("MAIL_DIR");
#ifdef MAIL_SPOOL_DIR
- if ((NULL == spool) && (getdef_str ("MAIL_FILE") == NULL)) {
- spool = MAIL_SPOOL_DIR;
- }
+ if ((NULL == spool) && (getdef_str("MAIL_FILE") == NULL)) {
+ spool = MAIL_SPOOL_DIR;
+ }
#endif /* MAIL_SPOOL_DIR */
- if (NULL == spool) {
- return;
- }
- file = alloca (strlen (prefix) + strlen (spool) + strlen (user_name) + 3);
- if (prefix[0])
- sprintf (file, "%s/%s/%s", prefix, spool, user_name);
- else
- sprintf (file, "%s/%s", spool, user_name);
+ if (NULL == spool) {
+ return;
+ }
+ if (prefix[0])
+ xasprintf(&file, "%s/%s/%s", prefix, spool, user_name);
+ else
+ xasprintf(&file, "%s/%s", spool, user_name);
#ifdef WITH_SELINUX
- if (set_selinux_file_context (file, S_IFREG) != 0) {
- fprintf (stderr,
- _("%s: cannot set SELinux context for mailbox file %s\n"),
- Prog, file);
- fail_exit (E_MAILBOXFILE);
- }
+ if (set_selinux_file_context(file, S_IFREG) != 0) {
+ fprintf(stderr,
+ _("%s: cannot set SELinux context for mailbox file %s\n"),
+ Prog, file);
+ fail_exit(E_MAILBOXFILE);
+ }
#endif
- fd = open (file, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0);
- if (fd < 0) {
- perror (_("Creating mailbox file"));
- return;
- }
+ fd = open(file, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0);
+ free(file);
- gr = prefix_getgrnam ("mail"); /* local, no need for xgetgrnam */
- if (NULL == gr) {
- fputs (_("Group 'mail' not found. Creating the user mailbox file with 0600 mode.\n"),
- stderr);
- gid = user_gid;
- mode = 0600;
- } else {
- gid = gr->gr_gid;
- mode = 0660;
- }
+ if (fd < 0) {
+ perror(_("Creating mailbox file"));
+ return;
+ }
- if ( (fchown (fd, user_id, gid) != 0)
- || (fchmod (fd, mode) != 0)) {
- perror (_("Setting mailbox file permissions"));
- }
+ gr = prefix_getgrnam("mail"); /* local, no need for xgetgrnam */
+ if (NULL == gr) {
+ fputs(_("Group 'mail' not found. Creating the user mailbox file with 0600 mode.\n"),
+ stderr);
+ gid = user_gid;
+ mode = 0600;
+ } else {
+ gid = gr->gr_gid;
+ mode = 0660;
+ }
+
+ if (fchown(fd, user_id, gid) != 0
+ || fchmod(fd, mode) != 0)
+ {
+ perror(_("Setting mailbox file permissions"));
+ }
- fsync (fd);
- close (fd);
+ if (fsync(fd) != 0) {
+ perror (_("Synchronize mailbox file"));
+ }
+ if (close(fd) != 0 && errno != EINTR) {
+ perror (_("Closing mailbox file"));
+ }
#ifdef WITH_SELINUX
- /* Reset SELinux to create files with default contexts */
- if (reset_selinux_file_context () != 0) {
- fprintf (stderr,
- _("%s: cannot reset SELinux file creation context\n"),
- Prog);
- fail_exit (E_MAILBOXFILE);
- }
-#endif
+ /* Reset SELinux to create files with default contexts */
+ if (reset_selinux_file_context() != 0) {
+ fprintf(stderr,
+ _("%s: cannot reset SELinux file creation context\n"),
+ Prog);
+ fail_exit(E_MAILBOXFILE);
}
+#endif
}
static void check_uid_range(int rflg, uid_t user_id)
@@ -2428,13 +2435,13 @@ static void check_uid_range(int rflg, uid_t user_id)
uid_t uid_min ;
uid_t uid_max ;
if (rflg) {
- uid_max = (uid_t)getdef_ulong("SYS_UID_MAX",getdef_ulong("UID_MIN",1000UL)-1);
+ uid_max = getdef_ulong("SYS_UID_MAX",getdef_ulong("UID_MIN",1000UL)-1);
if (user_id > uid_max) {
fprintf(stderr, _("%s warning: %s's uid %d is greater than SYS_UID_MAX %d\n"), Prog, user_name, user_id, uid_max);
}
}else{
- uid_min = (uid_t)getdef_ulong("UID_MIN", 1000UL);
- uid_max = (uid_t)getdef_ulong("UID_MAX", 6000UL);
+ uid_min = getdef_ulong("UID_MIN", 1000UL);
+ uid_max = getdef_ulong("UID_MAX", 6000UL);
if (uid_min <= uid_max) {
if (user_id < uid_min || user_id >uid_max)
fprintf(stderr, _("%s warning: %s's uid %d outside of the UID_MIN %d and UID_MAX %d range.\n"), Prog, user_name, user_id, uid_min, uid_max);
@@ -2461,10 +2468,6 @@ int main (int argc, char **argv)
unsigned long subuid_count = 0;
unsigned long subgid_count = 0;
- /*
- * Get my name so that I can use it to report errors.
- */
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -2476,17 +2479,17 @@ int main (int argc, char **argv)
prefix = process_prefix_flag("-P", argc, argv);
- OPENLOG ("useradd");
+ OPENLOG (Prog);
#ifdef WITH_AUDIT
audit_help_open ();
#endif
sys_ngroups = sysconf (_SC_NGROUPS_MAX);
- user_groups = (char **) xmalloc ((1 + sys_ngroups) * sizeof (char *));
+ user_groups = XMALLOC(1 + sys_ngroups, char *);
/*
* Initialize the list to be empty
*/
- user_groups[0] = (char *) 0;
+ user_groups[0] = NULL;
is_shadow_pwd = spw_file_present ();
@@ -2499,8 +2502,8 @@ int main (int argc, char **argv)
process_flags (argc, argv);
#ifdef ENABLE_SUBIDS
- uid_min = (uid_t) getdef_ulong ("UID_MIN", 1000UL);
- uid_max = (uid_t) getdef_ulong ("UID_MAX", 60000UL);
+ uid_min = getdef_ulong ("UID_MIN", 1000UL);
+ uid_max = getdef_ulong ("UID_MAX", 60000UL);
subuid_count = getdef_ulong ("SUB_UID_COUNT", 65536);
subgid_count = getdef_ulong ("SUB_GID_COUNT", 65536);
is_sub_uid = subuid_count > 0 && sub_uid_file_present () &&
@@ -2528,7 +2531,7 @@ int main (int argc, char **argv)
fail_exit (1);
}
- retval = pam_start ("useradd", pampw?pampw->pw_name:"root", &conv, &pamh);
+ retval = pam_start (Prog, pampw?pampw->pw_name:"root", &conv, &pamh);
}
if (PAM_SUCCESS == retval) {
@@ -2629,7 +2632,7 @@ int main (int argc, char **argv)
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
"adding user",
- user_name, (unsigned int) user_id,
+ user_name, user_id,
SHADOW_AUDIT_FAILURE);
#endif
fail_exit (E_UID_IN_USE);
@@ -2701,14 +2704,14 @@ int main (int argc, char **argv)
#ifdef WITH_SELINUX
if (Zflg) {
- if (set_seuser (user_name, user_selinux) != 0) {
+ if (set_seuser (user_name, user_selinux, user_selinux_range) != 0) {
fprintf (stderr,
_("%s: warning: the user name %s to %s SELinux user mapping failed.\n"),
Prog, user_name, user_selinux);
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
"adding SELinux user mapping",
- user_name, (unsigned int) user_id, 0);
+ user_name, user_id, 0);
#endif /* WITH_AUDIT */
fail_exit (E_SE_UPDATE);
}
@@ -2720,6 +2723,8 @@ int main (int argc, char **argv)
if (home_added) {
copy_tree (def_template, prefix_user_home, false, true,
(uid_t)-1, user_id, (gid_t)-1, user_gid);
+ copy_tree (def_usrtemplate, prefix_user_home, false, true,
+ (uid_t)-1, user_id, (gid_t)-1, user_gid);
} else {
fprintf (stderr,
_("%s: warning: the home directory %s already exists.\n"
@@ -2742,3 +2747,23 @@ int main (int argc, char **argv)
return E_SUCCESS;
}
+
+static FILE *
+fmkstemp(char *template)
+{
+ int fd;
+ FILE *fp;
+
+ fd = mkstemp(template);
+ if (fd == -1)
+ return NULL;
+
+ fp = fdopen(fd, "w");
+ if (fp == NULL) {
+ close(fd);
+ unlink(template);
+ return NULL;
+ }
+
+ return fp;
+}
diff --git a/src/userdel.c b/src/userdel.c
index 7012b0e..ff1f7dd 100644
--- a/src/userdel.c
+++ b/src/userdel.c
@@ -19,6 +19,8 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
+
+#include "alloc.h"
#ifdef ACCT_TOOLS_SETUID
#ifdef USE_PAM
#include "pam_defs.h"
@@ -50,6 +52,8 @@
#include "subordinateio.h"
#endif /* ENABLE_SUBIDS */
#include "shadowlog.h"
+#include "string/sprintf.h"
+
/*
* exit status values
@@ -68,7 +72,7 @@
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "userdel";
static char *user_name;
static uid_t user_id;
@@ -204,8 +208,7 @@ static void update_groups (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"deleting user from group",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_SUCCESS);
+ user_name, user_id, SHADOW_AUDIT_SUCCESS);
#endif /* WITH_AUDIT */
SYSLOG ((LOG_INFO, "delete '%s' from group '%s'\n",
user_name, ngrp->gr_name));
@@ -266,8 +269,7 @@ static void update_groups (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"deleting user from shadow group",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_SUCCESS);
+ user_name, user_id, SHADOW_AUDIT_SUCCESS);
#endif /* WITH_AUDIT */
SYSLOG ((LOG_INFO, "delete '%s' from shadow group '%s'\n",
user_name, nsgrp->sg_name));
@@ -526,8 +528,7 @@ static void fail_exit (int code)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"deleting user",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
exit (code);
@@ -548,8 +549,7 @@ static void open_files (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"locking password file",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
fail_exit (E_PW_UPDATE);
}
@@ -560,8 +560,7 @@ static void open_files (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"opening password file",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
fail_exit (E_PW_UPDATE);
}
@@ -573,8 +572,7 @@ static void open_files (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"locking shadow password file",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
fail_exit (E_PW_UPDATE);
}
@@ -586,8 +584,7 @@ static void open_files (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"opening shadow password file",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
fail_exit (E_PW_UPDATE);
}
@@ -599,8 +596,7 @@ static void open_files (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"locking group file",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
fail_exit (E_GRP_UPDATE);
}
@@ -610,8 +606,7 @@ static void open_files (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"opening group file",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
fail_exit (E_GRP_UPDATE);
}
@@ -624,8 +619,7 @@ static void open_files (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"locking shadow group file",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
fail_exit (E_GRP_UPDATE);
}
@@ -636,8 +630,7 @@ static void open_files (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"opening shadow group file",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
fail_exit (E_GRP_UPDATE);
}
@@ -652,8 +645,7 @@ static void open_files (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"locking subordinate user file",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
fail_exit (E_SUB_UID_UPDATE);
}
@@ -664,8 +656,7 @@ static void open_files (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"opening subordinate user file",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
fail_exit (E_SUB_UID_UPDATE);
}
@@ -678,8 +669,7 @@ static void open_files (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"locking subordinate group file",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
fail_exit (E_SUB_GID_UPDATE);
}
@@ -690,8 +680,7 @@ static void open_files (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"opening subordinate group file",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
fail_exit (E_SUB_GID_UPDATE);
}
@@ -738,8 +727,7 @@ static void update_user (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"deleting user entries",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_SUCCESS);
+ user_name, user_id, SHADOW_AUDIT_SUCCESS);
#endif /* WITH_AUDIT */
SYSLOG ((LOG_INFO, "delete user '%s'\n", user_name));
}
@@ -763,7 +751,7 @@ static void user_cancel (const char *user)
}
argv[0] = cmd;
argv[1] = user;
- argv[2] = (char *)0;
+ argv[2] = NULL;
(void) run_command (cmd, argv, NULL, &status);
}
@@ -802,11 +790,9 @@ static int is_owner (uid_t uid, const char *path)
static int remove_mailbox (void)
{
- const char *maildir;
- char* mailfile;
- int i;
- int errors = 0;
- size_t len;
+ int i, errors = 0;
+ char *mailfile;
+ const char *maildir;
maildir = getdef_str ("MAIL_DIR");
#ifdef MAIL_SPOOL_DIR
@@ -818,18 +804,11 @@ static int remove_mailbox (void)
return 0;
}
- len = strlen (prefix) + strlen (maildir) + strlen (user_name) + 2;
- mailfile = xmalloc (len);
-
if (prefix[0]) {
- (void) snprintf (mailfile, len, "%s/%s/%s",
- prefix, maildir, user_name);
- }
- else {
- (void) snprintf (mailfile, len, "%s/%s",
- maildir, user_name);
+ xasprintf(&mailfile, "%s/%s/%s", prefix, maildir, user_name);
+ } else {
+ xasprintf(&mailfile, "%s/%s", maildir, user_name);
}
- mailfile[len-1] = '\0';
if (access (mailfile, F_OK) != 0) {
if (ENOENT == errno) {
@@ -846,8 +825,7 @@ static int remove_mailbox (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"deleting mail file",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
free(mailfile);
return -1;
@@ -863,8 +841,7 @@ static int remove_mailbox (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"deleting mail file",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
errors = 1;
/* continue */
@@ -874,8 +851,7 @@ static int remove_mailbox (void)
{
audit_logger (AUDIT_DEL_USER, Prog,
"deleting mail file",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_SUCCESS);
+ user_name, user_id, SHADOW_AUDIT_SUCCESS);
}
#endif /* WITH_AUDIT */
free(mailfile);
@@ -892,8 +868,7 @@ static int remove_mailbox (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"deleting mail file",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
free(mailfile);
return 1;
@@ -909,8 +884,7 @@ static int remove_mailbox (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"deleting mail file",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
errors = 1;
/* continue */
@@ -920,8 +894,7 @@ static int remove_mailbox (void)
{
audit_logger (AUDIT_DEL_USER, Prog,
"deleting mail file",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_SUCCESS);
+ user_name, user_id, SHADOW_AUDIT_SUCCESS);
}
#endif /* WITH_AUDIT */
free(mailfile);
@@ -931,22 +904,19 @@ static int remove_mailbox (void)
#ifdef WITH_TCB
static int remove_tcbdir (const char *user_name, uid_t user_id)
{
- char *buf;
- int ret = 0;
- size_t buflen = (sizeof TCB_DIR) + strlen (user_name) + 2;
+ int ret = 0;
+ char *buf;
if (!getdef_bool ("USE_TCB")) {
return 0;
}
- buf = malloc (buflen);
- if (NULL == buf) {
- fprintf (stderr, _("%s: Can't allocate memory, "
- "tcb entry for %s not removed.\n"),
- Prog, user_name);
+ if (asprintf(&buf, TCB_DIR "/%s", user_name) == -1) {
+ fprintf(stderr,
+ _("%s: Can't allocate memory, tcb entry for %s not removed.\n"),
+ Prog, user_name);
return 1;
}
- snprintf (buf, buflen, TCB_DIR "/%s", user_name);
if (shadowtcb_drop_priv () == SHADOWTCB_FAILURE) {
fprintf (stderr, _("%s: Cannot drop privileges: %s\n"),
Prog, strerror (errno));
@@ -989,10 +959,6 @@ int main (int argc, char **argv)
#endif /* USE_PAM */
#endif /* ACCT_TOOLS_SETUID */
- /*
- * Get my name so that I can use it to report errors.
- */
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
(void) setlocale (LC_ALL, "");
@@ -1002,7 +968,7 @@ int main (int argc, char **argv)
process_root_flag ("-R", argc, argv);
prefix = process_prefix_flag ("-P", argc, argv);
- OPENLOG ("userdel");
+ OPENLOG (Prog);
#ifdef WITH_AUDIT
audit_help_open ();
#endif /* WITH_AUDIT */
@@ -1086,7 +1052,7 @@ int main (int argc, char **argv)
exit (E_PW_UPDATE);
}
- retval = pam_start ("userdel", pampw->pw_name, &conv, &pamh);
+ retval = pam_start (Prog, pampw->pw_name, &conv, &pamh);
}
if (PAM_SUCCESS == retval) {
@@ -1148,15 +1114,9 @@ int main (int argc, char **argv)
user_gid = pwd->pw_gid;
if (prefix[0]) {
-
- size_t len = strlen(prefix) + strlen(pwd->pw_dir) + 2;
- int wlen;
- user_home = xmalloc(len);
- wlen = snprintf(user_home, len, "%s/%s", prefix, pwd->pw_dir);
- assert (wlen == (int) len -1);
- }
- else {
- user_home = xstrdup (pwd->pw_dir);
+ xasprintf(&user_home, "%s/%s", prefix, pwd->pw_dir);
+ } else {
+ user_home = xstrdup(pwd->pw_dir);
}
pw_close();
}
@@ -1165,26 +1125,6 @@ int main (int argc, char **argv)
exit (E_NOTFOUND);
}
#endif /* WITH_TCB */
-#ifdef USE_NIS
-
- /*
- * Now make sure it isn't an NIS user.
- */
- if (__ispwNIS ()) {
- char *nis_domain;
- char *nis_master;
-
- fprintf (stderr,
- _("%s: user %s is a NIS user\n"), Prog, user_name);
- if ( !yp_get_default_domain (&nis_domain)
- && !yp_master (nis_domain, "passwd.byname", &nis_master)) {
- fprintf (stderr,
- _("%s: %s is the NIS master\n"),
- Prog, nis_master);
- }
- exit (E_NOTFOUND);
- }
-#endif /* USE_NIS */
/*
* Check to make certain the user isn't logged in.
* Note: This is a best effort basis. The user may log in between,
@@ -1290,8 +1230,7 @@ int main (int argc, char **argv)
{
audit_logger (AUDIT_DEL_USER, Prog,
"deleting home directory",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_SUCCESS);
+ user_name, user_id, SHADOW_AUDIT_SUCCESS);
}
#endif /* WITH_AUDIT */
}
@@ -1313,8 +1252,7 @@ int main (int argc, char **argv)
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
"removing SELinux user mapping",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
fail_exit (E_SE_UPDATE);
}
diff --git a/src/usermod.c b/src/usermod.c
index c1a5b2c..f889698 100644
--- a/src/usermod.c
+++ b/src/usermod.c
@@ -17,7 +17,9 @@
#include <fcntl.h>
#include <getopt.h>
#include <grp.h>
+#ifdef ENABLE_LASTLOG
#include <lastlog.h>
+#endif /* ENABLE_LASTLOG */
#include <pwd.h>
#ifdef ACCT_TOOLS_SETUID
#ifdef USE_PAM
@@ -25,14 +27,19 @@
#endif /* USE_PAM */
#endif /* ACCT_TOOLS_SETUID */
#include <stdio.h>
+#include <strings.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
+
+#include "alloc.h"
+#include "atoi/str2i.h"
#include "chkname.h"
#include "defines.h"
#include "faillog.h"
#include "getdef.h"
#include "groupio.h"
+#include "memzero.h"
#include "nscd.h"
#include "sssd.h"
#include "prototypes.h"
@@ -52,6 +59,9 @@
#include "tcbfuncs.h"
#endif
#include "shadowlog.h"
+#include "string/sprintf.h"
+#include "time/day_to_str.h"
+
/*
* exit status values
@@ -82,7 +92,7 @@
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "usermod";
static char *user_name;
static char *user_newname;
@@ -98,6 +108,7 @@ static char *user_newhome;
static char *user_shell;
#ifdef WITH_SELINUX
static const char *user_selinux = "";
+static const char *user_selinux_range = NULL;
#endif /* WITH_SELINUX */
static char *user_newshell;
static long user_expire;
@@ -163,14 +174,16 @@ static bool sub_gid_locked = false;
/* local function prototypes */
static int get_groups (char *);
-static /*@noreturn@*/void usage (int status);
+NORETURN static void usage (int status);
static void new_pwent (struct passwd *);
static void new_spent (struct spwd *);
-static /*@noreturn@*/void fail_exit (int);
-static void update_group (void);
+NORETURN static void fail_exit (int);
+static void update_group_file(void);
+static void update_group(const struct group *grp);
#ifdef SHADOWGRP
-static void update_gshadow (void);
+static void update_gshadow_file(void);
+static void update_gshadow(const struct sgrp *sgrp);
#endif
static void grp_update (void);
@@ -179,7 +192,9 @@ static void close_files (void);
static void open_files (void);
static void usr_update (void);
static void move_home (void);
+#ifdef ENABLE_LASTLOG
static void update_lastlog (void);
+#endif /* ENABLE_LASTLOG */
static void update_faillog (void);
#ifndef NO_MOVE_MAILBOX
@@ -198,14 +213,14 @@ extern int allow_bad_names;
static int get_groups (char *list)
{
char *cp;
- const struct group *grp;
+ struct group *grp;
int errors = 0;
int ngroups = 0;
/*
* Initialize the list to be empty
*/
- user_groups[0] = (char *) 0;
+ user_groups[0] = NULL;
if ('\0' == *list) {
return 0;
@@ -251,25 +266,11 @@ static int get_groups (char *list)
continue;
}
-#ifdef USE_NIS
- /*
- * Don't add this group if they are an NIS group. Tell the
- * user to go to the server for this group.
- */
- if (__isgrNIS ()) {
- fprintf (stderr,
- _("%s: group '%s' is a NIS group.\n"),
- Prog, grp->gr_name);
- gr_free ((struct group *)grp);
- continue;
- }
-#endif
-
if (ngroups == sys_ngroups) {
fprintf (stderr,
_("%s: too many groups specified (max %d).\n"),
Prog, ngroups);
- gr_free ((struct group *)grp);
+ gr_free (grp);
break;
}
@@ -277,10 +278,10 @@ static int get_groups (char *list)
* Add the group name to the user's list of groups.
*/
user_groups[ngroups++] = xstrdup (grp->gr_name);
- gr_free ((struct group *)grp);
+ gr_free (grp);
} while (NULL != list);
- user_groups[ngroups] = (char *) 0;
+ user_groups[ngroups] = NULL;
/*
* Any errors in finding group names are fatal
@@ -307,21 +308,28 @@ static struct ulong_range getulong_range(const char *str)
errno = 0;
first = strtoll(str, &pos, 10);
- if (('\0' == *str) || ('-' != *pos ) || (ERANGE == errno) ||
- (first != (unsigned long int)first))
+ if (('\0' == *str) || ('-' != *pos ) || (0 != errno) ||
+ (first != (unsigned long)first))
goto out;
errno = 0;
last = strtoll(pos + 1, &pos, 10);
- if (('\0' != *pos ) || (ERANGE == errno) ||
- (last != (unsigned long int)last))
+ if (('\0' != *pos ) || (0 != errno) ||
+ (last != (unsigned long)last))
goto out;
if (first > last)
goto out;
- result.first = (unsigned long int)first;
- result.last = (unsigned long int)last;
+ /*
+ * uid_t in linux is an unsigned int, anything over this is an invalid
+ * range will be later refused anyway by get_map_ranges().
+ */
+ if (first > UINT_MAX || last > UINT_MAX)
+ goto out;
+
+ result.first = (unsigned long)first;
+ result.last = (unsigned long)last;
out:
return result;
}
@@ -342,7 +350,7 @@ static int prepend_range(const char *str, struct ulong_range_list_entry **head)
if (range.first > range.last)
return 0;
- entry = malloc(sizeof(*entry));
+ entry = MALLOC(1, struct ulong_range_list_entry);
if (!entry) {
fprintf (stderr,
_("%s: failed to allocate memory: %s\n"),
@@ -359,7 +367,9 @@ static int prepend_range(const char *str, struct ulong_range_list_entry **head)
/*
* usage - display usage message and exit
*/
-static /*@noreturn@*/void usage (int status)
+NORETURN
+static void
+usage (int status)
{
FILE *usageout = (E_SUCCESS != status) ? stderr : stdout;
(void) fprintf (usageout,
@@ -401,6 +411,7 @@ static /*@noreturn@*/void usage (int status)
#endif /* ENABLE_SUBIDS */
#ifdef WITH_SELINUX
(void) fputs (_(" -Z, --selinux-user SEUSER new SELinux user mapping for the user account\n"), usageout);
+ (void) fputs (_(" --selinux-range SERANGE new SELinux MLS range for the user account\n"), usageout);
#endif /* WITH_SELINUX */
(void) fputs ("\n", usageout);
exit (status);
@@ -413,20 +424,17 @@ static /*@noreturn@*/void usage (int status)
static char *new_pw_passwd (char *pw_pass)
{
if (Lflg && ('!' != pw_pass[0])) {
- char *buf = xmalloc (strlen (pw_pass) + 2);
+ char *buf = XMALLOC(strlen(pw_pass) + 2, char);
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
- "updating passwd",
- user_newname, (unsigned int) user_newid, 0);
+ "updating passwd", user_newname, user_newid, 0);
#endif
SYSLOG ((LOG_INFO, "lock user '%s' password", user_newname));
strcpy (buf, "!");
strcat (buf, pw_pass);
pw_pass = buf;
} else if (Uflg && pw_pass[0] == '!') {
- char *s;
-
if (pw_pass[1] == '\0') {
fprintf (stderr,
_("%s: unlocking the user's password would result in a passwordless account.\n"
@@ -437,20 +445,14 @@ static char *new_pw_passwd (char *pw_pass)
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
- "updating password",
- user_newname, (unsigned int) user_newid, 0);
+ "updating password", user_newname, user_newid, 0);
#endif
SYSLOG ((LOG_INFO, "unlock user '%s' password", user_newname));
- s = pw_pass;
- while ('\0' != *s) {
- *s = *(s + 1);
- s++;
- }
+ memmove(pw_pass, pw_pass + 1, strlen(pw_pass));
} else if (pflg) {
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
- "changing password",
- user_newname, (unsigned int) user_newid, 1);
+ "changing password", user_newname, user_newid, 1);
#endif
SYSLOG ((LOG_INFO, "change user '%s' password", user_newname));
pw_pass = xstrdup (user_pass);
@@ -479,8 +481,7 @@ static void new_pwent (struct passwd *pwent)
}
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
- "changing name",
- user_newname, (unsigned int) user_newid, 1);
+ "changing name", user_newname, user_newid, 1);
#endif
SYSLOG ((LOG_INFO,
"change user name '%s' to '%s'",
@@ -500,8 +501,7 @@ static void new_pwent (struct passwd *pwent)
if (uflg) {
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
- "changing uid",
- user_newname, (unsigned int) user_newid, 1);
+ "changing uid", user_newname, user_newid, 1);
#endif
SYSLOG ((LOG_INFO,
"change user '%s' UID from '%d' to '%d'",
@@ -512,7 +512,7 @@ static void new_pwent (struct passwd *pwent)
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
"changing primary group",
- user_newname, (unsigned int) user_newid, 1);
+ user_newname, user_newid, 1);
#endif
SYSLOG ((LOG_INFO,
"change user '%s' GID from '%d' to '%d'",
@@ -522,8 +522,7 @@ static void new_pwent (struct passwd *pwent)
if (cflg) {
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
- "changing comment",
- user_newname, (unsigned int) user_newid, 1);
+ "changing comment", user_newname, user_newid, 1);
#endif
pwent->pw_gecos = user_newcomment;
}
@@ -532,7 +531,7 @@ static void new_pwent (struct passwd *pwent)
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
"changing home directory",
- user_newname, (unsigned int) user_newid, 1);
+ user_newname, user_newid, 1);
#endif
SYSLOG ((LOG_INFO,
"change user '%s' home from '%s' to '%s'",
@@ -549,7 +548,7 @@ static void new_pwent (struct passwd *pwent)
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
"changing user shell",
- user_newname, (unsigned int) user_newid, 1);
+ user_newname, user_newid, 1);
#endif
SYSLOG ((LOG_INFO,
"change user '%s' shell from '%s' to '%s'",
@@ -580,7 +579,7 @@ static void new_spent (struct spwd *spent)
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
"changing inactive days",
- user_newname, (unsigned int) user_newid, 1);
+ user_newname, user_newid, 1);
#endif
SYSLOG ((LOG_INFO,
"change user '%s' inactive from '%ld' to '%ld'",
@@ -590,12 +589,13 @@ static void new_spent (struct spwd *spent)
if (eflg) {
/* log dates rather than numbers of days. */
char new_exp[16], old_exp[16];
- date_to_str (sizeof(new_exp), new_exp, user_newexpire * DAY);
- date_to_str (sizeof(old_exp), old_exp, user_expire * DAY);
+
+ DAY_TO_STR(new_exp, user_newexpire);
+ DAY_TO_STR(old_exp, user_expire);
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
"changing expiration date",
- user_newname, (unsigned int) user_newid, 1);
+ user_newname, user_newid, 1);
#endif
SYSLOG ((LOG_INFO,
"change user '%s' expiration from '%s' to '%s'",
@@ -615,7 +615,7 @@ static void new_spent (struct spwd *spent)
spent->sp_pwdp = new_pw_passwd (spent->sp_pwdp);
if (pflg) {
- spent->sp_lstchg = (long) gettime () / SCALE;
+ spent->sp_lstchg = gettime () / DAY;
if (0 == spent->sp_lstchg) {
/* Better disable aging than requiring a password
* change. */
@@ -627,7 +627,9 @@ static void new_spent (struct spwd *spent)
/*
* fail_exit - exit with an error code after unlocking files
*/
-static /*@noreturn@*/void fail_exit (int code)
+NORETURN
+static void
+fail_exit (int code)
{
if (gr_locked) {
if (gr_unlock () == 0) {
@@ -685,263 +687,277 @@ static /*@noreturn@*/void fail_exit (int code)
}
-static void update_group (void)
+static void
+update_group_file(void)
{
- bool is_member;
- bool was_member;
- bool changed;
- const struct group *grp;
- struct group *ngrp;
-
- changed = false;
+ const struct group *grp;
/*
* Scan through the entire group file looking for the groups that
* the user is a member of.
*/
- while ((grp = gr_next ()) != NULL) {
- /*
- * See if the user specified this group as one of their
- * concurrent groups.
- */
- was_member = is_on_list (grp->gr_mem, user_name);
- is_member = Gflg && ( (was_member && aflg)
- || is_on_list (user_groups, grp->gr_name));
+ while ((grp = gr_next()) != NULL)
+ update_group(grp);
+}
- if (!was_member && !is_member) {
- continue;
- }
- /*
- * If rflg+Gflg is passed in AKA -rG invert is_member flag, which removes
- * mentioned groups while leaving the others.
- */
- if (Gflg && rflg) {
- is_member = !is_member;
- }
+static void
+update_group(const struct group *grp)
+{
+ bool changed;
+ bool is_member;
+ bool was_member;
+ struct group *ngrp;
- ngrp = __gr_dup (grp);
- if (NULL == ngrp) {
- fprintf (stderr,
- _("%s: Out of memory. Cannot update %s.\n"),
- Prog, gr_dbname ());
- fail_exit (E_GRP_UPDATE);
- }
+ changed = false;
- if (was_member) {
- if ((!Gflg) || is_member) {
- /* User was a member and is still a member
- * of this group.
- * But the user might have been renamed.
- */
- if (lflg) {
- ngrp->gr_mem = del_list (ngrp->gr_mem,
- user_name);
- ngrp->gr_mem = add_list (ngrp->gr_mem,
- user_newname);
- changed = true;
-#ifdef WITH_AUDIT
- audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
- "changing group member",
- user_newname, AUDIT_NO_ID, 1);
-#endif
- SYSLOG ((LOG_INFO,
- "change '%s' to '%s' in group '%s'",
- user_name, user_newname,
- ngrp->gr_name));
- }
- } else {
- /* User was a member but is no more a
- * member of this group.
- */
- ngrp->gr_mem = del_list (ngrp->gr_mem, user_name);
+ /*
+ * See if the user specified this group as one of their
+ * concurrent groups.
+ */
+ was_member = is_on_list (grp->gr_mem, user_name);
+ is_member = Gflg && ( (was_member && aflg)
+ || is_on_list (user_groups, grp->gr_name));
+
+ if (!was_member && !is_member)
+ return;
+
+ /*
+ * If rflg+Gflg is passed in AKA -rG invert is_member flag, which removes
+ * mentioned groups while leaving the others.
+ */
+ if (Gflg && rflg) {
+ is_member = !is_member;
+ }
+
+ ngrp = __gr_dup (grp);
+ if (NULL == ngrp) {
+ fprintf (stderr,
+ _("%s: Out of memory. Cannot update %s.\n"),
+ Prog, gr_dbname ());
+ fail_exit (E_GRP_UPDATE);
+ }
+
+ if (was_member) {
+ if ((!Gflg) || is_member) {
+ /* User was a member and is still a member
+ * of this group.
+ * But the user might have been renamed.
+ */
+ if (lflg) {
+ ngrp->gr_mem = del_list (ngrp->gr_mem,
+ user_name);
+ ngrp->gr_mem = add_list (ngrp->gr_mem,
+ user_newname);
changed = true;
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
- "removing group member",
- user_name, AUDIT_NO_ID, 1);
+ "changing group member",
+ user_newname, AUDIT_NO_ID, 1);
#endif
SYSLOG ((LOG_INFO,
- "delete '%s' from group '%s'",
- user_name, ngrp->gr_name));
+ "change '%s' to '%s' in group '%s'",
+ user_name, user_newname,
+ ngrp->gr_name));
}
- } else if (is_member) {
- /* User was not a member but is now a member this
- * group.
+ } else {
+ /* User was a member but is no more a
+ * member of this group.
*/
- ngrp->gr_mem = add_list (ngrp->gr_mem, user_newname);
+ ngrp->gr_mem = del_list (ngrp->gr_mem, user_name);
changed = true;
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
- "adding user to group",
- user_name, AUDIT_NO_ID, 1);
+ "removing group member",
+ user_name, AUDIT_NO_ID, 1);
#endif
- SYSLOG ((LOG_INFO, "add '%s' to group '%s'",
- user_newname, ngrp->gr_name));
- }
- if (!changed) {
- continue;
- }
-
- changed = false;
- if (gr_update (ngrp) == 0) {
- fprintf (stderr,
- _("%s: failed to prepare the new %s entry '%s'\n"),
- Prog, gr_dbname (), ngrp->gr_name);
- SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", gr_dbname (), ngrp->gr_name));
- fail_exit (E_GRP_UPDATE);
+ SYSLOG ((LOG_INFO,
+ "delete '%s' from group '%s'",
+ user_name, ngrp->gr_name));
}
+ } else if (is_member) {
+ /* User was not a member but is now a member this
+ * group.
+ */
+ ngrp->gr_mem = add_list (ngrp->gr_mem, user_newname);
+ changed = true;
+#ifdef WITH_AUDIT
+ audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
+ "adding user to group",
+ user_name, AUDIT_NO_ID, 1);
+#endif
+ SYSLOG ((LOG_INFO, "add '%s' to group '%s'",
+ user_newname, ngrp->gr_name));
+ }
+ if (!changed)
+ goto free_ngrp;
- gr_free(ngrp);
+ if (gr_update (ngrp) == 0) {
+ fprintf (stderr,
+ _("%s: failed to prepare the new %s entry '%s'\n"),
+ Prog, gr_dbname (), ngrp->gr_name);
+ SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", gr_dbname (), ngrp->gr_name));
+ fail_exit (E_GRP_UPDATE);
}
+
+free_ngrp:
+ gr_free(ngrp);
}
+
#ifdef SHADOWGRP
-static void update_gshadow (void)
+static void
+update_gshadow_file(void)
{
- bool is_member;
- bool was_member;
- bool was_admin;
- bool changed;
- const struct sgrp *sgrp;
- struct sgrp *nsgrp;
-
- changed = false;
+ const struct sgrp *sgrp;
/*
* Scan through the entire shadow group file looking for the groups
* that the user is a member of.
*/
- while ((sgrp = sgr_next ()) != NULL) {
+ while ((sgrp = sgr_next()) != NULL)
+ update_gshadow(sgrp);
+}
+#endif /* SHADOWGRP */
- /*
- * See if the user was a member of this group
- */
- was_member = is_on_list (sgrp->sg_mem, user_name);
- /*
- * See if the user was an administrator of this group
- */
- was_admin = is_on_list (sgrp->sg_adm, user_name);
+#ifdef SHADOWGRP
+static void
+update_gshadow(const struct sgrp *sgrp)
+{
+ bool changed;
+ bool is_member;
+ bool was_member;
+ bool was_admin;
+ struct sgrp *nsgrp;
- /*
- * See if the user specified this group as one of their
- * concurrent groups.
- */
- is_member = Gflg && ( (was_member && aflg)
- || is_on_list (user_groups, sgrp->sg_name));
+ changed = false;
- if (!was_member && !was_admin && !is_member) {
- continue;
- }
+ /*
+ * See if the user was a member of this group
+ */
+ was_member = is_on_list (sgrp->sg_mem, user_name);
- /*
- * If rflg+Gflg is passed in AKA -rG invert is_member, to remove targeted
- * groups while leaving the user apart of groups not mentioned
- */
- if (Gflg && rflg) {
- is_member = !is_member;
- }
+ /*
+ * See if the user was an administrator of this group
+ */
+ was_admin = is_on_list (sgrp->sg_adm, user_name);
- nsgrp = __sgr_dup (sgrp);
- if (NULL == nsgrp) {
- fprintf (stderr,
- _("%s: Out of memory. Cannot update %s.\n"),
- Prog, sgr_dbname ());
- fail_exit (E_GRP_UPDATE);
- }
+ /*
+ * See if the user specified this group as one of their
+ * concurrent groups.
+ */
+ is_member = Gflg && ( (was_member && aflg)
+ || is_on_list (user_groups, sgrp->sg_name));
- if (was_admin && lflg) {
- /* User was an admin of this group but the user
- * has been renamed.
- */
- nsgrp->sg_adm = del_list (nsgrp->sg_adm, user_name);
- nsgrp->sg_adm = add_list (nsgrp->sg_adm, user_newname);
- changed = true;
-#ifdef WITH_AUDIT
- audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
- "changing admin name in shadow group",
- user_name, AUDIT_NO_ID, 1);
-#endif
- SYSLOG ((LOG_INFO,
- "change admin '%s' to '%s' in shadow group '%s'",
- user_name, user_newname, nsgrp->sg_name));
- }
-
- if (was_member) {
- if ((!Gflg) || is_member) {
- /* User was a member and is still a member
- * of this group.
- * But the user might have been renamed.
- */
- if (lflg) {
- nsgrp->sg_mem = del_list (nsgrp->sg_mem,
- user_name);
- nsgrp->sg_mem = add_list (nsgrp->sg_mem,
- user_newname);
- changed = true;
+ if (!was_member && !was_admin && !is_member)
+ return;
+
+ /*
+ * If rflg+Gflg is passed in AKA -rG invert is_member, to remove targeted
+ * groups while leaving the user apart of groups not mentioned
+ */
+ if (Gflg && rflg) {
+ is_member = !is_member;
+ }
+
+ nsgrp = __sgr_dup (sgrp);
+ if (NULL == nsgrp) {
+ fprintf (stderr,
+ _("%s: Out of memory. Cannot update %s.\n"),
+ Prog, sgr_dbname ());
+ fail_exit (E_GRP_UPDATE);
+ }
+
+ if (was_admin && lflg) {
+ /* User was an admin of this group but the user
+ * has been renamed.
+ */
+ nsgrp->sg_adm = del_list (nsgrp->sg_adm, user_name);
+ nsgrp->sg_adm = add_list (nsgrp->sg_adm, user_newname);
+ changed = true;
#ifdef WITH_AUDIT
- audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
- "changing member in shadow group",
- user_name, AUDIT_NO_ID, 1);
+ audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
+ "changing admin name in shadow group",
+ user_name, AUDIT_NO_ID, 1);
#endif
- SYSLOG ((LOG_INFO,
- "change '%s' to '%s' in shadow group '%s'",
- user_name, user_newname,
- nsgrp->sg_name));
- }
- } else {
- /* User was a member but is no more a
- * member of this group.
- */
- nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name);
+ SYSLOG ((LOG_INFO,
+ "change admin '%s' to '%s' in shadow group '%s'",
+ user_name, user_newname, nsgrp->sg_name));
+ }
+
+ if (was_member) {
+ if ((!Gflg) || is_member) {
+ /* User was a member and is still a member
+ * of this group.
+ * But the user might have been renamed.
+ */
+ if (lflg) {
+ nsgrp->sg_mem = del_list (nsgrp->sg_mem,
+ user_name);
+ nsgrp->sg_mem = add_list (nsgrp->sg_mem,
+ user_newname);
changed = true;
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
- "removing user from shadow group",
- user_name, AUDIT_NO_ID, 1);
+ "changing member in shadow group",
+ user_name, AUDIT_NO_ID, 1);
#endif
SYSLOG ((LOG_INFO,
- "delete '%s' from shadow group '%s'",
- user_name, nsgrp->sg_name));
+ "change '%s' to '%s' in shadow group '%s'",
+ user_name, user_newname,
+ nsgrp->sg_name));
}
- } else if (is_member) {
- /* User was not a member but is now a member this
- * group.
+ } else {
+ /* User was a member but is no more a
+ * member of this group.
*/
- nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_newname);
+ nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name);
changed = true;
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
- "adding user to shadow group",
- user_newname, AUDIT_NO_ID, 1);
+ "removing user from shadow group",
+ user_name, AUDIT_NO_ID, 1);
#endif
- SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'",
- user_newname, nsgrp->sg_name));
- }
- if (!changed) {
- continue;
+ SYSLOG ((LOG_INFO,
+ "delete '%s' from shadow group '%s'",
+ user_name, nsgrp->sg_name));
}
-
- changed = false;
-
- /*
- * Update the group entry to reflect the changes.
+ } else if (is_member) {
+ /* User was not a member but is now a member this
+ * group.
*/
- if (sgr_update (nsgrp) == 0) {
- fprintf (stderr,
- _("%s: failed to prepare the new %s entry '%s'\n"),
- Prog, sgr_dbname (), nsgrp->sg_name);
- SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'",
- sgr_dbname (), nsgrp->sg_name));
- fail_exit (E_GRP_UPDATE);
- }
+ nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_newname);
+ changed = true;
+#ifdef WITH_AUDIT
+ audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
+ "adding user to shadow group",
+ user_newname, AUDIT_NO_ID, 1);
+#endif
+ SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'",
+ user_newname, nsgrp->sg_name));
+ }
+ if (!changed)
+ goto free_nsgrp;
- free (nsgrp);
+ /*
+ * Update the group entry to reflect the changes.
+ */
+ if (sgr_update (nsgrp) == 0) {
+ fprintf (stderr,
+ _("%s: failed to prepare the new %s entry '%s'\n"),
+ Prog, sgr_dbname (), nsgrp->sg_name);
+ SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'",
+ sgr_dbname (), nsgrp->sg_name));
+ fail_exit (E_GRP_UPDATE);
}
+
+free_nsgrp:
+ free (nsgrp);
}
#endif /* SHADOWGRP */
+
/*
* grp_update - add user to secondary group set
*
@@ -950,10 +966,10 @@ static void update_gshadow (void)
*/
static void grp_update (void)
{
- update_group ();
+ update_group_file();
#ifdef SHADOWGRP
if (is_shadow_grp) {
- update_gshadow ();
+ update_gshadow_file();
}
#endif
}
@@ -967,7 +983,6 @@ static void grp_update (void)
*/
static void process_flags (int argc, char **argv)
{
- const struct group *grp;
struct stat st;
bool anyflag = false;
@@ -978,6 +993,7 @@ static void process_flags (int argc, char **argv)
int c;
static struct option long_options[] = {
{"append", no_argument, NULL, 'a'},
+ {"badname", no_argument, NULL, 'b'},
{"badnames", no_argument, NULL, 'b'},
{"comment", required_argument, NULL, 'c'},
{"home", required_argument, NULL, 'd'},
@@ -1000,11 +1016,12 @@ static void process_flags (int argc, char **argv)
#ifdef ENABLE_SUBIDS
{"add-subuids", required_argument, NULL, 'v'},
{"del-subuids", required_argument, NULL, 'V'},
- {"add-subgids", required_argument, NULL, 'w'},
- {"del-subgids", required_argument, NULL, 'W'},
+ {"add-subgids", required_argument, NULL, 'w'},
+ {"del-subgids", required_argument, NULL, 'W'},
#endif /* ENABLE_SUBIDS */
#ifdef WITH_SELINUX
- {"selinux-user", required_argument, NULL, 'Z'},
+ {"selinux-user", required_argument, NULL, 'Z'},
+ {"selinux-range", required_argument, NULL, 202},
#endif /* WITH_SELINUX */
{NULL, 0, NULL, '\0'}
};
@@ -1058,11 +1075,10 @@ static void process_flags (int argc, char **argv)
Prog, optarg);
exit (E_BAD_ARG);
}
- user_newexpire *= DAY / SCALE;
eflg = true;
break;
case 'f':
- if ( (getlong (optarg, &user_newinactive) == 0)
+ if ( (str2sl(&user_newinactive, optarg) == -1)
|| (user_newinactive < -1)) {
fprintf (stderr,
_("%s: invalid numeric argument '%s'\n"),
@@ -1072,7 +1088,10 @@ static void process_flags (int argc, char **argv)
fflg = true;
break;
case 'g':
- grp = getgr_nam_gid (optarg);
+ {
+ struct group *grp;
+
+ grp = prefix_getgr_nam_gid (optarg);
if (NULL == grp) {
fprintf (stderr,
_("%s: group '%s' does not exist\n"),
@@ -1083,6 +1102,7 @@ static void process_flags (int argc, char **argv)
gflg = true;
gr_free (grp);
break;
+ }
case 'G':
if (get_groups (optarg) != 0) {
exit (E_NOTFOUND);
@@ -1146,7 +1166,7 @@ static void process_flags (int argc, char **argv)
sflg = true;
break;
case 'u':
- if ( (get_uid (optarg, &user_newid) ==0)
+ if ( (get_uid(optarg, &user_newid) == -1)
|| (user_newid == (uid_t)-1)) {
fprintf (stderr,
_("%s: invalid user ID '%s'\n"),
@@ -1214,6 +1234,9 @@ static void process_flags (int argc, char **argv)
exit (E_BAD_ARG);
}
break;
+ case 202:
+ user_selinux_range = optarg;
+ break;
#endif /* WITH_SELINUX */
default:
usage (E_USAGE);
@@ -1258,46 +1281,16 @@ static void process_flags (int argc, char **argv)
user_newgid = user_gid;
}
if (prefix[0]) {
- size_t len = strlen(prefix) + strlen(user_home) + 2;
- int wlen;
- prefix_user_home = xmalloc(len);
- wlen = snprintf(prefix_user_home, len, "%s/%s", prefix, user_home);
- assert (wlen == (int) len -1);
+ xasprintf(&prefix_user_home, "%s/%s", prefix, user_home);
if (user_newhome) {
- len = strlen(prefix) + strlen(user_newhome) + 2;
- prefix_user_newhome = xmalloc(len);
- wlen = snprintf(prefix_user_newhome, len, "%s/%s", prefix, user_newhome);
- assert (wlen == (int) len -1);
+ xasprintf(&prefix_user_newhome, "%s/%s",
+ prefix, user_newhome);
}
-
- }
- else {
+ } else {
prefix_user_home = user_home;
prefix_user_newhome = user_newhome;
}
-#ifdef USE_NIS
- /*
- * Now make sure it isn't an NIS user.
- */
- if (__ispwNIS ()) {
- char *nis_domain;
- char *nis_master;
-
- fprintf (stderr,
- _("%s: user %s is a NIS user\n"),
- Prog, user_name);
-
- if ( !yp_get_default_domain (&nis_domain)
- && !yp_master (nis_domain, "passwd.byname", &nis_master)) {
- fprintf (stderr,
- _("%s: %s is the NIS master\n"),
- Prog, nis_master);
- }
- exit (E_NOTFOUND);
- }
-#endif
-
{
const struct spwd *spwd = NULL;
/* local, no need for xgetspnam */
@@ -1354,6 +1347,15 @@ static void process_flags (int argc, char **argv)
usage (E_USAGE);
}
+#ifdef WITH_SELINUX
+ if (user_selinux_range && !Zflg) {
+ fprintf (stderr,
+ _("%s: %s flag is only allowed with the %s flag\n"),
+ Prog, "--selinux-range", "--selinux-user");
+ usage (E_USAGE);
+ }
+#endif /* WITH_SELINUX */
+
if (user_newid == user_id) {
uflg = false;
oflg = false;
@@ -1723,7 +1725,7 @@ static void usr_update (void)
* a shadowed password
* + aging information is requested
*/
- memset (&spent, 0, sizeof spent);
+ bzero(&spent, sizeof spent);
spent.sp_namp = user_name;
/* The user explicitly asked for a shadow feature.
@@ -1732,7 +1734,7 @@ static void usr_update (void)
spent.sp_pwdp = xstrdup (pwent.pw_passwd);
pwent.pw_passwd = xstrdup (SHADOW_PASSWD_STRING);
- spent.sp_lstchg = (long) gettime () / SCALE;
+ spent.sp_lstchg = gettime () / DAY;
if (0 == spent.sp_lstchg) {
/* Better disable aging than
* requiring a password change */
@@ -1819,7 +1821,7 @@ static void move_home (void)
if (uflg || gflg) {
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
"changing home directory owner",
- user_newname, (unsigned int) user_newid, 1);
+ user_newname, user_newid, 1);
}
#endif
@@ -1838,8 +1840,7 @@ static void move_home (void)
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
"moving home directory",
- user_newname, (unsigned int) user_newid,
- 1);
+ user_newname, user_newid, 1);
#endif
return;
} else {
@@ -1869,7 +1870,7 @@ static void move_home (void)
Prog,
"moving home directory",
user_newname,
- (unsigned int) user_newid,
+ user_newid,
1);
#endif
return;
@@ -1897,6 +1898,7 @@ static void move_home (void)
* left alone in case the UID was shared. It doesn't hurt anything
* to just leave it be.
*/
+#ifdef ENABLE_LASTLOG
static void update_lastlog (void)
{
struct lastlog ll;
@@ -1909,7 +1911,7 @@ static void update_lastlog (void)
return;
}
- max_uid = (uid_t) getdef_ulong ("LASTLOG_UID_MAX", 0xFFFFFFFFUL);
+ max_uid = getdef_ulong ("LASTLOG_UID_MAX", 0xFFFFFFFFUL);
if (user_newid > max_uid) {
/* do not touch lastlog for large uids */
return;
@@ -1928,7 +1930,7 @@ static void update_lastlog (void)
&& (read (fd, &ll, sizeof ll) == (ssize_t) sizeof ll)) {
/* Copy the old entry to its new location */
if ( (lseek (fd, off_newuid, SEEK_SET) != off_newuid)
- || (write (fd, &ll, sizeof ll) != (ssize_t) sizeof ll)
+ || (write_full(fd, &ll, sizeof ll) == -1)
|| (fsync (fd) != 0)) {
fprintf (stderr,
_("%s: failed to copy the lastlog entry of user %lu to user %lu: %s\n"),
@@ -1944,7 +1946,7 @@ static void update_lastlog (void)
/* Reset the new uid's lastlog entry */
memzero (&ll, sizeof (ll));
if ( (lseek (fd, off_newuid, SEEK_SET) != off_newuid)
- || (write (fd, &ll, sizeof ll) != (ssize_t) sizeof ll)
+ || (write_full(fd, &ll, sizeof ll) == -1)
|| (fsync (fd) != 0)) {
fprintf (stderr,
_("%s: failed to copy the lastlog entry of user %lu to user %lu: %s\n"),
@@ -1953,8 +1955,13 @@ static void update_lastlog (void)
}
}
- (void) close (fd);
+ if (close (fd) != 0 && errno != EINTR) {
+ fprintf (stderr,
+ _("%s: failed to copy the lastlog entry of user %ju to user %ju: %s\n"),
+ Prog, (uintmax_t) user_id, (uintmax_t) user_newid, strerror (errno));
+ }
}
+#endif /* ENABLE_LASTLOG */
/*
* update_faillog - update the faillog file
@@ -1984,10 +1991,10 @@ static void update_faillog (void)
}
if ( (lseek (fd, off_uid, SEEK_SET) == off_uid)
- && (read (fd, (char *) &fl, sizeof fl) == (ssize_t) sizeof fl)) {
+ && (read (fd, &fl, sizeof fl) == (ssize_t) sizeof fl)) {
/* Copy the old entry to its new location */
if ( (lseek (fd, off_newuid, SEEK_SET) != off_newuid)
- || (write (fd, &fl, sizeof fl) != (ssize_t) sizeof fl)
+ || (write_full(fd, &fl, sizeof fl) == -1)
|| (fsync (fd) != 0)) {
fprintf (stderr,
_("%s: failed to copy the faillog entry of user %lu to user %lu: %s\n"),
@@ -2003,7 +2010,8 @@ static void update_faillog (void)
/* Reset the new uid's faillog entry */
memzero (&fl, sizeof (fl));
if ( (lseek (fd, off_newuid, SEEK_SET) != off_newuid)
- || (write (fd, &fl, sizeof fl) != (ssize_t) sizeof fl)) {
+ || (write_full(fd, &fl, sizeof fl) == -1))
+ {
fprintf (stderr,
_("%s: failed to copy the faillog entry of user %lu to user %lu: %s\n"),
Prog, (unsigned long) user_id, (unsigned long) user_newid, strerror (errno));
@@ -2011,7 +2019,11 @@ static void update_faillog (void)
}
}
- (void) close (fd);
+ if (close (fd) != 0 && errno != EINTR) {
+ fprintf (stderr,
+ _("%s: failed to copy the faillog entry of user %ju to user %ju: %s\n"),
+ Prog, (uintmax_t) user_id, (uintmax_t) user_newid, strerror (errno));
+ }
}
#ifndef NO_MOVE_MAILBOX
@@ -2024,12 +2036,10 @@ static void update_faillog (void)
*/
static void move_mailbox (void)
{
- const char *maildir;
- char* mailfile;
- char* newmailfile;
- int fd;
- struct stat st;
- size_t len;
+ int fd;
+ char *mailfile;
+ const char *maildir;
+ struct stat st;
maildir = getdef_str ("MAIL_DIR");
#ifdef MAIL_SPOOL_DIR
@@ -2040,8 +2050,6 @@ static void move_mailbox (void)
if (NULL == maildir) {
return;
}
- len = strlen (prefix) + strlen (maildir) + strlen (user_name) + 2;
- mailfile = alloca (len);
/*
* O_NONBLOCK is to make sure open won't hang on mandatory locks.
@@ -2050,14 +2058,10 @@ static void move_mailbox (void)
* between stat and chown). --marekm
*/
if (prefix[0]) {
- (void) snprintf (mailfile, len, "%s/%s/%s",
- prefix, maildir, user_name);
- }
- else {
- (void) snprintf (mailfile, len, "%s/%s",
- maildir, user_name);
+ xasprintf(&mailfile, "%s/%s/%s", prefix, maildir, user_name);
+ } else {
+ xasprintf(&mailfile, "%s/%s", maildir, user_name);
}
- mailfile[len-1] = '\0';
fd = open (mailfile, O_RDONLY | O_NONBLOCK, 0);
if (fd < 0) {
@@ -2065,11 +2069,13 @@ static void move_mailbox (void)
if (errno != ENOENT) {
perror (mailfile);
}
+ free(mailfile);
return;
}
if (fstat (fd, &st) < 0) {
perror ("fstat");
(void) close (fd);
+ free(mailfile);
return;
}
if (st.st_uid != user_id) {
@@ -2077,6 +2083,7 @@ static void move_mailbox (void)
fprintf (stderr, _("%s: warning: %s not owned by %s\n"),
Prog, mailfile, user_name);
(void) close (fd);
+ free(mailfile);
return;
}
if (uflg) {
@@ -2087,7 +2094,7 @@ static void move_mailbox (void)
else {
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
"changing mail file owner",
- user_newname, (unsigned int) user_newid, 1);
+ user_newname, user_newid, 1);
}
#endif
}
@@ -2095,17 +2102,14 @@ static void move_mailbox (void)
(void) close (fd);
if (lflg) {
- len = strlen (prefix) + strlen (maildir) + strlen (user_newname) + 2;
- newmailfile = alloca(len);
+ char *newmailfile;
+
if (prefix[0]) {
- (void) snprintf (newmailfile, len, "%s/%s/%s",
- prefix, maildir, user_newname);
- }
- else {
- (void) snprintf (newmailfile, len, "%s/%s",
- maildir, user_newname);
+ xasprintf(&newmailfile, "%s/%s/%s",
+ prefix, maildir, user_newname);
+ } else {
+ xasprintf(&newmailfile, "%s/%s", maildir, user_newname);
}
- newmailfile[len - 1] = '\0';
if ( (link (mailfile, newmailfile) != 0)
|| (unlink (mailfile) != 0)) {
perror (_("failed to rename mailbox"));
@@ -2114,10 +2118,14 @@ static void move_mailbox (void)
else {
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
"changing mail file name",
- user_newname, (unsigned int) user_newid, 1);
+ user_newname, user_newid, 1);
}
+
+ free(newmailfile);
#endif
}
+
+ free(mailfile);
}
#endif
@@ -2133,10 +2141,6 @@ int main (int argc, char **argv)
#endif /* USE_PAM */
#endif /* ACCT_TOOLS_SETUID */
- /*
- * Get my name so that I can use it to report errors.
- */
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -2147,14 +2151,14 @@ int main (int argc, char **argv)
process_root_flag ("-R", argc, argv);
prefix = process_prefix_flag ("-P", argc, argv);
- OPENLOG ("usermod");
+ OPENLOG (Prog);
#ifdef WITH_AUDIT
audit_help_open ();
#endif
sys_ngroups = sysconf (_SC_NGROUPS_MAX);
- user_groups = (char **) malloc (sizeof (char *) * (1 + sys_ngroups));
- user_groups[0] = (char *) 0;
+ user_groups = XMALLOC(sys_ngroups + 1, char *);
+ user_groups[0] = NULL;
is_shadow_pwd = spw_file_present ();
#ifdef SHADOWGRP
@@ -2193,7 +2197,7 @@ int main (int argc, char **argv)
exit (1);
}
- retval = pam_start ("usermod", pampw->pw_name, &conv, &pamh);
+ retval = pam_start (Prog, pampw->pw_name, &conv, &pamh);
}
if (PAM_SUCCESS == retval) {
@@ -2305,14 +2309,14 @@ int main (int argc, char **argv)
#ifdef WITH_SELINUX
if (Zflg) {
if ('\0' != *user_selinux) {
- if (set_seuser (user_name, user_selinux) != 0) {
+ if (set_seuser (user_name, user_selinux, user_selinux_range) != 0) {
fprintf (stderr,
_("%s: warning: the user name %s to %s SELinux user mapping failed.\n"),
Prog, user_name, user_selinux);
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
"modifying User mapping ",
- user_name, (unsigned int) user_id,
+ user_name, user_id,
SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
fail_exit (E_SE_UPDATE);
@@ -2325,7 +2329,7 @@ int main (int argc, char **argv)
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
"removing SELinux user mapping",
- user_name, (unsigned int) user_id,
+ user_name, user_id,
SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
fail_exit (E_SE_UPDATE);
@@ -2345,7 +2349,9 @@ int main (int argc, char **argv)
#endif /* NO_MOVE_MAILBOX */
if (uflg) {
+#ifdef ENABLE_LASTLOG
update_lastlog ();
+#endif /* ENABLE_LASTLOG */
update_faillog ();
}
@@ -2367,7 +2373,7 @@ int main (int argc, char **argv)
if (uflg || gflg) {
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
"changing home directory owner",
- user_newname, (unsigned int) user_newid, 1);
+ user_newname, user_newid, 1);
}
#endif
if (chown_tree (dflg ? prefix_user_newhome : prefix_user_home,
diff --git a/src/vipw.c b/src/vipw.c
index 488a97d..c30b32d 100644
--- a/src/vipw.c
+++ b/src/vipw.c
@@ -26,7 +26,10 @@
#include <sys/types.h>
#include <unistd.h>
#include <utime.h>
+
+#include "alloc.h"
#include "defines.h"
+#include "getdef.h"
#include "groupio.h"
#include "nscd.h"
#include "sssd.h"
@@ -41,6 +44,8 @@
#include "tcbfuncs.h"
#endif /* WITH_TCB */
#include "shadowlog.h"
+#include "string/sprintf.h"
+
#define MSG_WARN_EDIT_OTHER_FILE _( \
"You have modified %s.\n"\
@@ -50,7 +55,7 @@
/*
* Global variables
*/
-const char *Prog;
+static const char *Prog;
static const char *filename, *fileeditname;
static bool filelocked = false;
@@ -190,18 +195,17 @@ static void vipwexit (const char *msg, int syserr, int ret)
static void
vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
{
- const char *editor;
- pid_t pid;
- struct stat st1, st2;
- int status;
- FILE *f;
- pid_t orig_pgrp, editor_pgrp = -1;
- sigset_t mask, omask;
+ int status;
+ char *to_rename;
+ FILE *f;
+ pid_t pid, orig_pgrp, editor_pgrp = -1;
+ sigset_t mask, omask;
+ const char *editor;
+ struct stat st1, st2;
/* FIXME: the following should have variable sizes */
- char filebackup[1024], fileedit[1024];
- char *to_rename;
+ char filebackup[1024], fileedit[1024];
- snprintf (filebackup, sizeof filebackup, "%s-", file);
+ SNPRINTF(filebackup, "%s-", file);
#ifdef WITH_TCB
if (tcb_mode) {
if ( (mkdir (TCB_DIR "/" SHADOWTCB_SCRATCHDIR, 0700) != 0)
@@ -211,12 +215,12 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
if (shadowtcb_drop_priv () == SHADOWTCB_FAILURE) {
vipwexit (_("failed to drop privileges"), errno, 1);
}
- snprintf (fileedit, sizeof fileedit,
- TCB_DIR "/" SHADOWTCB_SCRATCHDIR "/.vipw.shadow.%s",
- user);
+ SNPRINTF(fileedit,
+ TCB_DIR "/" SHADOWTCB_SCRATCHDIR "/.vipw.shadow.%s",
+ user);
} else {
#endif /* WITH_TCB */
- snprintf (fileedit, sizeof fileedit, "%s.edit", file);
+ SNPRINTF(fileedit, "%s.edit", file);
#ifdef WITH_TCB
}
#endif /* WITH_TCB */
@@ -292,7 +296,7 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
} else if (0 == pid) {
/* use the system() call to invoke the editor so that it accepts
command line args in the EDITOR and VISUAL environment vars */
- char *buf;
+ char *buf;
/* Wait for parent to make us the foreground pgrp. */
if (orig_pgrp != -1) {
@@ -302,9 +306,8 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
continue;
}
- buf = (char *) malloc (strlen (editor) + strlen (fileedit) + 2);
- snprintf (buf, strlen (editor) + strlen (fileedit) + 2,
- "%s %s", editor, fileedit);
+ xasprintf(&buf, "%s %s", editor, fileedit);
+
status = system (buf);
if (-1 == status) {
fprintf (stderr, _("%s: %s: %s\n"), Prog, editor,
@@ -418,13 +421,11 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
if (stat (file, &st1) != 0) {
vipwexit (_("failed to stat edited file"), errno, 1);
}
- to_rename = malloc (strlen (file) + 2);
- if (NULL == to_rename) {
- vipwexit (_("failed to allocate memory"), errno, 1);
- }
- snprintf (to_rename, strlen (file) + 2, "%s+", file);
+ if (asprintf(&to_rename, "%s+", file) == -1)
+ vipwexit (_("asprintf(3) failed"), errno, 1);
+
if (create_backup_file (f, to_rename, &st1) != 0) {
- free (to_rename);
+ free(to_rename);
vipwexit (_("failed to create backup file"), errno, 1);
}
(void) fclose (f);
@@ -442,7 +443,7 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
Prog, file, strerror (errno), to_rename);
#ifdef WITH_TCB
if (tcb_mode) {
- free (to_rename);
+ free(to_rename);
}
#endif /* WITH_TCB */
vipwexit (0, 0, 1);
@@ -450,7 +451,7 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
#ifdef WITH_TCB
if (tcb_mode) {
- free (to_rename);
+ free(to_rename);
if (shadowtcb_gain_priv () == SHADOWTCB_FAILURE) {
vipwexit (_("failed to gain privileges"), errno, 1);
}
@@ -467,10 +468,12 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
int main (int argc, char **argv)
{
- bool editshadow = false;
- bool do_vipw;
+ bool editshadow = false;
+ bool do_vigr;
+
+ do_vigr = (strcmp(Basename(argv[0]), "vigr") == 0);
- Prog = Basename (argv[0]);
+ Prog = do_vigr ? "vigr" : "vipw";
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -480,9 +483,7 @@ int main (int argc, char **argv)
process_root_flag ("-R", argc, argv);
- do_vipw = (strcmp (Prog, "vigr") != 0);
-
- OPENLOG (do_vipw ? "vipw" : "vigr");
+ OPENLOG(Prog);
{
/*
@@ -510,13 +511,13 @@ int main (int argc, char **argv)
long_options, NULL)) != -1) {
switch (c) {
case 'g':
- do_vipw = false;
+ do_vigr = true;
break;
case 'h':
usage (E_SUCCESS);
break;
case 'p':
- do_vipw = true;
+ do_vigr = false;
break;
case 'q':
quiet = true;
@@ -541,7 +542,27 @@ int main (int argc, char **argv)
}
}
- if (do_vipw) {
+ if (do_vigr) {
+#ifdef SHADOWGRP
+ if (editshadow) {
+ vipwedit (sgr_dbname (), sgr_lock, sgr_unlock);
+ printf (MSG_WARN_EDIT_OTHER_FILE,
+ sgr_dbname (),
+ gr_dbname (),
+ "vigr");
+ } else {
+#endif /* SHADOWGRP */
+ vipwedit (gr_dbname (), gr_lock, gr_unlock);
+#ifdef SHADOWGRP
+ if (sgr_file_present ()) {
+ printf (MSG_WARN_EDIT_OTHER_FILE,
+ gr_dbname (),
+ sgr_dbname (),
+ "vigr -s");
+ }
+ }
+#endif /* SHADOWGRP */
+ } else {
if (editshadow) {
#ifdef WITH_TCB
if (getdef_bool ("USE_TCB") && (NULL != user)) {
@@ -568,26 +589,6 @@ int main (int argc, char **argv)
"vipw -s");
}
}
- } else {
-#ifdef SHADOWGRP
- if (editshadow) {
- vipwedit (sgr_dbname (), sgr_lock, sgr_unlock);
- printf (MSG_WARN_EDIT_OTHER_FILE,
- sgr_dbname (),
- gr_dbname (),
- "vigr");
- } else {
-#endif /* SHADOWGRP */
- vipwedit (gr_dbname (), gr_lock, gr_unlock);
-#ifdef SHADOWGRP
- if (sgr_file_present ()) {
- printf (MSG_WARN_EDIT_OTHER_FILE,
- gr_dbname (),
- sgr_dbname (),
- "vigr -s");
- }
- }
-#endif /* SHADOWGRP */
}
nscd_flush_cache ("passwd");