Imported Upstream version 4.1.5.1

This commit is contained in:
Christian Perrier
2013-07-27 18:42:08 +02:00
parent 6d11fd0a58
commit db1dc7288b
920 changed files with 432894 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
-kr
-i8
-bad
-pcs
-l80
+68
View File
@@ -0,0 +1,68 @@
EXTRA_DIST = .indent.pro xgetXXbyYY.c
INCLUDES = -I$(top_srcdir)/lib
noinst_LIBRARIES = libmisc.a
libmisc_a_SOURCES = \
addgrps.c \
age.c \
audit_help.c \
basename.c \
chkname.c \
chkname.h \
chowndir.c \
chowntty.c \
cleanup.c \
cleanup_group.c \
cleanup_user.c \
console.c \
copydir.c \
entry.c \
env.c \
failure.c \
failure.h \
find_new_gid.c \
find_new_uid.c \
getdate.h \
getdate.y \
getgr_nam_gid.c \
getrange.c \
hushed.c \
isexpired.c \
limits.c \
list.c log.c \
loginprompt.c \
mail.c \
motd.c \
myname.c \
obscure.c \
pam_pass.c \
pam_pass_non_interractive.c \
pwd2spwd.c \
pwdcheck.c \
pwd_init.c \
remove_tree.c \
rlogin.c \
root_flag.c \
salt.c \
setugid.c \
setupenv.c \
shell.c \
strtoday.c \
sub.c \
sulog.c \
ttytype.c \
tz.c \
ulimit.c \
user_busy.c \
utmp.c \
valid.c \
xgetpwnam.c \
xgetpwuid.c \
xgetgrnam.c \
xgetgrgid.c \
xgetspnam.c \
xmalloc.c \
yesno.c
+675
View File
@@ -0,0 +1,675 @@
# Makefile.in generated by automake 1.11.5 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
# Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__make_dryrun = \
{ \
am__dry=no; \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
| grep '^AM OK$$' >/dev/null || am__dry=yes;; \
*) \
for am__flg in $$MAKEFLAGS; do \
case $$am__flg in \
*=*|--*) ;; \
*n*) am__dry=yes; break;; \
esac; \
done;; \
esac; \
test $$am__dry = yes; \
}
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = libmisc
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in getdate.c
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LIBRARIES = $(noinst_LIBRARIES)
ARFLAGS = cru
libmisc_a_AR = $(AR) $(ARFLAGS)
libmisc_a_LIBADD =
am_libmisc_a_OBJECTS = addgrps.$(OBJEXT) age.$(OBJEXT) \
audit_help.$(OBJEXT) basename.$(OBJEXT) chkname.$(OBJEXT) \
chowndir.$(OBJEXT) chowntty.$(OBJEXT) cleanup.$(OBJEXT) \
cleanup_group.$(OBJEXT) cleanup_user.$(OBJEXT) \
console.$(OBJEXT) copydir.$(OBJEXT) entry.$(OBJEXT) \
env.$(OBJEXT) failure.$(OBJEXT) find_new_gid.$(OBJEXT) \
find_new_uid.$(OBJEXT) getdate.$(OBJEXT) \
getgr_nam_gid.$(OBJEXT) getrange.$(OBJEXT) hushed.$(OBJEXT) \
isexpired.$(OBJEXT) limits.$(OBJEXT) list.$(OBJEXT) \
log.$(OBJEXT) loginprompt.$(OBJEXT) mail.$(OBJEXT) \
motd.$(OBJEXT) myname.$(OBJEXT) obscure.$(OBJEXT) \
pam_pass.$(OBJEXT) pam_pass_non_interractive.$(OBJEXT) \
pwd2spwd.$(OBJEXT) pwdcheck.$(OBJEXT) pwd_init.$(OBJEXT) \
remove_tree.$(OBJEXT) rlogin.$(OBJEXT) root_flag.$(OBJEXT) \
salt.$(OBJEXT) setugid.$(OBJEXT) setupenv.$(OBJEXT) \
shell.$(OBJEXT) strtoday.$(OBJEXT) sub.$(OBJEXT) \
sulog.$(OBJEXT) ttytype.$(OBJEXT) tz.$(OBJEXT) \
ulimit.$(OBJEXT) user_busy.$(OBJEXT) utmp.$(OBJEXT) \
valid.$(OBJEXT) xgetpwnam.$(OBJEXT) xgetpwuid.$(OBJEXT) \
xgetgrnam.$(OBJEXT) xgetgrgid.$(OBJEXT) xgetspnam.$(OBJEXT) \
xmalloc.$(OBJEXT) yesno.$(OBJEXT)
libmisc_a_OBJECTS = $(am_libmisc_a_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
@MAINTAINER_MODE_FALSE@am__skipyacc = test -f $@ ||
YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS)
LTYACCCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS)
YLWRAP = $(top_srcdir)/ylwrap
SOURCES = $(libmisc_a_SOURCES)
DIST_SOURCES = $(libmisc_a_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
GMSGFMT = @GMSGFMT@
GMSGFMT_015 = @GMSGFMT_015@
GREP = @GREP@
GROUP_NAME_MAX_LENGTH = @GROUP_NAME_MAX_LENGTH@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INTLLIBS = @INTLLIBS@
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBACL = @LIBACL@
LIBATTR = @LIBATTR@
LIBAUDIT = @LIBAUDIT@
LIBCRACK = @LIBCRACK@
LIBCRYPT = @LIBCRYPT@
LIBICONV = @LIBICONV@
LIBINTL = @LIBINTL@
LIBMD = @LIBMD@
LIBOBJS = @LIBOBJS@
LIBPAM = @LIBPAM@
LIBS = @LIBS@
LIBSELINUX = @LIBSELINUX@
LIBSEMANAGE = @LIBSEMANAGE@
LIBSKEY = @LIBSKEY@
LIBTCB = @LIBTCB@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
MSGFMT = @MSGFMT@
MSGFMT_015 = @MSGFMT_015@
MSGMERGE = @MSGMERGE@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
POSUB = @POSUB@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
XGETTEXT = @XGETTEXT@
XGETTEXT_015 = @XGETTEXT_015@
XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
XMLCATALOG = @XMLCATALOG@
XML_CATALOG_FILE = @XML_CATALOG_FILE@
XSLTPROC = @XSLTPROC@
YACC = @YACC@
YFLAGS = @YFLAGS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
EXTRA_DIST = .indent.pro xgetXXbyYY.c
INCLUDES = -I$(top_srcdir)/lib
noinst_LIBRARIES = libmisc.a
libmisc_a_SOURCES = \
addgrps.c \
age.c \
audit_help.c \
basename.c \
chkname.c \
chkname.h \
chowndir.c \
chowntty.c \
cleanup.c \
cleanup_group.c \
cleanup_user.c \
console.c \
copydir.c \
entry.c \
env.c \
failure.c \
failure.h \
find_new_gid.c \
find_new_uid.c \
getdate.h \
getdate.y \
getgr_nam_gid.c \
getrange.c \
hushed.c \
isexpired.c \
limits.c \
list.c log.c \
loginprompt.c \
mail.c \
motd.c \
myname.c \
obscure.c \
pam_pass.c \
pam_pass_non_interractive.c \
pwd2spwd.c \
pwdcheck.c \
pwd_init.c \
remove_tree.c \
rlogin.c \
root_flag.c \
salt.c \
setugid.c \
setupenv.c \
shell.c \
strtoday.c \
sub.c \
sulog.c \
ttytype.c \
tz.c \
ulimit.c \
user_busy.c \
utmp.c \
valid.c \
xgetpwnam.c \
xgetpwuid.c \
xgetgrnam.c \
xgetgrgid.c \
xgetspnam.c \
xmalloc.c \
yesno.c
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj .y
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libmisc/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu libmisc/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
libmisc.a: $(libmisc_a_OBJECTS) $(libmisc_a_DEPENDENCIES) $(EXTRA_libmisc_a_DEPENDENCIES)
-rm -f libmisc.a
$(libmisc_a_AR) libmisc.a $(libmisc_a_OBJECTS) $(libmisc_a_LIBADD)
$(RANLIB) libmisc.a
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addgrps.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/age.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audit_help.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/basename.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chkname.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chowndir.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chowntty.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cleanup.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cleanup_group.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cleanup_user.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/console.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/copydir.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entry.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/env.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/failure.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/find_new_gid.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/find_new_uid.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getdate.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getgr_nam_gid.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getrange.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hushed.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isexpired.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/limits.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loginprompt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mail.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/motd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/myname.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/obscure.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_pass.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_pass_non_interractive.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pwd2spwd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pwd_init.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pwdcheck.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/remove_tree.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rlogin.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/root_flag.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/salt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/setugid.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/setupenv.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shell.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strtoday.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sub.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sulog.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttytype.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tz.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ulimit.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/user_busy.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utmp.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/valid.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xgetgrgid.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xgetgrnam.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xgetpwnam.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xgetpwuid.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xgetspnam.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmalloc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yesno.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
.y.c:
$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE)
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LIBRARIES)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-rm -f getdate.c
clean: clean-am
clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am:
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-libtool clean-noinstLIBRARIES ctags distclean \
distclean-compile distclean-generic distclean-libtool \
distclean-tags distdir dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
pdf pdf-am ps ps-am tags uninstall uninstall-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
+131
View File
@@ -0,0 +1,131 @@
/*
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2001 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#if defined (HAVE_SETGROUPS) && ! defined (USE_PAM)
#include "prototypes.h"
#include "defines.h"
#include <stdio.h>
#include <grp.h>
#include <errno.h>
#ident "$Id: addgrps.c 3318 2011-06-02 15:36:29Z nekral-guest $"
#define SEP ",:"
/*
* Add groups with names from LIST (separated by commas or colons)
* to the supplementary group set. Silently ignore groups which are
* already there. Warning: uses strtok().
*/
int add_groups (const char *list)
{
GETGROUPS_T *grouplist, *tmp;
size_t i;
int ngroups;
bool added;
char *token;
char buf[1024];
if (strlen (list) >= sizeof (buf)) {
errno = EINVAL;
return -1;
}
strcpy (buf, list);
i = 16;
for (;;) {
grouplist = (gid_t *) malloc (i * sizeof (GETGROUPS_T));
if (NULL == grouplist) {
return -1;
}
ngroups = getgroups (i, grouplist);
if ( ( (-1 == ngroups)
&& (EINVAL != errno))
|| (i > (size_t)ngroups)) {
/* Unexpected failure of getgroups or successful
* reception of the groups */
break;
}
/* not enough room, so try allocating a larger buffer */
free (grouplist);
i *= 2;
}
if (ngroups < 0) {
free (grouplist);
return -1;
}
added = false;
for (token = strtok (buf, SEP); NULL != token; token = strtok (NULL, SEP)) {
struct group *grp;
grp = getgrnam (token); /* local, no need for xgetgrnam */
if (NULL == grp) {
fprintf (stderr, _("Warning: unknown group %s\n"),
token);
continue;
}
for (i = 0; i < (size_t)ngroups && grouplist[i] != grp->gr_gid; i++);
if (i < (size_t)ngroups) {
continue;
}
if (ngroups >= sysconf (_SC_NGROUPS_MAX)) {
fputs (_("Warning: too many groups\n"), stderr);
break;
}
tmp = (gid_t *) realloc (grouplist, (size_t)(ngroups + 1) * sizeof (GETGROUPS_T));
if (NULL == tmp) {
free (grouplist);
return -1;
}
tmp[ngroups] = grp->gr_gid;
ngroups++;
grouplist = tmp;
added = true;
}
if (added) {
return setgroups ((size_t)ngroups, grouplist);
}
return 0;
}
#else /* HAVE_SETGROUPS && !USE_PAM */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* HAVE_SETGROUPS && !USE_PAM */
+201
View File
@@ -0,0 +1,201 @@
/*
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2001 - 2006, Tomasz Kłoczko
* Copyright (c) 2008 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <sys/types.h>
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include "prototypes.h"
#include "defines.h"
#include "exitcodes.h"
#include <pwd.h>
#include <grp.h>
#ident "$Id: age.c 2775 2009-04-23 17:33:21Z nekral-guest $"
#ifndef PASSWD_PROGRAM
#define PASSWD_PROGRAM "/bin/passwd"
#endif
/*
* expire - force password change if password expired
*
* expire() calls /bin/passwd to change the user's password
* if it has expired.
*/
int expire (const struct passwd *pw, /*@null@*/const struct spwd *sp)
{
int status;
pid_t child;
pid_t pid;
if (NULL == sp) {
return 0;
}
/*
* See if the user's password has expired, and if so
* force them to change their password.
*/
status = isexpired (pw, sp);
switch (status) {
case 0:
return 0;
case 1:
(void) fputs (_("Your password has expired."), stdout);
break;
case 2:
(void) fputs (_("Your password is inactive."), stdout);
break;
case 3:
(void) fputs (_("Your login has expired."), stdout);
break;
}
/*
* Setting the maximum valid period to less than the minimum
* valid period means that the minimum period will never
* occur while the password is valid, so the user can never
* change that password.
*/
if ((status > 1) || (sp->sp_max < sp->sp_min)) {
(void) puts (_(" Contact the system administrator."));
exit (EXIT_FAILURE);
}
(void) puts (_(" Choose a new password."));
(void) fflush (stdout);
/*
* Close all the files so that unauthorized access won't
* occur. This needs to be done anyway because those files
* might become stale after "passwd" is executed.
*/
endspent ();
endpwent ();
#ifdef SHADOWGRP
endsgent ();
#endif
endgrent ();
/*
* Execute the /bin/passwd command. The exit status will be
* examined to see what the result is. If there are any
* errors the routine will exit. This forces the user to
* change their password before being able to use the account.
*/
pid = fork ();
if (0 == pid) {
int err;
/*
* Set the UID to be that of the user. This causes
* passwd to work just like it would had they executed
* it from the command line while logged in.
*/
#if defined(HAVE_INITGROUPS) && ! defined(USE_PAM)
if (setup_uid_gid (pw, false) != 0)
#else
if (setup_uid_gid (pw) != 0)
#endif
{
_exit (126);
}
(void) execl (PASSWD_PROGRAM, PASSWD_PROGRAM, pw->pw_name, (char *) 0);
err = errno;
perror ("Can't execute " PASSWD_PROGRAM);
_exit ((ENOENT == err) ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
} else if ((pid_t) -1 == pid) {
perror ("fork");
exit (EXIT_FAILURE);
}
while (((child = wait (&status)) != pid) && (child != (pid_t)-1));
if ((child == pid) && (0 == status)) {
return 1;
}
exit (EXIT_FAILURE);
/*@notreached@*/}
/*
* agecheck - see if warning is needed for password expiration
*
* agecheck sees how many days until the user's password is going
* to expire and warns the user of the pending password expiration.
*/
void agecheck (/*@null@*/const struct spwd *sp)
{
long now = (long) time ((time_t *) 0) / SCALE;
long remain;
if (NULL == sp) {
return;
}
/*
* The last, max, and warn fields must be supported or the
* warning period cannot be calculated.
*/
if ( (-1 == sp->sp_lstchg)
|| (-1 == sp->sp_max)
|| (-1 == sp->sp_warn)) {
return;
}
if (0 == sp->sp_lstchg) {
(void) puts (_("You must change your password."));
return;
}
remain = sp->sp_lstchg + sp->sp_max - now;
if (remain <= sp->sp_warn) {
remain /= DAY / SCALE;
if (remain > 1) {
(void) printf (_("Your password will expire in %ld days.\n"),
remain);
} else if (1 == remain) {
(void) puts (_("Your password will expire tomorrow."));
} else if (remain == 0) {
(void) puts (_("Your password will expire today."));
}
}
}
+109
View File
@@ -0,0 +1,109 @@
/*
* Copyright (c) 2005 , Red Hat, Inc.
* Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Audit helper functions used throughout shadow
*
*/
#include <config.h>
#ifdef WITH_AUDIT
#include <stdlib.h>
#include <syslog.h>
#include <stdarg.h>
#include <libaudit.h>
#include <errno.h>
#include <stdio.h>
#include "prototypes.h"
int audit_fd;
void audit_help_open (void)
{
audit_fd = audit_open ();
if (audit_fd < 0) {
/* You get these only when the kernel doesn't have
* audit compiled in. */
if ( (errno == EINVAL)
|| (errno == EPROTONOSUPPORT)
|| (errno == EAFNOSUPPORT)) {
return;
}
(void) fputs (_("Cannot open audit interface - aborting.\n"),
stderr);
exit (EXIT_FAILURE);
}
}
/*
* This function will log a message to the audit system using a predefined
* message format. Parameter usage is as follows:
*
* type - type of message: AUDIT_USER_CHAUTHTOK for changing any account
* attributes.
* pgname - program's name
* op - operation. "adding user", "changing finger info", "deleting group"
* name - user's account or group name. If not available use NULL.
* id - uid or gid that the operation is being performed on. This is used
* only when user is NULL.
*/
void audit_logger (int type, unused const char *pgname, const char *op,
const char *name, unsigned int id,
shadow_audit_result result)
{
if (audit_fd < 0) {
return;
} else {
audit_log_acct_message (audit_fd, type, NULL, op, name, id,
NULL, NULL, NULL, (int) result);
}
}
void audit_logger_message (const char *message, shadow_audit_result result)
{
if (audit_fd < 0) {
return;
} else {
audit_log_user_message (audit_fd,
AUDIT_USYS_CONFIG,
message,
NULL, /* hostname */
NULL, /* addr */
NULL, /* tty */
(int) result);
}
}
#else /* WITH_AUDIT */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* WITH_AUDIT */
+50
View File
@@ -0,0 +1,50 @@
/*
* Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1997, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* basename.c - not worth copyrighting :-). Some versions of Linux libc
* already have basename(), other versions don't. To avoid confusion,
* we will not use the function from libc and use a different name here.
* --marekm
*/
#include <config.h>
#ident "$Id: basename.c 3493 2011-09-18 21:02:43Z nekral-guest $"
#include "defines.h"
#include "prototypes.h"
/*@observer@*/const char *Basename (const char *str)
{
char *cp = strrchr (str, '/');
return (NULL != cp) ? cp + 1 : str;
}
+99
View File
@@ -0,0 +1,99 @@
/*
* Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 - 2005, Tomasz Kłoczko
* Copyright (c) 2005 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* is_valid_user_name(), is_valid_group_name() - check the new user/group
* name for validity;
* return values:
* true - OK
* false - bad name
*/
#include <config.h>
#ident "$Id: chkname.c 2828 2009-04-28 19:14:05Z nekral-guest $"
#include <ctype.h>
#include "defines.h"
#include "chkname.h"
static bool is_valid_name (const char *name)
{
/*
* User/group names must match [a-z_][a-z0-9_-]*[$]
*/
if (('\0' == *name) ||
!((('a' <= *name) && ('z' >= *name)) || ('_' == *name))) {
return false;
}
while ('\0' != *++name) {
if (!(( ('a' <= *name) && ('z' >= *name) ) ||
( ('0' <= *name) && ('9' >= *name) ) ||
('_' == *name) ||
('-' == *name) ||
( ('$' == *name) && ('\0' == *(name + 1)) )
)) {
return false;
}
}
return true;
}
bool is_valid_user_name (const char *name)
{
/*
* User names are limited by whatever utmp can
* handle.
*/
if (strlen (name) > USER_NAME_MAX_LENGTH) {
return false;
}
return is_valid_name (name);
}
bool is_valid_group_name (const char *name)
{
/*
* Arbitrary limit for group names.
* HP-UX 10 limits to 16 characters
*/
if ( (GROUP_NAME_MAX_LENGTH > 0)
&& (strlen (name) > GROUP_NAME_MAX_LENGTH)) {
return false;
}
return is_valid_name (name);
}
+50
View File
@@ -0,0 +1,50 @@
/*
* Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1997 - 2000, Marek Michałkiewicz
* Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* $Id: chkname.h 2036 2008-05-25 23:31:10Z nekral-guest $ */
#ifndef _CHKNAME_H_
#define _CHKNAME_H_
/*
* is_valid_user_name(), is_valid_group_name() - check the new user/group
* name for validity;
* return values:
* true - OK
* false - bad name
*/
#include "defines.h"
extern bool is_valid_user_name (const char *name);
extern bool is_valid_group_name (const char *name);
#endif
+201
View File
@@ -0,0 +1,201 @@
/*
* Copyright (c) 1992 - 1993, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2010 - , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: chowndir.c 3465 2011-08-14 14:00:14Z nekral-guest $"
#include <sys/types.h>
#include <sys/stat.h>
#include "prototypes.h"
#include "defines.h"
#include <fcntl.h>
#include <stdio.h>
/*
* chown_tree - change ownership of files in a directory tree
*
* chown_dir() walks a directory tree and changes the ownership
* of all files owned by the provided user ID.
*
* Only files owned (resp. group-owned) by old_uid (resp. by old_gid)
* will have their ownership (resp. group-ownership) modified, unless
* old_uid (resp. old_gid) is set to -1.
*
* new_uid and new_gid can be set to -1 to indicate that no owner or
* group-owner shall be changed.
*/
int chown_tree (const char *root,
uid_t old_uid,
uid_t new_uid,
gid_t old_gid,
gid_t new_gid)
{
char *new_name;
size_t new_name_len;
int rc = 0;
struct DIRECT *ent;
struct stat sb;
DIR *dir;
new_name = malloc (1024);
if (NULL == new_name) {
return -1;
}
new_name_len = 1024;
/*
* Make certain the directory exists. This routine is called
* directly by the invoker, or recursively.
*/
if (access (root, F_OK) != 0) {
free (new_name);
return -1;
}
/*
* Open the directory and read each entry. Every entry is tested
* to see if it is a directory, and if so this routine is called
* recursively. If not, it is checked to see if an ownership
* shall be changed.
*/
dir = opendir (root);
if (NULL == dir) {
free (new_name);
return -1;
}
while ((ent = readdir (dir))) {
size_t ent_name_len;
uid_t tmpuid = (uid_t) -1;
gid_t tmpgid = (gid_t) -1;
/*
* Skip the "." and ".." entries
*/
if ( (strcmp (ent->d_name, ".") == 0)
|| (strcmp (ent->d_name, "..") == 0)) {
continue;
}
/*
* Make the filename for both the source and the
* destination files.
*/
ent_name_len = strlen (root) + strlen (ent->d_name) + 2;
if (ent_name_len > new_name_len) {
/*@only@*/char *tmp = realloc (new_name, ent_name_len);
if (NULL == tmp) {
rc = -1;
break;
}
new_name = tmp;
new_name_len = ent_name_len;
}
(void) snprintf (new_name, new_name_len, "%s/%s", root, ent->d_name);
/* Don't follow symbolic links! */
if (LSTAT (new_name, &sb) == -1) {
continue;
}
if (S_ISDIR (sb.st_mode) && !S_ISLNK (sb.st_mode)) {
/*
* Do the entire subdirectory.
*/
rc = chown_tree (new_name, old_uid, new_uid,
old_gid, new_gid);
if (0 != rc) {
break;
}
}
#ifndef HAVE_LCHOWN
/* don't use chown (follows symbolic links!) */
if (S_ISLNK (sb.st_mode)) {
continue;
}
#endif
/*
* By default, the IDs are not changed (-1).
*
* If the file is not owned by the user, the owner is not
* changed.
*
* If the file is not group-owned by the group, the
* group-owner is not changed.
*/
if (((uid_t) -1 == old_uid) || (sb.st_uid == old_uid)) {
tmpuid = new_uid;
}
if (((gid_t) -1 == old_gid) || (sb.st_gid == old_gid)) {
tmpgid = new_gid;
}
if (((uid_t) -1 != tmpuid) || ((gid_t) -1 != tmpgid)) {
rc = LCHOWN (new_name, tmpuid, tmpgid);
if (0 != rc) {
break;
}
}
}
free (new_name);
(void) closedir (dir);
/*
* Now do the root of the tree
*/
if ((0 == rc) && (stat (root, &sb) == 0)) {
uid_t tmpuid = (uid_t) -1;
gid_t tmpgid = (gid_t) -1;
if (((uid_t) -1 == old_uid) || (sb.st_uid == old_uid)) {
tmpuid = new_uid;
}
if (((gid_t) -1 == old_gid) || (sb.st_gid == old_gid)) {
tmpgid = new_gid;
}
if (((uid_t) -1 != tmpuid) || ((gid_t) -1 != tmpgid)) {
rc = LCHOWN (root, tmpuid, tmpgid);
}
} else {
rc = -1;
}
return rc;
}
+99
View File
@@ -0,0 +1,99 @@
/*
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2001, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: chowntty.c 3232 2010-08-22 19:13:53Z nekral-guest $"
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <grp.h>
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
#include "getdef.h"
/*
* chown_tty() sets the login tty to be owned by the new user ID
* with TTYPERM modes
*/
void chown_tty (const struct passwd *info)
{
struct group *grent;
gid_t gid;
/*
* See if login.defs has some value configured for the port group
* ID. Otherwise, use the user's primary group ID.
*/
grent = getgr_nam_gid (getdef_str ("TTYGROUP"));
if (NULL != grent) {
gid = grent->gr_gid;
} else {
gid = info->pw_gid;
}
/*
* Change the permissions on the TTY to be owned by the user with
* the group as determined above.
*/
if ( (fchown (STDIN_FILENO, info->pw_uid, gid) != 0)
|| (fchmod (STDIN_FILENO, (mode_t)getdef_num ("TTYPERM", 0600)) != 0)) {
int err = errno;
fprintf (stderr,
_("Unable to change owner or mode of tty stdin: %s"),
strerror (err));
SYSLOG ((LOG_WARN,
"unable to change owner or mode of tty stdin for user `%s': %s\n",
info->pw_name, strerror (err)));
if (EROFS != err) {
closelog ();
exit (EXIT_FAILURE);
}
}
#ifdef __linux__
/*
* Please don't add code to chown /dev/vcs* to the user logging in -
* it's a potential security hole. I wouldn't like the previous user
* to hold the file descriptor open and watch my screen. We don't
* have the *BSD revoke() system call yet, and vhangup() only works
* for tty devices (which vcs* is not). --marekm
*/
#endif
}
+144
View File
@@ -0,0 +1,144 @@
/*
* Copyright (c) 2008 - 2011, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <assert.h>
#include <stdio.h>
#include "prototypes.h"
/*
* The cleanup_functions stack.
*/
#define CLEANUP_FUNCTIONS 10
typedef /*@null@*/void * parg_t;
static cleanup_function cleanup_functions[CLEANUP_FUNCTIONS];
static parg_t cleanup_function_args[CLEANUP_FUNCTIONS];
static pid_t cleanup_pid = 0;
/*
* - Cleanup functions shall not fail.
* - You should register do_cleanups with atexit.
* - You should add cleanup functions to the stack with add_cleanup when
* an operation is expected to be executed later, and remove it from the
* stack with del_cleanup when it has been executed.
*
**/
/*
* do_cleanups - perform the actions stored in the cleanup_functions stack.
*
* Cleanup action are not executed on exit of the processes started by the
* parent (first caller of add_cleanup).
*
* It is intended to be used as:
* atexit (do_cleanups);
*/
void do_cleanups (void)
{
unsigned int i;
/* Make sure there were no overflow */
assert (NULL == cleanup_functions[CLEANUP_FUNCTIONS-1]);
if (getpid () != cleanup_pid) {
return;
}
i = CLEANUP_FUNCTIONS;
do {
i--;
if (cleanup_functions[i] != NULL) {
cleanup_functions[i] (cleanup_function_args[i]);
}
} while (i>0);
}
/*
* add_cleanup - Add a cleanup_function to the cleanup_functions stack.
*/
void add_cleanup (/*@notnull@*/cleanup_function pcf, /*@null@*/void *arg)
{
unsigned int i;
assert (NULL != pcf);
assert (NULL == cleanup_functions[CLEANUP_FUNCTIONS-2]);
if (0 == cleanup_pid) {
cleanup_pid = getpid ();
}
/* Add the cleanup_function at the end of the stack */
for (i=0; NULL != cleanup_functions[i]; i++);
cleanup_functions[i] = pcf;
cleanup_function_args[i] = arg;
}
/*
* del_cleanup - Remove a cleanup_function from the cleanup_functions stack.
*/
void del_cleanup (/*@notnull@*/cleanup_function pcf)
{
unsigned int i;
assert (NULL != pcf);
/* Find the pcf cleanup function */
for (i=0; i<CLEANUP_FUNCTIONS; i++) {
if (cleanup_functions[i] == pcf) {
break;
}
}
/* Make sure the cleanup function was found */
assert (i<CLEANUP_FUNCTIONS);
/* Move the rest of the cleanup functions */
for (; i<CLEANUP_FUNCTIONS; i++) {
/* Make sure the cleanup function was specified only once */
assert ( (i == (CLEANUP_FUNCTIONS -1))
|| (cleanup_functions[i+1] != pcf));
if (i == (CLEANUP_FUNCTIONS -1)) {
cleanup_functions[i] = NULL;
cleanup_function_args[i] = NULL;
} else {
cleanup_functions[i] = cleanup_functions[i+1];
cleanup_function_args[i] = cleanup_function_args[i+1];
}
/* A NULL indicates the end of the stack */
if (NULL == cleanup_functions[i]) {
break;
}
}
}
+237
View File
@@ -0,0 +1,237 @@
/*
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <assert.h>
#include <stdio.h>
#include "defines.h"
#include "groupio.h"
#include "sgroupio.h"
#include "prototypes.h"
/*
* cleanup_report_add_group - Report failure to add a group to the system
*
* It should be registered when it is decided to add a group to the system.
*/
void cleanup_report_add_group (void *group_name)
{
const char *name = (const char *)group_name;
SYSLOG ((LOG_ERR, "failed to add group %s", name));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_GROUP, Prog,
"",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
/*
* cleanup_report_del_group - Report failure to remove a group from the system
*
* It should be registered when it is decided to remove a group from the system.
*/
void cleanup_report_del_group (void *group_name)
{
const char *name = (const char *)group_name;
SYSLOG ((LOG_ERR, "failed to remove group %s", name));
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_GROUP, Prog,
"",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
void cleanup_report_mod_group (void *cleanup_info)
{
const struct cleanup_info_mod *info;
info = (const struct cleanup_info_mod *)cleanup_info;
SYSLOG ((LOG_ERR,
"failed to change %s (%s)",
gr_dbname (),
info->action));
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_ACCT, Prog,
info->audit_msg,
info->name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
#ifdef SHADOWGRP
void cleanup_report_mod_gshadow (void *cleanup_info)
{
const struct cleanup_info_mod *info;
info = (const struct cleanup_info_mod *)cleanup_info;
SYSLOG ((LOG_ERR,
"failed to change %s (%s)",
sgr_dbname (),
info->action));
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_ACCT, Prog,
info->audit_msg,
info->name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
#endif
/*
* cleanup_report_add_group_group - Report failure to add a group to group
*
* It should be registered when it is decided to add a group to the
* group database.
*/
void cleanup_report_add_group_group (void *group_name)
{
const char *name = (const char *)group_name;
SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, gr_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_GROUP, Prog,
"adding group to /etc/group",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
#ifdef SHADOWGRP
/*
* cleanup_report_add_group_gshadow - Report failure to add a group to gshadow
*
* It should be registered when it is decided to add a group to the
* gshadow database.
*/
void cleanup_report_add_group_gshadow (void *group_name)
{
const char *name = (const char *)group_name;
SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, sgr_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_GROUP, Prog,
"adding group to /etc/gshadow",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
#endif
/*
* cleanup_report_del_group_group - Report failure to remove a group from the
* regular group database
*
* It should be registered when it is decided to remove a group from the
* regular group database.
*/
void cleanup_report_del_group_group (void *group_name)
{
const char *name = (const char *)group_name;
SYSLOG ((LOG_ERR,
"failed to remove group %s from %s",
name, gr_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_GROUP, Prog,
"removing group from /etc/group",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
#ifdef SHADOWGRP
/*
* cleanup_report_del_group_gshadow - Report failure to remove a group from
* gshadow
*
* It should be registered when it is decided to remove a group from the
* gshadow database.
*/
void cleanup_report_del_group_gshadow (void *group_name)
{
const char *name = (const char *)group_name;
SYSLOG ((LOG_ERR,
"failed to remove group %s from %s",
name, sgr_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_GROUP, Prog,
"removing group from /etc/gshadow",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
#endif
/*
* cleanup_unlock_group - Unlock the group file
*
* It should be registered after the group file is successfully locked.
*/
void cleanup_unlock_group (unused void *arg)
{
if (gr_unlock () == 0) {
fprintf (stderr,
_("%s: failed to unlock %s\n"),
Prog, gr_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
#ifdef WITH_AUDIT
audit_logger_message ("unlocking group file",
SHADOW_AUDIT_FAILURE);
#endif
}
}
#ifdef SHADOWGRP
/*
* cleanup_unlock_gshadow - Unlock the gshadow file
*
* It should be registered after the gshadow file is successfully locked.
*/
void cleanup_unlock_gshadow (unused void *arg)
{
if (sgr_unlock () == 0) {
fprintf (stderr,
_("%s: failed to unlock %s\n"),
Prog, sgr_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
#ifdef WITH_AUDIT
audit_logger_message ("unlocking gshadow file",
SHADOW_AUDIT_FAILURE);
#endif
}
}
#endif
+152
View File
@@ -0,0 +1,152 @@
/*
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <assert.h>
#include <stdio.h>
#include "defines.h"
#include "pwio.h"
#include "shadowio.h"
#include "prototypes.h"
/*
* cleanup_report_add_user - Report failure to add an user to the system
*
* It should be registered when it is decided to add an user to the system.
*/
void cleanup_report_add_user (void *user_name)
{
const char *name = (const char *)user_name;
SYSLOG ((LOG_ERR, "failed to add user %s", name));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
"",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
void cleanup_report_mod_passwd (void *cleanup_info)
{
const struct cleanup_info_mod *info;
info = (const struct cleanup_info_mod *)cleanup_info;
SYSLOG ((LOG_ERR,
"failed to change %s (%s)",
pw_dbname (),
info->action));
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_ACCT, Prog,
info->audit_msg,
info->name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
/*
* cleanup_report_add_user_passwd - Report failure to add an user to
* /etc/passwd
*
* It should be registered when it is decided to add an user to the
* /etc/passwd database.
*/
void cleanup_report_add_user_passwd (void *user_name)
{
const char *name = (const char *)user_name;
SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, pw_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
"adding user to /etc/passwd",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
/*
* cleanup_report_add_user_shadow - Report failure to add an user to
* /etc/shadow
*
* It should be registered when it is decided to add an user to the
* /etc/shadow database.
*/
void cleanup_report_add_user_shadow (void *user_name)
{
const char *name = (const char *)user_name;
SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, spw_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
"adding user to /etc/shadow",
name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
}
/*
* cleanup_unlock_passwd - Unlock the /etc/passwd database
*
* It should be registered after the passwd database is successfully locked.
*/
void cleanup_unlock_passwd (unused void *arg)
{
if (pw_unlock () == 0) {
fprintf (stderr,
_("%s: failed to unlock %s\n"),
Prog, pw_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
#ifdef WITH_AUDIT
audit_logger_message ("unlocking passwd file",
SHADOW_AUDIT_FAILURE);
#endif
}
}
/*
* cleanup_unlock_shadow - Unlock the /etc/shadow database
*
* It should be registered after the shadow database is successfully locked.
*/
void cleanup_unlock_shadow (unused void *arg)
{
if (spw_unlock () == 0) {
fprintf (stderr,
_("%s: failed to unlock %s\n"),
Prog, spw_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
#ifdef WITH_AUDIT
audit_logger_message ("unlocking shadow file",
SHADOW_AUDIT_FAILURE);
#endif
}
}
+133
View File
@@ -0,0 +1,133 @@
/*
* Copyright (c) 1991 , Julianne Frances Haugh
* Copyright (c) 1991 , Chip Rosenthal
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include "defines.h"
#include <stdio.h>
#include "getdef.h"
#include "prototypes.h"
#ident "$Id: console.c 3289 2010-11-19 21:54:41Z nekral-guest $"
/* local function prototypes */
static bool is_listed (const char *cfgin, const char *tty, bool def);
/*
* This is now rather generic function which decides if "tty" is listed
* under "cfgin" in config (directly or indirectly). Fallback to default if
* something is bad.
*/
static bool is_listed (const char *cfgin, const char *tty, bool def)
{
FILE *fp;
char buf[200], *s;
const char *cons;
/*
* If the CONSOLE configuration definition isn't given,
* fallback to default.
*/
cons = getdef_str (cfgin);
if (NULL == cons) {
return def;
}
/*
* If this isn't a filename, then it is a ":" delimited list of
* console devices upon which root logins are allowed.
*/
if (*cons != '/') {
char *pbuf;
strcpy (buf, cons);
pbuf = &buf[0];
while ((s = strtok (pbuf, ":")) != NULL) {
if (strcmp (s, tty) == 0) {
return true;
}
pbuf = NULL;
}
return false;
}
/*
* If we can't open the console list, then call everything a
* console - otherwise root will never be allowed to login.
*/
fp = fopen (cons, "r");
if (NULL == fp) {
return def;
}
/*
* See if this tty is listed in the console file.
*/
while (fgets (buf, (int) sizeof (buf), fp) != NULL) {
buf[strlen (buf) - 1] = '\0';
if (strcmp (buf, tty) == 0) {
(void) fclose (fp);
return true;
}
}
/*
* This tty isn't a console.
*/
(void) fclose (fp);
return false;
}
/*
* console - return 1 if the "tty" is a console device, else 0.
*
* Note - we need to take extreme care here to avoid locking out root logins
* if something goes awry. That's why we do things like call everything a
* console if the consoles file can't be opened. Because of this, we must
* warn the user to protect against the remove of the consoles file since
* that would allow an unauthorized root login.
*/
bool console (const char *tty)
{
if (strncmp (tty, "/dev/", 5) == 0) {
tty += 5;
}
return is_listed ("CONSOLE", tty, true);
}
+839
View File
@@ -0,0 +1,839 @@
/*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2001, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: copydir.c 3706 2012-02-13 19:16:29Z nekral-guest $"
#include <assert.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <fcntl.h>
#include <stdio.h>
#include "prototypes.h"
#include "defines.h"
#ifdef WITH_SELINUX
#include <selinux/selinux.h>
#endif /* WITH_SELINUX */
#if defined(WITH_ACL) || defined(WITH_ATTR)
#include <stdarg.h>
#include <attr/error_context.h>
#endif /* WITH_ACL || WITH_ATTR */
#ifdef WITH_ACL
#include <acl/libacl.h>
#endif /* WITH_ACL */
#ifdef WITH_ATTR
#include <attr/libattr.h>
#endif /* WITH_ATTR */
static /*@null@*/const char *src_orig;
static /*@null@*/const char *dst_orig;
struct link_name {
dev_t ln_dev;
ino_t ln_ino;
nlink_t ln_count;
char *ln_name;
/*@dependent@*/struct link_name *ln_next;
};
static /*@exposed@*/struct link_name *links;
static int copy_entry (const char *src, const char *dst,
bool reset_selinux,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static int copy_dir (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
#ifdef S_IFLNK
static /*@null@*/char *readlink_malloc (const char *filename);
static int copy_symlink (const char *src, const char *dst,
unused bool reset_selinux,
const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
#endif /* S_IFLNK */
static int copy_hardlink (const char *dst,
unused bool reset_selinux,
struct link_name *lp);
static int copy_special (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static int copy_file (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static int chown_if_needed (const char *dst, const struct stat *statp,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static int lchown_if_needed (const char *dst, const struct stat *statp,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static int fchown_if_needed (int fdst, const struct stat *statp,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
#if defined(WITH_ACL) || defined(WITH_ATTR)
/*
* error_acl - format the error messages for the ACL and EQ libraries.
*/
static void error_acl (struct error_context *ctx, const char *fmt, ...)
{
va_list ap;
/* ignore the case when destination does not support ACLs
* or extended attributes */
if (ENOTSUP == errno) {
errno = 0;
return;
}
va_start (ap, fmt);
(void) fprintf (stderr, _("%s: "), Prog);
if (vfprintf (stderr, fmt, ap) != 0) {
(void) fputs (_(": "), stderr);
}
(void) fprintf (stderr, "%s\n", strerror (errno));
va_end (ap);
}
static struct error_context ctx = {
error_acl
};
#endif /* WITH_ACL || WITH_ATTR */
/*
* remove_link - delete a link from the linked list
*/
static void remove_link (/*@only@*/struct link_name *ln)
{
struct link_name *lp;
if (links == ln) {
links = ln->ln_next;
free (ln->ln_name);
free (ln);
return;
}
for (lp = links; NULL !=lp; lp = lp->ln_next) {
if (lp->ln_next == ln) {
break;
}
}
if (NULL == lp) {
free (ln->ln_name);
free (ln);
return;
}
lp->ln_next = lp->ln_next->ln_next;
free (ln->ln_name);
free (ln);
}
/*
* check_link - see if a file is really a link
*/
static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, const struct stat *sb)
{
struct link_name *lp;
size_t src_len;
size_t dst_len;
size_t name_len;
size_t len;
/* copy_tree () must be the entry point */
assert (NULL != src_orig);
assert (NULL != dst_orig);
for (lp = links; NULL != lp; lp = lp->ln_next) {
if ((lp->ln_dev == sb->st_dev) && (lp->ln_ino == sb->st_ino)) {
return lp;
}
}
if (sb->st_nlink == 1) {
return NULL;
}
lp = (struct link_name *) xmalloc (sizeof *lp);
src_len = strlen (src_orig);
dst_len = strlen (dst_orig);
name_len = strlen (name);
lp->ln_dev = sb->st_dev;
lp->ln_ino = sb->st_ino;
lp->ln_count = sb->st_nlink;
len = name_len - src_len + dst_len + 1;
lp->ln_name = (char *) xmalloc (len);
(void) snprintf (lp->ln_name, len, "%s%s", dst_orig, name + src_len);
lp->ln_next = links;
links = lp;
return NULL;
}
/*
* copy_tree - copy files in a directory tree
*
* copy_tree() walks a directory tree and copies ordinary files
* as it goes.
*
* When reset_selinux is enabled, extended attributes (and thus
* SELinux attributes) are not copied.
*
* old_uid and new_uid are used to set the ownership of the copied
* files. Unless old_uid is set to -1, only the files owned by
* old_uid have their ownership changed to new_uid. In addition, if
* new_uid is set to -1, no ownership will be changed.
*
* The same logic applies for the group-ownership and
* old_gid/new_gid.
*/
int copy_tree (const char *src_root, const char *dst_root,
bool copy_root, bool reset_selinux,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{
int err = 0;
bool set_orig = false;
struct DIRECT *ent;
DIR *dir;
if (copy_root) {
struct stat sb;
if (access (dst_root, F_OK) == 0) {
return -1;
}
if (LSTAT (src_root, &sb) == -1) {
return -1;
}
if (!S_ISDIR (sb.st_mode)) {
fprintf (stderr,
"%s: %s is not a directory",
Prog, src_root);
return -1;
}
return copy_entry (src_root, dst_root, reset_selinux,
old_uid, new_uid, old_gid, new_gid);
}
/*
* Make certain both directories exist. This routine is called
* after the home directory is created, or recursively after the
* target is created. It assumes the target directory exists.
*/
if ( (access (src_root, F_OK) != 0)
|| (access (dst_root, F_OK) != 0)) {
return -1;
}
/*
* Open the source directory and read each entry. Every file
* entry in the directory is copied with the UID and GID set
* to the provided values. As an added security feature only
* regular files (and directories ...) are copied, and no file
* is made set-ID.
*/
dir = opendir (src_root);
if (NULL == dir) {
return -1;
}
if (src_orig == NULL) {
src_orig = src_root;
dst_orig = dst_root;
set_orig = true;
}
while ((0 == err) && (ent = readdir (dir)) != NULL) {
/*
* Skip the "." and ".." entries
*/
if ((strcmp (ent->d_name, ".") != 0) &&
(strcmp (ent->d_name, "..") != 0)) {
char *src_name;
char *dst_name;
size_t src_len = strlen (ent->d_name) + 2;
size_t dst_len = strlen (ent->d_name) + 2;
src_len += strlen (src_root);
dst_len += strlen (dst_root);
src_name = (char *) malloc (src_len);
dst_name = (char *) malloc (dst_len);
if ((NULL == src_name) || (NULL == dst_name)) {
err = -1;
} else {
/*
* Build the filename for both the source and
* the destination files.
*/
(void) snprintf (src_name, src_len, "%s/%s",
src_root, ent->d_name);
(void) snprintf (dst_name, dst_len, "%s/%s",
dst_root, ent->d_name);
err = copy_entry (src_name, dst_name,
reset_selinux,
old_uid, new_uid,
old_gid, new_gid);
}
if (NULL != src_name) {
free (src_name);
}
if (NULL != dst_name) {
free (dst_name);
}
}
}
(void) closedir (dir);
if (set_orig) {
src_orig = NULL;
dst_orig = NULL;
/* FIXME: clean links
* Since there can be hardlinks elsewhere on the device,
* we cannot check that all the hardlinks were found:
assert (NULL == links);
*/
}
#ifdef WITH_SELINUX
/* Reset SELinux to create files with default contexts.
* Note that the context is only reset on exit of copy_tree (it is
* assumed that the program would quit without needing a restored
* context if copy_tree failed previously), and that copy_tree can
* be called recursively (hence the context is set on the
* sub-functions of copy_entry).
*/
if (reset_selinux_file_context () != 0) {
err = -1;
}
#endif /* WITH_SELINUX */
return err;
}
/*
* copy_entry - copy the entry of a directory
*
* Copy the entry src to dst.
* Depending on the type of entry, this function will forward the
* request to copy_dir(), copy_symlink(), copy_hardlink(),
* copy_special(), or copy_file().
*
* The access and modification time will not be modified.
*
* The permissions will be set to new_uid/new_gid.
*
* If new_uid (resp. new_gid) is equal to -1, the user (resp. group) will
* not be modified.
*
* Only the files owned (resp. group-owned) by old_uid (resp.
* old_gid) will be modified, unless old_uid (resp. old_gid) is set
* to -1.
*/
static int copy_entry (const char *src, const char *dst,
bool reset_selinux,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{
int err = 0;
struct stat sb;
struct link_name *lp;
struct timeval mt[2];
if (LSTAT (src, &sb) == -1) {
/* If we cannot stat the file, do not care. */
} else {
#ifdef HAVE_STRUCT_STAT_ST_ATIM
mt[0].tv_sec = sb.st_atim.tv_sec;
mt[0].tv_usec = sb.st_atim.tv_nsec / 1000;
#else /* !HAVE_STRUCT_STAT_ST_ATIM */
mt[0].tv_sec = sb.st_atime;
# ifdef HAVE_STRUCT_STAT_ST_ATIMENSEC
mt[0].tv_usec = sb.st_atimensec / 1000;
# else /* !HAVE_STRUCT_STAT_ST_ATIMENSEC */
mt[0].tv_usec = 0;
# endif /* !HAVE_STRUCT_STAT_ST_ATIMENSEC */
#endif /* !HAVE_STRUCT_STAT_ST_ATIM */
#ifdef HAVE_STRUCT_STAT_ST_MTIM
mt[1].tv_sec = sb.st_mtim.tv_sec;
mt[1].tv_usec = sb.st_mtim.tv_nsec / 1000;
#else /* !HAVE_STRUCT_STAT_ST_MTIM */
mt[1].tv_sec = sb.st_mtime;
# ifdef HAVE_STRUCT_STAT_ST_MTIMENSEC
mt[1].tv_usec = sb.st_mtimensec / 1000;
# else /* !HAVE_STRUCT_STAT_ST_MTIMENSEC */
mt[1].tv_usec = 0;
# endif /* !HAVE_STRUCT_STAT_ST_MTIMENSEC */
#endif /* !HAVE_STRUCT_STAT_ST_MTIM */
if (S_ISDIR (sb.st_mode)) {
err = copy_dir (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
}
#ifdef S_IFLNK
/*
* Copy any symbolic links
*/
else if (S_ISLNK (sb.st_mode)) {
err = copy_symlink (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
}
#endif /* S_IFLNK */
/*
* See if this is a previously copied link
*/
else if ((lp = check_link (src, &sb)) != NULL) {
err = copy_hardlink (dst, reset_selinux, lp);
}
/*
* Deal with FIFOs and special files. The user really
* shouldn't have any of these, but it seems like it
* would be nice to copy everything ...
*/
else if (!S_ISREG (sb.st_mode)) {
err = copy_special (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
}
/*
* Create the new file and copy the contents. The new
* file will be owned by the provided UID and GID values.
*/
else {
err = copy_file (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
}
}
return err;
}
/*
* copy_dir - copy a directory
*
* Copy a directory (recursively) from src to dst.
*
* statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
* the access and modification and the access rights.
*
* Return 0 on success, -1 on error.
*/
static int copy_dir (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{
int err = 0;
/*
* Create a new target directory, make it owned by
* the user and then recursively copy that directory.
*/
#ifdef WITH_SELINUX
if (set_selinux_file_context (dst) != 0) {
return -1;
}
#endif /* WITH_SELINUX */
if ( (mkdir (dst, statp->st_mode) != 0)
|| (chown_if_needed (dst, statp,
old_uid, new_uid, old_gid, new_gid) != 0)
#ifdef WITH_ACL
|| ( (perm_copy_file (src, dst, &ctx) != 0)
&& (errno != 0))
#else /* !WITH_ACL */
|| (chmod (dst, statp->st_mode) != 0)
#endif /* !WITH_ACL */
#ifdef WITH_ATTR
/*
* If the third parameter is NULL, all extended attributes
* except those that define Access Control Lists are copied.
* ACLs are excluded by default because copying them between
* file systems with and without ACL support needs some
* additional logic so that no unexpected permissions result.
*/
|| ( !reset_selinux
&& (attr_copy_file (src, dst, NULL, &ctx) != 0)
&& (errno != 0))
#endif /* WITH_ATTR */
|| (copy_tree (src, dst, false, reset_selinux,
old_uid, new_uid, old_gid, new_gid) != 0)
|| (utimes (dst, mt) != 0)) {
err = -1;
}
return err;
}
#ifdef S_IFLNK
/*
* readlink_malloc - wrapper for readlink
*
* return NULL on error.
* The return string shall be freed by the caller.
*/
static /*@null@*/char *readlink_malloc (const char *filename)
{
size_t size = 1024;
while (true) {
ssize_t nchars;
char *buffer = (char *) malloc (size);
if (NULL == buffer) {
return NULL;
}
nchars = readlink (filename, buffer, size);
if (nchars < 0) {
free(buffer);
return NULL;
}
if ((size_t) nchars < size) { /* The buffer was large enough */
/* readlink does not nul-terminate */
buffer[nchars] = '\0';
return buffer;
}
/* Try again with a bigger buffer */
free (buffer);
size *= 2;
}
}
/*
* copy_symlink - copy a symlink
*
* Copy a symlink from src to dst.
*
* statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
* the access and modification and the access rights.
*
* Return 0 on success, -1 on error.
*/
static int copy_symlink (const char *src, const char *dst,
unused bool reset_selinux,
const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{
char *oldlink;
/* copy_tree () must be the entry point */
assert (NULL != src_orig);
assert (NULL != dst_orig);
/*
* Get the name of the file which the link points
* to. If that name begins with the original
* source directory name, that part of the link
* name will be replaced with the original
* destination directory name.
*/
oldlink = readlink_malloc (src);
if (NULL == oldlink) {
return -1;
}
/* If src was a link to an entry of the src_orig directory itself,
* create a link to the corresponding entry in the dst_orig
* directory.
*/
if (strncmp (oldlink, src_orig, strlen (src_orig)) == 0) {
size_t len = strlen (dst_orig) + strlen (oldlink) - strlen (src_orig) + 1;
char *dummy = (char *) xmalloc (len);
(void) snprintf (dummy, len, "%s%s",
dst_orig,
oldlink + strlen (src_orig));
free (oldlink);
oldlink = dummy;
}
#ifdef WITH_SELINUX
if (set_selinux_file_context (dst) != 0) {
free (oldlink);
return -1;
}
#endif /* WITH_SELINUX */
if ( (symlink (oldlink, dst) != 0)
|| (lchown_if_needed (dst, statp,
old_uid, new_uid, old_gid, new_gid) != 0)) {
/* FIXME: there are no modes on symlinks, right?
* ACL could be copied, but this would be much more
* complex than calling perm_copy_file.
* Ditto for Extended Attributes.
* We currently only document that ACL and Extended
* Attributes are not copied.
*/
free (oldlink);
return -1;
}
free (oldlink);
#ifdef HAVE_LUTIMES
/* 2007-10-18: We don't care about
* exit status of lutimes because
* it returns ENOSYS on many system
* - not implemented
*/
(void) lutimes (dst, mt);
#endif /* HAVE_LUTIMES */
return 0;
}
#endif /* S_IFLNK */
/*
* copy_hardlink - copy a hardlink
*
* Copy a hardlink from src to dst.
*
* Return 0 on success, -1 on error.
*/
static int copy_hardlink (const char *dst,
unused bool reset_selinux,
struct link_name *lp)
{
/* FIXME: selinux, ACL, Extended Attributes needed? */
if (link (lp->ln_name, dst) != 0) {
return -1;
}
/* If the file could be unlinked, decrement the links counter,
* and forget about this link if it was the last reference */
lp->ln_count--;
if (lp->ln_count <= 0) {
remove_link (lp);
}
return 0;
}
/*
* copy_special - copy a special file
*
* Copy a special file from src to dst.
*
* statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
* the access and modification and the access rights.
*
* Return 0 on success, -1 on error.
*/
static int copy_special (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{
int err = 0;
#ifdef WITH_SELINUX
if (set_selinux_file_context (dst) != 0) {
return -1;
}
#endif /* WITH_SELINUX */
if ( (mknod (dst, statp->st_mode & ~07777, statp->st_rdev) != 0)
|| (chown_if_needed (dst, statp,
old_uid, new_uid, old_gid, new_gid) != 0)
#ifdef WITH_ACL
|| ( (perm_copy_file (src, dst, &ctx) != 0)
&& (errno != 0))
#else /* !WITH_ACL */
|| (chmod (dst, statp->st_mode & 07777) != 0)
#endif /* !WITH_ACL */
#ifdef WITH_ATTR
/*
* If the third parameter is NULL, all extended attributes
* except those that define Access Control Lists are copied.
* ACLs are excluded by default because copying them between
* file systems with and without ACL support needs some
* additional logic so that no unexpected permissions result.
*/
|| ( !reset_selinux
&& (attr_copy_file (src, dst, NULL, &ctx) != 0)
&& (errno != 0))
#endif /* WITH_ATTR */
|| (utimes (dst, mt) != 0)) {
err = -1;
}
return err;
}
/*
* copy_file - copy a file
*
* Copy a file from src to dst.
*
* statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
* the access and modification and the access rights.
*
* Return 0 on success, -1 on error.
*/
static int copy_file (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{
int err = 0;
int ifd;
int ofd;
char buf[1024];
ssize_t cnt;
ifd = open (src, O_RDONLY);
if (ifd < 0) {
return -1;
}
#ifdef WITH_SELINUX
if (set_selinux_file_context (dst) != 0) {
return -1;
}
#endif /* WITH_SELINUX */
ofd = open (dst, O_WRONLY | O_CREAT | O_TRUNC, statp->st_mode & 07777);
if ( (ofd < 0)
|| (fchown_if_needed (ofd, statp,
old_uid, new_uid, old_gid, new_gid) != 0)
#ifdef WITH_ACL
|| ( (perm_copy_fd (src, ifd, dst, ofd, &ctx) != 0)
&& (errno != 0))
#else /* !WITH_ACL */
|| (fchmod (ofd, statp->st_mode & 07777) != 0)
#endif /* !WITH_ACL */
#ifdef WITH_ATTR
/*
* If the third parameter is NULL, all extended attributes
* except those that define Access Control Lists are copied.
* ACLs are excluded by default because copying them between
* file systems with and without ACL support needs some
* additional logic so that no unexpected permissions result.
*/
|| ( !reset_selinux
&& (attr_copy_fd (src, ifd, dst, ofd, NULL, &ctx) != 0)
&& (errno != 0))
#endif /* WITH_ATTR */
) {
(void) close (ifd);
return -1;
}
while ((cnt = read (ifd, buf, sizeof buf)) > 0) {
if (write (ofd, buf, (size_t)cnt) != cnt) {
(void) close (ifd);
return -1;
}
}
(void) close (ifd);
#ifdef HAVE_FUTIMES
if (futimes (ofd, mt) != 0) {
return -1;
}
#endif /* HAVE_FUTIMES */
if (close (ofd) != 0) {
return -1;
}
#ifndef HAVE_FUTIMES
if (utimes(dst, mt) != 0) {
return -1;
}
#endif /* !HAVE_FUTIMES */
return err;
}
#define def_chown_if_needed(chown_function, type_dst) \
static int chown_function ## _if_needed (type_dst dst, \
const struct stat *statp, \
uid_t old_uid, uid_t new_uid, \
gid_t old_gid, gid_t new_gid) \
{ \
uid_t tmpuid = (uid_t) -1; \
gid_t tmpgid = (gid_t) -1; \
\
/* Use new_uid if old_uid is set to -1 or if the file was \
* owned by the user. */ \
if (((uid_t) -1 == old_uid) || (statp->st_uid == old_uid)) { \
tmpuid = new_uid; \
} \
/* Otherwise, or if new_uid was set to -1, we keep the same \
* owner. */ \
if ((uid_t) -1 == tmpuid) { \
tmpuid = statp->st_uid; \
} \
\
if (((gid_t) -1 == old_gid) || (statp->st_gid == old_gid)) { \
tmpgid = new_gid; \
} \
if ((gid_t) -1 == tmpgid) { \
tmpgid = statp->st_gid; \
} \
\
return chown_function (dst, tmpuid, tmpgid); \
}
def_chown_if_needed (chown, const char *)
def_chown_if_needed (lchown, const char *)
def_chown_if_needed (fchown, int)
+68
View File
@@ -0,0 +1,68 @@
/*
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: entry.c 1980 2008-04-27 00:40:09Z nekral-guest $"
#include <sys/types.h>
#include <stdio.h>
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
void pw_entry (const char *name, struct passwd *pwent)
{
struct passwd *passwd;
struct spwd *spwd;
if (!(passwd = getpwnam (name))) { /* local, no need for xgetpwnam */
pwent->pw_name = (char *) 0;
return;
} else {
pwent->pw_name = xstrdup (passwd->pw_name);
pwent->pw_uid = passwd->pw_uid;
pwent->pw_gid = passwd->pw_gid;
pwent->pw_gecos = xstrdup (passwd->pw_gecos);
pwent->pw_dir = xstrdup (passwd->pw_dir);
pwent->pw_shell = xstrdup (passwd->pw_shell);
#if !defined(AUTOSHADOW)
/* local, no need for xgetspnam */
if ((spwd = getspnam (name))) {
pwent->pw_passwd = xstrdup (spwd->sp_pwdp);
return;
}
#endif
pwent->pw_passwd = xstrdup (passwd->pw_passwd);
}
}
+275
View File
@@ -0,0 +1,275 @@
/*
* Copyright (c) 1989 - 1992, Julianne Frances Haugh
* Copyright (c) 1996 - 1999, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: env.c 3362 2011-06-16 21:25:36Z nekral-guest $"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "prototypes.h"
#include "defines.h"
/*
* NEWENVP_STEP must be a power of two. This is the number
* of (char *) pointers to allocate at a time, to avoid using
* realloc() too often.
*/
#define NEWENVP_STEP 16
size_t newenvc = 0;
/*@null@*/char **newenvp = NULL;
extern char **environ;
static const char *forbid[] = {
"_RLD_=",
"BASH_ENV=", /* GNU creeping featurism strikes again... */
"ENV=",
"HOME=",
"IFS=",
"KRB_CONF=",
"LD_", /* anything with the LD_ prefix */
"LIBPATH=",
"MAIL=",
"NLSPATH=",
"PATH=",
"SHELL=",
"SHLIB_PATH=",
(char *) 0
};
/* these are allowed, but with no slashes inside
(to work around security problems in GNU gettext) */
static const char *noslash[] = {
"LANG=",
"LANGUAGE=",
"LC_", /* anything with the LC_ prefix */
(char *) 0
};
/*
* initenv() must be called once before using addenv().
*/
void initenv (void)
{
newenvp = (char **) xmalloc (NEWENVP_STEP * sizeof (char *));
*newenvp = NULL;
}
void addenv (const char *string, /*@null@*/const char *value)
{
char *cp, *newstring;
size_t i;
size_t n;
if (NULL != value) {
size_t len = strlen (string) + strlen (value) + 2;
int wlen;
newstring = xmalloc (len);
wlen = snprintf (newstring, len, "%s=%s", string, value);
assert (wlen == (int) len -1);
} else {
newstring = xstrdup (string);
}
/*
* Search for a '=' character within the string and if none is found
* just ignore the whole string.
*/
cp = strchr (newstring, '=');
if (NULL == cp) {
free (newstring);
return;
}
n = (size_t) (cp - newstring);
/*
* If this environment variable is already set, change its value.
*/
for (i = 0; i < newenvc; i++) {
if ( (strncmp (newstring, newenvp[i], n) == 0)
&& (('=' == newenvp[i][n]) || ('\0' == newenvp[i][n]))) {
break;
}
}
if (i < newenvc) {
free (newenvp[i]);
newenvp[i] = newstring;
return;
}
/*
* Otherwise, save the new environment variable
*/
newenvp[newenvc++] = newstring;
/*
* And extend the environment if needed.
*/
/*
* Check whether newenvc is a multiple of NEWENVP_STEP.
* If so we have to resize the vector.
* the expression (newenvc & (NEWENVP_STEP - 1)) == 0
* is equal to (newenvc % NEWENVP_STEP) == 0
* as long as NEWENVP_STEP is a power of 2.
*/
if ((newenvc & (NEWENVP_STEP - 1)) == 0) {
char **__newenvp;
size_t newsize;
/*
* If the resize operation succeeds we can
* happily go on, else print a message.
*/
newsize = (newenvc + NEWENVP_STEP) * sizeof (char *);
__newenvp = (char **) realloc (newenvp, newsize);
if (NULL != __newenvp) {
/*
* If this is our current environment, update
* environ so that it doesn't point to some
* free memory area (realloc() could move it).
*/
if (environ == newenvp) {
environ = __newenvp;
}
newenvp = __newenvp;
} else {
(void) fputs (_("Environment overflow\n"), stderr);
newenvc--;
free (newenvp[newenvc]);
}
}
/*
* The last entry of newenvp must be NULL
*/
newenvp[newenvc] = NULL;
}
/*
* set_env - copy command line arguments into the environment
*/
void set_env (int argc, char *const *argv)
{
int noname = 1;
char variable[1024];
char *cp;
for (; argc > 0; argc--, argv++) {
if (strlen (*argv) >= sizeof variable) {
continue; /* ignore long entries */
}
cp = strchr (*argv, '=');
if (NULL == cp) {
int wlen;
wlen = snprintf (variable, sizeof variable, "L%d", noname);
assert (wlen < (int) sizeof(variable));
noname++;
addenv (variable, *argv);
} else {
const char **p;
for (p = forbid; NULL != *p; p++) {
if (strncmp (*argv, *p, strlen (*p)) == 0) {
break;
}
}
if (NULL != *p) {
strncpy (variable, *argv, (size_t)(cp - *argv));
variable[cp - *argv] = '\0';
printf (_("You may not change $%s\n"),
variable);
continue;
}
addenv (*argv, NULL);
}
}
}
/*
* sanitize_env - remove some nasty environment variables
* If you fall into a total paranoia, you should call this
* function for any root-setuid program or anything the user
* might change the environment with. 99% useless as almost
* all modern Unixes will handle setuid executables properly,
* but... I feel better with that silly precaution. -j.
*/
void sanitize_env (void)
{
char **envp = environ;
const char **bad;
char **cur;
char **move;
for (cur = envp; NULL != *cur; cur++) {
for (bad = forbid; NULL != *bad; bad++) {
if (strncmp (*cur, *bad, strlen (*bad)) == 0) {
for (move = cur; NULL != *move; move++) {
*move = *(move + 1);
}
cur--;
break;
}
}
}
for (cur = envp; NULL != *cur; cur++) {
for (bad = noslash; NULL != *bad; bad++) {
if (strncmp (*cur, *bad, strlen (*bad)) != 0) {
continue;
}
if (strchr (*cur, '/') == NULL) {
continue; /* OK */
}
for (move = cur; NULL != *move; move++) {
*move = *(move + 1);
}
cur--;
break;
}
}
}
+343
View File
@@ -0,0 +1,343 @@
/*
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2002 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2010, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: failure.c 3232 2010-08-22 19:13:53Z nekral-guest $"
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include "defines.h"
#include "faillog.h"
#include "getdef.h"
#include "failure.h"
#define YEAR (365L*DAY)
/*
* failure - make failure entry
*
* failure() creates a new (struct faillog) entry or updates an
* existing one with the current failed login information.
*/
void failure (uid_t uid, const char *tty, struct faillog *fl)
{
int fd;
off_t offset_uid = (off_t) (sizeof *fl) * uid;
/*
* Don't do anything if failure logging isn't set up.
*/
if (access (FAILLOG_FILE, F_OK) != 0) {
return;
}
fd = open (FAILLOG_FILE, O_RDWR);
if (fd < 0) {
SYSLOG ((LOG_WARN,
"Can't write faillog entry for UID %lu in %s.",
(unsigned long) uid, FAILLOG_FILE));
return;
}
/*
* The file is indexed by UID value meaning that shared UID's
* share failure log records. That's OK since they really
* share just about everything else ...
*/
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|| (read (fd, (char *) fl, sizeof *fl) != (ssize_t) sizeof *fl)) {
/* This is not necessarily a failure. The file is
* initially zero length.
*
* If lseek() or read() failed for any other reason, this
* might reset the counter. But the new failure will be
* logged.
*/
memzero (fl, sizeof *fl);
}
/*
* Update the record. We increment the failure count to log the
* latest failure. The only concern here is overflow, and we'll
* check for that. The line name and time of day are both
* updated as well.
*/
if (fl->fail_cnt + 1 > 0) {
fl->fail_cnt++;
}
strncpy (fl->fail_line, tty, sizeof fl->fail_line);
(void) time (&fl->fail_time);
/*
* Seek back to the correct position in the file and write the
* record out. Ideally we should lock the file in case the same
* account is being logged simultaneously. But the risk doesn't
* seem that great.
*/
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|| (write (fd, (char *) fl, sizeof *fl) != (ssize_t) sizeof *fl)
|| (close (fd) != 0)) {
SYSLOG ((LOG_WARN,
"Can't write faillog entry for UID %lu in %s.",
(unsigned long) uid, FAILLOG_FILE));
(void) close (fd);
}
}
static bool too_many_failures (const struct faillog *fl)
{
time_t now;
if ((0 == fl->fail_max) || (fl->fail_cnt < fl->fail_max)) {
return false;
}
if (0 == fl->fail_locktime) {
return true; /* locked until reset manually */
}
(void) time (&now);
if ((fl->fail_time + fl->fail_locktime) < now) {
return false; /* enough time since last failure */
}
return true;
}
/*
* failcheck - check for failures > allowable
*
* failcheck() is called AFTER the password has been validated. If the
* account has been "attacked" with too many login failures, failcheck()
* returns 0 to indicate that the login should be denied even though
* the password is valid.
*
* failed indicates if the login failed AFTER the password has been
* validated.
*/
int failcheck (uid_t uid, struct faillog *fl, bool failed)
{
int fd;
struct faillog fail;
off_t offset_uid = (off_t) (sizeof *fl) * uid;
/*
* Suppress the check if the log file isn't there.
*/
if (access (FAILLOG_FILE, F_OK) != 0) {
return 1;
}
fd = open (FAILLOG_FILE, failed?O_RDONLY:O_RDWR);
if (fd < 0) {
SYSLOG ((LOG_WARN,
"Can't open the faillog file (%s) to check UID %lu. "
"User access authorized.",
FAILLOG_FILE, (unsigned long) uid));
return 1;
}
/*
* Get the record from the file and determine if the user has
* exceeded the failure limit. If "max" is zero, any number
* of failures are permitted. Only when "max" is non-zero and
* "cnt" is greater than or equal to "max" is the account
* considered to be locked.
*
* If read fails, there is no record for this user yet (the
* file is initially zero length and extended by writes), so
* no need to reset the count.
*/
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|| (read (fd, (char *) fl, sizeof *fl) != (ssize_t) sizeof *fl)) {
(void) close (fd);
return 1;
}
if (too_many_failures (fl)) {
(void) close (fd);
return 0;
}
/*
* The record is updated if this is not a failure. The count will
* be reset to zero, but the rest of the information will be left
* in the record in case someone wants to see where the failed
* login originated.
*/
if (!failed) {
fail = *fl;
fail.fail_cnt = 0;
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|| (write (fd, (const void *) &fail, sizeof fail) != (ssize_t) sizeof fail)
|| (close (fd) != 0)) {
SYSLOG ((LOG_WARN,
"Can't reset faillog entry for UID %lu in %s.",
(unsigned long) uid, FAILLOG_FILE));
(void) close (fd);
}
} else {
(void) close (fd);
}
return 1;
}
/*
* failprint - print line of failure information
*
* failprint takes a (struct faillog) entry and formats it into a
* message which is displayed at login time.
*/
void failprint (const struct faillog *fail)
{
struct tm *tp;
#if HAVE_STRFTIME
char lasttimeb[256];
char *lasttime = lasttimeb;
#else
char *lasttime;
#endif
time_t NOW;
if (0 == fail->fail_cnt) {
return;
}
tp = localtime (&(fail->fail_time));
(void) time (&NOW);
#if HAVE_STRFTIME
/*
* Print all information we have.
*/
(void) strftime (lasttimeb, sizeof lasttimeb, "%c", tp);
#else
/*
* Do the same thing, but don't use strftime since it
* probably doesn't exist on this system
*/
lasttime = asctime (tp);
lasttime[24] = '\0';
if ((NOW - fail->fail_time) < YEAR) {
lasttime[19] = '\0';
}
if ((NOW - fail->fail_time) < DAY) {
lasttime = lasttime + 11;
}
if (' ' == *lasttime) {
lasttime++;
}
#endif
/*@-formatconst@*/
(void) printf (ngettext ("%d failure since last login.\n"
"Last was %s on %s.\n",
"%d failures since last login.\n"
"Last was %s on %s.\n",
(unsigned long) fail->fail_cnt),
fail->fail_cnt, lasttime, fail->fail_line);
/*@=formatconst@*/
}
/*
* failtmp - update the cumulative failure log
*
* failtmp updates the (struct utmp) formatted failure log which
* maintains a record of all login failures.
*/
void failtmp (const char *username,
#ifdef USE_UTMPX
const struct utmpx *failent
#else /* !USE_UTMPX */
const struct utmp *failent
#endif /* !USE_UTMPX */
)
{
const char *ftmp;
int fd;
/*
* Get the name of the failure file. If no file has been defined
* in login.defs, don't do this.
*/
ftmp = getdef_str ("FTMP_FILE");
if (NULL == ftmp) {
return;
}
/*
* Open the file for append. It must already exist for this
* feature to be used.
*/
if (access (ftmp, F_OK) != 0) {
return;
}
fd = open (ftmp, O_WRONLY | O_APPEND);
if (-1 == fd) {
SYSLOG ((LOG_WARN,
"Can't append failure of user %s to %s.",
username, ftmp));
return;
}
/*
* Append the new failure record and close the log file.
*/
if ( (write (fd, (const void *) failent, sizeof *failent) != (ssize_t) sizeof *failent)
|| (close (fd) != 0)) {
SYSLOG ((LOG_WARN,
"Can't append failure of user %s to %s.",
username, ftmp));
(void) close (fd);
}
}
+84
View File
@@ -0,0 +1,84 @@
/*
* Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1997 - 2000, Marek Michałkiewicz
* Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2008 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* $Id: failure.h 2831 2009-04-28 19:19:33Z nekral-guest $ */
#ifndef _FAILURE_H_
#define _FAILURE_H_
#include "defines.h"
#include "faillog.h"
#ifdef USE_UTMPX
#include <utmpx.h>
#else /* !USE_UTMPX */
#include <utmp.h>
#endif /* !USE_UTMPX */
/*
* failure - make failure entry
*
* failure() creates a new (struct faillog) entry or updates an
* existing one with the current failed login information.
*/
extern void failure (uid_t, const char *, struct faillog *);
/*
* failcheck - check for failures > allowable
*
* failcheck() is called AFTER the password has been validated. If the
* account has been "attacked" with too many login failures, failcheck()
* returns FALSE to indicate that the login should be denied even though
* the password is valid.
*/
extern int failcheck (uid_t uid, struct faillog *fl, bool failed);
/*
* failprint - print line of failure information
*
* failprint takes a (struct faillog) entry and formats it into a
* message which is displayed at login time.
*/
extern void failprint (const struct faillog *);
/*
* failtmp - update the cummulative failure log
*
* failtmp updates the (struct utmp) formatted failure log which
* maintains a record of all login failures.
*/
#ifdef USE_UTMPX
extern void failtmp (const char *username, const struct utmpx *);
#else /* !USE_UTMPX */
extern void failtmp (const char *username, const struct utmp *);
#endif /* !USE_UTMPX */
#endif
+209
View File
@@ -0,0 +1,209 @@
/*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 2008 - 2011, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include "prototypes.h"
#include "groupio.h"
#include "getdef.h"
/*
* find_new_gid - Find a new unused GID.
*
* If successful, find_new_gid provides an unused group ID in the
* [GID_MIN:GID_MAX] range.
* This ID should be higher than all the used GID, but if not possible,
* the lowest unused ID in the range will be returned.
*
* Return 0 on success, -1 if no unused GIDs are available.
*/
int find_new_gid (bool sys_group,
gid_t *gid,
/*@null@*/gid_t const *preferred_gid)
{
const struct group *grp;
gid_t gid_min, gid_max, group_id;
bool *used_gids;
assert (gid != NULL);
if (!sys_group) {
gid_min = (gid_t) getdef_ulong ("GID_MIN", 1000UL);
gid_max = (gid_t) getdef_ulong ("GID_MAX", 60000UL);
if (gid_max < gid_min) {
(void) fprintf (stderr,
_("%s: Invalid configuration: GID_MIN (%lu), GID_MAX (%lu)\n"),
Prog, (unsigned long) gid_min, (unsigned long) gid_max);
return -1;
}
} else {
gid_min = (gid_t) getdef_ulong ("SYS_GID_MIN", 101UL);
gid_max = (gid_t) getdef_ulong ("GID_MIN", 1000UL) - 1;
gid_max = (gid_t) getdef_ulong ("SYS_GID_MAX", (unsigned long) gid_max);
if (gid_max < gid_min) {
(void) fprintf (stderr,
_("%s: Invalid configuration: SYS_GID_MIN (%lu), GID_MIN (%lu), SYS_GID_MAX (%lu)\n"),
Prog, (unsigned long) gid_min, getdef_ulong ("GID_MIN", 1000UL), (unsigned long) gid_max);
return -1;
}
}
used_gids = malloc (sizeof (bool) * (gid_max +1));
if (NULL == used_gids) {
fprintf (stderr,
_("%s: failed to allocate memory: %s\n"),
Prog, strerror (errno));
return -1;
}
memset (used_gids, false, sizeof (bool) * (gid_max + 1));
if ( (NULL != preferred_gid)
&& (*preferred_gid >= gid_min)
&& (*preferred_gid <= gid_max)
/* Check if the user exists according to NSS */
&& (getgrgid (*preferred_gid) == NULL)
/* Check also the local database in case of uncommitted
* changes */
&& (gr_locate_gid (*preferred_gid) == NULL)) {
*gid = *preferred_gid;
free (used_gids);
return 0;
}
/*
* Search the entire group file,
* looking for the largest unused value.
*
* We check the list of groups according to NSS (setgrent/getgrent),
* but we also check the local database (gr_rewind/gr_next) in case
* some groups were created but the changes were not committed yet.
*/
if (sys_group) {
gid_t id;
/* setgrent / getgrent / endgrent can be very slow with
* LDAP configurations (and many accounts).
* Since there is a limited amount of IDs to be tested
* for system accounts, we just check the existence
* of IDs with getgrgid.
*/
group_id = gid_max;
for (id = gid_max; id >= gid_min; id--) {
if (getgrgid (id) != NULL) {
group_id = id - 1;
used_gids[id] = true;
}
}
(void) gr_rewind ();
while ((grp = gr_next ()) != NULL) {
if ((grp->gr_gid <= group_id) && (grp->gr_gid >= gid_min)) {
group_id = grp->gr_gid - 1;
}
/* create index of used GIDs */
if (grp->gr_gid <= gid_max) {
used_gids[grp->gr_gid] = true;
}
}
} else {
group_id = gid_min;
setgrent ();
while ((grp = getgrent ()) != NULL) {
if ((grp->gr_gid >= group_id) && (grp->gr_gid <= gid_max)) {
group_id = grp->gr_gid + 1;
}
/* create index of used GIDs */
if (grp->gr_gid <= gid_max) {
used_gids[grp->gr_gid] = true;
}
}
endgrent ();
(void) gr_rewind ();
while ((grp = gr_next ()) != NULL) {
if ((grp->gr_gid >= group_id) && (grp->gr_gid <= gid_max)) {
group_id = grp->gr_gid + 1;
}
/* create index of used GIDs */
if (grp->gr_gid <= gid_max) {
used_gids[grp->gr_gid] = true;
}
}
}
/*
* If a group (resp. system group) with GID equal to GID_MAX (resp.
* GID_MIN) exists, the above algorithm will give us GID_MAX+1
* (resp. GID_MIN-1) even if not unique. Search for the first free
* GID starting with GID_MIN (resp. GID_MAX).
*/
if (sys_group) {
if (group_id < gid_min) {
for (group_id = gid_max; group_id >= gid_min; group_id--) {
if (false == used_gids[group_id]) {
break;
}
}
if (group_id < gid_min) {
fprintf (stderr,
_("%s: Can't get unique system GID (no more available GIDs)\n"),
Prog);
SYSLOG ((LOG_WARN,
"no more available GID on the system"));
free (used_gids);
return -1;
}
}
} else {
if (group_id > gid_max) {
for (group_id = gid_min; group_id <= gid_max; group_id++) {
if (false == used_gids[group_id]) {
break;
}
}
if (group_id > gid_max) {
fprintf (stderr,
_("%s: Can't get unique GID (no more available GIDs)\n"),
Prog);
SYSLOG ((LOG_WARN, "no more available GID on the system"));
free (used_gids);
return -1;
}
}
}
free (used_gids);
*gid = group_id;
return 0;
}
+209
View File
@@ -0,0 +1,209 @@
/*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 2008 - 2011, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include "prototypes.h"
#include "pwio.h"
#include "getdef.h"
/*
* find_new_uid - Find a new unused UID.
*
* If successful, find_new_uid provides an unused user ID in the
* [UID_MIN:UID_MAX] range.
* This ID should be higher than all the used UID, but if not possible,
* the lowest unused ID in the range will be returned.
*
* Return 0 on success, -1 if no unused UIDs are available.
*/
int find_new_uid (bool sys_user,
uid_t *uid,
/*@null@*/uid_t const *preferred_uid)
{
const struct passwd *pwd;
uid_t uid_min, uid_max, user_id;
bool *used_uids;
assert (uid != NULL);
if (!sys_user) {
uid_min = (uid_t) getdef_ulong ("UID_MIN", 1000UL);
uid_max = (uid_t) getdef_ulong ("UID_MAX", 60000UL);
if (uid_max < uid_min) {
(void) fprintf (stderr,
_("%s: Invalid configuration: UID_MIN (%lu), UID_MAX (%lu)\n"),
Prog, (unsigned long) uid_min, (unsigned long) uid_max);
return -1;
}
} else {
uid_min = (uid_t) getdef_ulong ("SYS_UID_MIN", 101UL);
uid_max = (uid_t) getdef_ulong ("UID_MIN", 1000UL) - 1;
uid_max = (uid_t) getdef_ulong ("SYS_UID_MAX", (unsigned long) uid_max);
if (uid_max < uid_min) {
(void) fprintf (stderr,
_("%s: Invalid configuration: SYS_UID_MIN (%lu), UID_MIN (%lu), SYS_UID_MAX (%lu)\n"),
Prog, (unsigned long) uid_min, getdef_ulong ("UID_MIN", 1000UL), (unsigned long) uid_max);
return -1;
}
}
used_uids = malloc (sizeof (bool) * (uid_max +1));
if (NULL == used_uids) {
fprintf (stderr,
_("%s: failed to allocate memory: %s\n"),
Prog, strerror (errno));
return -1;
}
memset (used_uids, false, sizeof (bool) * (uid_max + 1));
if ( (NULL != preferred_uid)
&& (*preferred_uid >= uid_min)
&& (*preferred_uid <= uid_max)
/* Check if the user exists according to NSS */
&& (getpwuid (*preferred_uid) == NULL)
/* Check also the local database in case of uncommitted
* changes */
&& (pw_locate_uid (*preferred_uid) == NULL)) {
*uid = *preferred_uid;
free (used_uids);
return 0;
}
/*
* Search the entire password file,
* looking for the largest unused value.
*
* We check the list of users according to NSS (setpwent/getpwent),
* but we also check the local database (pw_rewind/pw_next) in case
* some users were created but the changes were not committed yet.
*/
if (sys_user) {
uid_t id;
/* setpwent / getpwent / endpwent can be very slow with
* LDAP configurations (and many accounts).
* Since there is a limited amount of IDs to be tested
* for system accounts, we just check the existence
* of IDs with getpwuid.
*/
user_id = uid_max;
for (id = uid_max; id >= uid_min; id--) {
if (getpwuid (id) != NULL) {
user_id = id - 1;
used_uids[id] = true;
}
}
(void) pw_rewind ();
while ((pwd = pw_next ()) != NULL) {
if ((pwd->pw_uid <= user_id) && (pwd->pw_uid >= uid_min)) {
user_id = pwd->pw_uid - 1;
}
/* create index of used UIDs */
if (pwd->pw_uid <= uid_max) {
used_uids[pwd->pw_uid] = true;
}
}
} else {
user_id = uid_min;
setpwent ();
while ((pwd = getpwent ()) != NULL) {
if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) {
user_id = pwd->pw_uid + 1;
}
/* create index of used UIDs */
if (pwd->pw_uid <= uid_max) {
used_uids[pwd->pw_uid] = true;
}
}
endpwent ();
(void) pw_rewind ();
while ((pwd = pw_next ()) != NULL) {
if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) {
user_id = pwd->pw_uid + 1;
}
/* create index of used UIDs */
if (pwd->pw_uid <= uid_max) {
used_uids[pwd->pw_uid] = true;
}
}
}
/*
* If a user (resp. system user) with UID equal to UID_MAX (resp.
* UID_MIN) exists, the above algorithm will give us UID_MAX+1
* (resp. UID_MIN-1) even if not unique. Search for the first free
* UID starting with UID_MIN (resp. UID_MAX).
*/
if (sys_user) {
if (user_id < uid_min) {
for (user_id = uid_max; user_id >= uid_min; user_id--) {
if (false == used_uids[user_id]) {
break;
}
}
if (user_id < uid_min ) {
fprintf (stderr,
_("%s: Can't get unique system UID (no more available UIDs)\n"),
Prog);
SYSLOG ((LOG_WARN,
"no more available UID on the system"));
free (used_uids);
return -1;
}
}
} else {
if (user_id > uid_max) {
for (user_id = uid_min; user_id <= uid_max; user_id++) {
if (false == used_uids[user_id]) {
break;
}
}
if (user_id > uid_max) {
fprintf (stderr,
_("%s: Can't get unique UID (no more available UIDs)\n"),
Prog);
SYSLOG ((LOG_WARN, "no more available UID on the system"));
free (used_uids);
return -1;
}
}
}
free (used_uids);
*uid = user_id;
return 0;
}
+2732
View File
File diff suppressed because it is too large Load Diff
+39
View File
@@ -0,0 +1,39 @@
/*
* Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1997 - 2000, Marek Michałkiewicz
* Copyright (c) 2005 , Tomasz Kłoczko
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _GETDATE_H_
#define _GETDATE_H_
#include <config.h>
#include "defines.h"
time_t get_date (const char *p, /*@null@*/const time_t *now);
#endif
+977
View File
@@ -0,0 +1,977 @@
%{
/*
** Originally written by Steven M. Bellovin <smb@research.att.com> while
** at the University of North Carolina at Chapel Hill. Later tweaked by
** a couple of people on Usenet. Completely overhauled by Rich $alz
** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
**
** This grammar has 13 shift/reduce conflicts.
**
** This code is in the public domain and has no copyright.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
# ifdef FORCE_ALLOCA_H
# include <alloca.h>
# endif
#endif
/* Since the code of getdate.y is not included in the Emacs executable
itself, there is no need to #define static in this file. Even if
the code were included in the Emacs executable, it probably
wouldn't do any harm to #undef it here; this will only cause
problems if we try to write to a static variable, which I don't
think this code needs to do. */
#ifdef emacs
# undef static
#endif
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
# define IN_CTYPE_DOMAIN(c) 1
#else
# define IN_CTYPE_DOMAIN(c) isascii(c)
#endif
#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c))
#define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c))
#define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))
/* ISDIGIT differs from ISDIGIT_LOCALE, as follows:
- Its arg may be any int or unsigned int; it need not be an unsigned char.
- It's guaranteed to evaluate its argument exactly once.
- It's typically faster.
Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that
only '0' through '9' are digits. Prefer ISDIGIT to ISDIGIT_LOCALE unless
it's important to use the locale's definition of `digit' even when the
host does not conform to Posix. */
#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
#include "getdate.h"
#if defined (STDC_HEADERS)
# include <string.h>
#endif
/* Some old versions of bison generate parsers that use bcopy.
That loses on systems that don't provide the function, so we have
to redefine it here. */
#if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy)
# define bcopy(from, to, len) memcpy ((to), (from), (len))
#endif
/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
as well as gratuitiously global symbol names, so we can have multiple
yacc generated parsers in the same program. Note that these are only
the variables produced by yacc. If other parser generators (bison,
byacc, etc) produce additional global names that conflict at link time,
then those parser generators need to be fixed instead of adding those
names to this list. */
#define yymaxdepth gd_maxdepth
#define yyparse gd_parse
#define yylex gd_lex
#define yyerror gd_error
#define yylval gd_lval
#define yychar gd_char
#define yydebug gd_debug
#define yypact gd_pact
#define yyr1 gd_r1
#define yyr2 gd_r2
#define yydef gd_def
#define yychk gd_chk
#define yypgo gd_pgo
#define yyact gd_act
#define yyexca gd_exca
#define yyerrflag gd_errflag
#define yynerrs gd_nerrs
#define yyps gd_ps
#define yypv gd_pv
#define yys gd_s
#define yy_yys gd_yys
#define yystate gd_state
#define yytmp gd_tmp
#define yyv gd_v
#define yy_yyv gd_yyv
#define yyval gd_val
#define yylloc gd_lloc
#define yyreds gd_reds /* With YYDEBUG defined */
#define yytoks gd_toks /* With YYDEBUG defined */
#define yylhs gd_yylhs
#define yylen gd_yylen
#define yydefred gd_yydefred
#define yydgoto gd_yydgoto
#define yysindex gd_yysindex
#define yyrindex gd_yyrindex
#define yygindex gd_yygindex
#define yytable gd_yytable
#define yycheck gd_yycheck
static int yylex (void);
static int yyerror (const char *s);
#define EPOCH 1970
#define HOUR(x) ((x) * 60)
#define MAX_BUFF_LEN 128 /* size of buffer to read the date into */
/*
** An entry in the lexical lookup table.
*/
typedef struct _TABLE {
const char *name;
int type;
int value;
} TABLE;
/*
** Meridian: am, pm, or 24-hour style.
*/
typedef enum _MERIDIAN {
MERam, MERpm, MER24
} MERIDIAN;
/*
** Global variables. We could get rid of most of these by using a good
** union as the yacc stack. (This routine was originally written before
** yacc had the %union construct.) Maybe someday; right now we only use
** the %union very rarely.
*/
static const char *yyInput;
static int yyDayOrdinal;
static int yyDayNumber;
static int yyHaveDate;
static int yyHaveDay;
static int yyHaveRel;
static int yyHaveTime;
static int yyHaveZone;
static int yyTimezone;
static int yyDay;
static int yyHour;
static int yyMinutes;
static int yyMonth;
static int yySeconds;
static int yyYear;
static MERIDIAN yyMeridian;
static int yyRelDay;
static int yyRelHour;
static int yyRelMinutes;
static int yyRelMonth;
static int yyRelSeconds;
static int yyRelYear;
%}
%union {
int Number;
enum _MERIDIAN Meridian;
}
%token tAGO tDAY tDAY_UNIT tDAYZONE tDST tHOUR_UNIT tID
%token tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
%token tSEC_UNIT tSNUMBER tUNUMBER tYEAR_UNIT tZONE
%type <Number> tDAY tDAY_UNIT tDAYZONE tHOUR_UNIT tMINUTE_UNIT
%type <Number> tMONTH tMONTH_UNIT
%type <Number> tSEC_UNIT tSNUMBER tUNUMBER tYEAR_UNIT tZONE
%type <Meridian> tMERIDIAN o_merid
%%
spec : /* NULL */
| spec item
;
item : time {
yyHaveTime++;
}
| zone {
yyHaveZone++;
}
| date {
yyHaveDate++;
}
| day {
yyHaveDay++;
}
| rel {
yyHaveRel++;
}
| number
;
time : tUNUMBER tMERIDIAN {
yyHour = $1;
yyMinutes = 0;
yySeconds = 0;
yyMeridian = $2;
}
| tUNUMBER ':' tUNUMBER o_merid {
yyHour = $1;
yyMinutes = $3;
yySeconds = 0;
yyMeridian = $4;
}
| tUNUMBER ':' tUNUMBER tSNUMBER {
yyHour = $1;
yyMinutes = $3;
yyMeridian = MER24;
yyHaveZone++;
yyTimezone = ($4 < 0
? -$4 % 100 + (-$4 / 100) * 60
: - ($4 % 100 + ($4 / 100) * 60));
}
| tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
yyHour = $1;
yyMinutes = $3;
yySeconds = $5;
yyMeridian = $6;
}
| tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
yyHour = $1;
yyMinutes = $3;
yySeconds = $5;
yyMeridian = MER24;
yyHaveZone++;
yyTimezone = ($6 < 0
? -$6 % 100 + (-$6 / 100) * 60
: - ($6 % 100 + ($6 / 100) * 60));
}
;
zone : tZONE {
yyTimezone = $1;
}
| tDAYZONE {
yyTimezone = $1 - 60;
}
|
tZONE tDST {
yyTimezone = $1 - 60;
}
;
day : tDAY {
yyDayOrdinal = 1;
yyDayNumber = $1;
}
| tDAY ',' {
yyDayOrdinal = 1;
yyDayNumber = $1;
}
| tUNUMBER tDAY {
yyDayOrdinal = $1;
yyDayNumber = $2;
}
;
date : tUNUMBER '/' tUNUMBER {
yyMonth = $1;
yyDay = $3;
}
| tUNUMBER '/' tUNUMBER '/' tUNUMBER {
/* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY.
The goal in recognizing YYYY/MM/DD is solely to support legacy
machine-generated dates like those in an RCS log listing. If
you want portability, use the ISO 8601 format. */
if ($1 >= 1000)
{
yyYear = $1;
yyMonth = $3;
yyDay = $5;
}
else
{
yyMonth = $1;
yyDay = $3;
yyYear = $5;
}
}
| tUNUMBER tSNUMBER tSNUMBER {
/* ISO 8601 format. yyyy-mm-dd. */
yyYear = $1;
yyMonth = -$2;
yyDay = -$3;
}
| tUNUMBER tMONTH tSNUMBER {
/* e.g. 17-JUN-1992. */
yyDay = $1;
yyMonth = $2;
yyYear = -$3;
}
| tMONTH tUNUMBER {
yyMonth = $1;
yyDay = $2;
}
| tMONTH tUNUMBER ',' tUNUMBER {
yyMonth = $1;
yyDay = $2;
yyYear = $4;
}
| tUNUMBER tMONTH {
yyMonth = $2;
yyDay = $1;
}
| tUNUMBER tMONTH tUNUMBER {
yyMonth = $2;
yyDay = $1;
yyYear = $3;
}
;
rel : relunit tAGO {
yyRelSeconds = -yyRelSeconds;
yyRelMinutes = -yyRelMinutes;
yyRelHour = -yyRelHour;
yyRelDay = -yyRelDay;
yyRelMonth = -yyRelMonth;
yyRelYear = -yyRelYear;
}
| relunit
;
relunit : tUNUMBER tYEAR_UNIT {
yyRelYear += $1 * $2;
}
| tSNUMBER tYEAR_UNIT {
yyRelYear += $1 * $2;
}
| tYEAR_UNIT {
yyRelYear++;
}
| tUNUMBER tMONTH_UNIT {
yyRelMonth += $1 * $2;
}
| tSNUMBER tMONTH_UNIT {
yyRelMonth += $1 * $2;
}
| tMONTH_UNIT {
yyRelMonth++;
}
| tUNUMBER tDAY_UNIT {
yyRelDay += $1 * $2;
}
| tSNUMBER tDAY_UNIT {
yyRelDay += $1 * $2;
}
| tDAY_UNIT {
yyRelDay++;
}
| tUNUMBER tHOUR_UNIT {
yyRelHour += $1 * $2;
}
| tSNUMBER tHOUR_UNIT {
yyRelHour += $1 * $2;
}
| tHOUR_UNIT {
yyRelHour++;
}
| tUNUMBER tMINUTE_UNIT {
yyRelMinutes += $1 * $2;
}
| tSNUMBER tMINUTE_UNIT {
yyRelMinutes += $1 * $2;
}
| tMINUTE_UNIT {
yyRelMinutes++;
}
| tUNUMBER tSEC_UNIT {
yyRelSeconds += $1 * $2;
}
| tSNUMBER tSEC_UNIT {
yyRelSeconds += $1 * $2;
}
| tSEC_UNIT {
yyRelSeconds++;
}
;
number : tUNUMBER
{
if ((yyHaveTime != 0) && (yyHaveDate != 0) && (yyHaveRel == 0))
yyYear = $1;
else
{
if ($1>10000)
{
yyHaveDate++;
yyDay= ($1)%100;
yyMonth= ($1/100)%100;
yyYear = $1/10000;
}
else
{
yyHaveTime++;
if ($1 < 100)
{
yyHour = $1;
yyMinutes = 0;
}
else
{
yyHour = $1 / 100;
yyMinutes = $1 % 100;
}
yySeconds = 0;
yyMeridian = MER24;
}
}
}
;
o_merid : /* NULL */
{
$$ = MER24;
}
| tMERIDIAN
{
$$ = $1;
}
;
%%
/* Month and day table. */
static TABLE const MonthDayTable[] = {
{ "january", tMONTH, 1 },
{ "february", tMONTH, 2 },
{ "march", tMONTH, 3 },
{ "april", tMONTH, 4 },
{ "may", tMONTH, 5 },
{ "june", tMONTH, 6 },
{ "july", tMONTH, 7 },
{ "august", tMONTH, 8 },
{ "september", tMONTH, 9 },
{ "sept", tMONTH, 9 },
{ "october", tMONTH, 10 },
{ "november", tMONTH, 11 },
{ "december", tMONTH, 12 },
{ "sunday", tDAY, 0 },
{ "monday", tDAY, 1 },
{ "tuesday", tDAY, 2 },
{ "tues", tDAY, 2 },
{ "wednesday", tDAY, 3 },
{ "wednes", tDAY, 3 },
{ "thursday", tDAY, 4 },
{ "thur", tDAY, 4 },
{ "thurs", tDAY, 4 },
{ "friday", tDAY, 5 },
{ "saturday", tDAY, 6 },
{ NULL, 0, 0 }
};
/* Time units table. */
static TABLE const UnitsTable[] = {
{ "year", tYEAR_UNIT, 1 },
{ "month", tMONTH_UNIT, 1 },
{ "fortnight", tDAY_UNIT, 14 },
{ "week", tDAY_UNIT, 7 },
{ "day", tDAY_UNIT, 1 },
{ "hour", tHOUR_UNIT, 1 },
{ "minute", tMINUTE_UNIT, 1 },
{ "min", tMINUTE_UNIT, 1 },
{ "second", tSEC_UNIT, 1 },
{ "sec", tSEC_UNIT, 1 },
{ NULL, 0, 0 }
};
/* Assorted relative-time words. */
static TABLE const OtherTable[] = {
{ "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 },
{ "yesterday", tMINUTE_UNIT, -1 * 24 * 60 },
{ "today", tMINUTE_UNIT, 0 },
{ "now", tMINUTE_UNIT, 0 },
{ "last", tUNUMBER, -1 },
{ "this", tMINUTE_UNIT, 0 },
{ "next", tUNUMBER, 2 },
{ "first", tUNUMBER, 1 },
/* { "second", tUNUMBER, 2 }, */
{ "third", tUNUMBER, 3 },
{ "fourth", tUNUMBER, 4 },
{ "fifth", tUNUMBER, 5 },
{ "sixth", tUNUMBER, 6 },
{ "seventh", tUNUMBER, 7 },
{ "eighth", tUNUMBER, 8 },
{ "ninth", tUNUMBER, 9 },
{ "tenth", tUNUMBER, 10 },
{ "eleventh", tUNUMBER, 11 },
{ "twelfth", tUNUMBER, 12 },
{ "ago", tAGO, 1 },
{ NULL, 0, 0 }
};
/* The timezone table. */
static TABLE const TimezoneTable[] = {
{ "gmt", tZONE, HOUR ( 0) }, /* Greenwich Mean */
{ "ut", tZONE, HOUR ( 0) }, /* Universal (Coordinated) */
{ "utc", tZONE, HOUR ( 0) },
{ "wet", tZONE, HOUR ( 0) }, /* Western European */
{ "bst", tDAYZONE, HOUR ( 0) }, /* British Summer */
{ "wat", tZONE, HOUR ( 1) }, /* West Africa */
{ "at", tZONE, HOUR ( 2) }, /* Azores */
{ "ast", tZONE, HOUR ( 4) }, /* Atlantic Standard */
{ "adt", tDAYZONE, HOUR ( 4) }, /* Atlantic Daylight */
{ "est", tZONE, HOUR ( 5) }, /* Eastern Standard */
{ "edt", tDAYZONE, HOUR ( 5) }, /* Eastern Daylight */
{ "cst", tZONE, HOUR ( 6) }, /* Central Standard */
{ "cdt", tDAYZONE, HOUR ( 6) }, /* Central Daylight */
{ "mst", tZONE, HOUR ( 7) }, /* Mountain Standard */
{ "mdt", tDAYZONE, HOUR ( 7) }, /* Mountain Daylight */
{ "pst", tZONE, HOUR ( 8) }, /* Pacific Standard */
{ "pdt", tDAYZONE, HOUR ( 8) }, /* Pacific Daylight */
{ "yst", tZONE, HOUR ( 9) }, /* Yukon Standard */
{ "ydt", tDAYZONE, HOUR ( 9) }, /* Yukon Daylight */
{ "hst", tZONE, HOUR (10) }, /* Hawaii Standard */
{ "hdt", tDAYZONE, HOUR (10) }, /* Hawaii Daylight */
{ "cat", tZONE, HOUR (10) }, /* Central Alaska */
{ "ahst", tZONE, HOUR (10) }, /* Alaska-Hawaii Standard */
{ "nt", tZONE, HOUR (11) }, /* Nome */
{ "idlw", tZONE, HOUR (12) }, /* International Date Line West */
{ "cet", tZONE, -HOUR (1) }, /* Central European */
{ "met", tZONE, -HOUR (1) }, /* Middle European */
{ "mewt", tZONE, -HOUR (1) }, /* Middle European Winter */
{ "mest", tDAYZONE, -HOUR (1) }, /* Middle European Summer */
{ "mesz", tDAYZONE, -HOUR (1) }, /* Middle European Summer */
{ "swt", tZONE, -HOUR (1) }, /* Swedish Winter */
{ "sst", tDAYZONE, -HOUR (1) }, /* Swedish Summer */
{ "fwt", tZONE, -HOUR (1) }, /* French Winter */
{ "fst", tDAYZONE, -HOUR (1) }, /* French Summer */
{ "eet", tZONE, -HOUR (2) }, /* Eastern Europe, USSR Zone 1 */
{ "bt", tZONE, -HOUR (3) }, /* Baghdad, USSR Zone 2 */
{ "zp4", tZONE, -HOUR (4) }, /* USSR Zone 3 */
{ "zp5", tZONE, -HOUR (5) }, /* USSR Zone 4 */
{ "zp6", tZONE, -HOUR (6) }, /* USSR Zone 5 */
{ "wast", tZONE, -HOUR (7) }, /* West Australian Standard */
{ "wadt", tDAYZONE, -HOUR (7) }, /* West Australian Daylight */
{ "cct", tZONE, -HOUR (8) }, /* China Coast, USSR Zone 7 */
{ "jst", tZONE, -HOUR (9) }, /* Japan Standard, USSR Zone 8 */
{ "east", tZONE, -HOUR (10) }, /* Eastern Australian Standard */
{ "eadt", tDAYZONE, -HOUR (10) }, /* Eastern Australian Daylight */
{ "gst", tZONE, -HOUR (10) }, /* Guam Standard, USSR Zone 9 */
{ "nzt", tZONE, -HOUR (12) }, /* New Zealand */
{ "nzst", tZONE, -HOUR (12) }, /* New Zealand Standard */
{ "nzdt", tDAYZONE, -HOUR (12) }, /* New Zealand Daylight */
{ "idle", tZONE, -HOUR (12) }, /* International Date Line East */
{ NULL, 0, 0 }
};
/* Military timezone table. */
static TABLE const MilitaryTable[] = {
{ "a", tZONE, HOUR ( 1) },
{ "b", tZONE, HOUR ( 2) },
{ "c", tZONE, HOUR ( 3) },
{ "d", tZONE, HOUR ( 4) },
{ "e", tZONE, HOUR ( 5) },
{ "f", tZONE, HOUR ( 6) },
{ "g", tZONE, HOUR ( 7) },
{ "h", tZONE, HOUR ( 8) },
{ "i", tZONE, HOUR ( 9) },
{ "k", tZONE, HOUR ( 10) },
{ "l", tZONE, HOUR ( 11) },
{ "m", tZONE, HOUR ( 12) },
{ "n", tZONE, HOUR (- 1) },
{ "o", tZONE, HOUR (- 2) },
{ "p", tZONE, HOUR (- 3) },
{ "q", tZONE, HOUR (- 4) },
{ "r", tZONE, HOUR (- 5) },
{ "s", tZONE, HOUR (- 6) },
{ "t", tZONE, HOUR (- 7) },
{ "u", tZONE, HOUR (- 8) },
{ "v", tZONE, HOUR (- 9) },
{ "w", tZONE, HOUR (-10) },
{ "x", tZONE, HOUR (-11) },
{ "y", tZONE, HOUR (-12) },
{ "z", tZONE, HOUR ( 0) },
{ NULL, 0, 0 }
};
static int yyerror (unused const char *s)
{
return 0;
}
static int ToHour (int Hours, MERIDIAN Meridian)
{
switch (Meridian)
{
case MER24:
if (Hours < 0 || Hours > 23)
return -1;
return Hours;
case MERam:
if (Hours < 1 || Hours > 12)
return -1;
if (Hours == 12)
Hours = 0;
return Hours;
case MERpm:
if (Hours < 1 || Hours > 12)
return -1;
if (Hours == 12)
Hours = 0;
return Hours + 12;
default:
abort ();
}
/* NOTREACHED */
}
static int ToYear (int Year)
{
if (Year < 0)
Year = -Year;
/* XPG4 suggests that years 00-68 map to 2000-2068, and
years 69-99 map to 1969-1999. */
if (Year < 69)
Year += 2000;
else if (Year < 100)
Year += 1900;
return Year;
}
static int LookupWord (char *buff)
{
register char *p;
register char *q;
register const TABLE *tp;
int i;
bool abbrev;
/* Make it lowercase. */
for (p = buff; '\0' != *p; p++)
if (ISUPPER (*p))
*p = tolower (*p);
if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0)
{
yylval.Meridian = MERam;
return tMERIDIAN;
}
if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0)
{
yylval.Meridian = MERpm;
return tMERIDIAN;
}
/* See if we have an abbreviation for a month. */
if (strlen (buff) == 3)
abbrev = true;
else if (strlen (buff) == 4 && buff[3] == '.')
{
abbrev = true;
buff[3] = '\0';
}
else
abbrev = false;
for (tp = MonthDayTable; tp->name; tp++)
{
if (abbrev)
{
if (strncmp (buff, tp->name, 3) == 0)
{
yylval.Number = tp->value;
return tp->type;
}
}
else if (strcmp (buff, tp->name) == 0)
{
yylval.Number = tp->value;
return tp->type;
}
}
for (tp = TimezoneTable; tp->name; tp++)
if (strcmp (buff, tp->name) == 0)
{
yylval.Number = tp->value;
return tp->type;
}
if (strcmp (buff, "dst") == 0)
return tDST;
for (tp = UnitsTable; tp->name; tp++)
if (strcmp (buff, tp->name) == 0)
{
yylval.Number = tp->value;
return tp->type;
}
/* Strip off any plural and try the units table again. */
i = strlen (buff) - 1;
if (buff[i] == 's')
{
buff[i] = '\0';
for (tp = UnitsTable; tp->name; tp++)
if (strcmp (buff, tp->name) == 0)
{
yylval.Number = tp->value;
return tp->type;
}
buff[i] = 's'; /* Put back for "this" in OtherTable. */
}
for (tp = OtherTable; tp->name; tp++)
if (strcmp (buff, tp->name) == 0)
{
yylval.Number = tp->value;
return tp->type;
}
/* Military timezones. */
if (buff[1] == '\0' && ISALPHA (*buff))
{
for (tp = MilitaryTable; tp->name; tp++)
if (strcmp (buff, tp->name) == 0)
{
yylval.Number = tp->value;
return tp->type;
}
}
/* Drop out any periods and try the timezone table again. */
for (i = 0, p = q = buff; '\0' != *q; q++)
if (*q != '.')
*p++ = *q;
else
i++;
*p = '\0';
if (0 != i)
for (tp = TimezoneTable; NULL != tp->name; tp++)
if (strcmp (buff, tp->name) == 0)
{
yylval.Number = tp->value;
return tp->type;
}
return tID;
}
static int
yylex (void)
{
register char c;
register char *p;
char buff[20];
int Count;
int sign;
for (;;)
{
while (ISSPACE (*yyInput))
yyInput++;
if (ISDIGIT (c = *yyInput) || c == '-' || c == '+')
{
if (c == '-' || c == '+')
{
sign = c == '-' ? -1 : 1;
if (!ISDIGIT (*++yyInput))
/* skip the '-' sign */
continue;
}
else
sign = 0;
for (yylval.Number = 0; ISDIGIT (c = *yyInput++);)
yylval.Number = 10 * yylval.Number + c - '0';
yyInput--;
if (sign < 0)
yylval.Number = -yylval.Number;
return (0 != sign) ? tSNUMBER : tUNUMBER;
}
if (ISALPHA (c))
{
for (p = buff; (c = *yyInput++, ISALPHA (c)) || c == '.';)
if (p < &buff[sizeof buff - 1])
*p++ = c;
*p = '\0';
yyInput--;
return LookupWord (buff);
}
if (c != '(')
return *yyInput++;
Count = 0;
do
{
c = *yyInput++;
if (c == '\0')
return c;
if (c == '(')
Count++;
else if (c == ')')
Count--;
}
while (Count > 0);
}
}
#define TM_YEAR_ORIGIN 1900
/* Yield A - B, measured in seconds. */
static long difftm (struct tm *a, struct tm *b)
{
int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
long days = (
/* difference in day of year */
a->tm_yday - b->tm_yday
/* + intervening leap days */
+ ((ay >> 2) - (by >> 2))
- (ay / 100 - by / 100)
+ ((ay / 100 >> 2) - (by / 100 >> 2))
/* + difference in years * 365 */
+ (long) (ay - by) * 365
);
return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
+ (a->tm_min - b->tm_min))
+ (a->tm_sec - b->tm_sec));
}
time_t get_date (const char *p, const time_t *now)
{
struct tm tm, tm0, *tmp;
time_t Start;
yyInput = p;
Start = now ? *now : time ((time_t *) NULL);
tmp = localtime (&Start);
yyYear = tmp->tm_year + TM_YEAR_ORIGIN;
yyMonth = tmp->tm_mon + 1;
yyDay = tmp->tm_mday;
yyHour = tmp->tm_hour;
yyMinutes = tmp->tm_min;
yySeconds = tmp->tm_sec;
yyMeridian = MER24;
yyRelSeconds = 0;
yyRelMinutes = 0;
yyRelHour = 0;
yyRelDay = 0;
yyRelMonth = 0;
yyRelYear = 0;
yyHaveDate = 0;
yyHaveDay = 0;
yyHaveRel = 0;
yyHaveTime = 0;
yyHaveZone = 0;
if (yyparse ()
|| yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
return -1;
tm.tm_year = ToYear (yyYear) - TM_YEAR_ORIGIN + yyRelYear;
tm.tm_mon = yyMonth - 1 + yyRelMonth;
tm.tm_mday = yyDay + yyRelDay;
if ((yyHaveTime != 0) ||
( (yyHaveRel != 0) && (yyHaveDate == 0) && (yyHaveDay == 0) ))
{
tm.tm_hour = ToHour (yyHour, yyMeridian);
if (tm.tm_hour < 0)
return -1;
tm.tm_min = yyMinutes;
tm.tm_sec = yySeconds;
}
else
{
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
}
tm.tm_hour += yyRelHour;
tm.tm_min += yyRelMinutes;
tm.tm_sec += yyRelSeconds;
tm.tm_isdst = -1;
tm0 = tm;
Start = mktime (&tm);
if (Start == (time_t) -1)
{
/* Guard against falsely reporting errors near the time_t boundaries
when parsing times in other time zones. For example, if the min
time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead
of UTC, then the min localtime value is 1970-01-01 08:00:00; if
we apply mktime to 1970-01-01 00:00:00 we will get an error, so
we apply mktime to 1970-01-02 08:00:00 instead and adjust the time
zone by 24 hours to compensate. This algorithm assumes that
there is no DST transition within a day of the time_t boundaries. */
if (yyHaveZone)
{
tm = tm0;
if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN)
{
tm.tm_mday++;
yyTimezone -= 24 * 60;
}
else
{
tm.tm_mday--;
yyTimezone += 24 * 60;
}
Start = mktime (&tm);
}
if (Start == (time_t) -1)
return Start;
}
if (yyHaveDay && !yyHaveDate)
{
tm.tm_mday += ((yyDayNumber - tm.tm_wday + 7) % 7
+ 7 * (yyDayOrdinal - (0 < yyDayOrdinal)));
Start = mktime (&tm);
if (Start == (time_t) -1)
return Start;
}
if (yyHaveZone)
{
long delta = yyTimezone * 60L + difftm (&tm, gmtime (&Start));
if ((Start + delta < Start) != (delta < 0))
return -1; /* time_t overflow */
Start += delta;
}
return Start;
}
#if defined (TEST)
/* ARGSUSED */
int
main (ac, av)
int ac;
char *av[];
{
char buff[MAX_BUFF_LEN + 1];
time_t d;
(void) printf ("Enter date, or blank line to exit.\n\t> ");
(void) fflush (stdout);
buff[MAX_BUFF_LEN] = 0;
while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
{
d = get_date (buff, (time_t *) NULL);
if (d == -1)
(void) printf ("Bad format - couldn't convert.\n");
else
(void) printf ("%s", ctime (&d));
(void) printf ("\t> ");
(void) fflush (stdout);
}
exit (0);
/* NOTREACHED */
}
#endif /* defined (TEST) */
+66
View File
@@ -0,0 +1,66 @@
/*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2000 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id$"
#include <stdlib.h>
#include <errno.h>
#include <grp.h>
#include "prototypes.h"
/*
* getgr_nam_gid - Return a pointer to the group specified by a string.
* The string may be a valid GID or a valid groupname.
* If the group does not exist on the system, NULL is returned.
*/
extern /*@only@*//*@null@*/struct group *getgr_nam_gid (/*@null@*/const char *grname)
{
long long int gid;
char *endptr;
if (NULL == grname) {
return NULL;
}
errno = 0;
gid = strtoll (grname, &endptr, 10);
if ( ('\0' != *grname)
&& ('\0' == *endptr)
&& (ERANGE != errno)
&& (/*@+longintegral@*/gid == (gid_t)gid)/*@=longintegral@*/) {
return xgetgrgid ((gid_t) gid);
}
return xgetgrnam (grname);
}
+124
View File
@@ -0,0 +1,124 @@
/*
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: $"
#include <ctype.h>
#include <stdlib.h>
#include "defines.h"
#include "prototypes.h"
/*
* Parse a range and indicate if the range is valid.
* Valid ranges are in the form:
* <long> -> min=max=long has_min has_max
* -<long> -> max=long !has_min has_max
* <long>- -> min=long has_min !has_max
* <long1>-<long2> -> min=long1 max=long2 has_min has_max
*
* If the range is valid, getrange returns 1.
* If the range is not valid, getrange returns 0.
*/
int getrange (char *range,
unsigned long *min, bool *has_min,
unsigned long *max, bool *has_max)
{
char *endptr;
unsigned long n;
if (NULL == range) {
return 0;
}
if ('-' == range[0]) {
if (!isdigit(range[1])) {
/* invalid */
return 0;
}
errno = 0;
n = strtoul (&range[1], &endptr, 10);
if (('\0' != *endptr) || (ERANGE == errno)) {
/* invalid */
return 0;
}
/* -<long> */
*has_min = false;
*has_max = true;
*max = n;
} else {
errno = 0;
n = strtoul (range, &endptr, 10);
if (ERANGE == errno) {
/* invalid */
return 0;
}
switch (*endptr) {
case '\0':
/* <long> */
*has_min = true;
*has_max = true;
*min = n;
*max = n;
break;
case '-':
endptr++;
if ('\0' == *endptr) {
/* <long>- */
*has_min = true;
*has_max = false;
*min = n;
} else if (!isdigit (*endptr)) {
/* invalid */
return 0;
} else {
*has_min = true;
*min = n;
errno = 0;
n = strtoul (endptr, &endptr, 10);
if ( ('\0' != *endptr)
|| (ERANGE == errno)) {
/* invalid */
return 0;
}
/* <long>-<long> */
*has_max = true;
*max = n;
}
break;
default:
return 0;
}
}
return 1;
}
+100
View File
@@ -0,0 +1,100 @@
/*
* Copyright (c) 1991 - 1993, Julianne Frances Haugh
* Copyright (c) 1991 - 1993, Chip Rosenthal
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2010, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: hushed.c 3232 2010-08-22 19:13:53Z nekral-guest $"
#include <sys/types.h>
#include <stdio.h>
#include <pwd.h>
#include "defines.h"
#include "prototypes.h"
#include "getdef.h"
/*
* hushed - determine if a user receives login messages
*
* Look in the hushed-logins file (or user's home directory) to see
* if the user is to receive the login-time messages.
*/
bool hushed (const char *username)
{
struct passwd *pw;
const char *hushfile;
char buf[BUFSIZ];
bool found;
FILE *fp;
/*
* Get the name of the file to use. If this option is not
* defined, default to a noisy login.
*/
hushfile = getdef_str ("HUSHLOGIN_FILE");
if (NULL == hushfile) {
return false;
}
pw = getpwnam (username);
if (NULL == pw) {
return false;
}
/*
* If this is not a fully rooted path then see if the
* file exists in the user's home directory.
*/
if (hushfile[0] != '/') {
(void) snprintf (buf, sizeof (buf), "%s/%s", pw->pw_dir, hushfile);
return (access (buf, F_OK) == 0);
}
/*
* If this is a fully rooted path then go through the file
* and see if this user, or its shell is in there.
*/
fp = fopen (hushfile, "r");
if (NULL == fp) {
return false;
}
for (found = false; !found && (fgets (buf, (int) sizeof buf, fp) == buf);) {
buf[strlen (buf) - 1] = '\0';
found = (strcmp (buf, pw->pw_shell) == 0) ||
(strcmp (buf, pw->pw_name) == 0);
}
(void) fclose (fp);
return found;
}
+125
View File
@@ -0,0 +1,125 @@
/*
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1997, Marek Michałkiewicz
* Copyright (c) 2001 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Extracted from age.c and made part of libshadow.a - may be useful
* in other shadow-aware programs. --marekm
*/
#include <config.h>
#include <sys/types.h>
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
#include <time.h>
#ident "$Id: isexpired.c 3362 2011-06-16 21:25:36Z nekral-guest $"
/*
* isexpired - determine if account is expired yet
*
* isexpired calculates the expiration date based on the
* password expiration criteria.
*
* Return value:
* 0: The password is still valid
* 1: The password has expired, it must be changed
* 2: The password has expired since a long time and the account is
* now disabled. (password cannot be changed)
* 3: The account has expired
*/
int isexpired (const struct passwd *pw, /*@null@*/const struct spwd *sp)
{
long now;
now = (long) time ((time_t *) 0) / SCALE;
if (NULL == sp) {
return 0;
}
/*
* Quick and easy - there is an expired account field
* along with an inactive account field. Do the expired
* one first since it is worse.
*/
if ((sp->sp_expire > 0) && (now >= sp->sp_expire)) {
return 3;
}
/*
* Last changed date 1970-01-01 (not very likely) means that
* the password must be changed on next login (passwd -e).
*
* The check for "x" is a workaround for RedHat NYS libc bug -
* if /etc/shadow doesn't exist, getspnam() still succeeds and
* returns sp_lstchg==0 (must change password) instead of -1!
*/
if ( (0 == sp->sp_lstchg)
&& (strcmp (pw->pw_passwd, SHADOW_PASSWD_STRING) == 0)) {
return 1;
}
if ( (sp->sp_lstchg > 0)
&& (sp->sp_max >= 0)
&& (sp->sp_inact >= 0)
&& (now >= (sp->sp_lstchg + sp->sp_max + sp->sp_inact))) {
return 2;
}
/*
* The last and max fields must be present for an account
* to have an expired password. A maximum of >10000 days
* is considered to be infinite.
*/
if ( (-1 == sp->sp_lstchg)
|| (-1 == sp->sp_max)
|| (sp->sp_max >= ((10000L * DAY) / SCALE))) {
return 0;
}
/*
* Calculate today's day and the day on which the password
* is going to expire. If that date has already passed,
* the password has expired.
*/
if (now >= (sp->sp_lstchg + sp->sp_max)) {
return 1;
}
return 0;
}
+611
View File
@@ -0,0 +1,611 @@
/*
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1999, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Separated from setup.c. --marekm
* Resource limits thanks to Cristian Gafton.
* Enhancements of resource limit code by Thomas Orgis <thomas@orgis.org>
*/
#include <config.h>
#ifndef USE_PAM
#ident "$Id: limits.c 3558 2011-11-06 18:39:47Z nekral-guest $"
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <ctype.h>
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
#include "getdef.h"
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#define LIMITS
#endif
#ifdef LIMITS
#ifndef LIMITS_FILE
#define LIMITS_FILE "/etc/limits"
#endif
#define LOGIN_ERROR_RLIMIT 1
#define LOGIN_ERROR_LOGIN 2
/* Set a limit on a resource */
/*
* rlimit - RLIMIT_XXXX
* value - string value to be read
* multiplier - value*multiplier is the actual limit
*/
static int setrlimit_value (unsigned int resource,
const char *value,
unsigned int multiplier)
{
struct rlimit rlim;
rlim_t limit;
/* The "-" is special, not belonging to a strange negative limit.
* It is infinity, in a controlled way.
*/
if ('-' == value[0]) {
limit = RLIM_INFINITY;
}
else {
/* We cannot use getlong here because it fails when there
* is more to the value than just this number!
* Also, we are limited to base 10 here (hex numbers will not
* work with the limit string parser as is anyway)
*/
char *endptr;
long longlimit = strtol (value, &endptr, 10);
if ((0 == longlimit) && (value == endptr)) {
/* No argument at all. No-op.
* FIXME: We could instead throw an error, though.
*/
return 0;
}
longlimit *= multiplier;
limit = (rlim_t)longlimit;
if (longlimit != limit)
{
/* FIXME: Again, silent error handling...
* Wouldn't screaming make more sense?
*/
return 0;
}
}
rlim.rlim_cur = limit;
rlim.rlim_max = limit;
if (setrlimit (resource, &rlim) != 0) {
return LOGIN_ERROR_RLIMIT;
}
return 0;
}
static int set_prio (const char *value)
{
long prio;
if ( (getlong (value, &prio) == 0)
|| (prio != (int) prio)) {
return 0;
}
if (setpriority (PRIO_PROCESS, 0, (int) prio) != 0) {
return LOGIN_ERROR_RLIMIT;
}
return 0;
}
static int set_umask (const char *value)
{
unsigned long int mask;
if ( (getulong (value, &mask) == 0)
|| (mask != (mode_t) mask)) {
return 0;
}
(void) umask ((mode_t) mask);
return 0;
}
/* Counts the number of user logins and check against the limit */
static int check_logins (const char *name, const char *maxlogins)
{
#ifdef USE_UTMPX
struct utmpx *ut;
#else /* !USE_UTMPX */
struct utmp *ut;
#endif /* !USE_UTMPX */
unsigned long limit, count;
if (getulong (maxlogins, &limit) == 0) {
return 0;
}
if (0 == limit) { /* maximum 0 logins ? */
SYSLOG ((LOG_WARN, "No logins allowed for `%s'\n", name));
return LOGIN_ERROR_LOGIN;
}
count = 0;
#ifdef USE_UTMPX
setutxent ();
while ((ut = getutxent ()))
#else /* !USE_UTMPX */
setutent ();
while ((ut = getutent ()))
#endif /* !USE_UTMPX */
{
if (USER_PROCESS != ut->ut_type) {
continue;
}
if ('\0' == ut->ut_user[0]) {
continue;
}
if (strncmp (name, ut->ut_user, sizeof (ut->ut_user)) != 0) {
continue;
}
count++;
if (count > limit) {
break;
}
}
#ifdef USE_UTMPX
endutxent ();
#else /* !USE_UTMPX */
endutent ();
#endif /* !USE_UTMPX */
/*
* This is called after setutmp(), so the number of logins counted
* includes the user who is currently trying to log in.
*/
if (count > limit) {
SYSLOG ((LOG_WARN,
"Too many logins (max %lu) for %s\n",
limit, name));
return LOGIN_ERROR_LOGIN;
}
return 0;
}
/* Function setup_user_limits - checks/set limits for the curent login
* Original idea from Joel Katz's lshell. Ported to shadow-login
* by Cristian Gafton - gafton@sorosis.ro
*
* We are passed a string of the form ('BASH' constants for ulimit)
* [Aa][Cc][Dd][Ff][Mm][Nn][Rr][Ss][Tt][Uu][Ll][Pp][Ii][Oo]
* (eg. 'C2F256D2048N5' or 'C2 F256 D2048 N5')
* where:
* [Aa]: a = RLIMIT_AS max address space (KB)
* [Cc]: c = RLIMIT_CORE max core file size (KB)
* [Dd]: d = RLIMIT_DATA max data size (KB)
* [Ff]: f = RLIMIT_FSIZE max file size (KB)
* [Ii]: i = RLIMIT_NICE max nice value (0..39 translates to 20..-19)
* [Kk]: k = file creation masK (umask)
* [Ll]: l = max number of logins for this user
* [Mm]: m = RLIMIT_MEMLOCK max locked-in-memory address space (KB)
* [Nn]: n = RLIMIT_NOFILE max number of open files
* [Oo]: o = RLIMIT_RTPRIO max real time priority (linux/sched.h 0..MAX_RT_PRIO)
* [Pp]: p = process priority -20..20 (negative = high, positive = low)
* [Rr]: r = RLIMIT_RSS max resident set size (KB)
* [Ss]: s = RLIMIT_STACK max stack size (KB)
* [Tt]: t = RLIMIT_CPU max CPU time (MIN)
* [Uu]: u = RLIMIT_NPROC max number of processes
*
* NOTE: Remember to extend the "no-limits" string below when adding a new
* limit...
*
* Return value:
* 0 = okay, of course
* LOGIN_ERROR_RLIMIT = error setting some RLIMIT
* LOGIN_ERROR_LOGIN = error - too many logins for this user
*
* buf - the limits string
* name - the username
*/
static int do_user_limits (const char *buf, const char *name)
{
const char *pp;
int retval = 0;
bool reported = false;
pp = buf;
/* Skip leading whitespace. */
while ((' ' == *pp) || ('\t' == *pp)) {
pp++;
}
/* The special limit string "-" results in no limit for all known
* limits.
* We achieve that by parsing a full limit string, parts of it
* being ignored if a limit type is not known to the system.
* Though, there will be complaining for unknown limit types.
*/
if (strcmp (pp, "-") == 0) {
/* Remember to extend this, too, when adding new limits!
* Oh... but "unlimited" does not make sense for umask,
* or does it? (K-)
*/
pp = "A- C- D- F- I- L- M- N- O- P- R- S- T- U-";
}
while ('\0' != *pp) {
switch (*pp++) {
#ifdef RLIMIT_AS
case 'a':
case 'A':
/* RLIMIT_AS - max address space (KB) */
retval |= setrlimit_value (RLIMIT_AS, pp, 1024);
break;
#endif
#ifdef RLIMIT_CORE
case 'c':
case 'C':
/* RLIMIT_CORE - max core file size (KB) */
retval |= setrlimit_value (RLIMIT_CORE, pp, 1024);
break;
#endif
#ifdef RLIMIT_DATA
case 'd':
case 'D':
/* RLIMIT_DATA - max data size (KB) */
retval |= setrlimit_value (RLIMIT_DATA, pp, 1024);
break;
#endif
#ifdef RLIMIT_FSIZE
case 'f':
case 'F':
/* RLIMIT_FSIZE - Maximum filesize (KB) */
retval |= setrlimit_value (RLIMIT_FSIZE, pp, 1024);
break;
#endif
#ifdef RLIMIT_NICE
case 'i':
case 'I':
/* RLIMIT_NICE - max scheduling priority (0..39) */
retval |= setrlimit_value (RLIMIT_NICE, pp, 1);
break;
#endif
case 'k':
case 'K':
retval |= set_umask (pp);
break;
case 'l':
case 'L':
/* LIMIT the number of concurrent logins */
retval |= check_logins (name, pp);
break;
#ifdef RLIMIT_MEMLOCK
case 'm':
case 'M':
/* RLIMIT_MEMLOCK - max locked-in-memory address space (KB) */
retval |= setrlimit_value (RLIMIT_MEMLOCK, pp, 1024);
break;
#endif
#ifdef RLIMIT_NOFILE
case 'n':
case 'N':
/* RLIMIT_NOFILE - max number of open files */
retval |= setrlimit_value (RLIMIT_NOFILE, pp, 1);
break;
#endif
#ifdef RLIMIT_RTPRIO
case 'o':
case 'O':
/* RLIMIT_RTPRIO - max real time priority (0..MAX_RT_PRIO) */
retval |= setrlimit_value (RLIMIT_RTPRIO, pp, 1);
break;
#endif
case 'p':
case 'P':
retval |= set_prio (pp);
break;
#ifdef RLIMIT_RSS
case 'r':
case 'R':
/* RLIMIT_RSS - max resident set size (KB) */
retval |= setrlimit_value (RLIMIT_RSS, pp, 1024);
break;
#endif
#ifdef RLIMIT_STACK
case 's':
case 'S':
/* RLIMIT_STACK - max stack size (KB) */
retval |= setrlimit_value (RLIMIT_STACK, pp, 1024);
break;
#endif
#ifdef RLIMIT_CPU
case 't':
case 'T':
/* RLIMIT_CPU - max CPU time (MIN) */
retval |= setrlimit_value (RLIMIT_CPU, pp, 60);
break;
#endif
#ifdef RLIMIT_NPROC
case 'u':
case 'U':
/* RLIMIT_NPROC - max number of processes */
retval |= setrlimit_value (RLIMIT_NPROC, pp, 1);
break;
#endif
default:
/* Only report invalid strings once */
/* Note: A string can be invalid just because a
* specific (theoretically valid) setting is not
* supported by this build.
* It is just a warning in syslog anyway. The line
* is still processed
*/
if (!reported) {
SYSLOG ((LOG_WARN,
"Invalid limit string: '%s'",
pp-1));
reported = true;
retval |= LOGIN_ERROR_RLIMIT;
}
}
/* After parsing one limit setting (or just complaining
* about it), one still needs to skip its argument to
* prevent a bogus warning on trying to parse that as
* limit specification.
* So, let's skip all digits, "-" and our limited set of
* whitespace.
*/
while ( isdigit (*pp)
|| ('-' == *pp)
|| (' ' == *pp)
|| ('\t' ==*pp)) {
pp++;
}
}
return retval;
}
/* Check if user uname is in the group gname.
* Can I be sure that gr_mem contains no UID as string?
* Returns true when user is in the group, false when not.
* Any error is treated as false.
*/
static bool user_in_group (const char *uname, const char *gname)
{
struct group *groupdata;
if (uname == NULL || gname == NULL){
return false;
}
/* We are not claiming to be re-entrant!
* In case of paranoia or a multithreaded login program,
* one needs to add some mess for getgrnam_r. */
groupdata = getgrnam (gname);
if (NULL == groupdata) {
SYSLOG ((LOG_WARN, "Nonexisting group `%s' in limits file.",
gname));
return false;
}
return is_on_list (groupdata->gr_mem, uname);
}
static int setup_user_limits (const char *uname)
{
FILE *fil;
char buf[1024];
char name[1024];
char limits[1024];
char deflimits[1024];
char tempbuf[1024];
/* init things */
memzero (buf, sizeof (buf));
memzero (name, sizeof (name));
memzero (limits, sizeof (limits));
memzero (deflimits, sizeof (deflimits));
memzero (tempbuf, sizeof (tempbuf));
/* start the checks */
fil = fopen (LIMITS_FILE, "r");
if (fil == NULL) {
return 0;
}
/* The limits file have the following format:
* - '#' (comment) chars only as first chars on a line;
* - username must start on first column (or *, or @group)
*
* FIXME: A better (smarter) checking should be done
*/
while (fgets (buf, 1024, fil) != NULL) {
if (('#' == buf[0]) || ('\n' == buf[0])) {
continue;
}
memzero (tempbuf, sizeof (tempbuf));
/* a valid line should have a username, then spaces,
* then limits
* we allow the format:
* username L2 D2048 R4096
* where spaces={' ',\t}. Also, we reject invalid limits.
* Imposing a limit should be done with care, so a wrong
* entry means no care anyway :-).
*
* A '-' as a limits strings means no limits
*
* The username can also be:
* '*': the default limits (only the last is taken into
* account)
* @group: the limit applies to the members of the group
*
* To clarify: The first entry with matching user name rules,
* everything after it is ignored. If there is no user entry,
* the last encountered entry for a matching group rules.
* If there is no matching group entry, the default limits rule.
*/
if (sscanf (buf, "%s%[ACDFIKLMNOPRSTUacdfiklmnoprstu0-9 \t-]",
name, tempbuf) == 2) {
if (strcmp (name, uname) == 0) {
strcpy (limits, tempbuf);
break;
} else if (strcmp (name, "*") == 0) {
strcpy (deflimits, tempbuf);
} else if (name[0] == '@') {
/* If the user is in the group, the group
* limits apply unless later a line for
* the specific user is found.
*/
if (user_in_group (uname, name+1)) {
strcpy (limits, tempbuf);
}
}
}
}
(void) fclose (fil);
if (limits[0] == '\0') {
/* no user specific limits */
if (deflimits[0] == '\0') { /* no default limits */
return 0;
}
strcpy (limits, deflimits); /* use the default limits */
}
return do_user_limits (limits, uname);
}
#endif /* LIMITS */
static void setup_usergroups (const struct passwd *info)
{
const struct group *grp;
/*
* if not root, and UID == GID, and username is the same as primary
* group name, set umask group bits to be the same as owner bits
* (examples: 022 -> 002, 077 -> 007).
*/
if ((0 != info->pw_uid) && (info->pw_uid == info->pw_gid)) {
/* local, no need for xgetgrgid */
grp = getgrgid (info->pw_gid);
if ( (NULL != grp)
&& (strcmp (info->pw_name, grp->gr_name) == 0)) {
mode_t tmpmask;
tmpmask = umask (0777);
tmpmask = (tmpmask & ~070) | ((tmpmask >> 3) & 070);
(void) umask (tmpmask);
}
}
}
/*
* set the process nice, ulimit, and umask from the password file entry
*/
void setup_limits (const struct passwd *info)
{
char *cp;
if (getdef_bool ("USERGROUPS_ENAB")) {
setup_usergroups (info);
}
/*
* See if the GECOS field contains values for NICE, UMASK or ULIMIT.
* If this feature is enabled in /etc/login.defs, we make those
* values the defaults for this login session.
*/
if (getdef_bool ("QUOTAS_ENAB")) {
#ifdef LIMITS
if (info->pw_uid != 0) {
if ((setup_user_limits (info->pw_name) & LOGIN_ERROR_LOGIN) != 0) {
(void) fputs (_("Too many logins.\n"), stderr);
(void) sleep (2); /* XXX: Should be FAIL_DELAY */
exit (EXIT_FAILURE);
}
}
#endif
for (cp = info->pw_gecos; cp != NULL; cp = strchr (cp, ',')) {
if (',' == *cp) {
cp++;
}
if (strncmp (cp, "pri=", 4) == 0) {
long int inc;
if ( (getlong (cp + 4, &inc) == 1)
&& (inc >= -20) && (inc <= 20)) {
errno = 0;
if ( (nice ((int) inc) != -1)
|| (0 != errno)) {
continue;
}
}
/* Failed to parse or failed to nice() */
SYSLOG ((LOG_WARN,
"Can't set the nice value for user %s",
info->pw_name));
continue;
}
if (strncmp (cp, "ulimit=", 7) == 0) {
long int blocks;
if ( (getlong (cp + 7, &blocks) == 0)
|| (blocks != (int) blocks)
|| (set_filesize_limit ((int) blocks) != 0)) {
SYSLOG ((LOG_WARN,
"Can't set the ulimit for user %s",
info->pw_name));
}
continue;
}
if (strncmp (cp, "umask=", 6) == 0) {
unsigned long int mask;
if ( (getulong (cp + 6, &mask) == 0)
|| (mask != (mode_t) mask)) {
SYSLOG ((LOG_WARN,
"Can't set umask value for user %s",
info->pw_name));
} else {
(void) umask ((mode_t) mask);
}
continue;
}
}
}
}
#else /* !USE_PAM */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !USE_PAM */
+271
View File
@@ -0,0 +1,271 @@
/*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1997, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: list.c 3224 2010-08-21 15:32:53Z nekral-guest $"
#include <assert.h>
#include "prototypes.h"
#include "defines.h"
/*
* add_list - add a member to a list of group members
*
* the array of member names is searched for the new member
* name, and if not present it is added to a freshly allocated
* list of users.
*/
/*@only@*/ /*@out@*/char **add_list (/*@returned@*/ /*@only@*/char **list, const char *member)
{
int i;
char **tmp;
assert (NULL != member);
assert (NULL != list);
/*
* Scan the list for the new name. Return the original list
* pointer if it is present.
*/
for (i = 0; list[i] != (char *) 0; i++) {
if (strcmp (list[i], member) == 0) {
return list;
}
}
/*
* Allocate a new list pointer large enough to hold all the
* old entries, and the new entries as well.
*/
tmp = (char **) xmalloc ((i + 2) * sizeof member);
/*
* Copy the original list to the new list, then append the
* new member and NULL terminate the result. This new list
* is returned to the invoker.
*/
for (i = 0; list[i] != (char *) 0; i++) {
tmp[i] = list[i];
}
tmp[i] = xstrdup (member);
tmp[i+1] = (char *) 0;
return tmp;
}
/*
* del_list - delete a member from a list of group members
*
* the array of member names is searched for the old member
* name, and if present it is deleted from a freshly allocated
* list of users.
*/
/*@only@*/ /*@out@*/char **del_list (/*@returned@*/ /*@only@*/char **list, const char *member)
{
int i, j;
char **tmp;
assert (NULL != member);
assert (NULL != list);
/*
* Scan the list for the old name. Return the original list
* pointer if it is not present.
*/
for (i = j = 0; list[i] != (char *) 0; i++) {
if (strcmp (list[i], member) != 0) {
j++;
}
}
if (j == i) {
return list;
}
/*
* Allocate a new list pointer large enough to hold all the
* old entries.
*/
tmp = (char **) xmalloc ((j + 1) * sizeof member);
/*
* Copy the original list except the deleted members to the
* new list, then NULL terminate the result. This new list
* is returned to the invoker.
*/
for (i = j = 0; list[i] != (char *) 0; i++) {
if (strcmp (list[i], member) != 0) {
tmp[j] = list[i];
j++;
}
}
tmp[j] = (char *) 0;
return tmp;
}
/*
* Duplicate a list.
* The input list is not modified, but in order to allow the use of this
* function with list of members, the list elements are not enforced to be
* constant strings here.
*/
/*@only@*/ /*@out@*/char **dup_list (char *const *list)
{
int i;
char **tmp;
assert (NULL != list);
for (i = 0; NULL != list[i]; i++);
tmp = (char **) xmalloc ((i + 1) * sizeof (char *));
i = 0;
while (NULL != *list) {
tmp[i] = xstrdup (*list);
i++;
list++;
}
tmp[i] = (char *) 0;
return tmp;
}
/*
* Check if member is part of the input list
* The input list is not modified, but in order to allow the use of this
* function with list of members, the list elements are not enforced to be
* constant strings here.
*/
bool is_on_list (char *const *list, const char *member)
{
assert (NULL != member);
assert (NULL != list);
while (NULL != *list) {
if (strcmp (*list, member) == 0) {
return true;
}
list++;
}
return false;
}
/*
* comma_to_list - convert comma-separated list to (char *) array
*/
/*@only@*/char **comma_to_list (const char *comma)
{
char *members;
char **array;
int i;
char *cp;
char *cp2;
assert (NULL != comma);
/*
* Make a copy since we are going to be modifying the list
*/
members = xstrdup (comma);
/*
* Count the number of commas in the list
*/
for (cp = members, i = 0;; i++) {
cp2 = strchr (cp, ',');
if (NULL != cp2) {
cp = cp2 + 1;
} else {
break;
}
}
/*
* Add 2 - one for the ending NULL, the other for the last item
*/
i += 2;
/*
* Allocate the array we're going to store the pointers into.
*/
array = (char **) xmalloc (sizeof (char *) * i);
/*
* Empty list is special - 0 members, not 1 empty member. --marekm
*/
if ('\0' == *members) {
*array = (char *) 0;
return array;
}
/*
* Now go walk that list all over again, this time building the
* array of pointers.
*/
for (cp = members, i = 0;; i++) {
array[i] = cp;
cp2 = strchr (cp, ',');
if (NULL != cp2) {
*cp2 = '\0';
cp2++;
cp = cp2;
} else {
array[i + 1] = (char *) 0;
break;
}
}
/*
* Return the new array of pointers
*/
return array;
}
+116
View File
@@ -0,0 +1,116 @@
/*
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: log.c 2820 2009-04-27 20:15:09Z nekral-guest $"
#include <sys/types.h>
#include <pwd.h>
#include <fcntl.h>
#include <time.h>
#include "defines.h"
#include <lastlog.h>
#include "prototypes.h"
/*
* dolastlog - create lastlog entry
*
* A "last login" entry is created for the user being logged in. The
* UID is extracted from the global (struct passwd) entry and the
* TTY information is gotten from the (struct utmp).
*/
void dolastlog (
struct lastlog *ll,
const struct passwd *pw,
/*@unique@*/const char *line,
/*@unique@*/const char *host)
{
int fd;
off_t offset;
struct lastlog newlog;
time_t ll_time;
/*
* If the file does not exist, don't create it.
*/
fd = open (LASTLOG_FILE, O_RDWR);
if (-1 == fd) {
return;
}
/*
* The file is indexed by UID number. Seek to the record
* for this UID. Negative UID's will create problems, but ...
*/
offset = (off_t) pw->pw_uid * sizeof newlog;
if (lseek (fd, offset, SEEK_SET) != offset) {
SYSLOG ((LOG_WARN,
"Can't read last lastlog entry for UID %lu in %s. Entry not updated.",
(unsigned long) pw->pw_uid, LASTLOG_FILE));
(void) close (fd);
return;
}
/*
* Read the old entry so we can tell the user when they last
* logged in. Then construct the new entry and write it out
* the way we read the old one in.
*/
if (read (fd, (void *) &newlog, sizeof newlog) != (ssize_t) sizeof newlog) {
memzero (&newlog, sizeof newlog);
}
if (NULL != ll) {
*ll = newlog;
}
ll_time = newlog.ll_time;
(void) time (&ll_time);
newlog.ll_time = ll_time;
strncpy (newlog.ll_line, line, sizeof newlog.ll_line);
#if HAVE_LL_HOST
strncpy (newlog.ll_host, host, sizeof newlog.ll_host);
#endif
if ( (lseek (fd, offset, SEEK_SET) != offset)
|| (write (fd, (const void *) &newlog, sizeof newlog) != (ssize_t) sizeof newlog)
|| (close (fd) != 0)) {
SYSLOG ((LOG_WARN,
"Can't write lastlog entry for UID %lu in %s.",
(unsigned long) pw->pw_uid, LASTLOG_FILE));
(void) close (fd);
}
}
+178
View File
@@ -0,0 +1,178 @@
/*
* Copyright (c) 1989 - 1993, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2011, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: loginprompt.c 3490 2011-09-18 20:41:38Z nekral-guest $"
#include <assert.h>
#include <stdio.h>
#include <signal.h>
#include <ctype.h>
#include "prototypes.h"
#include "defines.h"
#include "getdef.h"
static void login_exit (unused int sig)
{
exit (EXIT_FAILURE);
}
/*
* login_prompt - prompt the user for their login name
*
* login_prompt() displays the standard login prompt. If ISSUE_FILE
* is set in login.defs, this file is displayed before the prompt.
*/
void login_prompt (const char *prompt, char *name, int namesize)
{
char buf[1024];
#define MAX_ENV 32
char *envp[MAX_ENV];
char *cp;
int i;
FILE *fp;
RETSIGTYPE (*sigquit) (int);
#ifdef SIGTSTP
RETSIGTYPE (*sigtstp) (int);
#endif
/*
* There is a small chance that a QUIT character will be part of
* some random noise during a prompt. Deal with this by exiting
* instead of core dumping. If SIGTSTP is defined, do the same
* thing for that signal.
*/
sigquit = signal (SIGQUIT, login_exit);
#ifdef SIGTSTP
sigtstp = signal (SIGTSTP, login_exit);
#endif
/*
* See if the user has configured the issue file to
* be displayed and display it before the prompt.
*/
if (NULL != prompt) {
const char *fname = getdef_str ("ISSUE_FILE");
if (NULL != fname) {
fp = fopen (fname, "r");
if (NULL != fp) {
while ((i = getc (fp)) != EOF) {
(void) putc (i, stdout);
}
(void) fclose (fp);
}
}
(void) gethostname (buf, sizeof buf);
printf (prompt, buf);
(void) fflush (stdout);
}
/*
* Read the user's response. The trailing newline will be
* removed.
*/
memzero (buf, sizeof buf);
if (fgets (buf, (int) sizeof buf, stdin) != buf) {
exit (EXIT_FAILURE);
}
cp = strchr (buf, '\n');
if (NULL == cp) {
exit (EXIT_FAILURE);
}
*cp = '\0'; /* remove \n [ must be there ] */
/*
* Skip leading whitespace. This makes " username" work right.
* Then copy the rest (up to the end or the first "non-graphic"
* character into the username.
*/
for (cp = buf; *cp == ' ' || *cp == '\t'; cp++);
for (i = 0; i < namesize - 1 && isgraph (*cp); name[i++] = *cp++);
while (isgraph (*cp)) {
cp++;
}
if ('\0' != *cp) {
cp++;
}
name[i] = '\0';
/*
* This is a disaster, at best. The user may have entered extra
* environmental variables at the prompt. There are several ways
* to do this, and I just take the easy way out.
*/
if ('\0' != *cp) { /* process new variables */
char *nvar;
int count = 1;
int envc;
for (envc = 0; envc < MAX_ENV; envc++) {
nvar = strtok ((0 != envc) ? (char *) 0 : cp, " \t,");
if (NULL == nvar) {
break;
}
if (strchr (nvar, '=') != NULL) {
envp[envc] = nvar;
} else {
size_t len = strlen (nvar) + 32;
envp[envc] = xmalloc (len);
(void) snprintf (envp[envc], len,
"L%d=%s", count++, nvar);
}
}
set_env (envc, envp);
}
/*
* Set the SIGQUIT handler back to its original value
*/
(void) signal (SIGQUIT, sigquit);
#ifdef SIGTSTP
(void) signal (SIGTSTP, sigtstp);
#endif
}
+92
View File
@@ -0,0 +1,92 @@
/*
* Copyright (c) 1989 - 1991, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include "prototypes.h"
#include "defines.h"
#include <assert.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include "getdef.h"
#ident "$Id: mail.c 2819 2009-04-27 20:09:18Z nekral-guest $"
void mailcheck (void)
{
struct stat statbuf;
char *mailbox;
if (!getdef_bool ("MAIL_CHECK_ENAB")) {
return;
}
/*
* Check incoming mail in Maildir format - J.
*/
mailbox = getenv ("MAILDIR");
if (NULL != mailbox) {
char *newmail;
size_t len = strlen (mailbox) + 5;
int wlen;
newmail = xmalloc (len);
wlen = snprintf (newmail, len, "%s/new", mailbox);
assert (wlen == (int) len - 1);
if (stat (newmail, &statbuf) != -1 && statbuf.st_size != 0) {
if (statbuf.st_mtime > statbuf.st_atime) {
free (newmail);
(void) puts (_("You have new mail."));
return;
}
}
free (newmail);
}
mailbox = getenv ("MAIL");
if (NULL == mailbox) {
return;
}
if ( (stat (mailbox, &statbuf) == -1)
|| (statbuf.st_size == 0)) {
(void) puts (_("No mail."));
} else if (statbuf.st_atime > statbuf.st_mtime) {
(void) puts (_("You have mail."));
} else {
(void) puts (_("You have new mail."));
}
}
+81
View File
@@ -0,0 +1,81 @@
/*
* Copyright (c) 1989 - 1991, Julianne Frances Haugh
* Copyright (c) 1996 - 1997, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2010 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: motd.c 3224 2010-08-21 15:32:53Z nekral-guest $"
#include <stdio.h>
#include "prototypes.h"
#include "defines.h"
#include "getdef.h"
/*
* motd -- output the /etc/motd file
*
* motd() determines the name of a login announcement file and outputs
* it to the user's terminal at login time. The MOTD_FILE configuration
* option is a colon-delimited list of filenames.
*/
void motd (void)
{
FILE *fp;
char *motdlist;
const char *motdfile;
char *mb;
register int c;
motdfile = getdef_str ("MOTD_FILE");
if (NULL == motdfile) {
return;
}
motdlist = xstrdup (motdfile);
for (mb = motdlist; ;mb = NULL) {
motdfile = strtok (mb, ":");
if (NULL == motdfile) {
break;
}
fp = fopen (motdfile, "r");
if (NULL != fp) {
while ((c = getc (fp)) != EOF) {
putchar (c);
}
fclose (fp);
}
}
fflush (stdout);
free (motdlist);
}
+69
View File
@@ -0,0 +1,69 @@
/*
* Copyright (c) 1996 - 1997, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* myname.c - determine the current username and get the passwd entry
*
*/
#include <config.h>
#ident "$Id: myname.c 2813 2009-04-26 17:10:49Z nekral-guest $"
#include "defines.h"
#include <pwd.h>
#include "prototypes.h"
/*@null@*/ /*@only@*/struct passwd *get_my_pwent (void)
{
struct passwd *pw;
const char *cp = getlogin ();
uid_t ruid = getuid ();
/*
* Try getlogin() first - if it fails or returns a non-existent
* username, or a username which doesn't match the real UID, fall
* back to getpwuid(getuid()). This should work reasonably with
* usernames longer than the utmp limit (8 characters), as well as
* shared UIDs - but not both at the same time...
*
* XXX - when running from su, will return the current user (not
* the original user, like getlogin() does). Does this matter?
*/
if ((NULL != cp) && ('\0' != *cp)) {
pw = xgetpwnam (cp);
if ((NULL != pw) && (pw->pw_uid == ruid)) {
return pw;
}
}
return xgetpwuid (ruid);
}
+323
View File
@@ -0,0 +1,323 @@
/*
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1999, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ifndef USE_PAM
#ident "$Id: obscure.c 3232 2010-08-22 19:13:53Z nekral-guest $"
/*
* This version of obscure.c contains modifications to support "cracklib"
* by Alec Muffet (alec.muffett@uk.sun.com). You must obtain the Cracklib
* library source code for this function to operate.
*/
#include <ctype.h>
#include <stdio.h>
#include "prototypes.h"
#include "defines.h"
#include "getdef.h"
/*
* can't be a palindrome - like `R A D A R' or `M A D A M'
*/
static bool palindrome (unused const char *old, const char *new)
{
size_t i, j;
i = strlen (new);
for (j = 0; j < i; j++) {
if (new[i - j - 1] != new[j]) {
return false;
}
}
return true;
}
/*
* more than half of the characters are different ones.
*/
static bool similar (/*@notnull@*/const char *old, /*@notnull@*/const char *new)
{
int i, j;
/*
* XXX - sometimes this fails when changing from a simple password
* to a really long one (MD5). For now, I just return success if
* the new password is long enough. Please feel free to suggest
* something better... --marekm
*/
if (strlen (new) >= 8) {
return false;
}
for (i = j = 0; ('\0' != new[i]) && ('\0' != old[i]); i++) {
if (strchr (new, old[i]) != NULL) {
j++;
}
}
if (i >= j * 2) {
return false;
}
return true;
}
/*
* a nice mix of characters.
*/
static bool simple (unused const char *old, const char *new)
{
bool digits = false;
bool uppers = false;
bool lowers = false;
bool others = false;
int size;
int i;
for (i = 0; '\0' != new[i]; i++) {
if (isdigit (new[i])) {
digits = true;
} else if (isupper (new[i])) {
uppers = true;
} else if (islower (new[i])) {
lowers = true;
} else {
others = true;
}
}
/*
* The scam is this - a password of only one character type
* must be 8 letters long. Two types, 7, and so on.
*/
size = 9;
if (digits) {
size--;
}
if (uppers) {
size--;
}
if (lowers) {
size--;
}
if (others) {
size--;
}
if (size <= i) {
return false;
}
return true;
}
static char *str_lower (/*@returned@*/char *string)
{
char *cp;
for (cp = string; '\0' != *cp; cp++) {
*cp = tolower (*cp);
}
return string;
}
static /*@observer@*//*@null@*/const char *password_check (
/*@notnull@*/const char *old,
/*@notnull@*/const char *new,
/*@notnull@*/const struct passwd *pwdp)
{
const char *msg = NULL;
char *oldmono, *newmono, *wrapped;
#ifdef HAVE_LIBCRACK
char *dictpath;
#ifdef HAVE_LIBCRACK_PW
char *FascistCheckPw ();
#else
char *FascistCheck ();
#endif
#endif
if (strcmp (new, old) == 0) {
return _("no change");
}
newmono = str_lower (xstrdup (new));
oldmono = str_lower (xstrdup (old));
wrapped = xmalloc (strlen (oldmono) * 2 + 1);
strcpy (wrapped, oldmono);
strcat (wrapped, oldmono);
if (palindrome (oldmono, newmono)) {
msg = _("a palindrome");
} else if (strcmp (oldmono, newmono) == 0) {
msg = _("case changes only");
} else if (similar (oldmono, newmono)) {
msg = _("too similar");
} else if (simple (old, new)) {
msg = _("too simple");
} else if (strstr (wrapped, newmono) != NULL) {
msg = _("rotated");
} else {
#ifdef HAVE_LIBCRACK
/*
* Invoke Alec Muffett's cracklib routines.
*/
dictpath = getdef_str ("CRACKLIB_DICTPATH");
if (NULL != dictpath) {
#ifdef HAVE_LIBCRACK_PW
msg = FascistCheckPw (new, dictpath, pwdp);
#else
msg = FascistCheck (new, dictpath);
#endif
}
#endif
}
strzero (newmono);
strzero (oldmono);
strzero (wrapped);
free (newmono);
free (oldmono);
free (wrapped);
return msg;
}
static /*@observer@*//*@null@*/const char *obscure_msg (
/*@notnull@*/const char *old,
/*@notnull@*/const char *new,
/*@notnull@*/const struct passwd *pwdp)
{
size_t maxlen, oldlen, newlen;
char *new1, *old1;
const char *msg;
const char *result;
oldlen = strlen (old);
newlen = strlen (new);
if (newlen < (size_t) getdef_num ("PASS_MIN_LEN", 0)) {
return _("too short");
}
/*
* Remaining checks are optional.
*/
if (!getdef_bool ("OBSCURE_CHECKS_ENAB")) {
return NULL;
}
msg = password_check (old, new, pwdp);
if (NULL != msg) {
return msg;
}
result = getdef_str ("ENCRYPT_METHOD");
if (NULL == result) {
/* The traditional crypt() truncates passwords to 8 chars. It is
possible to circumvent the above checks by choosing an easy
8-char password and adding some random characters to it...
Example: "password$%^&*123". So check it again, this time
truncated to the maximum length. Idea from npasswd. --marekm */
if (getdef_bool ("MD5_CRYPT_ENAB")) {
return NULL;
}
} else {
if ( (strcmp (result, "MD5") == 0)
#ifdef USE_SHA_CRYPT
|| (strcmp (result, "SHA256") == 0)
|| (strcmp (result, "SHA512") == 0)
#endif
) {
return NULL;
}
}
maxlen = (size_t) getdef_num ("PASS_MAX_LEN", 8);
if ( (oldlen <= maxlen)
&& (newlen <= maxlen)) {
return NULL;
}
new1 = xstrdup (new);
old1 = xstrdup (old);
if (newlen > maxlen) {
new1[maxlen] = '\0';
}
if (oldlen > maxlen) {
old1[maxlen] = '\0';
}
msg = password_check (old1, new1, pwdp);
memzero (new1, newlen);
memzero (old1, oldlen);
free (new1);
free (old1);
return msg;
}
/*
* Obscure - see if password is obscure enough.
*
* The programmer is encouraged to add as much complexity to this
* routine as desired. Included are some of my favorite ways to
* check passwords.
*/
bool obscure (const char *old, const char *new, const struct passwd *pwdp)
{
const char *msg = obscure_msg (old, new, pwdp);
if (NULL != msg) {
printf (_("Bad password: %s. "), msg);
return false;
}
return true;
}
#else /* !USE_PAM */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !USE_PAM */
+80
View File
@@ -0,0 +1,80 @@
/*
* Copyright (c) 1997 - 1999, Marek Michałkiewicz
* Copyright (c) 2001 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ifdef USE_PAM
#ident "$Id: pam_pass.c 2870 2009-05-09 13:15:17Z nekral-guest $"
/*
* Change the user's password using PAM.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include "defines.h"
#include "pam_defs.h"
#include "prototypes.h"
void do_pam_passwd (const char *user, bool silent, bool change_expired)
{
pam_handle_t *pamh = NULL;
int flags = 0, ret;
if (silent)
flags |= PAM_SILENT;
if (change_expired)
flags |= PAM_CHANGE_EXPIRED_AUTHTOK;
ret = pam_start ("passwd", user, &conv, &pamh);
if (ret != PAM_SUCCESS) {
fprintf (stderr,
_("passwd: pam_start() failed, error %d\n"), ret);
exit (10); /* XXX */
}
ret = pam_chauthtok (pamh, flags);
if (ret != PAM_SUCCESS) {
fprintf (stderr, _("passwd: %s\n"), pam_strerror (pamh, ret));
fputs (_("passwd: password unchanged\n"), stderr);
pam_end (pamh, ret);
exit (10); /* XXX */
}
fputs (_("passwd: password updated successfully\n"), stderr);
(void) pam_end (pamh, PAM_SUCCESS);
}
#else /* !USE_PAM */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !USE_PAM */
+167
View File
@@ -0,0 +1,167 @@
/*
* Copyright (c) 2009 - 2010, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id:$"
#ifdef USE_PAM
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <security/pam_appl.h>
#include "prototypes.h"
/*@null@*/ /*@only@*/static const char *non_interactive_password = NULL;
static int ni_conv (int num_msg,
const struct pam_message **msg,
struct pam_response **resp,
unused void *appdata_ptr);
static struct pam_conv non_interactive_pam_conv = {
ni_conv,
NULL
};
static int ni_conv (int num_msg,
const struct pam_message **msg,
struct pam_response **resp,
unused void *appdata_ptr)
{
struct pam_response *responses;
int count;
assert (NULL != non_interactive_password);
if (num_msg <= 0) {
return PAM_CONV_ERR;
}
responses = (struct pam_response *) calloc ((size_t) num_msg,
sizeof (*responses));
if (NULL == responses) {
return PAM_CONV_ERR;
}
for (count=0; count < num_msg; count++) {
responses[count].resp_retcode = 0;
switch (msg[count]->msg_style) {
case PAM_PROMPT_ECHO_ON:
fprintf (stderr,
_("%s: PAM modules requesting echoing are not supported.\n"),
Prog);
goto failed_conversation;
case PAM_PROMPT_ECHO_OFF:
responses[count].resp = strdup (non_interactive_password);
if (NULL == responses[count].resp) {
goto failed_conversation;
}
break;
case PAM_ERROR_MSG:
if ( (NULL == msg[count]->msg)
|| (fprintf (stderr, "%s\n", msg[count]->msg) <0)) {
goto failed_conversation;
}
responses[count].resp = NULL;
break;
case PAM_TEXT_INFO:
if ( (NULL == msg[count]->msg)
|| (fprintf (stdout, "%s\n", msg[count]->msg) <0)) {
goto failed_conversation;
}
responses[count].resp = NULL;
break;
default:
(void) fprintf (stderr,
_("%s: conversation type %d not supported.\n"),
Prog, msg[count]->msg_style);
goto failed_conversation;
}
}
*resp = responses;
return PAM_SUCCESS;
failed_conversation:
for (count=0; count < num_msg; count++) {
if (NULL != responses[count].resp) {
memset (responses[count].resp, 0,
strlen (responses[count].resp));
free (responses[count].resp);
responses[count].resp = NULL;
}
}
free (responses);
*resp = NULL;
return PAM_CONV_ERR;
}
/*
* Change non interactively the user's password using PAM.
*
* Return 0 on success, 1 on failure.
*/
int do_pam_passwd_non_interractive (const char *pam_service,
const char *username,
const char* password)
{
pam_handle_t *pamh = NULL;
int ret;
ret = pam_start (pam_service, username, &non_interactive_pam_conv, &pamh);
if (ret != PAM_SUCCESS) {
fprintf (stderr,
_("%s: (user %s) pam_start failure %d\n"),
Prog, username, ret);
return 1;
}
non_interactive_password = password;
ret = pam_chauthtok (pamh, 0);
if (ret != PAM_SUCCESS) {
fprintf (stderr,
_("%s: (user %s) pam_chauthtok() failed, error:\n"
"%s\n"),
Prog, username, pam_strerror (pamh, ret));
}
(void) pam_end (pamh, PAM_SUCCESS);
return ((PAM_SUCCESS == ret) ? 0 : 1);
}
#else /* !USE_PAM */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !USE_PAM */
+91
View File
@@ -0,0 +1,91 @@
/*
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1997, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: pwd2spwd.c 2595 2009-04-05 22:29:42Z nekral-guest $"
#ifndef USE_PAM
#include <sys/types.h>
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
extern time_t time (time_t *);
/*
* pwd_to_spwd - create entries for new spwd structure
*
* pwd_to_spwd() creates a new (struct spwd) containing the
* information in the pointed-to (struct passwd).
*/
struct spwd *pwd_to_spwd (const struct passwd *pw)
{
static struct spwd sp;
/*
* Nice, easy parts first. The name and passwd map directly
* from the old password structure to the new one.
*/
sp.sp_namp = pw->pw_name;
sp.sp_pwdp = pw->pw_passwd;
{
/*
* Defaults used if there is no pw_age information.
*/
sp.sp_min = 0;
sp.sp_max = (10000L * DAY) / SCALE;
sp.sp_lstchg = (long) time ((time_t *) 0) / SCALE;
if (0 == sp.sp_lstchg) {
/* Better disable aging than requiring a password
* change */
sp.sp_lstchg = -1;
}
}
/*
* These fields have no corresponding information in the password
* file. They are set to uninitialized values.
*/
sp.sp_warn = -1;
sp.sp_expire = -1;
sp.sp_inact = -1;
sp.sp_flag = SHADOW_SP_FLAG_UNSET;
return &sp;
}
#else /* USE_PAM */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !USE_PAM */
+102
View File
@@ -0,0 +1,102 @@
/*
* Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1997 , Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: pwd_init.c 1980 2008-04-27 00:40:09Z nekral-guest $"
#include "defines.h"
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#include "prototypes.h"
/*
* pwd_init - ignore signals, and set resource limits to safe
* values. Call this before modifying password files, so that
* it is less likely to fail in the middle of operation.
*/
void pwd_init (void)
{
#ifdef HAVE_SYS_RESOURCE_H
struct rlimit rlim;
#ifdef RLIMIT_CORE
rlim.rlim_cur = rlim.rlim_max = 0;
setrlimit (RLIMIT_CORE, &rlim);
#endif
rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
#ifdef RLIMIT_AS
setrlimit (RLIMIT_AS, &rlim);
#endif
#ifdef RLIMIT_CPU
setrlimit (RLIMIT_CPU, &rlim);
#endif
#ifdef RLIMIT_DATA
setrlimit (RLIMIT_DATA, &rlim);
#endif
#ifdef RLIMIT_FSIZE
setrlimit (RLIMIT_FSIZE, &rlim);
#endif
#ifdef RLIMIT_NOFILE
setrlimit (RLIMIT_NOFILE, &rlim);
#endif
#ifdef RLIMIT_RSS
setrlimit (RLIMIT_RSS, &rlim);
#endif
#ifdef RLIMIT_STACK
setrlimit (RLIMIT_STACK, &rlim);
#endif
#else /* !HAVE_SYS_RESOURCE_H */
set_filesize_limit (30000);
/* don't know how to set the other limits... */
#endif /* !HAVE_SYS_RESOURCE_H */
signal (SIGALRM, SIG_IGN);
signal (SIGHUP, SIG_IGN);
signal (SIGINT, SIG_IGN);
signal (SIGPIPE, SIG_IGN);
signal (SIGQUIT, SIG_IGN);
signal (SIGTERM, SIG_IGN);
#ifdef SIGTSTP
signal (SIGTSTP, SIG_IGN);
#endif
#ifdef SIGTTOU
signal (SIGTTOU, SIG_IGN);
#endif
umask (077);
}
+60
View File
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2000 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: pwdcheck.c 2779 2009-04-23 20:17:02Z nekral-guest $"
#ifndef USE_PAM
#include <stdio.h>
#include <shadow.h>
#include "prototypes.h"
#include "defines.h"
#include "pwauth.h"
void passwd_check (const char *user, const char *passwd, unused const char *progname)
{
struct spwd *sp;
sp = getspnam (user); /* !USE_PAM, no need for xgetspnam */
if (NULL != sp) {
passwd = sp->sp_pwdp;
}
if (pw_auth (passwd, user, PW_LOGIN, (char *) 0) != 0) {
SYSLOG ((LOG_WARN, "incorrect password for `%s'", user));
(void) sleep (1);
fprintf (stderr, _("Incorrect password for %s.\n"), user);
exit (EXIT_FAILURE);
}
}
#else /* USE_PAM */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* USE_PAM */
+133
View File
@@ -0,0 +1,133 @@
/*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2001, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: remove_tree.c 3283 2010-09-05 15:34:42Z nekral-guest $"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include "prototypes.h"
#include "defines.h"
/*
* remove_tree - delete a directory tree
*
* remove_tree() walks a directory tree and deletes all the files
* and directories.
* At the end, it deletes the root directory itself.
*/
int remove_tree (const char *root, bool remove_root)
{
char *new_name = NULL;
int err = 0;
struct DIRECT *ent;
struct stat sb;
DIR *dir;
/*
* Open the source directory and read each entry. Every file
* entry in the directory is copied with the UID and GID set
* to the provided values. As an added security feature only
* regular files (and directories ...) are copied, and no file
* is made set-ID.
*/
dir = opendir (root);
if (NULL == dir) {
return -1;
}
while ((ent = readdir (dir))) {
size_t new_len = strlen (root) + strlen (ent->d_name) + 2;
/*
* Skip the "." and ".." entries
*/
if (strcmp (ent->d_name, ".") == 0 ||
strcmp (ent->d_name, "..") == 0) {
continue;
}
/*
* Make the filename for the current entry.
*/
free (new_name);
new_name = (char *) malloc (new_len);
if (NULL == new_name) {
err = -1;
break;
}
(void) snprintf (new_name, new_len, "%s/%s", root, ent->d_name);
if (LSTAT (new_name, &sb) == -1) {
continue;
}
if (S_ISDIR (sb.st_mode)) {
/*
* Recursively delete this directory.
*/
if (remove_tree (new_name, true) != 0) {
err = -1;
break;
}
} else {
/*
* Delete the file.
*/
if (unlink (new_name) != 0) {
err = -1;
break;
}
}
}
if (NULL != new_name) {
free (new_name);
}
(void) closedir (dir);
if (remove_root && (0 == err)) {
if (rmdir (root) != 0) {
err = -1;
}
}
return err;
}
+198
View File
@@ -0,0 +1,198 @@
/*
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1999, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ifdef RLOGIN
#ident "$Id: rlogin.c 2849 2009-04-30 21:08:49Z nekral-guest $"
#include "prototypes.h"
#include "defines.h"
#include <stdio.h>
#include <pwd.h>
#include <netdb.h>
static struct {
int spd_name;
int spd_baud;
} speed_table[] =
{
#ifdef B50
{
B50, 50},
#endif
#ifdef B75
{
B75, 75},
#endif
#ifdef B110
{
B110, 110},
#endif
#ifdef B134
{
B134, 134},
#endif
#ifdef B150
{
B150, 150},
#endif
#ifdef B200
{
B200, 200},
#endif
#ifdef B300
{
B300, 300},
#endif
#ifdef B600
{
B600, 600},
#endif
#ifdef B1200
{
B1200, 1200},
#endif
#ifdef B1800
{
B1800, 1800},
#endif
#ifdef B2400
{
B2400, 2400},
#endif
#ifdef B4800
{
B4800, 4800},
#endif
#ifdef B9600
{
B9600, 9600},
#endif
#ifdef B19200
{
B19200, 19200},
#endif
#ifdef B38400
{
B38400, 38400},
#endif
{
-1, -1}
};
static void get_remote_string (char *buf, size_t size)
{
for (;;) {
if (read (0, buf, 1) != 1) {
exit (EXIT_FAILURE);
}
if ('\0' == *buf) {
return;
}
--size;
if (size > 0) {
++buf;
}
}
/*NOTREACHED*/}
int
do_rlogin (const char *remote_host, char *name, size_t namelen, char *term,
size_t termlen)
{
struct passwd *pwd;
char remote_name[32];
char *cp;
unsigned long remote_speed = 9600;
int speed_name = B9600;
int i;
TERMIO termio;
get_remote_string (remote_name, sizeof remote_name);
get_remote_string (name, namelen);
get_remote_string (term, termlen);
cp = strchr (term, '/');
if (NULL != cp) {
*cp = '\0';
cp++;
if (getulong (cp, &remote_speed) == 0) {
remote_speed = 9600;
}
}
for (i = 0;
( (speed_table[i].spd_baud != remote_speed)
&& (speed_table[i].spd_name != -1));
i++);
if (-1 != speed_table[i].spd_name) {
speed_name = speed_table[i].spd_name;
}
/*
* Put the terminal in cooked mode with echo turned on.
*/
GTTY (0, &termio);
termio.c_iflag |= ICRNL | IXON;
termio.c_oflag |= OPOST | ONLCR;
termio.c_lflag |= ICANON | ECHO | ECHOE;
#ifdef CBAUD
termio.c_cflag = (termio.c_cflag & ~CBAUD) | speed_name;
#else
termio.c_cflag = (termio.c_cflag) | speed_name;
#endif
STTY (0, &termio);
pwd = getpwnam (name); /* local, no need for xgetpwnam */
if (NULL == pwd) {
return 0;
}
/*
* ruserok() returns 0 for success on modern systems, and 1 on
* older ones. If you are having trouble with people logging
* in without giving a required password, THIS is the culprit -
* go fix the #define in config.h.
*/
#ifndef RUSEROK
return 0;
#else
return ruserok (remote_host, pwd->pw_uid == 0,
remote_name, name) == RUSEROK;
#endif
}
#endif /* RLOGIN */
+116
View File
@@ -0,0 +1,116 @@
/*
* Copyright (c) 2011 , Julian Pidancet
* Copyright (c) 2011 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id$"
#include <stdio.h>
#include <assert.h>
#include "defines.h"
#include "prototypes.h"
/*@-exitarg@*/
#include "exitcodes.h"
static void change_root (const char* newroot);
/*
* process_root_flag - chroot if given the --root option
*
* This shall be called before accessing the passwd, group, shadow,
* gshadow, useradd's default, login.defs files (non exhaustive list)
* or authenticating the caller.
*
* The audit, syslog, or locale files shall be open before
*/
extern void process_root_flag (const char* short_opt, int argc, char **argv)
{
/*
* Parse the command line options.
*/
int i;
const char *newroot = NULL;
for (i = 0; i < argc; i++) {
if ( (strcmp (argv[i], "--root") == 0)
|| (strcmp (argv[i], short_opt) == 0)) {
if (NULL != newroot) {
fprintf (stderr,
_("%s: multiple --root options\n"),
Prog);
exit (E_BAD_ARG);
}
if (i + 1 == argc) {
fprintf (stderr,
_("%s: option '%s' requires an argument\n"),
Prog, argv[i]);
exit (E_BAD_ARG);
}
newroot = argv[i + 1];
}
}
if (NULL != newroot) {
change_root (newroot);
}
}
static void change_root (const char* newroot)
{
/* Drop privileges */
if ( (setregid (getgid (), getgid ()) != 0)
|| (setreuid (getuid (), getuid ()) != 0)) {
fprintf (stderr, _("%s: failed to drop privileges (%s)\n"),
Prog, strerror (errno));
exit (EXIT_FAILURE);
}
if ('/' != newroot[0]) {
fprintf (stderr,
_("%s: invalid chroot path '%s'\n"),
Prog, newroot);
exit (E_BAD_ARG);
}
if (access (newroot, F_OK) != 0) {
fprintf(stderr,
_("%s: cannot access chroot directory %s: %s\n"),
Prog, newroot, strerror (errno));
exit (E_BAD_ARG);
}
if (chroot (newroot) != 0) {
fprintf(stderr,
_("%s: unable to chroot to directory %s: %s\n"),
Prog, newroot, strerror (errno));
exit (E_BAD_ARG);
}
}
+252
View File
@@ -0,0 +1,252 @@
/*
* salt.c - generate a random salt string for crypt()
*
* Written by Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>,
* it is in the public domain.
*
* l64a was Written by J.T. Conklin <jtc@netbsd.org>. Public domain.
*/
#include <config.h>
#ident "$Id: salt.c 3489 2011-09-18 20:40:50Z nekral-guest $"
#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "prototypes.h"
#include "defines.h"
#include "getdef.h"
/* local function prototypes */
static void seedRNG (void);
static /*@observer@*/const char *gensalt (size_t salt_size);
#ifdef USE_SHA_CRYPT
static size_t SHA_salt_size (void);
static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds);
#endif /* USE_SHA_CRYPT */
#ifndef HAVE_L64A
static /*@observer@*/char *l64a(long value)
{
static char buf[8];
char *s = buf;
int digit;
int i;
if (value < 0) {
errno = EINVAL;
return(NULL);
}
for (i = 0; value != 0 && i < 6; i++) {
digit = value & 0x3f;
if (digit < 2) {
*s = digit + '.';
} else if (digit < 12) {
*s = digit + '0' - 2;
} else if (digit < 38) {
*s = digit + 'A' - 12;
} else {
*s = digit + 'a' - 38;
}
value >>= 6;
s++;
}
*s = '\0';
return(buf);
}
#endif /* !HAVE_L64A */
static void seedRNG (void)
{
struct timeval tv;
static int seeded = 0;
if (0 == seeded) {
(void) gettimeofday (&tv, NULL);
srandom (tv.tv_sec ^ tv.tv_usec ^ getpid ());
seeded = 1;
}
}
/*
* Add the salt prefix.
*/
#define MAGNUM(array,ch) (array)[0]=(array)[2]='$',(array)[1]=(ch),(array)[3]='\0'
#ifdef USE_SHA_CRYPT
/*
* Return the salt size.
* The size of the salt string is between 8 and 16 bytes for the SHA crypt
* methods.
*/
static size_t SHA_salt_size (void)
{
double rand_size;
seedRNG ();
rand_size = (double) 9.0 * random () / RAND_MAX;
return (size_t) (8 + rand_size);
}
/* Default number of rounds if not explicitly specified. */
#define ROUNDS_DEFAULT 5000
/* Minimum number of rounds. */
#define ROUNDS_MIN 1000
/* Maximum number of rounds. */
#define ROUNDS_MAX 999999999
/*
* Return a salt prefix specifying the rounds number for the SHA crypt methods.
*/
static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds)
{
static char rounds_prefix[18]; /* Max size: rounds=999999999$ */
long rounds;
if (NULL == prefered_rounds) {
long min_rounds = getdef_long ("SHA_CRYPT_MIN_ROUNDS", -1);
long max_rounds = getdef_long ("SHA_CRYPT_MAX_ROUNDS", -1);
double rand_rounds;
if ((-1 == min_rounds) && (-1 == max_rounds)) {
return "";
}
if (-1 == min_rounds) {
min_rounds = max_rounds;
}
if (-1 == max_rounds) {
max_rounds = min_rounds;
}
if (min_rounds > max_rounds) {
max_rounds = min_rounds;
}
seedRNG ();
rand_rounds = (double) (max_rounds-min_rounds+1.0) * random ();
rand_rounds /= RAND_MAX;
rounds = min_rounds + rand_rounds;
} else if (0 == *prefered_rounds) {
return "";
} else {
rounds = *prefered_rounds;
}
/* Sanity checks. The libc should also check this, but this
* protects against a rounds_prefix overflow. */
if (rounds < ROUNDS_MIN) {
rounds = ROUNDS_MIN;
}
if (rounds > ROUNDS_MAX) {
rounds = ROUNDS_MAX;
}
(void) snprintf (rounds_prefix, sizeof rounds_prefix,
"rounds=%ld$", rounds);
return rounds_prefix;
}
#endif /* USE_SHA_CRYPT */
/*
* Generate salt of size salt_size.
*/
#define MAX_SALT_SIZE 16
#define MIN_SALT_SIZE 8
static /*@observer@*/const char *gensalt (size_t salt_size)
{
static char salt[32];
salt[0] = '\0';
assert (salt_size >= MIN_SALT_SIZE &&
salt_size <= MAX_SALT_SIZE);
seedRNG ();
strcat (salt, l64a (random()));
do {
strcat (salt, l64a (random()));
} while (strlen (salt) < salt_size);
salt[salt_size] = '\0';
return salt;
}
/*
* Generate 8 base64 ASCII characters of random salt. If MD5_CRYPT_ENAB
* in /etc/login.defs is "yes", the salt string will be prefixed by "$1$"
* (magic) and pw_encrypt() will execute the MD5-based FreeBSD-compatible
* version of crypt() instead of the standard one.
* Other methods can be set with ENCRYPT_METHOD
*
* The method can be forced with the meth parameter.
* If NULL, the method will be defined according to the MD5_CRYPT_ENAB and
* ENCRYPT_METHOD login.defs variables.
*
* If meth is specified, an additional parameter can be provided.
* * For the SHA256 and SHA512 method, this specifies the number of rounds
* (if not NULL).
*/
/*@observer@*/const char *crypt_make_salt (/*@null@*//*@observer@*/const char *meth, /*@null@*/void *arg)
{
/* Max result size for the SHA methods:
* +3 $5$
* +17 rounds=999999999$
* +16 salt
* +1 \0
*/
static char result[40];
size_t salt_len = 8;
const char *method;
result[0] = '\0';
if (NULL != meth)
method = meth;
else {
method = getdef_str ("ENCRYPT_METHOD");
if (NULL == method) {
method = getdef_bool ("MD5_CRYPT_ENAB") ? "MD5" : "DES";
}
}
if (0 == strcmp (method, "MD5")) {
MAGNUM(result, '1');
#ifdef USE_SHA_CRYPT
} else if (0 == strcmp (method, "SHA256")) {
MAGNUM(result, '5');
strcat(result, SHA_salt_rounds((int *)arg));
salt_len = SHA_salt_size();
} else if (0 == strcmp (method, "SHA512")) {
MAGNUM(result, '6');
strcat(result, SHA_salt_rounds((int *)arg));
salt_len = SHA_salt_size();
#endif /* USE_SHA_CRYPT */
} else if (0 != strcmp (method, "DES")) {
fprintf (stderr,
_("Invalid ENCRYPT_METHOD value: '%s'.\n"
"Defaulting to DES.\n"),
method);
result[0] = '\0';
}
/*
* Concatenate a pseudo random salt.
*/
assert (sizeof (result) > strlen (result) + salt_len);
strncat (result, gensalt (salt_len),
sizeof (result) - strlen (result) - 1);
return result;
}
+148
View File
@@ -0,0 +1,148 @@
/*
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2010, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Separated from setup.c. --marekm
*/
#include <config.h>
#ident "$Id: setugid.c 3231 2010-08-22 13:04:54Z nekral-guest $"
#include <stdio.h>
#include <grp.h>
#include <errno.h>
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
#include "getdef.h"
/*
* setup_groups - set the group credentials
* set the group ID to the value from the password file entry
* set the supplementary group IDs
*
* In case of PAM enabled configurations, this shall be called before
* pam_setcred.
*
* Returns 0 on success, or -1 on failure.
*/
int setup_groups (const struct passwd *info)
{
/*
* Set the real group ID to the primary group ID in the password
* file.
*/
if (setgid (info->pw_gid) == -1) {
int err = errno;
perror ("setgid");
SYSLOG ((LOG_ERR, "bad group ID `%d' for user `%s': %s\n",
info->pw_gid, info->pw_name, strerror (err)));
closelog ();
return -1;
}
#ifdef HAVE_INITGROUPS
/*
* For systems which support multiple concurrent groups, go get
* the group set from the /etc/group file.
*/
if (initgroups (info->pw_name, info->pw_gid) == -1) {
int err = errno;
perror ("initgroups");
SYSLOG ((LOG_ERR, "initgroups failed for user `%s': %s\n",
info->pw_name, strerror (err)));
closelog ();
return -1;
}
#endif
return 0;
}
/*
* change_uid - Set the real UID
*
* Returns 0 on success, or -1 on failure.
*/
int change_uid (const struct passwd *info)
{
/*
* Set the real UID to the UID value in the password file.
*/
if (setuid (info->pw_uid) != 0) {
int err = errno;
perror ("setuid");
SYSLOG ((LOG_ERR, "bad user ID `%d' for user `%s': %s\n",
(int) info->pw_uid, info->pw_name, strerror (err)));
closelog ();
return -1;
}
return 0;
}
/*
* setup_uid_gid() performs the following steps -
*
* set the group ID to the value from the password file entry
* set the supplementary group IDs
* optionally call specified function which may add more groups
* set the user ID to the value from the password file entry
*
* Returns 0 on success, or -1 on failure.
*/
#if defined (HAVE_INITGROUPS) && ! (defined USE_PAM)
int setup_uid_gid (const struct passwd *info, bool is_console)
#else
int setup_uid_gid (const struct passwd *info)
#endif
{
if (setup_groups (info) < 0) {
return -1;
}
#if defined (HAVE_INITGROUPS) && ! defined (USE_PAM)
if (is_console) {
const char *cp = getdef_str ("CONSOLE_GROUPS");
if ((NULL != cp) && (add_groups (cp) != 0)) {
perror ("Warning: add_groups");
}
}
#endif /* HAVE_INITGROUPS && !USE_PAM*/
if (change_uid (info) < 0) {
return -1;
}
return 0;
}
+310
View File
@@ -0,0 +1,310 @@
/*
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Separated from setup.c. --marekm
*/
#include <config.h>
#ident "$Id: setupenv.c 3232 2010-08-22 19:13:53Z nekral-guest $"
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <ctype.h>
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
#include "getdef.h"
#ifndef USE_PAM
static void
addenv_path (const char *varname, const char *dirname, const char *filename)
{
char *buf;
size_t len = strlen (dirname) + strlen (filename) + 2;
int wlen;
buf = xmalloc (len);
wlen = snprintf (buf, len, "%s/%s", dirname, filename);
assert (wlen == (int) len - 1);
addenv (varname, buf);
free (buf);
}
static void read_env_file (const char *filename)
{
FILE *fp;
char buf[1024];
char *cp, *name, *val;
fp = fopen (filename, "r");
if (NULL == fp) {
return;
}
while (fgets (buf, (int)(sizeof buf), fp) == buf) {
cp = strrchr (buf, '\n');
if (NULL == cp) {
break;
}
*cp = '\0';
cp = buf;
/* ignore whitespace and comments */
while (('\0' != *cp) && isspace (*cp)) {
cp++;
}
if (('\0' == *cp) || ('#' == *cp)) {
continue;
}
/*
* ignore lines which don't follow the name=value format
* (for example, the "export NAME" shell commands)
*/
name = cp;
while (('\0' != *cp) && !isspace (*cp) && ('=' != *cp)) {
cp++;
}
if ('=' != *cp) {
continue;
}
/* NUL-terminate the name */
*cp = '\0';
cp++;
val = cp;
#if 0 /* XXX untested, and needs rewrite with fewer goto's :-) */
/*
(state, char_type) -> (state, action)
state: unquoted, single_quoted, double_quoted, escaped, double_quoted_escaped
char_type: normal, white, backslash, single, double
action: remove_curr, remove_curr_skip_next, remove_prev, finish XXX
*/
no_quote:
if (*cp == '\\') {
/* remove the backslash */
remove_char (cp);
/* skip over the next character */
if (*cp)
cp++;
goto no_quote;
} else if (*cp == '\'') {
/* remove the quote */
remove_char (cp);
/* now within single quotes */
goto s_quote;
} else if (*cp == '"') {
/* remove the quote */
remove_char (cp);
/* now within double quotes */
goto d_quote;
} else if (*cp == '\0') {
/* end of string */
goto finished;
} else if (isspace (*cp)) {
/* unescaped whitespace - end of string */
*cp = '\0';
goto finished;
} else {
cp++;
goto no_quote;
}
s_quote:
if (*cp == '\'') {
/* remove the quote */
remove_char (cp);
/* unquoted again */
goto no_quote;
} else if (*cp == '\0') {
/* end of string */
goto finished;
} else {
/* preserve everything within single quotes */
cp++;
goto s_quote;
}
d_quote:
if (*cp == '\"') {
/* remove the quote */
remove_char (cp);
/* unquoted again */
goto no_quote;
} else if (*cp == '\\') {
cp++;
/* if backslash followed by double quote, remove backslash
else skip over the backslash and following char */
if (*cp == '"')
remove_char (cp - 1);
else if (*cp)
cp++;
goto d_quote;
}
eise if (*cp == '\0') {
/* end of string */
goto finished;
} else {
/* preserve everything within double quotes */
goto d_quote;
}
finished:
#endif /* 0 */
/*
* XXX - should handle quotes, backslash escapes, etc.
* like the shell does.
*/
addenv (name, val);
}
(void) fclose (fp);
}
#endif /* USE_PAM */
/*
* change to the user's home directory
* set the HOME, SHELL, MAIL, PATH, and LOGNAME or USER environmental
* variables.
*/
void setup_env (struct passwd *info)
{
#ifndef USE_PAM
const char *envf;
#endif
const char *cp;
/*
* Change the current working directory to be the home directory
* of the user. It is a fatal error for this process to be unable
* to change to that directory. There is no "default" home
* directory.
*
* We no longer do it as root - should work better on NFS-mounted
* home directories. Some systems default to HOME=/, so we make
* this a configurable option. --marekm
*/
if (chdir (info->pw_dir) == -1) {
static char temp_pw_dir[] = "/";
if (!getdef_bool ("DEFAULT_HOME") || chdir ("/") == -1) {
fprintf (stderr, _("Unable to cd to '%s'\n"),
info->pw_dir);
SYSLOG ((LOG_WARN,
"unable to cd to `%s' for user `%s'\n",
info->pw_dir, info->pw_name));
closelog ();
exit (EXIT_FAILURE);
}
(void) puts (_("No directory, logging in with HOME=/"));
info->pw_dir = temp_pw_dir;
}
/*
* Create the HOME environmental variable and export it.
*/
addenv ("HOME", info->pw_dir);
/*
* Create the SHELL environmental variable and export it.
*/
if ((NULL == info->pw_shell) || ('\0' == *info->pw_shell)) {
static char temp_pw_shell[] = SHELL;
info->pw_shell = temp_pw_shell;
}
addenv ("SHELL", info->pw_shell);
/*
* Export the user name. For BSD derived systems, it's "USER", for
* all others it's "LOGNAME". We set both of them.
*/
addenv ("USER", info->pw_name);
addenv ("LOGNAME", info->pw_name);
/*
* Create the PATH environmental variable and export it.
*/
cp = getdef_str ((info->pw_uid == 0) ? "ENV_SUPATH" : "ENV_PATH");
if (NULL == cp) {
/* not specified, use a minimal default */
addenv ((info->pw_uid == 0) ? "PATH=/sbin:/bin:/usr/sbin:/usr/bin" : "PATH=/bin:/usr/bin", NULL);
} else if (strchr (cp, '=')) {
/* specified as name=value (PATH=...) */
addenv (cp, NULL);
} else {
/* only value specified without "PATH=" */
addenv ("PATH", cp);
}
#ifndef USE_PAM
/*
* Create the MAIL environmental variable and export it. login.defs
* knows the prefix.
*/
if (getdef_bool ("MAIL_CHECK_ENAB")) {
cp = getdef_str ("MAIL_DIR");
if (NULL != cp) {
addenv_path ("MAIL", cp, info->pw_name);
} else {
cp = getdef_str ("MAIL_FILE");
if (NULL != cp) {
addenv_path ("MAIL", info->pw_dir, cp);
} else {
#if defined(MAIL_SPOOL_FILE)
addenv_path ("MAIL", info->pw_dir, MAIL_SPOOL_FILE);
#elif defined(MAIL_SPOOL_DIR)
addenv_path ("MAIL", MAIL_SPOOL_DIR, info->pw_name);
#endif
}
}
}
/*
* Read environment from optional config file. --marekm
*/
envf = getdef_str ("ENVIRON_FILE");
if (NULL != envf) {
read_env_file (envf);
}
#endif /* !USE_PAM */
}
+103
View File
@@ -0,0 +1,103 @@
/*
* Copyright (c) 1989 - 1991, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko
* Copyright (c) 2009 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: shell.c 3232 2010-08-22 19:13:53Z nekral-guest $"
#include <stdio.h>
#include <errno.h>
#include "prototypes.h"
#include "defines.h"
extern char **newenvp;
extern size_t newenvc;
/*
* shell - execute the named program
*
* shell begins by trying to figure out what argv[0] is going to
* be for the named process. The user may pass in that argument,
* or it will be the last pathname component of the file with a
* '-' prepended.
* Then, it executes the named file.
*/
int shell (const char *file, /*@null@*/const char *arg, char *const envp[])
{
char arg0[1024];
int err;
if (file == (char *) 0) {
errno = EINVAL;
return errno;
}
/*
* The argv[0]'th entry is usually the path name, but
* for various reasons the invoker may want to override
* that. So, we determine the 0'th entry only if they
* don't want to tell us what it is themselves.
*/
if (arg == (char *) 0) {
(void) snprintf (arg0, sizeof arg0, "-%s", Basename ((char *) file));
arg0[sizeof arg0 - 1] = '\0';
arg = arg0;
}
/*
* First we try the direct approach. The system should be
* able to figure out what we are up to without too much
* grief.
*/
(void) execle (file, arg, (char *) 0, envp);
err = errno;
if (access (file, R_OK|X_OK) == 0) {
/*
* Assume this is a shell script (with no shebang).
* Interpret it with /bin/sh
*/
(void) execle (SHELL, "sh", "-", file, (char *)0, envp);
err = errno;
}
/*
* Obviously something is really wrong - I can't figure out
* how to execute this stupid shell, so I might as well give
* up in disgust ...
*/
(void) snprintf (arg0, sizeof arg0, _("Cannot execute %s"), file);
errno = err;
perror (arg0);
return err;
}
+243
View File
@@ -0,0 +1,243 @@
/*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1999, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if !defined(__GLIBC__)
#define _XOPEN_SOURCE 500
#endif
#include <config.h>
#include <ctype.h>
#ident "$Id: strtoday.c 3169 2010-03-20 10:19:50Z nekral-guest $"
#include "defines.h"
#include "prototypes.h"
#ifndef USE_GETDATE
#define USE_GETDATE 1
#endif
#if USE_GETDATE
#include "getdate.h"
/*
* strtoday() now uses get_date() (borrowed from GNU shellutils)
* which can handle many date formats, for example:
* 1970-09-17 # ISO 8601.
* 70-9-17 # This century assumed by default.
* 70-09-17 # Leading zeros are ignored.
* 9/17/72 # Common U.S. writing.
* 24 September 1972
* 24 Sept 72 # September has a special abbreviation.
* 24 Sep 72 # Three-letter abbreviations always allowed.
* Sep 24, 1972
* 24-sep-72
* 24sep72
*/
long strtoday (const char *str)
{
time_t t;
bool isnum = true;
const char *s = str;
/*
* get_date() interprets an empty string as the current date,
* which is not what we expect, unless you're a BOFH :-).
* (useradd sets sp_expire = current date for new lusers)
*/
if ((NULL == str) || ('\0' == *str)) {
return -1;
}
/* If a numerical value is provided, this is already a number of
* days since EPOCH.
*/
if ('-' == *s) {
s++;
}
while (' ' == *s) {
s++;
}
while (isnum && ('\0' != *s)) {
if (!isdigit (*s)) {
isnum = false;
}
s++;
}
if (isnum) {
long retdate;
if (getlong (str, &retdate) == 0) {
return -2;
}
return retdate;
}
t = get_date (str, NULL);
if ((time_t) - 1 == t) {
return -2;
}
/* convert seconds to days since 1970-01-01 */
return (long) (t + DAY / 2) / DAY;
}
#else /* !USE_GETDATE */
/*
* Old code, just in case get_date() doesn't work as expected...
*/
#include <stdio.h>
#ifdef HAVE_STRPTIME
/*
* for now we allow just one format, but we can define more later
* (we try them all until one succeeds). --marekm
*/
static char *date_formats[] = {
"%Y-%m-%d",
(char *) 0
};
#else
/*
* days and juldays are used to compute the number of days in the
* current month, and the cummulative number of days in the preceding
* months. they are declared so that january is 1, not 0.
*/
static short days[13] = { 0,
31, 28, 31, 30, 31, 30, /* JAN - JUN */
31, 31, 30, 31, 30, 31
}; /* JUL - DEC */
static short juldays[13] = { 0,
0, 31, 59, 90, 120, 151, /* JAN - JUN */
181, 212, 243, 273, 304, 334
}; /* JUL - DEC */
#endif
/*
* strtoday - compute the number of days since 1970.
*
* the total number of days prior to the current date is
* computed. january 1, 1970 is used as the origin with
* it having a day number of 0.
*/
long strtoday (const char *str)
{
#ifdef HAVE_STRPTIME
struct tm tp;
char *const *fmt;
char *cp;
time_t result;
memzero (&tp, sizeof tp);
for (fmt = date_formats; *fmt; fmt++) {
cp = strptime ((char *) str, *fmt, &tp);
if ((NULL == cp) || ('\0' != *cp)) {
continue;
}
result = mktime (&tp);
if ((time_t) - 1 == result) {
continue;
}
return (long) (result / DAY); /* success */
}
return -1;
#else
char slop[2];
int month;
int day;
int year;
long total;
/*
* start by separating the month, day and year. the order
* is compiled in ...
*/
if (sscanf (str, "%d/%d/%d%c", &year, &month, &day, slop) != 3) {
return -1;
}
/*
* the month, day of the month, and year are checked for
* correctness and the year adjusted so it falls between
* 1970 and 2069.
*/
if ((month < 1) || (month > 12)) {
return -1;
}
if (day < 1) {
return -1;
}
if ( ((2 != month) || ((year % 4) != 0))
&& (day > days[month])) {
return -1;
} else if ((month == 2) && ((year % 4) == 0) && (day > 29)) {
return -1;
}
if (year < 0) {
return -1;
} else if (year <= 69) {
year += 2000;
} else if (year <= 99) {
year += 1900;
}
/*
* On systems with 32-bit signed time_t, time wraps around in 2038
* - for now we just limit the year to 2037 (instead of 2069).
* This limit can be removed once no one is using 32-bit systems
* anymore :-). --marekm
*/
if ((year < 1970) || (year > 2037)) {
return -1;
}
/*
* the total number of days is the total number of days in all
* the whole years, plus the number of leap days, plus the
* number of days in the whole months preceding, plus the number
* of days so far in the month.
*/
total = (long) ((year - 1970) * 365L) + (((year + 1) - 1970) / 4);
total += (long) juldays[month] + (month > 2 && (year % 4) == 0 ? 1 : 0);
total += (long) day - 1;
return total;
#endif /* HAVE_STRPTIME */
}
#endif /* !USE_GETDATE */
+78
View File
@@ -0,0 +1,78 @@
/*
* Copyright (c) 1989 - 1991, Julianne Frances Haugh
* Copyright (c) 1996 - 1999, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: sub.c 3232 2010-08-22 19:13:53Z nekral-guest $"
#include <pwd.h>
#include <stdio.h>
#include <sys/types.h>
#include "prototypes.h"
#include "defines.h"
#define BAD_SUBROOT2 "invalid root `%s' for user `%s'\n"
#define NO_SUBROOT2 "no subsystem root `%s' for user `%s'\n"
/*
* subsystem - change to subsystem root
*
* A subsystem login is indicated by the presense of a "*" as
* the first character of the login shell. The given home
* directory will be used as the root of a new filesystem which
* the user is actually logged into.
*/
void subsystem (const struct passwd *pw)
{
/*
* The new root directory must begin with a "/" character.
*/
if (pw->pw_dir[0] != '/') {
printf (_("Invalid root directory '%s'\n"), pw->pw_dir);
SYSLOG ((LOG_WARN, BAD_SUBROOT2, pw->pw_dir, pw->pw_name));
closelog ();
exit (EXIT_FAILURE);
}
/*
* The directory must be accessible and the current process
* must be able to change into it.
*/
if ( (chdir (pw->pw_dir) != 0)
|| (chroot (pw->pw_dir) != 0)) {
(void) printf (_("Can't change root directory to '%s'\n"),
pw->pw_dir);
SYSLOG ((LOG_WARN, NO_SUBROOT2, pw->pw_dir, pw->pw_name));
closelog ();
exit (EXIT_FAILURE);
}
}
+106
View File
@@ -0,0 +1,106 @@
/*
* Copyright (c) 1989 - 1992, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2010, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: sulog.c 3231 2010-08-22 13:04:54Z nekral-guest $"
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <time.h>
#include "prototypes.h"
#include "defines.h"
#include "getdef.h"
/*
* sulog - log a SU command execution result
*/
void sulog (const char *tty, bool success, const char *oldname, const char *name)
{
const char *sulog_file;
time_t now;
struct tm *tm;
FILE *fp;
mode_t oldmask;
gid_t oldgid = 0;
if (success) {
SYSLOG ((LOG_INFO,
"Successful su for %s by %s",name,oldname));
} else {
SYSLOG ((LOG_NOTICE,
"FAILED su for %s by %s",name,oldname));
}
sulog_file = getdef_str ("SULOG_FILE");
if (NULL == sulog_file) {
return;
}
oldgid = getgid ();
oldmask = umask (077);
/* Switch to group root to avoid creating the sulog file with
* the wrong group ownership. */
if ((oldgid != 0) && (setgid (0) != 0)) {
SYSLOG ((LOG_INFO,
"su session not logged to %s", sulog_file));
/* Continue, but do not switch back to oldgid later */
oldgid = 0;
}
fp = fopen (sulog_file, "a+");
(void) umask (oldmask);
if ((oldgid != 0) && (setgid (oldgid) != 0)) {
perror ("setgid");
SYSLOG ((LOG_ERR,
"can't switch back to group `%d' in sulog",
oldgid));
/* Do not return if the group permission were raised. */
exit (EXIT_FAILURE);
}
if (fp == (FILE *) 0) {
return; /* can't open or create logfile */
}
(void) time (&now);
tm = localtime (&now);
fprintf (fp, "SU %.02d/%.02d %.02d:%.02d %c %s %s-%s\n",
tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
success ? '+' : '-', tty, oldname, name);
(void) fflush (fp);
fsync (fileno (fp));
fclose (fp);
/* TODO: log if failure */
}
+90
View File
@@ -0,0 +1,90 @@
/*
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1997, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2010, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: ttytype.c 3232 2010-08-22 19:13:53Z nekral-guest $"
#include <stdio.h>
#include "prototypes.h"
#include "defines.h"
#include "getdef.h"
/*
* ttytype - set ttytype from port to terminal type mapping database
*/
void ttytype (const char *line)
{
FILE *fp;
char buf[BUFSIZ];
const char *typefile;
char *cp;
char type[1024] = "";
char port[1024];
if (getenv ("TERM") != NULL) {
return;
}
typefile = getdef_str ("TTYTYPE_FILE");
if (NULL == typefile) {
return;
}
if (access (typefile, F_OK) != 0) {
return;
}
fp = fopen (typefile, "r");
if (NULL == fp) {
perror (typefile);
return;
}
while (fgets (buf, (int) sizeof buf, fp) == buf) {
if (buf[0] == '#') {
continue;
}
cp = strchr (buf, '\n');
if (NULL != cp) {
*cp = '\0';
}
if ( (sscanf (buf, "%1023s %1023s", type, port) == 2)
&& (strcmp (line, port) == 0)) {
break;
}
}
if ((feof (fp) == 0) && (ferror (fp) == 0) && (type[0] != '\0')) {
addenv ("TERM", type);
}
(void) fclose (fp);
}
+80
View File
@@ -0,0 +1,80 @@
/*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1991 - 1994, Chip Rosenthal
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ifndef USE_PAM
#ident "$Id: tz.c 3231 2010-08-22 13:04:54Z nekral-guest $"
#include <stdio.h>
#include <string.h>
#include "defines.h"
#include "prototypes.h"
#include "getdef.h"
/*
* tz - return local timezone name
*
* tz() determines the name of the local timezone by reading the
* contents of the file named by ``fname''.
*/
/*@observer@*/const char *tz (const char *fname)
{
FILE *fp = NULL;
static char tzbuf[BUFSIZ];
const char *def_tz = "TZ=CST6CDT";
fp = fopen (fname, "r");
if ( (NULL == fp)
|| (fgets (tzbuf, (int) sizeof (tzbuf), fp) == NULL)) {
def_tz = getdef_str ("ENV_TZ");
if ((NULL == def_tz) || ('/' == def_tz[0])) {
def_tz = "TZ=CST6CDT";
}
strcpy (tzbuf, def_tz);
} else {
tzbuf[strlen (tzbuf) - 1] = '\0';
}
if (NULL != fp) {
(void) fclose (fp);
}
return tzbuf;
}
#else /* !USE_PAM */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !USE_PAM */
+70
View File
@@ -0,0 +1,70 @@
/*
* Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1997, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: ulimit.c 2188 2008-06-15 21:59:41Z nekral-guest $"
#if HAVE_ULIMIT_H
#include <ulimit.h>
#ifndef UL_SETFSIZE
#ifdef UL_SFILLIM
#define UL_SETFSIZE UL_SFILLIM
#else
#define UL_SETFSIZE 2
#endif
#endif
#elif HAVE_SYS_RESOURCE_H
#include <sys/time.h> /* for struct timeval on sunos4 */
/* XXX - is the above ok or should it be <time.h> on ultrix? */
#include <sys/resource.h>
#endif
#include "prototypes.h"
int set_filesize_limit (int blocks)
{
int ret = -1;
#if HAVE_ULIMIT_H
if (ulimit (UL_SETFSIZE, blocks) != -1) {
ret = 0;
}
#elif defined(RLIMIT_FSIZE)
struct rlimit rlimit_fsize;
rlimit_fsize.rlim_cur = 512L * blocks;
rlimit_fsize.rlim_max = rlimit_fsize.rlim_cur;
ret = setrlimit (RLIMIT_FSIZE, &rlimit_fsize);
#endif
return ret;
}
+237
View File
@@ -0,0 +1,237 @@
/*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2000 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: $"
#include <assert.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include "defines.h"
#include "prototypes.h"
#ifdef __linux__
static int check_status (const char *sname, uid_t uid);
static int user_busy_processes (const char *name, uid_t uid);
#else /* !__linux__ */
static int user_busy_utmp (const char *name);
#endif /* !__linux__ */
/*
* user_busy - check if an user if currently running processes
*/
int user_busy (const char *name, uid_t uid)
{
/* There are no standard ways to get the list of processes.
* An option could be to run an external tool (ps).
*/
#ifdef __linux__
/* On Linux, directly parse /proc */
return user_busy_processes (name, uid);
#else /* !__linux__ */
/* If we cannot rely on /proc, check is there is a record in utmp
* indicating that the user is still logged in */
return user_busy_utmp (name);
#endif /* !__linux__ */
}
#ifndef __linux__
static int user_busy_utmp (const char *name)
{
#ifdef USE_UTMPX
struct utmpx *utent;
setutxent ();
while ((utent = getutxent ()) != NULL)
#else /* !USE_UTMPX */
struct utmp *utent;
setutent ();
while ((utent = getutent ()) != NULL)
#endif /* !USE_UTMPX */
{
if (utent->ut_type != USER_PROCESS) {
continue;
}
if (strncmp (utent->ut_user, name, sizeof utent->ut_user) != 0) {
continue;
}
if (kill (utent->ut_pid, 0) != 0) {
continue;
}
fprintf (stderr,
_("%s: user %s is currently logged in\n"),
Prog, name);
return 1;
}
return 0;
}
#endif /* !__linux__ */
#ifdef __linux__
static int check_status (const char *sname, uid_t uid)
{
/* 40: /proc/xxxxxxxxxx/task/xxxxxxxxxx/status + \0 */
char status[40];
char line[1024];
FILE *sfile;
snprintf (status, 40, "/proc/%s/status", sname);
status[39] = '\0';
sfile = fopen (status, "r");
if (NULL == sfile) {
return 0;
}
while (fgets (line, sizeof (line), sfile) == line) {
if (strncmp (line, "Uid:\t", 5) == 0) {
unsigned long ruid, euid, suid;
assert (uid == (unsigned long) uid);
if (sscanf (line,
"Uid:\t%lu\t%lu\t%lu\n",
&ruid, &euid, &suid) == 3) {
if ( (ruid == (unsigned long) uid)
|| (euid == (unsigned long) uid)
|| (suid == (unsigned long) uid)) {
(void) fclose (sfile);
return 1;
}
} else {
/* Ignore errors. This is just a best effort. */
}
(void) fclose (sfile);
return 0;
}
}
(void) fclose (sfile);
return 0;
}
static int user_busy_processes (const char *name, uid_t uid)
{
DIR *proc;
struct dirent *ent;
char *tmp_d_name;
pid_t pid;
DIR *task_dir;
/* 22: /proc/xxxxxxxxxx/task + \0 */
char task_path[22];
char root_path[22];
struct stat sbroot;
struct stat sbroot_process;
proc = opendir ("/proc");
if (proc == NULL) {
perror ("opendir /proc");
return 0;
}
if (stat ("/", &sbroot) != 0) {
perror ("stat (\"/\")");
(void) closedir (proc);
return 0;
}
while ((ent = readdir (proc)) != NULL) {
tmp_d_name = ent->d_name;
/*
* Ingo Molnar's patch introducing NPTL for 2.4 hides
* threads in the /proc directory by prepending a period.
* This patch is applied by default in some RedHat
* kernels.
*/
if ( (strcmp (tmp_d_name, ".") == 0)
|| (strcmp (tmp_d_name, "..") == 0)) {
continue;
}
if (*tmp_d_name == '.') {
tmp_d_name++;
}
/* Check if this is a valid PID */
if (get_pid (tmp_d_name, &pid) == 0) {
continue;
}
/* Check if the process is in our chroot */
snprintf (root_path, 22, "/proc/%lu/root", (unsigned long) pid);
root_path[21] = '\0';
if (stat (root_path, &sbroot_process) != 0) {
continue;
}
if ( (sbroot.st_dev != sbroot_process.st_dev)
|| (sbroot.st_ino != sbroot_process.st_ino)) {
continue;
}
if (check_status (tmp_d_name, uid) != 0) {
(void) closedir (proc);
fprintf (stderr,
_("%s: user %s is currently used by process %d\n"),
Prog, name, pid);
return 1;
}
snprintf (task_path, 22, "/proc/%lu/task", (unsigned long) pid);
task_path[21] = '\0';
task_dir = opendir (task_path);
if (task_dir != NULL) {
while ((ent = readdir (task_dir)) != NULL) {
pid_t tid;
if (get_pid (ent->d_name, &tid) == 0) {
continue;
}
if (tid == pid) {
continue;
}
if (check_status (task_path+6, uid) != 0) {
(void) closedir (proc);
fprintf (stderr,
_("%s: user %s is currently used by process %d\n"),
Prog, name, pid);
return 1;
}
}
(void) closedir (task_dir);
} else {
/* Ignore errors. This is just a best effort */
}
}
(void) closedir (proc);
return 0;
}
#endif /* __linux__ */
+462
View File
@@ -0,0 +1,462 @@
/*
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1999, Marek Michałkiewicz
* Copyright (c) 2001 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include "defines.h"
#include "prototypes.h"
#include <utmp.h>
#ifdef USE_UTMPX
#include <utmpx.h>
#endif
#include <assert.h>
#include <netdb.h>
#include <stdio.h>
#ident "$Id: utmp.c 3720 2012-05-18 17:57:52Z nekral-guest $"
/*
* is_my_tty -- determine if "tty" is the same TTY stdin is using
*/
static bool is_my_tty (const char *tty)
{
/* full_tty shall be at least sizeof utmp.ut_line + 5 */
char full_tty[200];
/* tmptty shall be bigger than full_tty */
static char tmptty[sizeof (full_tty)+1];
if ('/' != *tty) {
(void) snprintf (full_tty, sizeof full_tty, "/dev/%s", tty);
tty = &full_tty[0];
}
if ('\0' == tmptty[0]) {
const char *tname = ttyname (STDIN_FILENO);
if (NULL != tname) {
(void) strncpy (tmptty, tname, sizeof tmptty);
tmptty[sizeof (tmptty) - 1] = '\0';
}
}
if ('\0' == tmptty[0]) {
(void) puts (_("Unable to determine your tty name."));
exit (EXIT_FAILURE);
} else if (strncmp (tty, tmptty, sizeof (tmptty)) != 0) {
return false;
} else {
return true;
}
}
/*
* get_current_utmp - return the most probable utmp entry for the current
* session
*
* The utmp file is scanned for an entry with the same process ID.
* The line enterred by the *getty / telnetd, etc. should also match
* the current terminal.
*
* When an entry is returned by get_current_utmp, and if the utmp
* structure has a ut_id field, this field should be used to update
* the entry information.
*
* Return NULL if no entries exist in utmp for the current process.
*/
/*@null@*/ /*@only@*/struct utmp *get_current_utmp (void)
{
struct utmp *ut;
struct utmp *ret = NULL;
setutent ();
/* First, try to find a valid utmp entry for this process. */
while ((ut = getutent ()) != NULL) {
if ( (ut->ut_pid == getpid ())
#ifdef HAVE_STRUCT_UTMP_UT_ID
&& ('\0' != ut->ut_id[0])
#endif
#ifdef HAVE_STRUCT_UTMP_UT_TYPE
&& ( (LOGIN_PROCESS == ut->ut_type)
|| (USER_PROCESS == ut->ut_type))
#endif
/* A process may have failed to close an entry
* Check if this entry refers to the current tty */
&& is_my_tty (ut->ut_line)) {
break;
}
}
if (NULL != ut) {
ret = (struct utmp *) xmalloc (sizeof (*ret));
memcpy (ret, ut, sizeof (*ret));
}
endutent ();
return ret;
}
#ifndef USE_PAM
/*
* Some systems already have updwtmp() and possibly updwtmpx(). Others
* don't, so we re-implement these functions if necessary.
*/
#ifndef HAVE_UPDWTMP
static void updwtmp (const char *filename, const struct utmp *ut)
{
int fd;
fd = open (filename, O_APPEND | O_WRONLY, 0);
if (fd >= 0) {
write (fd, (const char *) ut, sizeof (*ut));
close (fd);
}
}
#endif /* ! HAVE_UPDWTMP */
#ifdef USE_UTMPX
#ifndef HAVE_UPDWTMPX
static void updwtmpx (const char *filename, const struct utmpx *utx)
{
int fd;
fd = open (filename, O_APPEND | O_WRONLY, 0);
if (fd >= 0) {
write (fd, (const char *) utx, sizeof (*utx));
close (fd);
}
}
#endif /* ! HAVE_UPDWTMPX */
#endif /* ! USE_UTMPX */
#endif /* ! USE_PAM */
/*
* prepare_utmp - prepare an utmp entry so that it can be logged in a
* utmp/wtmp file.
*
* It accepts an utmp entry in input (ut) to return an entry with
* the right ut_id. This is typically an entry returned by
* get_current_utmp
* If ut is NULL, ut_id will be forged based on the line argument.
*
* The ut_host field of the input structure may also be kept, and is
* used to define the ut_addr/ut_addr_v6 fields. (if these fields
* exist)
*
* Other fields are discarded and filed with new values (if they
* exist).
*
* The returned structure shall be freed by the caller.
*/
/*@only@*/struct utmp *prepare_utmp (const char *name,
const char *line,
const char *host,
/*@null@*/const struct utmp *ut)
{
struct timeval tv;
char *hostname = NULL;
struct utmp *utent;
assert (NULL != name);
assert (NULL != line);
if ( (NULL != host)
&& ('\0' != host[0])) {
hostname = (char *) xmalloc (strlen (host) + 1);
strcpy (hostname, host);
#ifdef HAVE_STRUCT_UTMP_UT_HOST
} else if ( (NULL != ut)
&& ('\0' != ut->ut_host[0])) {
hostname = (char *) xmalloc (sizeof (ut->ut_host) + 1);
strncpy (hostname, ut->ut_host, sizeof (ut->ut_host));
hostname[sizeof (ut->ut_host)] = '\0';
#endif /* HAVE_STRUCT_UTMP_UT_HOST */
}
if (strncmp(line, "/dev/", 5) == 0) {
line += 5;
}
utent = (struct utmp *) xmalloc (sizeof (*utent));
memzero (utent, sizeof (*utent));
#ifdef HAVE_STRUCT_UTMP_UT_TYPE
utent->ut_type = USER_PROCESS;
#endif /* HAVE_STRUCT_UTMP_UT_TYPE */
utent->ut_pid = getpid ();
strncpy (utent->ut_line, line, sizeof (utent->ut_line));
#ifdef HAVE_STRUCT_UTMP_UT_ID
if (NULL != ut) {
strncpy (utent->ut_id, ut->ut_id, sizeof (utent->ut_id));
} else {
/* XXX - assumes /dev/tty?? */
strncpy (utent->ut_id, line + 3, sizeof (utent->ut_id));
}
#endif /* HAVE_STRUCT_UTMP_UT_ID */
#ifdef HAVE_STRUCT_UTMP_UT_NAME
strncpy (utent->ut_name, name, sizeof (utent->ut_name));
#endif /* HAVE_STRUCT_UTMP_UT_NAME */
#ifdef HAVE_STRUCT_UTMP_UT_USER
strncpy (utent->ut_user, name, sizeof (utent->ut_user));
#endif /* HAVE_STRUCT_UTMP_UT_USER */
if (NULL != hostname) {
struct addrinfo *info = NULL;
#ifdef HAVE_STRUCT_UTMP_UT_HOST
strncpy (utent->ut_host, hostname, sizeof (utent->ut_host));
#endif /* HAVE_STRUCT_UTMP_UT_HOST */
#ifdef HAVE_STRUCT_UTMP_UT_SYSLEN
utent->ut_syslen = MIN (strlen (hostname),
sizeof (utent->ut_host));
#endif /* HAVE_STRUCT_UTMP_UT_SYSLEN */
#if defined(HAVE_STRUCT_UTMP_UT_ADDR) || defined(HAVE_STRUCT_UTMP_UT_ADDR_V6)
if (getaddrinfo (hostname, NULL, NULL, &info) == 0) {
/* getaddrinfo might not be reliable.
* Just try to log what may be useful.
*/
if (info->ai_family == AF_INET) {
struct sockaddr_in *sa =
(struct sockaddr_in *) info->ai_addr;
#ifdef HAVE_STRUCT_UTMP_UT_ADDR
memcpy (&(utent->ut_addr),
&(sa->sin_addr),
MIN (sizeof (utent->ut_addr),
sizeof (sa->sin_addr)));
#endif /* HAVE_STRUCT_UTMP_UT_ADDR */
#ifdef HAVE_STRUCT_UTMP_UT_ADDR_V6
memcpy (utent->ut_addr_v6,
&(sa->sin_addr),
MIN (sizeof (utent->ut_addr_v6),
sizeof (sa->sin_addr)));
} else if (info->ai_family == AF_INET6) {
struct sockaddr_in6 *sa =
(struct sockaddr_in6 *) info->ai_addr;
memcpy (utent->ut_addr_v6,
&(sa->sin6_addr),
MIN (sizeof (utent->ut_addr_v6),
sizeof (sa->sin6_addr)));
#endif /* HAVE_STRUCT_UTMP_UT_ADDR_V6 */
}
freeaddrinfo (info);
}
#endif /* HAVE_STRUCT_UTMP_UT_ADDR || HAVE_STRUCT_UTMP_UT_ADDR_V6 */
free (hostname);
}
/* ut_exit is only for DEAD_PROCESS */
utent->ut_session = getsid (0);
if (gettimeofday (&tv, NULL) == 0) {
#ifdef HAVE_STRUCT_UTMP_UT_TIME
utent->ut_time = tv.tv_sec;
#endif /* HAVE_STRUCT_UTMP_UT_TIME */
#ifdef HAVE_STRUCT_UTMP_UT_XTIME
utent->ut_xtime = tv.tv_usec;
#endif /* HAVE_STRUCT_UTMP_UT_XTIME */
#ifdef HAVE_STRUCT_UTMP_UT_TV
utent->ut_tv.tv_sec = tv.tv_sec;
utent->ut_tv.tv_usec = tv.tv_usec;
#endif /* HAVE_STRUCT_UTMP_UT_TV */
}
return utent;
}
/*
* setutmp - Update an entry in utmp and log an entry in wtmp
*
* Return 1 on failure and 0 on success.
*/
int setutmp (struct utmp *ut)
{
int err = 0;
assert (NULL != ut);
setutent ();
if (pututline (ut) == NULL) {
err = 1;
}
endutent ();
#ifndef USE_PAM
/* This is done by pam_lastlog */
updwtmp (_WTMP_FILE, ut);
#endif /* ! USE_PAM */
return err;
}
#ifdef USE_UTMPX
/*
* prepare_utmpx - the UTMPX version for prepare_utmp
*/
/*@only@*/struct utmpx *prepare_utmpx (const char *name,
const char *line,
const char *host,
/*@null@*/const struct utmp *ut)
{
struct timeval tv;
char *hostname = NULL;
struct utmpx *utxent;
assert (NULL != name);
assert (NULL != line);
if ( (NULL != host)
&& ('\0' != host[0])) {
hostname = (char *) xmalloc (strlen (host) + 1);
strcpy (hostname, host);
#ifdef HAVE_STRUCT_UTMP_UT_HOST
} else if ( (NULL != ut)
&& (NULL != ut->ut_host)
&& ('\0' != ut->ut_host[0])) {
hostname = (char *) xmalloc (sizeof (ut->ut_host) + 1);
strncpy (hostname, ut->ut_host, sizeof (ut->ut_host));
hostname[sizeof (ut->ut_host)] = '\0';
#endif /* HAVE_STRUCT_UTMP_UT_TYPE */
}
if (strncmp(line, "/dev/", 5) == 0) {
line += 5;
}
utxent = (struct utmpx *) xmalloc (sizeof (*utxent));
memzero (utxent, sizeof (*utxent));
utxent->ut_type = USER_PROCESS;
utxent->ut_pid = getpid ();
strncpy (utxent->ut_line, line, sizeof (utxent->ut_line));
/* existence of ut->ut_id is enforced by configure */
if (NULL != ut) {
strncpy (utxent->ut_id, ut->ut_id, sizeof (utxent->ut_id));
} else {
/* XXX - assumes /dev/tty?? */
strncpy (utxent->ut_id, line + 3, sizeof (utxent->ut_id));
}
#ifdef HAVE_STRUCT_UTMPX_UT_NAME
strncpy (utxent->ut_name, name, sizeof (utxent->ut_name));
#endif /* HAVE_STRUCT_UTMPX_UT_NAME */
strncpy (utxent->ut_user, name, sizeof (utxent->ut_user));
if (NULL != hostname) {
struct addrinfo *info = NULL;
#ifdef HAVE_STRUCT_UTMPX_UT_HOST
strncpy (utxent->ut_host, hostname, sizeof (utxent->ut_host));
#endif /* HAVE_STRUCT_UTMPX_UT_HOST */
#ifdef HAVE_STRUCT_UTMPX_UT_SYSLEN
utxent->ut_syslen = MIN (strlen (hostname),
sizeof (utxent->ut_host));
#endif /* HAVE_STRUCT_UTMPX_UT_SYSLEN */
#if defined(HAVE_STRUCT_UTMPX_UT_ADDR) || defined(HAVE_STRUCT_UTMPX_UT_ADDR_V6)
if (getaddrinfo (hostname, NULL, NULL, &info) == 0) {
/* getaddrinfo might not be reliable.
* Just try to log what may be useful.
*/
if (info->ai_family == AF_INET) {
struct sockaddr_in *sa =
(struct sockaddr_in *) info->ai_addr;
#ifdef HAVE_STRUCT_UTMPX_UT_ADDR
memcpy (utxent->ut_addr,
&(sa->sin_addr),
MIN (sizeof (utxent->ut_addr),
sizeof (sa->sin_addr)));
#endif /* HAVE_STRUCT_UTMPX_UT_ADDR */
#ifdef HAVE_STRUCT_UTMPX_UT_ADDR_V6
memcpy (utxent->ut_addr_v6,
&(sa->sin_addr),
MIN (sizeof (utxent->ut_addr_v6),
sizeof (sa->sin_addr)));
} else if (info->ai_family == AF_INET6) {
struct sockaddr_in6 *sa =
(struct sockaddr_in6 *) info->ai_addr;
memcpy (utxent->ut_addr_v6,
&(sa->sin6_addr),
MIN (sizeof (utxent->ut_addr_v6),
sizeof (sa->sin6_addr)));
#endif /* HAVE_STRUCT_UTMPX_UT_ADDR_V6 */
}
freeaddrinfo (info);
}
#endif /* HAVE_STRUCT_UTMPX_UT_ADDR || HAVE_STRUCT_UTMPX_UT_ADDR_V6 */
free (hostname);
}
/* ut_exit is only for DEAD_PROCESS */
utxent->ut_session = getsid (0);
if (gettimeofday (&tv, NULL) == 0) {
#ifdef HAVE_STRUCT_UTMPX_UT_TIME
utxent->ut_time = tv.tv_sec;
#endif /* HAVE_STRUCT_UTMPX_UT_TIME */
#ifdef HAVE_STRUCT_UTMPX_UT_XTIME
utxent->ut_xtime = tv.tv_usec;
#endif /* HAVE_STRUCT_UTMPX_UT_XTIME */
utxent->ut_tv.tv_sec = tv.tv_sec;
utxent->ut_tv.tv_usec = tv.tv_usec;
}
return utxent;
}
/*
* setutmpx - the UTMPX version for setutmp
*/
int setutmpx (struct utmpx *utx)
{
int err = 0;
assert (NULL != utx);
setutxent ();
if (pututxline (utx) == NULL) {
err = 1;
}
endutxent ();
#ifndef USE_PAM
/* This is done by pam_lastlog */
updwtmpx (_WTMP_FILE "x", utx);
#endif /* ! USE_PAM */
return err;
}
#endif /* USE_UTMPX */
+104
View File
@@ -0,0 +1,104 @@
/*
* Copyright (c) 1989 - 1993, Julianne Frances Haugh
* Copyright (c) 1996 - 1999, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id: valid.c 3232 2010-08-22 19:13:53Z nekral-guest $"
#include <sys/types.h>
#include <stdio.h>
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
/*
* valid - compare encrypted passwords
*
* Valid() compares the DES encrypted password from the password file
* against the password which the user has entered after it has been
* encrypted using the same salt as the original. Entries which do
* not have a password file entry have a NULL pw_name field and this
* is used to indicate that a dummy salt must be used to encrypt the
* password anyway.
*/
bool valid (const char *password, const struct passwd *ent)
{
const char *encrypted;
/*@observer@*/const char *salt;
/*
* Start with blank or empty password entries. Always encrypt
* a password if no such user exists. Only if the ID exists and
* the password is really empty do you return quickly. This
* routine is meant to waste CPU time.
*/
if ((NULL != ent->pw_name) && ('\0' == ent->pw_passwd[0])) {
if ('\0' == password[0]) {
return true; /* user entered nothing */
} else {
return false; /* user entered something! */
}
}
/*
* If there is no entry then we need a salt to use.
*/
if ((NULL == ent->pw_name) || ('\0' == ent->pw_passwd[0])) {
salt = "xx";
} else {
salt = ent->pw_passwd;
}
/*
* Now, perform the encryption using the salt from before on
* the users input. Since we always encrypt the string, it
* should be very difficult to determine if the user exists by
* looking at execution time.
*/
encrypted = pw_encrypt (password, salt);
/*
* One last time we must deal with there being no password file
* entry for the user. We use the pw_name == NULL idiom to
* cause non-existent users to not be validated.
*/
if ( (NULL != ent->pw_name)
&& (strcmp (encrypted, ent->pw_passwd) == 0)) {
return true;
} else {
return false;
}
}
+144
View File
@@ -0,0 +1,144 @@
/*
* Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* According to the Linux-PAM documentation:
*
* 4.1. Care about standard library calls
*
* In general, writers of authorization-granting applications should
* assume that each module is likely to call any or all 'libc' functions.
* For 'libc' functions that return pointers to static/dynamically
* allocated structures (ie. the library allocates the memory and the
* user is not expected to 'free()' it) any module call to this function
* is likely to corrupt a pointer previously obtained by the application.
* The application programmer should either re-call such a 'libc'
* function after a call to the Linux-PAM library, or copy the structure
* contents to some safe area of memory before passing control to the
* Linux-PAM library.
*
* Two important function classes that fall into this category are
* getpwnam(3) and syslog(3).
*
* This file provide wrapper to the getpwnam or getpwnam_r functions.
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include "prototypes.h"
#define XFUNCTION_NAME XPREFIX (FUNCTION_NAME)
#define XPREFIX(name) XPREFIX1 (name)
#define XPREFIX1(name) x##name
#define REENTRANT_NAME APPEND_R (FUNCTION_NAME)
#define APPEND_R(name) APPEND_R1 (name)
#define APPEND_R1(name) name##_r
#define STRINGIZE(name) STRINGIZE1 (name)
#define STRINGIZE1(name) #name
/*@null@*/ /*@only@*/LOOKUP_TYPE *XFUNCTION_NAME (ARG_TYPE ARG_NAME)
{
#if HAVE_FUNCTION_R
LOOKUP_TYPE *result=NULL;
char *buffer=NULL;
/* we have to start with something */
size_t length = 0x100;
result = malloc(sizeof(LOOKUP_TYPE));
if (NULL == result) {
fprintf (stderr, _("%s: out of memory\n"),
"x" STRINGIZE(FUNCTION_NAME));
exit (13);
}
while (true) {
int status;
LOOKUP_TYPE *resbuf = NULL;
buffer = (char *)realloc (buffer, length);
if (NULL == buffer) {
fprintf (stderr, _("%s: out of memory\n"),
"x" STRINGIZE(FUNCTION_NAME));
exit (13);
}
errno = 0;
status = REENTRANT_NAME(ARG_NAME, result, buffer,
length, &resbuf);
if ((0 == status) && (resbuf == result)) {
/* Build a result structure that can be freed by
* the shadow *_free functions. */
LOOKUP_TYPE *ret_result = DUP_FUNCTION(result);
free(buffer);
free(result);
return ret_result;
}
if (ERANGE != errno) {
free (buffer);
free (result);
return NULL;
}
if (length <= ((size_t)-1 / 4)) {
length *= 4;
} else if (length == (size_t) -1) {
break;
} else {
length = (size_t) -1;
}
}
free(buffer);
free(result);
return NULL;
#else /* !HAVE_FUNCTION_R */
/* No reentrant function.
* Duplicate the structure to avoid other call to overwrite it.
*
* We should also restore the initial structure. But that would be
* overkill.
*/
LOOKUP_TYPE *result = FUNCTION_NAME(ARG_NAME);
if (result) {
result = DUP_FUNCTION(result);
if (NULL == result) {
fprintf (stderr, _("%s: out of memory\n"),
"x" STRINGIZE(FUNCTION_NAME));
exit (13);
}
}
return result;
#endif
}
+64
View File
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* According to the Linux-PAM documentation:
*
* 4.1. Care about standard library calls
*
* In general, writers of authorization-granting applications should
* assume that each module is likely to call any or all 'libc' functions.
* For 'libc' functions that return pointers to static/dynamically
* allocated structures (ie. the library allocates the memory and the
* user is not expected to 'free()' it) any module call to this function
* is likely to corrupt a pointer previously obtained by the application.
* The application programmer should either re-call such a 'libc'
* function after a call to the Linux-PAM library, or copy the structure
* contents to some safe area of memory before passing control to the
* Linux-PAM library.
*
* Two important function classes that fall into this category are
* getpwnam(3) and syslog(3).
*
* This file provide wrapper to the getpwnam or getpwnam_r functions.
*/
#include <config.h>
#include "groupio.h"
#define LOOKUP_TYPE struct group
#define FUNCTION_NAME getgrgid
#define ARG_TYPE gid_t
#define ARG_NAME gid
#define DUP_FUNCTION __gr_dup
#define HAVE_FUNCTION_R (defined HAVE_GETGRGID_R)
#include "xgetXXbyYY.c"
+64
View File
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* According to the Linux-PAM documentation:
*
* 4.1. Care about standard library calls
*
* In general, writers of authorization-granting applications should
* assume that each module is likely to call any or all 'libc' functions.
* For 'libc' functions that return pointers to static/dynamically
* allocated structures (ie. the library allocates the memory and the
* user is not expected to 'free()' it) any module call to this function
* is likely to corrupt a pointer previously obtained by the application.
* The application programmer should either re-call such a 'libc'
* function after a call to the Linux-PAM library, or copy the structure
* contents to some safe area of memory before passing control to the
* Linux-PAM library.
*
* Two important function classes that fall into this category are
* getpwnam(3) and syslog(3).
*
* This file provide wrapper to the getpwnam or getpwnam_r functions.
*/
#include <config.h>
#include "groupio.h"
#define LOOKUP_TYPE struct group
#define FUNCTION_NAME getgrnam
#define ARG_TYPE const char *
#define ARG_NAME name
#define DUP_FUNCTION __gr_dup
#define HAVE_FUNCTION_R (defined HAVE_GETGRNAM_R)
#include "xgetXXbyYY.c"
+64
View File
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* According to the Linux-PAM documentation:
*
* 4.1. Care about standard library calls
*
* In general, writers of authorization-granting applications should
* assume that each module is likely to call any or all 'libc' functions.
* For 'libc' functions that return pointers to static/dynamically
* allocated structures (ie. the library allocates the memory and the
* user is not expected to 'free()' it) any module call to this function
* is likely to corrupt a pointer previously obtained by the application.
* The application programmer should either re-call such a 'libc'
* function after a call to the Linux-PAM library, or copy the structure
* contents to some safe area of memory before passing control to the
* Linux-PAM library.
*
* Two important function classes that fall into this category are
* getpwnam(3) and syslog(3).
*
* This file provide wrapper to the getpwnam or getpwnam_r functions.
*/
#include <config.h>
#include "pwio.h"
#define LOOKUP_TYPE struct passwd
#define FUNCTION_NAME getpwnam
#define ARG_TYPE const char *
#define ARG_NAME name
#define DUP_FUNCTION __pw_dup
#define HAVE_FUNCTION_R (defined HAVE_GETPWNAM_R)
#include "xgetXXbyYY.c"
+64
View File
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* According to the Linux-PAM documentation:
*
* 4.1. Care about standard library calls
*
* In general, writers of authorization-granting applications should
* assume that each module is likely to call any or all 'libc' functions.
* For 'libc' functions that return pointers to static/dynamically
* allocated structures (ie. the library allocates the memory and the
* user is not expected to 'free()' it) any module call to this function
* is likely to corrupt a pointer previously obtained by the application.
* The application programmer should either re-call such a 'libc'
* function after a call to the Linux-PAM library, or copy the structure
* contents to some safe area of memory before passing control to the
* Linux-PAM library.
*
* Two important function classes that fall into this category are
* getpwnam(3) and syslog(3).
*
* This file provide wrapper to the getpwnam or getpwnam_r functions.
*/
#include <config.h>
#include "pwio.h"
#define LOOKUP_TYPE struct passwd
#define FUNCTION_NAME getpwuid
#define ARG_TYPE uid_t
#define ARG_NAME uid
#define DUP_FUNCTION __pw_dup
#define HAVE_FUNCTION_R (defined HAVE_GETPWUID_R)
#include "xgetXXbyYY.c"
+64
View File
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2008 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* According to the Linux-PAM documentation:
*
* 4.1. Care about standard library calls
*
* In general, writers of authorization-granting applications should
* assume that each module is likely to call any or all 'libc' functions.
* For 'libc' functions that return pointers to static/dynamically
* allocated structures (ie. the library allocates the memory and the
* user is not expected to 'free()' it) any module call to this function
* is likely to corrupt a pointer previously obtained by the application.
* The application programmer should either re-call such a 'libc'
* function after a call to the Linux-PAM library, or copy the structure
* contents to some safe area of memory before passing control to the
* Linux-PAM library.
*
* Two important function classes that fall into this category are
* getpwnam(3) and syslog(3).
*
* This file provide wrapper to the getpwnam or getpwnam_r functions.
*/
#include <config.h>
#include "shadowio.h"
#define LOOKUP_TYPE struct spwd
#define FUNCTION_NAME getspnam
#define ARG_TYPE const char *
#define ARG_NAME name
#define DUP_FUNCTION __spw_dup
#define HAVE_FUNCTION_R (defined HAVE_GETSPNAM_R)
#include "xgetXXbyYY.c"
+68
View File
@@ -0,0 +1,68 @@
/*
* Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko
* Copyright (c) 2008 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Replacements for malloc and strdup with error checking. Too trivial
to be worth copyrighting :-). I did that because a lot of code used
malloc and strdup without checking for NULL pointer, and I like some
message better than a core dump... --marekm
Yeh, but. Remember that bailing out might leave the system in some
bizarre state. You really want to put in error checking, then add
some back-out failure recovery code. -- jfh */
#include <config.h>
#ident "$Id: xmalloc.c 3320 2011-06-02 18:41:05Z nekral-guest $"
#include <stdio.h>
#include <errno.h>
#include "defines.h"
#include "prototypes.h"
/*@maynotreturn@*/ /*@only@*//*@out@*//*@notnull@*/char *xmalloc (size_t size)
{
char *ptr;
ptr = (char *) malloc (size);
if (NULL == ptr) {
(void) fprintf (stderr,
_("%s: failed to allocate memory: %s\n"),
Prog, strerror (errno));
exit (13);
}
return ptr;
}
/*@maynotreturn@*/ /*@only@*//*@notnull@*/char *xstrdup (const char *str)
{
return strcpy (xmalloc (strlen (str) + 1), str);
}
+79
View File
@@ -0,0 +1,79 @@
/*
* Copyright (c) 1992 - 1994, Julianne Frances Haugh
* Copyright (c) 2007 - 2008, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Common code for yes/no prompting
*
* Used by pwck.c and grpck.c
*/
#include <config.h>
#ident "$Id: yesno.c 2765 2009-04-23 11:14:56Z nekral-guest $"
#include <stdio.h>
#include "prototypes.h"
/*
* yes_or_no - get answer to question from the user
*
* It returns false if no.
*
* If the read_only flag is set, it will print No, and will return
* false.
*/
bool yes_or_no (bool read_only)
{
char buf[80];
/*
* In read-only mode all questions are answered "no".
*/
if (read_only) {
(void) puts (_("No"));
return false;
}
/*
* Typically, there's a prompt on stdout, sometimes unflushed.
*/
(void) fflush (stdout);
/*
* Get a line and see what the first character is.
*/
/* TODO: use gettext */
if (fgets (buf, (int) sizeof buf, stdin) == buf) {
return buf[0] == 'y' || buf[0] == 'Y';
}
return false;
}