[svn-upgrade] Integrating new upstream version, shadow (19990709)

This commit is contained in:
nekral-guest
2007-10-07 11:44:02 +00:00
parent 9c72ed9062
commit 45c6603cc8
350 changed files with 89554 additions and 0 deletions

20
libmisc/Makefile.am Normal file
View File

@@ -0,0 +1,20 @@
AUTOMAKE_OPTIONS = 1.0 foreign
noinst_HEADERS = chkname.h failure.h getdate.h
noinst_LIBRARIES = libmisc.a
libdir = $(prefix)/lib
localedir = $(datadir)/locale
INCLUDES = -I$(top_srcdir)/libmisc -I$(top_srcdir)/lib
DEFS = -DLOCALEDIR=\"$(localedir)\" -I. -I$(srcdir) -I.. @DEFS@
libmisc_a_SOURCES = addgrps.c age.c basename.c chkname.c chkshell.c \
chowndir.c chowntty.c console.c copydir.c entry.c env.c failure.c \
fields.c getdate.y hushed.c isexpired.c limits.c list.c log.c \
login_access.c login_desrpc.c login_krb.c loginprompt.c mail.c motd.c \
myname.c obscure.c pam_pass.c pwd2spwd.c pwdcheck.c pwd_init.c rlogin.c \
salt.c setugid.c setup.c setupenv.c shell.c strtoday.c suauth.c sub.c \
sulog.c ttytype.c tz.c ulimit.c utmp.c valid.c xmalloc.c

418
libmisc/Makefile.in Normal file
View File

@@ -0,0 +1,418 @@
# Makefile.in generated automatically by automake 1.3 from Makefile.am
# Copyright (C) 1994, 1995, 1996, 1997, 1998 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.
SHELL = /bin/sh
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DISTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
CATALOGS = @CATALOGS@
CATOBJEXT = @CATOBJEXT@
CC = @CC@
CPP = @CPP@
DATADIRNAME = @DATADIRNAME@
GENCAT = @GENCAT@
GMOFILES = @GMOFILES@
GMSGFMT = @GMSGFMT@
GT_NO = @GT_NO@
GT_YES = @GT_YES@
INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@
INSTOBJEXT = @INSTOBJEXT@
INTLDEPS = @INTLDEPS@
INTLLIBS = @INTLLIBS@
INTLOBJS = @INTLOBJS@
LD = @LD@
LIBCRACK = @LIBCRACK@
LIBCRYPT = @LIBCRYPT@
LIBPAM = @LIBPAM@
LIBSKEY = @LIBSKEY@
LIBTCFS = @LIBTCFS@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKINSTALLDIRS = @MKINSTALLDIRS@
MSGFMT = @MSGFMT@
NM = @NM@
PACKAGE = @PACKAGE@
POFILES = @POFILES@
POSUB = @POSUB@
RANLIB = @RANLIB@
U = @U@
USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
YACC = @YACC@
l = @l@
AUTOMAKE_OPTIONS = 1.0 foreign
noinst_HEADERS = chkname.h failure.h getdate.h
noinst_LIBRARIES = libmisc.a
libdir = $(prefix)/lib
localedir = $(datadir)/locale
INCLUDES = -I$(top_srcdir)/libmisc -I$(top_srcdir)/lib
DEFS = -DLOCALEDIR=\"$(localedir)\" -I. -I$(srcdir) -I.. @DEFS@
libmisc_a_SOURCES = addgrps.c age.c basename.c chkname.c chkshell.c \
chowndir.c chowntty.c console.c copydir.c entry.c env.c failure.c \
fields.c getdate.y hushed.c isexpired.c limits.c list.c log.c \
login_access.c login_desrpc.c login_krb.c loginprompt.c mail.c motd.c \
myname.c obscure.c pam_pass.c pwd2spwd.c pwdcheck.c pwd_init.c rlogin.c \
salt.c setugid.c setup.c setupenv.c shell.c strtoday.c suauth.c sub.c \
sulog.c ttytype.c tz.c ulimit.c utmp.c valid.c xmalloc.c
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../config.h
CONFIG_CLEAN_FILES =
LIBRARIES = $(noinst_LIBRARIES)
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
libmisc_a_LIBADD =
libmisc_a_OBJECTS = addgrps.o age.o basename.o chkname.o chkshell.o \
chowndir.o chowntty.o console.o copydir.o entry.o env.o failure.o \
fields.o getdate.o hushed.o isexpired.o limits.o list.o log.o \
login_access.o login_desrpc.o login_krb.o loginprompt.o mail.o motd.o \
myname.o obscure.o pam_pass.o pwd2spwd.o pwdcheck.o pwd_init.o rlogin.o \
salt.o setugid.o setup.o setupenv.o shell.o strtoday.o suauth.o sub.o \
sulog.o ttytype.o tz.o ulimit.o utmp.o valid.o xmalloc.o
AR = ar
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@
HEADERS = $(noinst_HEADERS)
DIST_COMMON = Makefile.am Makefile.in getdate.c
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP = --best
SOURCES = $(libmisc_a_SOURCES)
OBJECTS = $(libmisc_a_OBJECTS)
all: Makefile $(LIBRARIES) $(HEADERS)
.SUFFIXES:
.SUFFIXES: .S .c .lo .o .s .y
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps libmisc/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
mostlyclean-noinstLIBRARIES:
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
distclean-noinstLIBRARIES:
maintainer-clean-noinstLIBRARIES:
.c.o:
$(COMPILE) -c $<
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
mostlyclean-compile:
-rm -f *.o core *.core
clean-compile:
distclean-compile:
-rm -f *.tab.c
maintainer-clean-compile:
.c.lo:
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
.s.lo:
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
.S.lo:
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
maintainer-clean-libtool:
libmisc.a: $(libmisc_a_OBJECTS) $(libmisc_a_DEPENDENCIES)
-rm -f libmisc.a
$(AR) cru libmisc.a $(libmisc_a_OBJECTS) $(libmisc_a_LIBADD)
$(RANLIB) libmisc.a
.y.c:
$(YACC) $(YFLAGS) $< && mv y.tab.c $*.c
if test -f y.tab.h; then \
if cmp -s y.tab.h $*.h; then rm -f y.tab.h; else mv y.tab.h $*.h; fi; \
else :; fi
getdate.h: getdate.c
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
subdir = libmisc
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file; \
done
addgrps.o: addgrps.c ../config.h ../lib/prototypes.h ../lib/defines.h \
../lib/gshadow_.h ../lib/rcsid.h
age.o: age.c ../config.h ../lib/prototypes.h ../lib/defines.h \
../lib/gshadow_.h ../lib/rcsid.h
basename.o: basename.c ../config.h ../lib/rcsid.h ../lib/defines.h \
../lib/gshadow_.h ../lib/prototypes.h
chkname.o: chkname.c ../config.h ../lib/rcsid.h ../lib/defines.h \
../lib/gshadow_.h chkname.h
chkshell.o: chkshell.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h
chowndir.o: chowndir.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h
chowntty.o: chowntty.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h
console.o: console.c ../config.h ../lib/defines.h ../lib/gshadow_.h \
../lib/getdef.h ../lib/rcsid.h
copydir.o: copydir.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h
entry.o: entry.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h
env.o: env.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h
failure.o: failure.c ../config.h ../lib/rcsid.h ../lib/defines.h \
../lib/gshadow_.h ../lib/faillog.h ../lib/getdef.h failure.h
fields.o: fields.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h
getdate.o: getdate.c ../config.h getdate.h ../lib/defines.h \
../lib/gshadow_.h
hushed.o: hushed.c ../config.h ../lib/rcsid.h ../lib/defines.h \
../lib/gshadow_.h ../lib/prototypes.h ../lib/getdef.h
isexpired.o: isexpired.c ../config.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h ../lib/rcsid.h
limits.o: limits.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h
list.o: list.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h
login_access.o: login_access.c ../config.h ../lib/rcsid.h \
../lib/prototypes.h ../lib/defines.h ../lib/gshadow_.h
login_desrpc.o: login_desrpc.c ../config.h
login_krb.o: login_krb.c ../config.h
loginprompt.o: loginprompt.c ../config.h ../lib/rcsid.h \
../lib/prototypes.h ../lib/defines.h ../lib/gshadow_.h \
../lib/getdef.h
log.o: log.c ../config.h ../lib/rcsid.h ../lib/defines.h \
../lib/gshadow_.h
mail.o: mail.c ../config.h ../lib/prototypes.h ../lib/defines.h \
../lib/gshadow_.h ../lib/getdef.h ../lib/rcsid.h
motd.o: motd.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h
myname.o: myname.c ../config.h ../lib/rcsid.h ../lib/defines.h \
../lib/gshadow_.h ../lib/prototypes.h
obscure.o: obscure.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h
pam_pass.o: pam_pass.c ../config.h
pwd2spwd.o: pwd2spwd.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h
pwdcheck.o: pwdcheck.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h ../lib/pwauth.h
pwd_init.o: pwd_init.c ../config.h ../lib/rcsid.h ../lib/defines.h \
../lib/gshadow_.h
rlogin.o: rlogin.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h
salt.o: salt.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h
setugid.o: setugid.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h
setupenv.o: setupenv.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h
setup.o: setup.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h
shell.o: shell.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h
strtoday.o: strtoday.c ../config.h ../lib/rcsid.h ../lib/defines.h \
../lib/gshadow_.h getdate.h
suauth.o: suauth.c ../config.h ../lib/prototypes.h ../lib/defines.h \
../lib/gshadow_.h
sub.o: sub.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h
sulog.o: sulog.c ../config.h ../lib/rcsid.h ../lib/defines.h \
../lib/gshadow_.h ../lib/getdef.h
ttytype.o: ttytype.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h
tz.o: tz.c ../config.h ../lib/rcsid.h ../lib/defines.h ../lib/gshadow_.h \
../lib/getdef.h
ulimit.o: ulimit.c ../config.h ../lib/rcsid.h
utmp.o: utmp.c ../config.h ../lib/defines.h ../lib/gshadow_.h \
../lib/rcsid.h
valid.o: valid.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \
../lib/defines.h ../lib/gshadow_.h
xmalloc.o: xmalloc.c ../config.h ../lib/rcsid.h ../lib/defines.h \
../lib/gshadow_.h
info:
dvi:
check: all
$(MAKE)
installcheck:
install-exec:
@$(NORMAL_INSTALL)
install-data:
@$(NORMAL_INSTALL)
install: install-exec install-data all
@:
uninstall:
install-strip:
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
installdirs:
mostlyclean-generic:
-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-rm -f Makefile $(DISTCLEANFILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
mostlyclean: mostlyclean-noinstLIBRARIES mostlyclean-compile \
mostlyclean-libtool mostlyclean-tags \
mostlyclean-generic
clean: clean-noinstLIBRARIES clean-compile clean-libtool clean-tags \
clean-generic mostlyclean
distclean: distclean-noinstLIBRARIES distclean-compile \
distclean-libtool distclean-tags distclean-generic \
clean
-rm -f config.status
-rm -f libtool
maintainer-clean: maintainer-clean-noinstLIBRARIES \
maintainer-clean-compile maintainer-clean-libtool \
maintainer-clean-tags maintainer-clean-generic \
distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile mostlyclean-libtool distclean-libtool \
clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
distclean-tags clean-tags maintainer-clean-tags distdir info dvi \
installcheck install-exec install-data install uninstall all \
installdirs mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
# 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:

89
libmisc/addgrps.c Normal file
View File

@@ -0,0 +1,89 @@
#include <config.h>
#ifdef HAVE_SETGROUPS
#include "prototypes.h"
#include "defines.h"
#include <stdio.h>
#include <grp.h>
#include <errno.h>
#include "rcsid.h"
RCSID("$Id: addgrps.c,v 1.4 1998/12/28 20:34:41 marekm Exp $")
#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;
int i, ngroups, added;
struct group *grp;
char *token;
char buf[1024];
if (strlen(list) >= sizeof(buf)) {
errno = EINVAL;
return -1;
}
strcpy(buf, list);
i = 16;
for (;;) {
grouplist = malloc(i * sizeof(GETGROUPS_T));
if (!grouplist)
return -1;
ngroups = getgroups(i, grouplist);
if (i > ngroups)
break;
/* not enough room, so try allocating a larger buffer */
free(grouplist);
i *= 2;
}
if (ngroups < 0) {
free(grouplist);
return -1;
}
added = 0;
for (token = strtok(buf, SEP); token; token = strtok(NULL, SEP)) {
grp = getgrnam(token);
if (!grp) {
fprintf(stderr, _("Warning: unknown group %s\n"), token);
continue;
}
for (i = 0; i < ngroups && grouplist[i] != grp->gr_gid; i++)
;
if (i < ngroups)
continue;
if (ngroups >= NGROUPS_MAX) {
fprintf(stderr, _("Warning: too many groups\n"));
break;
}
tmp = realloc(grouplist, (ngroups + 1) * sizeof(GETGROUPS_T));
if (!tmp) {
free(grouplist);
return -1;
}
tmp[ngroups++] = grp->gr_gid;
grouplist = tmp;
added++;
}
if (added)
return setgroups(ngroups, grouplist);
return 0;
}
#endif

235
libmisc/age.c Normal file
View File

@@ -0,0 +1,235 @@
/*
* Copyright 1989 - 1994, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 <pwd.h>
#include <grp.h>
#ifdef HAVE_USERSEC_H
#include <userpw.h>
#include <usersec.h>
#include <userconf.h>
#endif
#ifndef AGING
#if defined(SHADOWPWD) || defined(HAVE_USERSEC_H)
#define AGING 1
#endif
#else
#if !defined(SHADOWPWD) && !defined(HAVE_USERSEC_H) && !defined(ATT_AGE)
#undef AGING
#endif
#endif
#if defined(SHADOWPWD) || defined(AGING) /*{*/
#include "rcsid.h"
RCSID("$Id: age.c,v 1.6 1998/12/28 20:34:42 marekm Exp $")
#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.
*/
#ifdef SHADOWPWD
int
expire(const struct passwd *pw, const struct spwd *sp)
{
#else
int
expire(const struct passwd *pw)
{
#endif
int status;
int child;
int pid;
#ifdef SHADOWPWD
if (! sp)
sp = pwd_to_spwd (pw);
#endif
/*
* See if the user's password has expired, and if so
* force them to change their password.
*/
#ifdef SHADOWPWD
switch (status = isexpired (pw, sp))
#else
switch (status = isexpired (pw))
#endif
{
case 0:
return 0;
case 1:
printf(_("Your password has expired."));
break;
case 2:
printf(_("Your password is inactive."));
break;
case 3:
printf(_("Your login has expired."));
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.
*/
#ifdef SHADOWPWD
if (status > 1 || sp->sp_max < sp->sp_min)
#else
if (status > 1 || c64i (pw->pw_age[0]) < c64i (pw->pw_age[1]))
#endif
{
puts(_(" Contact the system administrator.\n"));
exit(1);
}
puts(_(" Choose a new password.\n"));
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.
*/
#ifdef SHADOWPWD
endspent ();
#endif
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.
*/
if ((pid = fork ()) == 0) {
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 (setup_uid_gid(pw, 0))
_exit(126);
execl(PASSWD_PROGRAM, PASSWD_PROGRAM, pw->pw_name, (char *)0);
err = errno;
perror("Can't execute " PASSWD_PROGRAM);
_exit((err == ENOENT) ? 127 : 126);
} else if (pid == -1) {
perror("fork");
exit(1);
}
while ((child = wait (&status)) != pid && child != -1)
;
if (child == pid && status == 0)
return 1;
exit (1);
/*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.
*/
#ifdef SHADOWPWD
void
agecheck(const struct passwd *pw, const struct spwd *sp)
{
#else
void
agecheck(const struct passwd *pw)
{
#endif
long now = time ((long *) 0) / SCALE;
long remain;
#ifdef SHADOWPWD
if (! sp)
sp = pwd_to_spwd (pw);
/*
* The last, max, and warn fields must be supported or the
* warning period cannot be calculated.
*/
if (sp->sp_lstchg == -1 || sp->sp_max == -1 || sp->sp_warn == -1)
return;
#else
if (pw->pw_age[0] == '\0')
return;
#endif
#ifdef SHADOWPWD
if ((remain = (sp->sp_lstchg + sp->sp_max) - now) <= sp->sp_warn)
#else
if ((remain = (a64l (pw->pw_age + 2) + c64i (pw->pw_age[0])) * 7
- now) <= getdef_num ("PASS_WARN_AGE", 7))
#endif
{
remain /= DAY/SCALE;
if (remain > 1)
printf(_("Your password will expire in %ld days.\n"), remain);
else if (remain == 1)
printf(_("Your password will expire tomorrow.\n"));
else if (remain == 0)
printf(_("Your password will expire today.\n"));
}
}
#endif /*}*/

22
libmisc/basename.c Normal file
View File

@@ -0,0 +1,22 @@
/*
* 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>
#include "rcsid.h"
RCSID("$Id: basename.c,v 1.2 1997/12/07 23:27:00 marekm Exp $")
#include "defines.h"
#include "prototypes.h"
char *
Basename(char *str)
{
char *cp = strrchr(str, '/');
return cp ? cp+1 : str;
}

73
libmisc/chkname.c Normal file
View File

@@ -0,0 +1,73 @@
/*
* check_user_name(), check_group_name() - check the new user/group
* name for validity; return value: 1 - OK, 0 - bad name
*/
#include <config.h>
#include "rcsid.h"
RCSID("$Id: chkname.c,v 1.4 1998/04/16 19:57:43 marekm Exp $")
#include <ctype.h>
#include "defines.h"
#include "chkname.h"
#if HAVE_UTMPX_H
#include <utmpx.h>
#else
#include <utmp.h>
#endif
static int
good_name(const char *name)
{
/*
* User/group names must start with a letter, and may not
* contain colons, commas, newlines (used in passwd/group
* files...) or any non-printable characters.
*/
if (!*name || !isalpha(*name))
return 0;
while (*name) {
if (*name == ':' || *name == ',' ||
*name == '\n' || !isprint(*name))
return 0;
name++;
}
return 1;
}
int
check_user_name(const char *name)
{
#if HAVE_UTMPX_H
struct utmpx ut;
#else
struct utmp ut;
#endif
/*
* User names are limited by whatever utmp can
* handle (usually max 8 characters).
*/
if (strlen(name) > sizeof(ut.ut_user))
return 0;
return good_name(name);
}
int
check_group_name(const char *name)
{
/*
* Arbitrary limit for group names - max 16
* characters (same as on HP-UX 10).
*/
if (strlen(name) > 16)
return 0;
return good_name(name);
}

15
libmisc/chkname.h Normal file
View File

@@ -0,0 +1,15 @@
/* $Id: chkname.h,v 1.1 1997/12/07 23:27:00 marekm Exp $ */
#ifndef _CHKNAME_H_
#define _CHKNAME_H_
/*
* check_user_name(), check_group_name() - check the new user/group
* name for validity; return value: 1 - OK, 0 - bad name
*/
#include "defines.h"
extern int check_user_name P_((const char *));
extern int check_group_name P_((const char *name));
#endif

98
libmisc/chkshell.c Normal file
View File

@@ -0,0 +1,98 @@
/*
* Copyright 1989 - 1994, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: chkshell.c,v 1.1 1997/12/07 23:27:00 marekm Exp $")
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include "prototypes.h"
#include "defines.h"
#ifndef SHELLS_FILE
#define SHELLS_FILE "/etc/shells"
#endif
/*
* check_shell - see if the user's login shell is listed in /etc/shells
*
* The /etc/shells file is read for valid names of login shells. If the
* /etc/shells file does not exist the user cannot set any shell unless
* they are root.
*
* If getusershell() is available (Linux, *BSD, possibly others), use it
* instead of re-implementing it.
*/
int
check_shell(const char *sh)
{
char *cp;
int found = 0;
#ifndef HAVE_GETUSERSHELL
char buf[BUFSIZ];
FILE *fp;
#endif
#ifdef HAVE_GETUSERSHELL
setusershell();
while ((cp = getusershell())) {
if (*cp == '#')
continue;
if (strcmp(cp, sh) == 0) {
found = 1;
break;
}
}
endusershell();
#else
if ((fp = fopen (SHELLS_FILE, "r")) == (FILE *) 0)
return 0;
while (fgets (buf, sizeof(buf), fp)) {
if ((cp = strrchr(buf, '\n')))
*cp = '\0';
if (buf[0] == '#')
continue;
if (strcmp (buf, sh) == 0) {
found = 1;
break;
}
}
fclose (fp);
#endif
return found;
}

126
libmisc/chowndir.c Normal file
View File

@@ -0,0 +1,126 @@
/*
* Copyright 1992, 1993, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: chowndir.c,v 1.5 1998/04/16 19:57:43 marekm Exp $")
#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.
*/
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[1024];
int rc = 0;
struct DIRECT *ent;
struct stat sb;
DIR *dir;
/*
* Make certain the directory exists. This routine is called
* directory by the invoker, or recursively.
*/
if (access(root, F_OK) != 0)
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 it is owned by
* old user ID.
*/
if (! (dir = opendir (root)))
return -1;
while ((ent = readdir (dir))) {
/*
* 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.
*/
if (strlen (root) + strlen (ent->d_name) + 2 > sizeof new_name)
break;
snprintf(new_name, sizeof new_name, "%s/%s", root, ent->d_name);
if (stat (new_name, &sb) == -1)
continue;
if (S_ISDIR(sb.st_mode)) {
/*
* Do the entire subdirectory.
*/
if ((rc = chown_tree (new_name, old_uid, new_uid,
old_gid, new_gid)))
break;
}
if (sb.st_uid == old_uid)
chown (new_name, new_uid,
sb.st_gid == old_gid ? new_gid:sb.st_gid);
}
closedir (dir);
/*
* Now do the root of the tree
*/
if (! stat (root, &sb)) {
if (sb.st_uid == old_uid)
chown (root, new_uid,
sb.st_gid == old_gid ? new_gid:sb.st_gid);
}
return rc;
}

127
libmisc/chowntty.c Normal file
View File

@@ -0,0 +1,127 @@
/*
* Copyright 1989 - 1994, Julianne Frances Haugh
* 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.
* 4. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: chowntty.c,v 1.7 1998/12/28 20:34:43 marekm Exp $")
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <grp.h>
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
#include "getdef.h"
/*
* is_my_tty -- determine if "tty" is the same as TTY stdin is using
*/
static int
is_my_tty(const char *tty)
{
struct stat by_name, by_fd;
if (stat (tty, &by_name) || fstat (0, &by_fd))
return 0;
if (by_name.st_rdev != by_fd.st_rdev)
return 0;
else
return 1;
}
/*
* chown_tty() sets the login tty to be owned by the new user ID
* with TTYPERM modes
*/
void
chown_tty(const char *tty, const struct passwd *info)
{
char buf[200], full_tty[200];
char *group; /* TTY group name or number */
struct group *grent;
gid_t gid;
/*
* See if login.defs has some value configured for the port group
* ID. Otherwise, use the user's primary group ID.
*/
if (! (group = getdef_str ("TTYGROUP")))
gid = info->pw_gid;
else if (group[0] >= '0' && group[0] <= '9')
gid = atoi (group);
else if ((grent = getgrnam (group)))
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 (*tty != '/') {
snprintf(full_tty, sizeof full_tty, "/dev/%s", tty);
tty = full_tty;
}
if (! is_my_tty (tty)) {
SYSLOG((LOG_WARN, "unable to determine TTY name, got %s\n",
tty));
closelog();
exit (1);
}
if (chown(tty, info->pw_uid, gid) ||
chmod(tty, getdef_num("TTYPERM", 0600))) {
snprintf(buf, sizeof buf, _("Unable to change tty %s"), tty);
SYSLOG((LOG_WARN, "unable to change tty `%s' for user `%s'\n",
tty, info->pw_name));
closelog();
perror (buf);
exit(1);
}
#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
}

115
libmisc/console.c Normal file
View File

@@ -0,0 +1,115 @@
/*
* Copyright 1991, Julianne Frances Haugh and Chip Rosenthal
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: console.c,v 1.5 1998/12/28 20:34:44 marekm Exp $")
/*
* 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.
*/
int
is_listed(const char *cfgin, const char *tty, int def)
{
FILE *fp;
char buf[200], *cons, *s;
/*
* If the CONSOLE configuration definition isn't given,
* fallback to default.
*/
if ((cons = getdef_str(cfgin)) == NULL)
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 != '/') {
cons = strcpy(buf, cons);
while ((s = strtok(cons, ":")) != NULL) {
if (strcmp(s, tty) == 0)
return 1;
cons = NULL;
}
return 0;
}
/*
* If we can't open the console list, then call everything a
* console - otherwise root will never be allowed to login.
*/
if ((fp = fopen(cons, "r")) == NULL)
return def;
/*
* See if this tty is listed in the console file.
*/
while (fgets(buf, sizeof(buf), fp) != NULL) {
buf[strlen(buf) - 1] = '\0';
if (strcmp(buf, tty) == 0) {
(void) fclose(fp);
return 1;
}
}
/*
* This tty isn't a console.
*/
(void) fclose(fp);
return 0;
}
/*
* 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.
*/
int
console(const char *tty)
{
return is_listed("CONSOLE", tty, 1);
}

411
libmisc/copydir.c Normal file
View File

@@ -0,0 +1,411 @@
/*
* Copyright 1991 - 1994, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: copydir.c,v 1.6 1998/06/25 22:10:42 marekm Exp $")
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include "prototypes.h"
#include "defines.h"
static const char *src_orig;
static const char *dst_orig;
struct link_name {
dev_t ln_dev;
ino_t ln_ino;
int ln_count;
char *ln_name;
struct link_name *ln_next;
};
static struct link_name *links;
/*
* remove_link - delete a link from the link list
*/
static void
remove_link(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;lp;lp = lp->ln_next)
if (lp->ln_next == ln)
break;
if (! lp)
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 struct link_name *
check_link(const char *name, const struct stat *sb)
{
struct link_name *lp;
int src_len;
int dst_len;
int name_len;
int len;
for (lp = links;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 0;
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 = xmalloc(len);
snprintf(lp->ln_name, len, "%s%s", dst_orig, name + src_len);
lp->ln_next = links;
links = lp;
return 0;
}
/*
* copy_tree - copy files in a directory tree
*
* copy_tree() walks a directory tree and copies ordinary files
* as it goes.
*/
int
copy_tree(const char *src_root, const char *dst_root, uid_t uid, gid_t gid)
{
char src_name[1024];
char dst_name[1024];
char buf[1024];
int ifd;
int ofd;
int err = 0;
int cnt;
int set_orig = 0;
struct DIRECT *ent;
struct stat sb;
struct link_name *lp;
DIR *dir;
/*
* 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.
*/
if (! (dir = opendir (src_root)))
return -1;
if (src_orig == 0) {
src_orig = src_root;
dst_orig = dst_root;
set_orig++;
}
while ((ent = readdir (dir))) {
/*
* 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.
*/
if (strlen (src_root) + strlen (ent->d_name) + 2 > sizeof src_name) {
err++;
break;
}
snprintf(src_name, sizeof src_name, "%s/%s", src_root, ent->d_name);
if (strlen (dst_root) + strlen (ent->d_name) + 2 > sizeof dst_name) {
err++;
break;
}
snprintf(dst_name, sizeof dst_name, "%s/%s", dst_root, ent->d_name);
#ifdef S_IFLNK
if (lstat (src_name, &sb) == -1)
#else
if (stat (src_name, &sb) == -1)
#endif
continue;
if (S_ISDIR(sb.st_mode)) {
/*
* Create a new target directory, make it owned by
* the user and then recursively copy that directory.
*/
mkdir (dst_name, sb.st_mode & 0777);
chown (dst_name, uid == (uid_t) -1 ? sb.st_uid:uid,
gid == (gid_t) -1 ? sb.st_gid:gid);
if (copy_tree (src_name, dst_name, uid, gid)) {
err++;
break;
}
continue;
}
#ifdef S_IFLNK
/*
* Copy any symbolic links
*/
if (S_ISLNK(sb.st_mode)) {
char oldlink[1024];
char dummy[1024];
int len;
/*
* 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
* destinateion directory name.
*/
if ((len = readlink(src_name, oldlink, sizeof(oldlink) - 1)) < 0) {
err++;
break;
}
oldlink[len] = '\0'; /* readlink() does not NUL-terminate */
if (!strncmp(oldlink, src_orig, strlen(src_orig))) {
snprintf(dummy, sizeof dummy, "%s%s",
dst_orig, oldlink + strlen(src_orig));
strcpy(oldlink, dummy);
}
if (symlink(oldlink, dst_name)) {
err++;
break;
}
continue;
}
#endif
/*
* See if this is a previously copied link
*/
if ((lp = check_link (src_name, &sb))) {
if (link (lp->ln_name, dst_name)) {
err++;
break;
}
if (unlink (src_name)) {
err++;
break;
}
if (--lp->ln_count <= 0)
remove_link (lp);
continue;
}
/*
* 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 ...
*/
if (!S_ISREG(sb.st_mode)) {
if (mknod (dst_name, sb.st_mode & ~07777, sb.st_rdev) ||
chown (dst_name, uid == (uid_t) -1 ? sb.st_uid:uid,
gid == (gid_t) -1 ? sb.st_gid:gid) ||
chmod (dst_name, sb.st_mode & 07777)) {
err++;
break;
}
continue;
}
/*
* Create the new file and copy the contents. The new
* file will be owned by the provided UID and GID values.
*/
if ((ifd = open (src_name, O_RDONLY)) < 0) {
err++;
break;
}
if ((ofd = open (dst_name, O_WRONLY|O_CREAT, 0)) < 0 ||
chown (dst_name, uid == (uid_t) -1 ? sb.st_uid:uid,
gid == (gid_t) -1 ? sb.st_gid:gid) ||
chmod (dst_name, sb.st_mode & 07777)) {
close (ifd);
err++;
break;
}
while ((cnt = read (ifd, buf, sizeof buf)) > 0) {
if (write (ofd, buf, cnt) != cnt) {
cnt = -1;
break;
}
}
close (ifd);
close (ofd);
if (cnt == -1) {
err++;
break;
}
}
closedir (dir);
if (set_orig) {
src_orig = 0;
dst_orig = 0;
}
return err ? -1:0;
}
/*
* remove_tree - remove files in a directory tree
*
* remove_tree() walks a directory tree and deletes all the files
* and directories.
*/
int
remove_tree(const char *root)
{
char new_name[1024];
int err = 0;
struct DIRECT *ent;
struct stat sb;
DIR *dir;
/*
* Make certain the directory exists.
*/
if (access(root, F_OK) != 0)
return -1;
/*
* Open the source directory and read each entry. Every file
* entry in the directory is copied with the UID and GID set
* 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);
while ((ent = readdir (dir))) {
/*
* Skip the "." and ".." entries
*/
if (strcmp (ent->d_name, ".") == 0 ||
strcmp (ent->d_name, "..") == 0)
continue;
/*
* Make the filename for the current entry.
*/
if (strlen (root) + strlen (ent->d_name) + 2 > sizeof new_name) {
err++;
break;
}
snprintf(new_name, sizeof new_name, "%s/%s", root, ent->d_name);
#ifdef S_IFLNK
if (lstat (new_name, &sb) == -1)
#else
if (stat (new_name, &sb) == -1)
#endif
continue;
if (S_ISDIR(sb.st_mode)) {
/*
* Recursively delete this directory.
*/
if (remove_tree (new_name)) {
err++;
break;
}
if (rmdir (new_name)) {
err++;
break;
}
continue;
}
unlink (new_name);
}
closedir (dir);
return err ? -1:0;
}

99
libmisc/entry.c Normal file
View File

@@ -0,0 +1,99 @@
/*
* Copyright 1989 - 1994, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: entry.c,v 1.3 1997/12/07 23:27:03 marekm Exp $")
#include <sys/types.h>
#include <stdio.h>
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
struct passwd *fgetpwent ();
void
entry(const char *name, struct passwd *pwent)
{
struct passwd *passwd;
#ifdef SHADOWPWD
struct spwd *spwd;
#ifdef ATT_AGE
char *l64a ();
char *cp;
#endif
#endif
if (! (passwd = getpwnam (name))) {
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;
#ifdef ATT_COMMENT
pwent->pw_comment = xstrdup (passwd->pw_comment);
#endif
pwent->pw_gecos = xstrdup (passwd->pw_gecos);
pwent->pw_dir = xstrdup (passwd->pw_dir);
pwent->pw_shell = xstrdup (passwd->pw_shell);
#if defined(SHADOWPWD) && !defined(AUTOSHADOW)
setspent ();
if ((spwd = getspnam (name))) {
pwent->pw_passwd = xstrdup (spwd->sp_pwdp);
#ifdef ATT_AGE
pwent->pw_age = (char *) xmalloc (5);
if (spwd->sp_max > (63*7))
spwd->sp_max = (63*7);
if (spwd->sp_min > (63*7))
spwd->sp_min = (63*7);
pwent->pw_age[0] = i64c (spwd->sp_max / 7);
pwent->pw_age[1] = i64c (spwd->sp_min / 7);
cp = l64a (spwd->sp_lstchg / 7);
pwent->pw_age[2] = cp[0];
pwent->pw_age[3] = cp[1];
pwent->pw_age[4] = '\0';
#endif
endspent ();
return;
}
endspent ();
#endif
pwent->pw_passwd = xstrdup (passwd->pw_passwd);
#ifdef ATT_AGE
pwent->pw_age = xstrdup (passwd->pw_age);
#endif
}
}

250
libmisc/env.c Normal file
View File

@@ -0,0 +1,250 @@
/*
* Copyright 1989 - 1992, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: env.c,v 1.9 1999/03/07 19:14:38 marekm Exp $")
#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;
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, const char *value)
{
char *cp, *newstring;
size_t i;
size_t n;
if (value) {
newstring = xmalloc(strlen(string) + strlen(value) + 2);
sprintf(newstring, "%s=%s", string, value);
} 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 (!cp) {
free(newstring);
return;
}
n = (size_t)(cp - newstring);
for (i = 0; i < newenvc; i++) {
if (strncmp(newstring, newenvp[i], n) == 0 &&
(newenvp[i][n] == '=' || newenvp[i][n] == '\0'))
break;
}
if (i < newenvc) {
free(newenvp[i]);
newenvp[i] = newstring;
return;
}
newenvp[newenvc++] = newstring;
/*
* 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 succeds we can
* happily go on, else print a message.
*/
newsize = (newenvc + NEWENVP_STEP) * sizeof(char *);
__newenvp = (char **)realloc(newenvp, newsize);
if (__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 {
fprintf(stderr, _("Environment overflow\n"));
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 */
if (! (cp = strchr (*argv, '='))) {
snprintf(variable, sizeof variable, "L%d", noname++);
addenv(variable, *argv);
} else {
const char **p;
for (p = forbid; *p; p++)
if (strncmp(*argv, *p, strlen(*p)) == 0)
break;
if (*p) {
strncpy(variable, *argv, 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; *cur; cur++) {
for (bad = forbid; *bad; bad++) {
if (strncmp(*cur, *bad, strlen(*bad)) == 0) {
for (move = cur; *move; move++)
*move = *(move + 1);
cur--;
break;
}
}
}
for (cur = envp; *cur; cur++) {
for (bad = noslash; *bad; bad++) {
if (strncmp(*cur, *bad, strlen(*bad)) != 0)
continue;
if (!strchr(*cur, '/'))
continue; /* OK */
for (move = cur; *move; move++)
*move = *(move + 1);
cur--;
break;
}
}
}

278
libmisc/failure.c Normal file
View File

@@ -0,0 +1,278 @@
/*
* Copyright 1989 - 1994, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: failure.c,v 1.6 1998/12/28 20:34:46 marekm Exp $")
#include <fcntl.h>
#include <stdio.h>
#include "defines.h"
#include "faillog.h"
#include "getdef.h"
#include "failure.h"
#include <utmp.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;
/*
* Don't do anything if failure logging isn't set up.
*/
if ((fd = open(FAILLOG_FILE, O_RDWR)) < 0)
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 ...
*/
lseek(fd, (off_t) (sizeof *fl) * uid, SEEK_SET);
if (read(fd, (char *) fl, sizeof *fl) != sizeof *fl)
memzero(fl, sizeof *fl);
/*
* Update the record. We increment the failure count to log the
* 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);
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.
*/
lseek(fd, (off_t) (sizeof *fl) * uid, SEEK_SET);
write(fd, (char *) fl, sizeof *fl);
close(fd);
}
static int
too_many_failures(const struct faillog *fl)
{
time_t now;
if (fl->fail_max == 0 || fl->fail_cnt < fl->fail_max)
return 0;
if (fl->fail_locktime == 0)
return 1; /* locked until reset manually */
time(&now);
if (fl->fail_time + fl->fail_locktime > now)
return 0; /* enough time since last failure */
return 1;
}
/*
* 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.
*/
int
failcheck(uid_t uid, struct faillog *fl, int failed)
{
int fd;
struct faillog fail;
/*
* Suppress the check if the log file isn't there.
*/
if ((fd = open(FAILLOG_FILE, O_RDWR)) < 0)
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.
*/
lseek (fd, (off_t) (sizeof *fl) * uid, SEEK_SET);
if (read(fd, (char *) fl, sizeof *fl) != sizeof *fl) {
close(fd);
return 1;
}
if (too_many_failures(fl)) {
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;
lseek (fd, (off_t) sizeof fail * uid, SEEK_SET);
write (fd, (char *) &fail, sizeof fail);
}
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;
const char *fmt;
#else
char *lasttime;
#endif
time_t NOW;
if (fail->fail_cnt == 0)
return;
tp = localtime (&(fail->fail_time));
time(&NOW);
#if HAVE_STRFTIME
/*
* Only print as much date and time info as it needed to
* know when the failure was.
*/
if (NOW - fail->fail_time >= YEAR)
fmt = "%Y";
else if (NOW - fail->fail_time >= DAY)
fmt = "%A %T";
else
fmt = "%T";
strftime(lasttimeb, sizeof lasttimeb, fmt, 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
printf (_("%d %s since last login. Last was %s on %s.\n"),
fail->fail_cnt, fail->fail_cnt > 1 ? _("failures"):_("failure"),
lasttime, fail->fail_line);
}
/*
* failtmp - update the cummulative failure log
*
* failtmp updates the (struct utmp) formatted failure log which
* maintains a record of all login failures.
*/
void
failtmp(const struct utmp *failent)
{
char *ftmp;
int fd;
/*
* Get the name of the failure file. If no file has been defined
* in login.defs, don't do this.
*/
if (!(ftmp = getdef_str("FTMP_FILE")))
return;
/*
* Open the file for append. It must already exist for this
* feature to be used.
*/
if ((fd = open(ftmp, O_WRONLY|O_APPEND)) == -1)
return;
/*
* Output the new failure record and close the log file.
*/
write(fd, (const char *) failent, sizeof *failent);
close(fd);
}

44
libmisc/failure.h Normal file
View File

@@ -0,0 +1,44 @@
/* $Id: failure.h,v 1.1 1997/12/07 23:27:04 marekm Exp $ */
#ifndef _FAILURE_H_
#define _FAILURE_H_
#include "defines.h"
#include "faillog.h"
#include <utmp.h>
/*
* 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 P_((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 P_((uid_t, struct faillog *, int));
/*
* 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 P_((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.
*/
extern void failtmp P_((const struct utmp *));
#endif

104
libmisc/fields.c Normal file
View File

@@ -0,0 +1,104 @@
/*
* Copyright 1990, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: fields.c,v 1.5 1997/12/07 23:27:04 marekm Exp $")
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include "prototypes.h"
/*
* valid_field - insure that a field contains all legal characters
*
* The supplied field is scanned for non-printing and other illegal
* characters. If any illegal characters are found, valid_field
* returns -1. Zero is returned for success.
*/
int
valid_field(const char *field, const char *illegal)
{
const char *cp;
for (cp = field; *cp && isprint(*cp & 0x7F) && !strchr(illegal, *cp); cp++)
;
if (*cp)
return -1;
else
return 0;
}
/*
* change_field - change a single field if a new value is given.
*
* prompt the user with the name of the field being changed and the
* current value.
*/
void
change_field(char *buf, size_t maxsize, const char *prompt)
{
char newf[200];
char *cp;
if (maxsize > sizeof(newf))
maxsize = sizeof(newf);
printf ("\t%s [%s]: ", prompt, buf);
if (fgets(newf, maxsize, stdin) != newf)
return;
if (!(cp = strchr(newf, '\n')))
return;
*cp = '\0';
if (newf[0]) {
/*
* Remove leading and trailing whitespace. This also
* makes it possible to change the field to empty, by
* entering a space. --marekm
*/
while (--cp >= newf && isspace(*cp))
;
*++cp = '\0';
cp = newf;
while (*cp && isspace(*cp))
cp++;
strncpy(buf, cp, maxsize - 1);
buf[maxsize - 1] = '\0';
}
}

2006
libmisc/getdate.c Normal file

File diff suppressed because it is too large Load Diff

8
libmisc/getdate.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef _GETDATE_H_
#define _GETDATE_H_
#include <config.h>
#include "defines.h"
time_t get_date P_((const char *p, const time_t *now));
#endif

1024
libmisc/getdate.y Normal file

File diff suppressed because it is too large Load Diff

90
libmisc/hushed.c Normal file
View File

@@ -0,0 +1,90 @@
/*
* Copyright 1991, 1993, Julianne Frances Haugh and Chip Rosenthal
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: hushed.c,v 1.3 1997/12/07 23:27:05 marekm Exp $")
#include <sys/types.h>
#include <stdio.h>
#include "defines.h"
#include "prototypes.h"
#include "getdef.h"
#include <pwd.h>
/*
* hushed - determine if a user receives login messages
*
* Look in the hushed-logins file (or user's home directory) to see
* if the user is to receive the login-time messages.
*/
int
hushed(const struct passwd *pw)
{
char *hushfile;
char buf[BUFSIZ];
int found;
FILE *fp;
/*
* Get the name of the file to use. If this option is not
* defined, default to a noisy login.
*/
if ( (hushfile=getdef_str("HUSHLOGIN_FILE")) == NULL )
return 0;
/*
* If this is not a fully rooted path then see if the
* file exists in the user's home directory.
*/
if (hushfile[0] != '/') {
strcat(strcat(strcpy(buf, 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 is in there.
*/
if ((fp = fopen(hushfile, "r")) == NULL)
return 0;
for (found = 0;! found && fgets (buf, sizeof buf, fp);) {
buf[strlen (buf) - 1] = '\0';
found = ! strcmp (buf,
buf[0] == '/' ? pw->pw_shell:pw->pw_name);
}
(void) fclose(fp);
return found;
}

173
libmisc/isexpired.c Normal file
View File

@@ -0,0 +1,173 @@
/*
* Copyright 1989 - 1994, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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>
#ifdef HAVE_USERSEC_H
#include <userpw.h>
#include <usersec.h>
#include <userconf.h>
#endif
#ifndef AGING
#if defined(SHADOWPWD) || defined(HAVE_USERSEC_H)
#define AGING 1
#endif
#else
#if !defined(SHADOWPWD) && !defined(HAVE_USERSEC_H) && !defined(ATT_AGE)
#undef AGING
#endif
#endif
#if defined(SHADOWPWD) || defined(AGING) /*{*/
#include "rcsid.h"
RCSID("$Id: isexpired.c,v 1.7 1997/12/07 23:27:05 marekm Exp $")
/*
* isexpired - determine if account is expired yet
*
* isexpired calculates the expiration date based on the
* password expiration criteria.
*/
/*ARGSUSED*/
#ifdef SHADOWPWD
int
isexpired(const struct passwd *pw, const struct spwd *sp)
{
#else
int
isexpired(const struct passwd *pw)
{
#endif
long now;
#ifdef HAVE_USERSEC_H
int minage = 0;
int maxage = 10000;
int curage = 0;
struct userpw *pu;
#endif
now = time ((time_t *) 0) / SCALE;
#ifdef SHADOWPWD
if (!sp)
sp = pwd_to_spwd(pw);
/*
* 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 (sp->sp_lstchg == 0 && !strcmp(pw->pw_passwd, SHADOW_PASSWD_STRING))
return 1;
if (sp->sp_lstchg > 0 && sp->sp_max >= 0 && sp->sp_inact >= 0 &&
now >= sp->sp_lstchg + sp->sp_max + sp->sp_inact)
return 2;
#endif
#ifdef HAVE_USERSEC_H /*{*/
/*
* The aging information lives someplace else. Get it from the
* login.cfg file
*/
if (getconfattr (SC_SYS_PASSWD, SC_MINAGE, &minage, SEC_INT))
minage = -1;
if (getconfattr (SC_SYS_PASSWD, SC_MAXAGE, &maxage, SEC_INT))
maxage = -1;
pu = getuserpw (pw->pw_name);
curage = (time (0) - pu->upw_lastupdate) / (7*86400L);
if (maxage != -1 && curage > maxage)
return 1;
#else /*} !HAVE_USERSEC_H */
/*
* 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.
*/
#ifdef SHADOWPWD
if (sp->sp_lstchg == -1 ||
sp->sp_max == -1 || sp->sp_max >= (10000L*DAY/SCALE))
return 0;
#endif
#ifdef ATT_AGE
if (pw->pw_age[0] == '\0' || pw->pw_age[0] == '/')
return 0;
#endif
/*
* 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.
*/
#ifdef SHADOWPWD
if (now >= sp->sp_lstchg + sp->sp_max)
return 1;
#endif
#ifdef ATT_AGE
if (a64l (pw->pw_age + 2) + c64i (pw->pw_age[1]) < now / 7)
return 1;
#endif
#endif /*} HAVE_USERSEC_H */
return 0;
}
#endif /*}*/

394
libmisc/limits.c Normal file
View File

@@ -0,0 +1,394 @@
/*
* Copyright 1989 - 1994, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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.
*/
#include <config.h>
#include "rcsid.h"
RCSID("$Id: limits.c,v 1.9 1999/03/07 19:14:39 marekm Exp $")
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.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 rlimit, const char *value, unsigned int multiplier)
{
struct rlimit rlim;
long limit;
char **endptr = (char **) &value;
const char *value_orig = value;
limit = strtol(value, endptr, 10);
if (limit == 0 && value_orig == *endptr) /* no chars read */
return 0;
limit *= multiplier;
rlim.rlim_cur = limit;
rlim.rlim_max = limit;
if (setrlimit(rlimit, &rlim))
return LOGIN_ERROR_RLIMIT;
return 0;
}
static int
set_prio(const char *value)
{
int prio;
char **endptr = (char **) &value;
prio = strtol(value, endptr, 10);
if ((prio == 0) && (value == *endptr))
return 0;
if (setpriority(PRIO_PROCESS, 0, prio))
return LOGIN_ERROR_RLIMIT;
return 0;
}
/* Counts the number of user logins and check against the limit */
static int
check_logins(const char *name, const char *maxlogins)
{
struct utmp *ut;
unsigned int limit, count;
char **endptr = (char **) &maxlogins;
const char *ml_orig = maxlogins;
limit = strtol(maxlogins, endptr, 10);
if (limit == 0 && ml_orig == *endptr) /* no chars read */
return 0;
if (limit == 0) /* maximum 0 logins ? */ {
SYSLOG((LOG_WARN, "No logins allowed for `%s'\n", name));
return LOGIN_ERROR_LOGIN;
}
setutent();
count = 0;
while ((ut = getutent())) {
#ifdef USER_PROCESS
if (ut->ut_type != USER_PROCESS)
continue;
#endif
if (ut->ut_user[0] == '\0')
continue;
if (strncmp(name, ut->ut_user, sizeof(ut->ut_user)) != 0)
continue;
if (++count > limit)
break;
}
endutent();
/*
* 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 %d) 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]
* (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 Maximum filesize (KB)
* [Mm]: m = RLIMIT_MEMLOCK max locked-in-memory address space (KB)
* [Nn]: n = RLIMIT_NOFILE max number of open files
* [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
* [Ll]: l = max number of logins for this user
* [Pp]: p = process priority -20..20 (negative = high priority)
*
* 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;
pp = buf;
while (*pp != '\0') switch(*pp++) {
#ifdef RLIMIT_AS
case 'a':
case 'A':
/* RLIMIT_AS - max address space (KB) */
retval |= setrlimit_value(RLIMIT_AS, pp, 1024);
#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_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_NPROC
case 'u':
case 'U':
/* RLIMIT_NPROC - max number of processes */
retval |= setrlimit_value(RLIMIT_NPROC, pp, 1);
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_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_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
case 'l':
case 'L':
/* LIMIT the number of concurent logins */
retval |= check_logins(name, pp);
break;
case 'p':
case 'P':
retval |= set_prio(pp);
break;
}
return retval;
}
static int
setup_user_limits(const char *uname)
{
/* TODO: allow and use @group syntax --cristiang */
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) {
#if 0 /* no limits file is ok, not everyone is a BOFH :-). --marekm */
SYSLOG((LOG_WARN, NO_LIMITS, uname, LIMITS_FILE));
#endif
return 0;
}
/* The limits file have the following format:
* - '#' (comment) chars only as first chars on a line;
* - username must start on first column
* A better (smarter) checking should be done --cristiang */
while (fgets(buf, 1024, fil) != NULL) {
if (buf[0]=='#' || buf[0]=='\n')
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 --cristiang */
if (sscanf(buf, "%s%[ACDFMNRSTULPacdfmnrstulp0-9 \t-]",
name, tempbuf) == 2) {
if (strcmp(name, uname) == 0) {
strcpy(limits, tempbuf);
break;
} else if (strcmp(name, "*") == 0) {
strcpy(deflimits, tempbuf);
}
}
}
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 */
/*
* set the process nice, ulimit, and umask from the password file entry
*/
void
setup_limits(const struct passwd *info)
{
char *cp;
int i;
long l;
#ifdef USERGROUPS
if (info->pw_uid != 0 && info->pw_uid == info->pw_gid) {
const struct group *grp;
grp = getgrgid(info->pw_gid);
if (grp && !strcmp(info->pw_name, grp->gr_name)) {
umask(umask(0) & ~070);
}
}
#endif
/*
* 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)
if (setup_user_limits(info->pw_name) & LOGIN_ERROR_LOGIN) {
fprintf(stderr, _("Too many logins.\n"));
sleep(2);
exit(1);
}
#endif
for (cp = info->pw_gecos ; cp != NULL ; cp = strchr (cp, ',')) {
if (*cp == ',')
cp++;
if (strncmp (cp, "pri=", 4) == 0) {
i = atoi (cp + 4);
if (i >= -20 && i <= 20)
(void) nice (i);
continue;
}
if (strncmp (cp, "ulimit=", 7) == 0) {
l = strtol (cp + 7, (char **) 0, 10);
set_filesize_limit(l);
continue;
}
if (strncmp (cp, "umask=", 6) == 0) {
i = strtol (cp + 6, (char **) 0, 8) & 0777;
(void) umask (i);
continue;
}
}
}
}

234
libmisc/list.c Normal file
View File

@@ -0,0 +1,234 @@
/*
* Copyright 1991 - 1994, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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.
*/
/* Removed duplicated code from gpmain.c, useradd.c, userdel.c and
usermod.c. --marekm */
#include <config.h>
#include "rcsid.h"
RCSID("$Id: list.c,v 1.3 1997/12/07 23:27:05 marekm Exp $")
#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.
*/
char **
add_list(char **list, const char *member)
{
int i;
char **tmp;
/*
* 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] = (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.
*/
char **
del_list(char **list, const char *member)
{
int i, j;
char **tmp;
/*
* 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))
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))
tmp[j++] = list[i];
tmp[j] = (char *) 0;
return tmp;
}
char **
dup_list(char * const *list)
{
int i;
char **tmp;
for (i = 0; list[i]; i++)
;
tmp = (char **) xmalloc((i + 1) * sizeof(char *));
i = 0;
while (*list)
tmp[i++] = xstrdup(*list++);
tmp[i] = (char *) 0;
return tmp;
}
int
is_on_list(char * const *list, const char *member)
{
while (*list) {
if (strcmp(*list, member) == 0)
return 1;
list++;
}
return 0;
}
/*
* comma_to_list - convert comma-separated list to (char *) array
*/
char **
comma_to_list(const char *comma)
{
char *members;
char **array;
int i;
char *cp, *cp2;
/*
* 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++)
if ((cp2 = strchr (cp, ',')))
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 (!*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;
if ((cp2 = strchr (cp, ','))) {
*cp2++ = '\0';
cp = cp2;
} else {
array[i + 1] = (char *) 0;
break;
}
}
/*
* Return the new array of pointers
*/
return array;
}

100
libmisc/log.c Normal file
View File

@@ -0,0 +1,100 @@
/*
* Copyright 1989 - 1994, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: log.c,v 1.5 1998/04/16 19:57:44 marekm Exp $")
#include <sys/types.h>
#include <pwd.h>
#include <fcntl.h>
#include <time.h>
#include "defines.h"
#if HAVE_LASTLOG_H
#include <lastlog.h>
#else
#include "lastlog_.h"
#endif
/*
* 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, const char *line, const char *host)
{
int fd;
off_t offset;
struct lastlog newlog;
/*
* If the file does not exist, don't create it.
*/
if ((fd = open(LASTLOG_FILE, O_RDWR)) == -1)
return;
/*
* The file is indexed by UID number. Seek to the record
* for this UID. Negative UID's will create problems, but ...
*/
offset = (unsigned long) pw->pw_uid * sizeof newlog;
if (lseek(fd, offset, SEEK_SET) != offset) {
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, (char *) &newlog, sizeof newlog) != sizeof newlog)
memzero(&newlog, sizeof newlog);
if (ll)
*ll = newlog;
time(&newlog.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, (char *) &newlog, sizeof newlog);
close(fd);
}

340
libmisc/login_access.c Normal file
View File

@@ -0,0 +1,340 @@
/* Taken from logdaemon-5.0, only minimal changes. --marekm */
/************************************************************************
* Copyright 1995 by Wietse Venema. All rights reserved. Individual files
* may be covered by other copyrights (as noted in the file itself.)
*
* This material was originally written and compiled by Wietse Venema at
* Eindhoven University of Technology, The Netherlands, in 1990, 1991,
* 1992, 1993, 1994 and 1995.
*
* Redistribution and use in source and binary forms are permitted
* provided that this entire copyright notice is duplicated in all such
* copies.
*
* This software is provided "as is" and without any expressed or implied
* warranties, including, without limitation, the implied warranties of
* merchantibility and fitness for any particular purpose.
************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef LOGIN_ACCESS
#include "rcsid.h"
RCSID("$Id: login_access.c,v 1.6 1998/01/29 23:22:34 marekm Exp $")
#include "prototypes.h"
/*
* This module implements a simple but effective form of login access
* control based on login names and on host (or domain) names, internet
* addresses (or network numbers), or on terminal line names in case of
* non-networked logins. Diagnostics are reported through syslog(3).
*
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
*/
#include <sys/types.h>
#include <stdio.h>
#include <syslog.h>
#include <ctype.h>
#include <netdb.h>
#include <grp.h>
#ifdef PRIMARY_GROUP_MATCH
#include <pwd.h>
#endif
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> /* for inet_ntoa() */
extern struct group *getgrnam();
extern int innetgr();
#if 0 /* should be defined by <errno.h> */
extern int errno;
#endif
#if !defined(MAXHOSTNAMELEN) || (MAXHOSTNAMELEN < 64)
#undef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 256
#endif
/* Path name of the access control file. */
#ifndef TABLE
#define TABLE "/etc/login.access"
#endif
/* Delimiters for fields and for lists of users, ttys or hosts. */
static char fs[] = ":"; /* field separator */
static char sep[] = ", \t"; /* list-element separator */
/* Constants to be used in assignments only, not in comparisons... */
#define YES 1
#define NO 0
static int list_match();
static int user_match();
static int from_match();
static int string_match();
/* login_access - match username/group and host/tty with access control file */
int
login_access(const char *user, const char *from)
{
FILE *fp;
char line[BUFSIZ];
char *perm; /* becomes permission field */
char *users; /* becomes list of login names */
char *froms; /* becomes list of terminals or hosts */
int match = NO;
int end;
int lineno = 0; /* for diagnostics */
/*
* Process the table one line at a time and stop at the first match.
* Blank lines and lines that begin with a '#' character are ignored.
* Non-comment lines are broken at the ':' character. All fields are
* mandatory. The first field should be a "+" or "-" character. A
* non-existing table means no access control.
*/
if ((fp = fopen(TABLE, "r"))) {
while (!match && fgets(line, sizeof(line), fp)) {
lineno++;
if (line[end = strlen(line) - 1] != '\n') {
syslog(LOG_ERR, "%s: line %d: missing newline or line too long",
TABLE, lineno);
continue;
}
if (line[0] == '#')
continue; /* comment line */
while (end > 0 && isspace(line[end - 1]))
end--;
line[end] = 0; /* strip trailing whitespace */
if (line[0] == 0) /* skip blank lines */
continue;
if (!(perm = strtok(line, fs))
|| !(users = strtok((char *) 0, fs))
|| !(froms = strtok((char *) 0, fs))
|| strtok((char *) 0, fs)) {
syslog(LOG_ERR, "%s: line %d: bad field count", TABLE, lineno);
continue;
}
if (perm[0] != '+' && perm[0] != '-') {
syslog(LOG_ERR, "%s: line %d: bad first field", TABLE, lineno);
continue;
}
match = (list_match(froms, from, from_match)
&& list_match(users, user, user_match));
}
(void) fclose(fp);
} else if (errno != ENOENT) {
syslog(LOG_ERR, "cannot open %s: %m", TABLE);
}
return (match == 0 || (line[0] == '+'));
}
/* list_match - match an item against a list of tokens with exceptions */
static int
list_match(char *list, const char *item, int (*match_fn)())
{
char *tok;
int match = NO;
/*
* Process tokens one at a time. We have exhausted all possible matches
* when we reach an "EXCEPT" token or the end of the list. If we do find
* a match, look for an "EXCEPT" list and recurse to determine whether
* the match is affected by any exceptions.
*/
for (tok = strtok(list, sep); tok != 0; tok = strtok((char *) 0, sep)) {
if (strcasecmp(tok, "EXCEPT") == 0) /* EXCEPT: give up */
break;
if ((match = (*match_fn) (tok, item))) /* YES */
break;
}
/* Process exceptions to matches. */
if (match != NO) {
while ((tok = strtok((char *) 0, sep)) && strcasecmp(tok, "EXCEPT"))
/* VOID */ ;
if (tok == 0 || list_match((char *) 0, item, match_fn) == NO)
return (match);
}
return (NO);
}
/* myhostname - figure out local machine name */
static char *
myhostname(void)
{
static char name[MAXHOSTNAMELEN + 1] = "";
if (name[0] == 0) {
gethostname(name, sizeof(name));
name[MAXHOSTNAMELEN] = 0;
}
return (name);
}
/* netgroup_match - match group against machine or user */
static int
netgroup_match(const char *group, const char *machine, const char *user)
{
#if 0 /* original code */
#ifdef NIS
static char *mydomain = 0;
if (mydomain == 0)
yp_get_default_domain(&mydomain);
return (innetgr(group, machine, user, mydomain));
#else
syslog(LOG_ERR, "NIS netgroup support not configured");
return (NO);
#endif
#else /* works better with glibc? */
static char *mydomain = 0;
if (mydomain == 0) {
static char domain[MAXHOSTNAMELEN+1];
getdomainname(domain, MAXHOSTNAMELEN);
mydomain = domain;
}
return innetgr(group, machine, user, mydomain);
#endif
}
/* user_match - match a username against one token */
static int
user_match(const char *tok, const char *string)
{
struct group *group;
#ifdef PRIMARY_GROUP_MATCH
struct passwd *userinf;
#endif
int i;
char *at;
/*
* If a token has the magic value "ALL" the match always succeeds.
* Otherwise, return YES if the token fully matches the username, or if
* the token is a group that contains the username.
*/
if ((at = strchr(tok + 1, '@')) != 0) { /* split user@host pattern */
*at = 0;
return (user_match(tok, string) && from_match(at + 1, myhostname()));
} else if (tok[0] == '@') { /* netgroup */
return (netgroup_match(tok + 1, (char *) 0, string));
} else if (string_match(tok, string)) { /* ALL or exact match */
return (YES);
} else if ((group = getgrnam(tok))) { /* try group membership */
for (i = 0; group->gr_mem[i]; i++)
if (strcasecmp(string, group->gr_mem[i]) == 0)
return (YES);
#ifdef PRIMARY_GROUP_MATCH
/*
* If the sting is an user whose initial GID matches the token,
* accept it. May avoid excessively long lines in /etc/group.
* Radu-Adrian Feurdean <raf@licj.soroscj.ro>
*
* XXX - disabled by default for now. Need to verify that
* getpwnam() doesn't have some nasty side effects. --marekm
*/
if ((userinf = getpwnam(string)))
if (userinf->pw_gid == group->gr_gid)
return (YES);
#endif
}
return (NO);
}
static char *
resolve_hostname(string)
char *string;
{
#if 1
/*
* Resolve hostname to numeric IP address, as suggested
* by Dave Hagewood <admin@arrowweb.com>. --marekm
*/
struct hostent *hp;
hp = gethostbyname(string);
if (hp)
return inet_ntoa(*((struct in_addr *) *(hp->h_addr_list)));
syslog(LOG_ERR, "%s - unknown host", string);
#endif
return string;
}
/* from_match - match a host or tty against a list of tokens */
static int
from_match(const char *tok, const char *string)
{
int tok_len;
int str_len;
/*
* If a token has the magic value "ALL" the match always succeeds. Return
* YES if the token fully matches the string. If the token is a domain
* name, return YES if it matches the last fields of the string. If the
* token has the magic value "LOCAL", return YES if the string does not
* contain a "." character. If the token is a network number, return YES
* if it matches the head of the string.
*/
if (tok[0] == '@') { /* netgroup */
return (netgroup_match(tok + 1, string, (char *) 0));
} else if (string_match(tok, string)) { /* ALL or exact match */
return (YES);
} else if (tok[0] == '.') { /* domain: match last fields */
if ((str_len = strlen(string)) > (tok_len = strlen(tok))
&& strcasecmp(tok, string + str_len - tok_len) == 0)
return (YES);
} else if (strcasecmp(tok, "LOCAL") == 0) { /* local: no dots */
if (strchr(string, '.') == 0)
return (YES);
} else if (tok[(tok_len = strlen(tok)) - 1] == '.' /* network */
&& strncmp(tok, resolve_hostname(string), tok_len) == 0) {
return (YES);
}
return (NO);
}
/* string_match - match a string against one token */
static int
string_match(const char *tok, const char *string)
{
/*
* If the token has the magic value "ALL" the match always succeeds.
* Otherwise, return YES if the token fully matches the string.
*/
if (strcasecmp(tok, "ALL") == 0) { /* all: always matches */
return (YES);
} else if (strcasecmp(tok, string) == 0) { /* try exact match */
return (YES);
}
return (NO);
}
#endif /* LOGIN_ACCESS */

77
libmisc/login_desrpc.c Normal file
View File

@@ -0,0 +1,77 @@
/* Taken from logdaemon-5.0, only minimal changes. --marekm */
/************************************************************************
* Copyright 1995 by Wietse Venema. All rights reserved. Individual files
* may be covered by other copyrights (as noted in the file itself.)
*
* This material was originally written and compiled by Wietse Venema at
* Eindhoven University of Technology, The Netherlands, in 1990, 1991,
* 1992, 1993, 1994 and 1995.
*
* Redistribution and use in source and binary forms are permitted
* provided that this entire copyright notice is duplicated in all such
* copies.
*
* This software is provided "as is" and without any expressed or implied
* warranties, including, without limitation, the implied warranties of
* merchantibility and fitness for any particular purpose.
************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef DES_RPC
#include "rcsid.h"
RCSID("$Id: login_desrpc.c,v 1.7 1999/06/07 16:40:44 marekm Exp $")
#include "defines.h"
/*
* Decrypt the user's secret secure RPC key and stores it into the
* keyserver. Returns 0 if successful, -1 on failure.
*
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
*/
#include <stdio.h>
#include <rpc/rpc.h>
#include <rpc/key_prot.h>
#if !(defined __GLIBC__ && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 0)))
/* these don't seem to be in any header file (libc-5.4.33) */
/* but will be in glibc 2.1 <rpc/auth.h> and <rpc/auth_des.h> */
extern int getnetname(char *);
extern int getsecretkey(const char *, char *, const char *);
extern int key_setsecret(const char *);
#endif
int
login_desrpc(const char *passwd)
{
char netname[MAXNETNAMELEN + 1];
char secretkey[HEXKEYBYTES + 1];
if (getnetname(netname) == 0)
return -1;
if (getsecretkey(netname, secretkey, passwd) == 0)
return -1;
if (secretkey[0] == 0) {
fprintf(stderr,
_("Password does not decrypt secret key for %s.\n"),
netname);
return -1;
}
if (key_setsecret(secretkey) < 0) {
fprintf(stderr,
_("Could not set %s's secret key: is the keyserv daemon running?\n"),
netname);
return -1;
}
return 0;
}
#else
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif

61
libmisc/login_krb.c Normal file
View File

@@ -0,0 +1,61 @@
/* Taken from logdaemon-5.0, only minimal changes. --marekm */
/************************************************************************
* Copyright 1995 by Wietse Venema. All rights reserved. Individual files
* may be covered by other copyrights (as noted in the file itself.)
*
* This material was originally written and compiled by Wietse Venema at
* Eindhoven University of Technology, The Netherlands, in 1990, 1991,
* 1992, 1993, 1994 and 1995.
*
* Redistribution and use in source and binary forms are permitted
* provided that this entire copyright notice is duplicated in all such
* copies.
*
* This software is provided "as is" and without any expressed or implied
* warranties, including, without limitation, the implied warranties of
* merchantibility and fitness for any particular purpose.
************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef KERBEROS
#include "rcsid.h"
RCSID("$Id: login_krb.c,v 1.3 1998/01/29 23:22:34 marekm Exp $")
#include <krb.h>
/*
* Do an equivalent to kinit here. We need to do the kinit before trying to
* cd to the home directory, because it might be on a remote filesystem that
* uses Kerberos authentication. We also need to do this after we've
* setuid() to the user, or krb_get_pw_in_tkt() won't know where to put the
* ticket.
*
* We don't really care about whether or not it succeeds; if it fails, we'll
* just carry on bravely.
*
* NB: we assume: local realm, same username and password as supplied to login.
*
* Security note: if pp is NULL, login doesn't have the password. This is
* common when it's called by rlogind. Since this is almost always a remote
* connection, we don't want to risk asking for the password by supplying a
* NULL pp to krb_get_pw_in_tkt(), because somebody could be listening. So
* we'll just forget the whole thing. -jdd
*/
int
login_kerberos(const char *username, const char *password)
{
char realm[REALM_SZ];
(void) krb_get_lrealm(realm, 1);
if (password != 0)
(void) krb_get_pw_in_tkt(username, "", realm, "krbtgt",
realm, DEFAULT_TKT_LIFE, password);
}
#else
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* KERBEROS */

165
libmisc/loginprompt.c Normal file
View File

@@ -0,0 +1,165 @@
/*
* Copyright 1989 - 1993, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: loginprompt.c,v 1.5 1998/04/16 19:57:44 marekm Exp $")
#include <stdio.h>
#include <signal.h>
#include <ctype.h>
#include "prototypes.h"
#include "defines.h"
#include "getdef.h"
static void
login_exit(int sig)
{
exit(1);
}
/*
* 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];
int envc;
char *cp;
int i;
FILE *fp;
RETSIGTYPE (*sigquit) P_((int));
#ifdef SIGTSTP
RETSIGTYPE (*sigtstp) P_((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 (prompt) {
cp = getdef_str("ISSUE_FILE");
if (cp && (fp = fopen(cp, "r"))) {
while ((i = getc(fp)) != EOF)
putc(i, stdout);
fclose(fp);
}
gethostname(buf, sizeof buf);
printf(prompt, buf);
fflush(stdout);
}
/*
* Read the user's response. The trailing newline will be
* removed.
*/
memzero(buf, sizeof buf);
if (fgets(buf, sizeof buf, stdin) != buf)
exit(1);
cp = strchr(buf, '\n');
if (!cp)
exit(1);
*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 (*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 (*cp != '\0') { /* process new variables */
char *nvar;
int count = 1;
for (envc = 0; envc < MAX_ENV; envc++) {
nvar = strtok(envc ? (char *)0 : cp, " \t,");
if (!nvar)
break;
if (strchr(nvar, '=')) {
envp[envc] = nvar;
} else {
envp[envc] = xmalloc(strlen(nvar) + 32);
sprintf(envp[envc], "L%d=%s", count++, nvar);
}
}
set_env(envc, envp);
}
/*
* Set the SIGQUIT handler back to its original value
*/
signal(SIGQUIT, sigquit);
#ifdef SIGTSTP
signal(SIGTSTP, sigtstp);
#endif
}

79
libmisc/mail.c Normal file
View File

@@ -0,0 +1,79 @@
/*
* Copyright 1989 - 1991, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include "getdef.h"
#include "rcsid.h"
RCSID("$Id: mail.c,v 1.7 1998/12/28 20:34:49 marekm Exp $")
void
mailcheck(void)
{
struct stat statbuf;
char *mailbox;
if (!getdef_bool("MAIL_CHECK_ENAB"))
return;
/*
* Check incoming mail in Maildir format - J.
*/
if ((mailbox = getenv("MAILDIR"))) {
char *newmail;
newmail = xmalloc(strlen(mailbox) + 5);
sprintf(newmail, "%s/new", mailbox);
if (stat(newmail, &statbuf) != -1 && statbuf.st_size != 0) {
if (statbuf.st_mtime > statbuf.st_atime) {
free(newmail);
puts(_("You have new mail."));
return;
}
}
free(newmail);
}
if (!(mailbox = getenv("MAIL")))
return;
if (stat(mailbox, &statbuf) == -1 || statbuf.st_size == 0)
puts(_("No mail."));
else if (statbuf.st_atime > statbuf.st_mtime)
puts(_("You have mail."));
else
puts(_("You have new mail."));
}

69
libmisc/motd.c Normal file
View File

@@ -0,0 +1,69 @@
/*
* Copyright 1989 - 1991, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: motd.c,v 1.3 1997/12/07 23:27:07 marekm Exp $")
#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[BUFSIZ], *motdfile, *mb;
register int c;
if ((mb = getdef_str("MOTD_FILE")) == NULL)
return;
strncpy(motdlist, mb, sizeof(motdlist));
motdlist[sizeof(motdlist)-1] = '\0';
for (mb = motdlist ; (motdfile = strtok(mb,":")) != NULL ; mb = NULL) {
if ((fp = fopen(motdfile, "r")) != NULL) {
while ((c = getc (fp)) != EOF)
putchar (c);
fclose (fp);
}
}
fflush (stdout);
}

41
libmisc/myname.c Normal file
View File

@@ -0,0 +1,41 @@
/*
* myname.c - determine the current username and get the passwd entry
*
* Copyright (C) 1996 Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>
*
* This code may be freely used, modified and distributed for any purpose.
* There is no warranty, if it breaks you have to keep both pieces, etc.
* If you improve it, please send me your changes. Thanks!
*/
#include <config.h>
#include "rcsid.h"
RCSID("$Id: myname.c,v 1.2 1997/12/07 23:27:07 marekm Exp $")
#include "defines.h"
#include <pwd.h>
#include "prototypes.h"
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 (cp && *cp && (pw = getpwnam(cp)) && pw->pw_uid == ruid)
return pw;
return getpwuid(ruid);
}

286
libmisc/obscure.c Normal file
View File

@@ -0,0 +1,286 @@
/*
* Copyright 1989 - 1994, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: obscure.c,v 1.9 1999/03/07 19:14:40 marekm Exp $")
/*
* 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'
*/
/*ARGSUSED*/
static int
palindrome(const char *old, const char *new)
{
int i, j;
i = strlen (new);
for (j = 0;j < i;j++)
if (new[i - j - 1] != new[j])
return 0;
return 1;
}
/*
* more than half of the characters are different ones.
*/
/*ARGSUSED*/
static int
similar(const char *old, 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 0;
for (i = j = 0; new[i] && old[i]; i++)
if (strchr(new, old[i]))
j++;
if (i >= j * 2)
return 0;
return 1;
}
/*
* a nice mix of characters.
*/
/*ARGSUSED*/
static int
simple(const char *old, const char *new)
{
int digits = 0;
int uppers = 0;
int lowers = 0;
int others = 0;
int size;
int i;
for (i = 0;new[i];i++) {
if (isdigit (new[i]))
digits++;
else if (isupper (new[i]))
uppers++;
else if (islower (new[i]))
lowers++;
else
others++;
}
/*
* 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 0;
return 1;
}
static char *
str_lower(char *string)
{
char *cp;
for (cp = string; *cp; cp++)
*cp = tolower(*cp);
return string;
}
static const char *
password_check(const char *old, const char *new, 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";
if (!msg && strcmp(oldmono, newmono) == 0)
msg = "case changes only";
if (!msg && similar(oldmono, newmono))
msg = "too similar";
if (!msg && simple(old, new))
msg = "too simple";
if (!msg && strstr(wrapped, newmono))
msg = "rotated";
#ifdef HAVE_LIBCRACK
/*
* Invoke Alec Muffett's cracklib routines.
*/
if (!msg && (dictpath = getdef_str("CRACKLIB_DICTPATH")))
#ifdef HAVE_LIBCRACK_PW
msg = FascistCheckPw(new, dictpath, pwdp);
#else
msg = FascistCheck(new, dictpath);
#endif
#endif
strzero(newmono);
strzero(oldmono);
strzero(wrapped);
free(newmono);
free(oldmono);
free(wrapped);
return msg;
}
/*ARGSUSED*/
static const char *
obscure_msg(const char *old, const char *new, const struct passwd *pwdp)
{
int maxlen, oldlen, newlen;
char *new1, *old1;
const char *msg;
oldlen = strlen(old);
newlen = strlen(new);
#if 0 /* why not check the password when set for the first time? --marekm */
if (old[0] == '\0')
return NULL;
#endif
if ( newlen < 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 (msg)
return msg;
/* 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; /* unlimited password length */
maxlen = 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.
*/
int
obscure(const char *old, const char *new, const struct passwd *pwdp)
{
const char *msg = obscure_msg(old, new, pwdp);
if (msg) {
printf(_("Bad password: %s. "), msg);
return 0;
}
return 1;
}

58
libmisc/pam_pass.c Normal file
View File

@@ -0,0 +1,58 @@
#include <config.h>
#ifdef USE_PAM
#include "rcsid.h"
RCSID("$Id: pam_pass.c,v 1.6 1999/06/07 16:40:44 marekm Exp $")
/*
* Change the user's password using PAM. Requires libpam and libpam_misc
* (for misc_conv). Note: libpam_misc is probably Linux-PAM specific,
* so you may have to port it if you want to use this code on non-Linux
* systems with PAM (such as Solaris 2.6). --marekm
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include "defines.h"
#include "pam_defs.h"
static const struct pam_conv conv = {
misc_conv,
NULL
};
void
do_pam_passwd(const char *user, int silent, int 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));
pam_end(pamh, ret);
exit(10); /* XXX */
}
pam_end(pamh, PAM_SUCCESS);
}
#else /* !USE_PAM */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !USE_PAM */

103
libmisc/pwd2spwd.c Normal file
View File

@@ -0,0 +1,103 @@
/*
* Copyright 1989 - 1994, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 SHADOWPWD
#include "rcsid.h"
RCSID("$Id: pwd2spwd.c,v 1.3 1997/12/07 23:27:07 marekm Exp $")
#include <sys/types.h>
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
extern time_t time ();
/*
* 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;
#ifdef ATT_AGE
/*
* AT&T-style password aging maps the sp_min, sp_max, and
* sp_lstchg information from the pw_age field, which appears
* after the encrypted password.
*/
if (pw->pw_age[0]) {
sp.sp_max = (c64i(pw->pw_age[0]) * WEEK) / SCALE;
if (pw->pw_age[1])
sp.sp_min = (c64i(pw->pw_age[1]) * WEEK) / SCALE;
else
sp.sp_min = (10000L * DAY) / SCALE;
if (pw->pw_age[1] && pw->pw_age[2])
sp.sp_lstchg = (a64l(pw->pw_age + 2) * WEEK) / SCALE;
else
sp.sp_lstchg = time((time_t *) 0) / SCALE;
} else
#endif
{
/*
* Defaults used if there is no pw_age information.
*/
sp.sp_min = 0;
sp.sp_max = (10000L * DAY) / SCALE;
sp.sp_lstchg = time((time_t *) 0) / SCALE;
}
/*
* 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 = -1;
return &sp;
}
#endif /* SHADOWPWD */

73
libmisc/pwd_init.c Normal file
View File

@@ -0,0 +1,73 @@
#include <config.h>
#include "rcsid.h"
RCSID("$Id: pwd_init.c,v 1.1 1997/12/07 23:27:07 marekm Exp $")
#include "defines.h"
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
/*
* 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);
}

69
libmisc/pwdcheck.c Normal file
View File

@@ -0,0 +1,69 @@
#include <config.h>
#include "rcsid.h"
RCSID("$Id$")
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
#include "pwauth.h"
#ifdef HAVE_SHADOW_H
#include <shadow.h>
#endif
#ifdef USE_PAM
#include "pam_defs.h"
#endif
#define WRONGPWD2 "incorrect password for `%s'"
void
passwd_check(const char *user, const char *passwd, const char *progname)
{
#ifdef USE_PAM
pam_handle_t *pamh = NULL;
int retcode;
struct pam_conv conv = { misc_conv, NULL };
if (pam_start(progname, user, &conv, &pamh)) {
bailout:
SYSLOG((LOG_WARN, WRONGPWD2, user));
sleep(1);
fprintf(stderr, _("Incorrect password for %s.\n"), user);
exit(1);
}
if (pam_authenticate(pamh, 0))
goto bailout;
retcode = pam_acct_mgmt(pamh, 0);
if (retcode == PAM_NEW_AUTHTOK_REQD) {
retcode = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
} else if (retcode)
goto bailout;
if (pam_setcred(pamh, 0))
goto bailout;
/* no need to establish a session; this isn't a session-oriented
* activity... */
#else /* !USE_PAM */
#ifdef SHADOWPWD
struct spwd *sp;
if ((sp = getspnam(user)))
passwd = sp->sp_pwdp;
endspent();
#endif
if (pw_auth(passwd, user, PW_LOGIN, (char *) 0) != 0) {
SYSLOG((LOG_WARN, WRONGPWD2, user));
sleep(1);
fprintf(stderr, _("Incorrect password for %s.\n"), user);
exit(1);
}
#endif /* !USE_PAM */
}

170
libmisc/rlogin.c Normal file
View File

@@ -0,0 +1,170 @@
/*
* Copyright 1989 - 1994, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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
#include "rcsid.h"
RCSID("$Id: rlogin.c,v 1.4 1997/12/14 20:07:20 marekm Exp $")
#include "prototypes.h"
#include "defines.h"
#include <stdio.h>
#include <pwd.h>
extern int ruserok();
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, int size)
{
for (;;) {
if (read (0, buf, 1) != 1)
exit (1);
if (*buf == '\0')
return;
if (--size > 0)
++buf;
}
/*NOTREACHED*/
}
int
do_rlogin(const char *remote_host, char *name, int namelen, char *term, int termlen)
{
struct passwd *pwd;
char remote_name[32];
char *cp;
int 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);
if ((cp = strchr (term, '/'))) {
*cp++ = '\0';
if (! (remote_speed = atoi (cp)))
remote_speed = 9600;
}
for (i = 0;speed_table[i].spd_baud != remote_speed &&
speed_table[i].spd_name != -1;i++)
;
if (speed_table[i].spd_name != -1)
speed_name = speed_table[i].spd_name;
/*
* Put the terminal in cooked mode with echo turned on.
*/
GTTY (0, &termio);
#ifndef USE_SGTTY
termio.c_iflag |= ICRNL|IXON;
termio.c_oflag |= OPOST|ONLCR;
termio.c_lflag |= ICANON|ECHO|ECHOE;
termio.c_cflag = (termio.c_cflag & ~CBAUD) | speed_name;
#else
#endif
STTY (0, &termio);
if (! (pwd = getpwnam (name)))
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 */

70
libmisc/salt.c Normal file
View File

@@ -0,0 +1,70 @@
/*
* salt.c - generate a random salt string for crypt()
*
* Written by Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>,
* public domain.
*/
#include <config.h>
#include "rcsid.h"
RCSID("$Id: salt.c,v 1.5 1997/12/07 23:27:09 marekm Exp $")
#include "prototypes.h"
#include "defines.h"
#include <sys/time.h>
#if 1
#include "getdef.h"
extern char *l64a();
/*
* 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.
*/
char *
crypt_make_salt(void)
{
struct timeval tv;
static char result[40];
result[0] = '\0';
if (getdef_bool("MD5_CRYPT_ENAB")) {
strcpy(result, "$1$"); /* magic for the new MD5 crypt() */
}
/*
* Generate 8 chars of salt, the old crypt() will use only first 2.
*/
gettimeofday(&tv, (struct timezone *) 0);
strcat(result, l64a(tv.tv_usec));
strcat(result, l64a(tv.tv_sec + getpid() + clock()));
if (strlen(result) > 3 + 8) /* magic+salt */
result[11] = '\0';
return result;
}
#else
/*
* This is the old style random salt generator...
*/
char *
crypt_make_salt(void)
{
time_t now;
static unsigned long x;
static char result[3];
time(&now);
x += now + getpid() + clock();
result[0] = i64c(((x >> 18) ^ (x >> 6)) & 077);
result[1] = i64c(((x >> 12) ^ x) & 077);
result[2] = '\0';
return result;
}
#endif

134
libmisc/setugid.c Normal file
View File

@@ -0,0 +1,134 @@
/*
* Copyright 1989 - 1994, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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>
#include "rcsid.h"
RCSID("$Id: setugid.c,v 1.6 1998/07/23 22:13:16 marekm Exp $")
#include <stdio.h>
#include <grp.h>
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
#include "getdef.h"
/*
* setup_uid_gid() split in two functions for PAM support -
* pam_setcred() needs to be called after initgroups(), but
* before setuid().
*/
int
setup_groups(const struct passwd *info)
{
/*
* Set the real group ID to the primary group ID in the password
* file.
*/
if (setgid (info->pw_gid) == -1) {
perror("setgid");
SYSLOG((LOG_ERR, "bad group ID `%d' for user `%s': %m\n",
info->pw_gid, info->pw_name));
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) {
perror("initgroups");
SYSLOG((LOG_ERR, "initgroups failed for user `%s': %m\n",
info->pw_name));
closelog();
return -1;
}
#endif
return 0;
}
int
change_uid(const struct passwd *info)
{
/*
* Set the real UID to the UID value in the password file.
*/
#ifndef BSD
if (setuid(info->pw_uid))
#else
if (setreuid(info->pw_uid, info->pw_uid))
#endif
{
perror("setuid");
SYSLOG((LOG_ERR, "bad user ID `%d' for user `%s': %m\n",
(int) info->pw_uid, info->pw_name));
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.
*/
int
setup_uid_gid(const struct passwd *info, int is_console)
{
if (setup_groups(info) < 0)
return -1;
#ifdef HAVE_INITGROUPS
if (is_console) {
char *cp = getdef_str("CONSOLE_GROUPS");
if (cp && add_groups(cp))
perror("Warning: add_groups");
}
#endif /* HAVE_INITGROUPS */
if (change_uid(info) < 0)
return -1;
return 0;
}

72
libmisc/setup.c Normal file
View File

@@ -0,0 +1,72 @@
/*
* Copyright 1989 - 1994, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: setup.c,v 1.3 1997/12/07 23:27:09 marekm Exp $")
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
/*
* setup - initialize login environment
*
* setup() performs the following steps -
*
* set the process nice, ulimit, and umask from the password file entry
* set the group ID to the value from the password file entry
* set the supplementary group IDs
* set the user ID to the value from the password file entry
* change to the user's home directory
* set the HOME, SHELL, MAIL, PATH, and LOGNAME or USER environmental
* variables.
*/
void
setup(struct passwd *info)
{
/*
* Set resource limits.
*/
setup_limits(info);
/*
* Set the real group ID, do initgroups, and set the real user ID
* to the value in the password file.
*/
if (setup_uid_gid(info, 0))
exit(1);
/*
* Change to the home directory, and set up environment.
*/
setup_env(info);
}

277
libmisc/setupenv.c Normal file
View File

@@ -0,0 +1,277 @@
/*
* Copyright 1989 - 1994, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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>
#include "rcsid.h"
RCSID("$Id: setupenv.c,v 1.9 1999/03/07 19:14:41 marekm Exp $")
#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"
static void
addenv_path(const char *varname, const char *dirname, const char *filename)
{
char *buf;
buf = xmalloc(strlen(dirname) + strlen(filename) + 2);
sprintf(buf, "%s/%s", dirname, filename);
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 (!fp)
return;
while (fgets(buf, sizeof buf, fp) == buf) {
cp = strrchr(buf, '\n');
if (!cp)
break;
*cp = '\0';
cp = buf;
/* ignore whitespace and comments */
while (*cp && isspace(*cp))
cp++;
if (*cp == '\0' || *cp == '#')
continue;
/*
* ignore lines which don't follow the name=value format
* (for example, the "export NAME" shell commands)
*/
name = cp;
while (*cp && !isspace(*cp) && *cp != '=')
cp++;
if (*cp != '=')
continue;
/* NUL-terminate the name */
*cp++ = '\0';
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);
}
fclose(fp);
}
/*
* 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)
{
char *cp, *envf;
/*
* 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 (1);
}
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 (info->pw_shell == (char *) 0 || ! *info->pw_shell) {
static char temp_pw_shell[] = "/bin/sh";
info->pw_shell = temp_pw_shell;
}
addenv("SHELL", info->pw_shell);
/*
* Create the PATH environmental variable and export it.
*/
cp = getdef_str( info->pw_uid == 0 ? "ENV_SUPATH" : "ENV_PATH" );
addenv(cp ? cp : "PATH=/bin:/usr/bin", NULL);
/*
* 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);
/*
* MAILDIR environment variable for Qmail
*/
if ((cp=getdef_str("QMAIL_DIR")))
addenv_path("MAILDIR", info->pw_dir, cp);
/*
* Create the MAIL environmental variable and export it. login.defs
* knows the prefix.
*/
if ((cp=getdef_str("MAIL_DIR")))
addenv_path("MAIL", cp, info->pw_name);
else if ((cp=getdef_str("MAIL_FILE")))
addenv_path("MAIL", info->pw_dir, cp);
else {
#if defined(MAIL_SPOOL_FILE)
addenv_path("MAIL", info->pw_dir, MAIL_SPOOL_FILE);
#elif defined(MAIL_SPOOL_DIR)
addenv_path("MAIL", MAIL_SPOOL_DIR, info->pw_name);
#endif
}
/*
* Read environment from optional config file. --marekm
*/
if ((envf = getdef_str("ENVIRON_FILE")))
read_env_file(envf);
}

126
libmisc/shell.c Normal file
View File

@@ -0,0 +1,126 @@
/*
* Copyright 1989 - 1991, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: shell.c,v 1.7 1998/12/28 20:34:53 marekm Exp $")
#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. The first attempt is to just execute the named
* file. If the errno comes back "ENOEXEC", the file is assumed
* at first glance to be a shell script. The first two characters
* must be "#!", in which case "/bin/sh" is executed to process
* the file. If all that fails, give up in disgust ...
*/
void
shell(const char *file, const char *arg)
{
char arg0[1024];
int err;
if (file == (char *) 0)
exit (1);
/*
* 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) {
snprintf(arg0, sizeof arg0, "-%s", Basename((char *) file));
arg = arg0;
}
#ifdef DEBUG
printf (_("Executing shell %s\n"), file);
#endif
/*
* First we try the direct approach. The system should be
* able to figure out what we are up to without too much
* grief.
*/
execle (file, arg, (char *) 0, newenvp);
err = errno;
/* Linux handles #! in the kernel, and bash doesn't make
sense of "#!" so it wouldn't work anyway... --marekm */
#ifndef __linux__
/*
* It is perfectly OK to have a shell script for a login
* shell, and this code attempts to support that. It
* relies on the standard shell being able to make sense
* of the "#!" magic number.
*/
if (err == ENOEXEC) {
FILE *fp;
if ((fp = fopen (file, "r"))) {
if (getc (fp) == '#' && getc (fp) == '!') {
fclose (fp);
execle ("/bin/sh", "sh",
file, (char *) 0, newenvp);
err = errno;
} else {
fclose (fp);
}
}
}
#endif
/*
* 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 ...
*/
snprintf(arg0, sizeof arg0, _("Cannot execute %s"), file);
errno = err;
perror(arg0);
exit(1);
}

207
libmisc/strtoday.c Normal file
View File

@@ -0,0 +1,207 @@
/*
* Copyright 1991 - 1994, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: strtoday.c,v 1.8 1999/03/07 19:14:42 marekm Exp $")
#include "defines.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;
/*
* 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 (!str || *str == '\0')
return -1;
t = get_date(str, (time_t *) 0);
if (t == (time_t) -1)
return -1;
/* convert seconds to days since 1970-01-01 */
return (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 (!cp || *cp != '\0')
continue;
result = mktime(&tp);
if (result == (time_t) -1)
continue;
return 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 ((month != 2 || (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 */

201
libmisc/suauth.c Normal file
View File

@@ -0,0 +1,201 @@
#include <config.h>
#ifdef SU_ACCESS
#include <stdio.h>
#include <pwd.h>
#include <grp.h>
#include <sys/types.h>
#include <errno.h>
#include "prototypes.h"
#include "defines.h"
#ifndef SUAUTHFILE
#define SUAUTHFILE "/etc/suauth"
#endif
#define NOACTION 0
#define NOPWORD 1
#define DENY -1
#define OWNPWORD 2
/* Really, I could do with a few const char's here defining all the
* strings output to the user or the syslog. -- chris
*/
static int applies P_((const char *, char *));
int check_su_auth P_((const char *, const char *));
int isgrp P_((const char *, const char *));
static int lines = 0;
extern struct passwd pwent;
int
check_su_auth(const char *actual_id, const char *wanted_id)
{
int posn, endline;
const char field[] = ":";
FILE *authfile_fd;
char temp[1024];
char *to_users;
char *from_users;
char *action;
if (!(authfile_fd = fopen(SUAUTHFILE, "r"))) {
/*
* If the file doesn't exist - default to the standard su
* behaviour (no access control). If open fails for some
* other reason - maybe someone is trying to fool us with
* file descriptors limit etc., so deny access. --marekm
*/
if (errno == ENOENT)
return NOACTION;
SYSLOG((LOG_ERR, "could not open/read config file '%s': %m\n",
SUAUTHFILE));
return DENY;
}
while (fgets(temp, sizeof(temp), authfile_fd) != NULL) {
lines++;
if (temp[endline = strlen(temp) - 1] != '\n') {
SYSLOG((LOG_ERR,
"%s, line %d: line too long or missing newline",
SUAUTHFILE, lines));
continue;
}
while (endline > 0 && (temp[endline-1] == ' '
|| temp[endline-1] == '\t' || temp[endline-1] == '\n'))
endline--;
temp[endline] = '\0';
posn = 0;
while (temp[posn] == ' ' || temp[posn] == '\t')
posn++;
if (temp[posn] == '\n' || temp[posn] == '#' || temp[posn] == '\0') {
continue;
}
if (!(to_users = strtok(temp + posn, field))
|| !(from_users = strtok((char *)NULL, field))
|| !(action = strtok((char *)NULL, field))
|| strtok((char *)NULL, field)) {
SYSLOG((LOG_ERR, "%s, line %d. Bad number of fields.\n",
SUAUTHFILE, lines));
continue;
}
if (!applies(wanted_id, to_users))
continue;
if (!applies(actual_id, from_users))
continue;
if (!strcmp(action, "DENY")) {
SYSLOG((pwent.pw_uid ? LOG_NOTICE : LOG_WARN,
"DENIED su from `%s' to `%s' (%s)\n",
actual_id, wanted_id, SUAUTHFILE));
fprintf(stderr, _("Access to su to that account DENIED.\n"));
fclose(authfile_fd);
return DENY;
} else if (!strcmp(action, "NOPASS")) {
SYSLOG((pwent.pw_uid ? LOG_INFO : LOG_NOTICE,
"NO password asked for su from `%s' to `%s' (%s)\n",
actual_id, wanted_id, SUAUTHFILE));
fprintf(stderr, _("Password authentication bypassed.\n"));
fclose(authfile_fd);
return NOPWORD;
} else if (!strcmp(action, "OWNPASS")) {
SYSLOG((pwent.pw_uid ? LOG_INFO : LOG_NOTICE,
"su from `%s' to `%s': asking for user's own password (%s)\n",
actual_id, wanted_id, SUAUTHFILE));
fprintf(stderr, _("Please enter your OWN password as authentication.\n"));
fclose(authfile_fd);
return OWNPWORD;
} else {
SYSLOG((LOG_ERR, "%s, line %d: unrecognised action!\n",
SUAUTHFILE, lines));
}
}
fclose(authfile_fd);
return NOACTION;
}
static int
applies(const char *single, char *list)
{
const char split[] = ", ";
char *tok;
int state = 0;
for (tok = strtok(list, split); tok != NULL; tok = strtok(NULL, split)) {
if (!strcmp(tok, "ALL")) {
if (state != 0) {
SYSLOG((LOG_ERR,
"%s, line %d: ALL in bad place\n",
SUAUTHFILE, lines));
return 0;
}
state = 1;
} else if (!strcmp(tok, "EXCEPT")) {
if (state != 1) {
SYSLOG((LOG_ERR,
"%s, line %d: EXCEPT in bas place\n",
SUAUTHFILE, lines));
return 0;
}
state = 2;
} else if (!strcmp(tok, "GROUP")) {
if ((state != 0) && (state != 2)) {
SYSLOG((LOG_ERR,
"%s, line %d: GROUP in bad place\n",
SUAUTHFILE, lines));
return 0;
}
state = (state == 0) ? 3 : 4;
} else {
switch (state) {
case 0: /* No control words yet */
if (!strcmp(tok, single))
return 1;
break;
case 1: /* An all */
SYSLOG((LOG_ERR, "%s, line %d: expect another token after ALL\n",
SUAUTHFILE, lines));
return 0;
case 2: /* All except */
if (!strcmp(tok, single))
return 0;
break;
case 3: /* Group */
if (isgrp(single, tok))
return 1;
break;
case 4: /* All except group */
if (isgrp(single, tok))
return 0;
/* FALL THRU */
}
}
}
if ((state != 0) && (state != 3))
return 1;
return 0;
}
int
isgrp(const char *name, const char *group)
{
struct group *grp;
grp = getgrnam(group);
if (!grp || !grp->gr_mem)
return 0;
return is_on_list(grp->gr_mem, name);
}
#endif /* SU_ACCESS */

78
libmisc/sub.c Normal file
View File

@@ -0,0 +1,78 @@
/*
* Copyright 1989 - 1991, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: sub.c,v 1.6 1999/03/07 19:14:43 marekm Exp $")
#include <sys/types.h>
#include "prototypes.h"
#include "defines.h"
#include <pwd.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 (1);
}
/*
* The directory must be accessible and the current process
* must be able to change into it.
*/
if (chdir (pw->pw_dir) || chroot (pw->pw_dir)) {
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 (1);
}
}

77
libmisc/sulog.c Normal file
View File

@@ -0,0 +1,77 @@
/*
* Copyright 1989 - 1992, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: sulog.c,v 1.4 1998/04/02 21:51:51 marekm Exp $")
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <time.h>
#include "defines.h"
#include "getdef.h"
extern char name[];
extern char oldname[];
extern struct tm *localtime ();
/*
* sulog - log a SU command execution result
*/
void
sulog(const char *tty, int success)
{
char *sulog_file;
time_t now;
struct tm *tm;
FILE *fp;
mode_t oldmask;
if ((sulog_file = getdef_str("SULOG_FILE")) == (char *) 0)
return;
oldmask = umask(077);
fp = fopen(sulog_file, "a+");
umask(oldmask);
if (fp == (FILE *) 0)
return; /* can't open or create logfile */
time(&now);
tm = localtime(&now);
fprintf(fp, "SU %.02d/%.02d %.02d:%.02d %c %.6s %s-%s\n",
tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
success ? '+':'-', tty, oldname, name);
fflush(fp);
fclose(fp);
}

89
libmisc/ttytype.c Normal file
View File

@@ -0,0 +1,89 @@
/*
* Copyright 1989 - 1994, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: ttytype.c,v 1.5 1997/12/07 23:27:10 marekm Exp $")
#include <stdio.h>
#include "prototypes.h"
#include "defines.h"
#include "getdef.h"
extern char *getenv();
/*
* ttytype - set ttytype from port to terminal type mapping database
*/
void
ttytype(const char *line)
{
FILE *fp;
char buf[BUFSIZ];
char *typefile;
char *cp;
char type[BUFSIZ];
char port[BUFSIZ];
if (getenv ("TERM"))
return;
if ((typefile=getdef_str("TTYTYPE_FILE")) == NULL )
return;
if (access(typefile, F_OK))
return;
if (! (fp = fopen (typefile, "r"))) {
perror (typefile);
return;
}
while (fgets(buf, sizeof buf, fp)) {
if (buf[0] == '#')
continue;
if ((cp = strchr (buf, '\n')))
*cp = '\0';
#if defined(SUN) || defined(BSD) || defined(SUN4)
if ((sscanf (buf, "%s \"%*[^\"]\" %s", port, type) == 2 ||
sscanf (buf, "%s %*s %s", port, type) == 2) &&
strcmp (line, port) == 0)
break;
#else /* USG */
if (sscanf (buf, "%s %s", type, port) == 2 &&
strcmp (line, port) == 0)
break;
#endif
}
if (! feof (fp) && ! ferror (fp))
addenv("TERM", type);
fclose (fp);
}

67
libmisc/tz.c Normal file
View File

@@ -0,0 +1,67 @@
/*
* Copyright 1991 - 1994, Julianne Frances Haugh and Chip Rosenthal
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: tz.c,v 1.4 1998/01/29 23:22:36 marekm Exp $")
#include <stdio.h>
#include <string.h>
#include "defines.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''.
*/
char *
tz(const char *fname)
{
FILE *fp = 0;
static char tzbuf[BUFSIZ];
const char *def_tz;
if ((fp = fopen(fname,"r")) == NULL ||
fgets (tzbuf, sizeof (tzbuf), fp) == NULL) {
if (! (def_tz = getdef_str ("ENV_TZ")) || def_tz[0] == '/')
def_tz = "TZ=CST6CDT";
strcpy (tzbuf, def_tz);
} else
tzbuf[strlen(tzbuf) - 1] = '\0';
if (fp)
(void) fclose(fp);
return tzbuf;
}

34
libmisc/ulimit.c Normal file
View File

@@ -0,0 +1,34 @@
#include <config.h>
#include "rcsid.h"
RCSID("$Id: ulimit.c,v 1.2 1997/12/07 23:27:11 marekm Exp $")
#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
void
set_filesize_limit(int blocks)
{
#if HAVE_ULIMIT_H
ulimit(UL_SETFSIZE, blocks);
#elif defined(RLIMIT_FSIZE)
struct rlimit rlimit_fsize;
rlimit_fsize.rlim_cur = rlimit_fsize.rlim_max = 512L * blocks;
setrlimit(RLIMIT_FSIZE, &rlimit_fsize);
#endif
}

478
libmisc/utmp.c Normal file
View File

@@ -0,0 +1,478 @@
/*
* Copyright 1989 - 1994, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 <utmp.h>
#if HAVE_UTMPX_H
#include <utmpx.h>
#endif
#include <fcntl.h>
#include <stdio.h>
#include "rcsid.h"
RCSID("$Id: utmp.c,v 1.8 1999/06/07 16:40:44 marekm Exp $")
#if HAVE_UTMPX_H
extern struct utmpx utxent;
#endif
extern struct utmp utent;
extern struct utmp *getutent();
extern struct utmp *getutline();
extern void setutent();
extern void endutent();
extern time_t time();
extern char *ttyname();
extern long lseek();
#define NO_UTENT \
"No utmp entry. You must exec \"login\" from the lowest level \"sh\""
#define NO_TTY \
"Unable to determine your tty name."
/*
* checkutmp - see if utmp file is correct for this process
*
* System V is very picky about the contents of the utmp file
* and requires that a slot for the current process exist.
* The utmp file is scanned for an entry with the same process
* ID. If no entry exists the process exits with a message.
*
* The "picky" flag is for network and other logins that may
* use special flags. It allows the pid checks to be overridden.
* This means that getty should never invoke login with any
* command line flags.
*/
#if defined(__linux__) /* XXX */
void
checkutmp(int picky)
{
char *line;
struct utmp *ut;
pid_t pid = getpid();
setutent();
/* First, try to find a valid utmp entry for this process. */
while ((ut = getutent()))
if (ut->ut_pid == pid && ut->ut_line[0] && ut->ut_id[0] &&
(ut->ut_type==LOGIN_PROCESS || ut->ut_type==USER_PROCESS))
break;
/* If there is one, just use it, otherwise create a new one. */
if (ut) {
utent = *ut;
} else {
if (picky) {
puts(NO_UTENT);
exit(1);
}
line = ttyname(0);
if (!line) {
puts(NO_TTY);
exit(1);
}
if (strncmp(line, "/dev/", 5) == 0)
line += 5;
memset((void *) &utent, 0, sizeof utent);
utent.ut_type = LOGIN_PROCESS;
utent.ut_pid = pid;
strncpy(utent.ut_line, line, sizeof utent.ut_line);
/* XXX - assumes /dev/tty?? */
strncpy(utent.ut_id, utent.ut_line + 3, sizeof utent.ut_id);
strcpy(utent.ut_user, "LOGIN");
time(&utent.ut_time);
}
}
#elif defined(LOGIN_PROCESS)
void
checkutmp(int picky)
{
char *line;
struct utmp *ut;
#if HAVE_UTMPX_H
struct utmpx *utx;
#endif
pid_t pid = getpid();
#if HAVE_UTMPX_H
setutxent();
#endif
setutent();
if (picky) {
#if HAVE_UTMPX_H
while ((utx = getutxent()))
if (utx->ut_pid == pid)
break;
if (utx)
utxent = *utx;
#endif
while ((ut = getutent()))
if (ut->ut_pid == pid)
break;
if (ut)
utent = *ut;
#if HAVE_UTMPX_H
endutxent();
#endif
endutent();
if (!ut) {
puts(NO_UTENT);
exit(1);
}
#ifndef UNIXPC
/*
* If there is no ut_line value in this record, fill
* it in by getting the TTY name and stuffing it in
* the structure. The UNIX/PC is broken in this regard
* and needs help ...
*/
if (utent.ut_line[0] == '\0')
#endif /* !UNIXPC */
{
if (!(line = ttyname(0))) {
puts(NO_TTY);
exit(1);
}
if (strncmp(line, "/dev/", 5) == 0)
line += 5;
strncpy(utent.ut_line, line, sizeof utent.ut_line);
#if HAVE_UTMPX_H
strncpy(utxent.ut_line, line, sizeof utxent.ut_line);
#endif
}
} else {
if (!(line = ttyname(0))) {
puts(NO_TTY);
exit(1);
}
if (strncmp(line, "/dev/", 5) == 0)
line += 5;
strncpy (utent.ut_line, line, sizeof utent.ut_line);
if ((ut = getutline(&utent)))
strncpy(utent.ut_id, ut->ut_id, sizeof ut->ut_id);
strcpy(utent.ut_user, "LOGIN");
utent.ut_pid = getpid();
utent.ut_type = LOGIN_PROCESS;
time(&utent.ut_time);
#if HAVE_UTMPX_H
strncpy(utxent.ut_line, line, sizeof utxent.ut_line);
if ((utx = getutxline(&utxent)))
strncpy(utxent.ut_id, utx->ut_id, sizeof utxent.ut_id);
strcpy(utxent.ut_user, "LOGIN");
utxent.ut_pid = utent.ut_pid;
utxent.ut_type = utent.ut_type;
gettimeofday((struct timeval *) &utxent.ut_tv, NULL);
utent.ut_time = utxent.ut_tv.tv_sec;
#endif
}
}
#else /* !USG */
void
checkutmp(int picky)
{
char *line;
/*
* Hand-craft a new utmp entry.
*/
memzero(&utent, sizeof utent);
if (! (line = ttyname (0))) {
puts (NO_TTY);
exit (1);
}
if (strncmp (line, "/dev/", 5) == 0)
line += 5;
(void) strncpy (utent.ut_line, line, sizeof utent.ut_line);
(void) time (&utent.ut_time);
}
#endif /* !USG */
/*
* Some systems already have updwtmp() and possibly updwtmpx(). Others
* don't, so we re-implement these functions if necessary. --marekm
*/
#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 HAVE_UTMPX_H
#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 /* ! HAVE_UTMPX_H */
/*
* setutmp - put a USER_PROCESS entry in the utmp file
*
* setutmp changes the type of the current utmp entry to
* USER_PROCESS. the wtmp file will be updated as well.
*/
#if defined(__linux__) /* XXX */
void
setutmp(const char *name, const char *line, const char *host)
{
utent.ut_type = USER_PROCESS;
strncpy(utent.ut_user, name, sizeof utent.ut_user);
time(&utent.ut_time);
/* other fields already filled in by checkutmp above */
setutent();
pututline(&utent);
endutent();
updwtmp(_WTMP_FILE, &utent);
}
#elif HAVE_UTMPX_H
void
setutmp(const char *name, const char *line, const char *host)
{
struct utmp *utmp, utline;
struct utmpx *utmpx, utxline;
pid_t pid = getpid ();
int found_utmpx = 0, found_utmp = 0;
/*
* The canonical device name doesn't include "/dev/"; skip it
* if it is already there.
*/
if (strncmp (line, "/dev/", 5) == 0)
line += 5;
/*
* Update utmpx. We create an empty entry in case there is
* no matching entry in the utmpx file.
*/
setutxent ();
setutent ();
while (utmpx = getutxent ()) {
if (utmpx->ut_pid == pid) {
found_utmpx = 1;
break;
}
}
while (utmp = getutent ()) {
if (utmp->ut_pid == pid) {
found_utmp = 1;
break;
}
}
/*
* If the entry matching `pid' cannot be found, create a new
* entry with the device name in it.
*/
if (! found_utmpx) {
memset ((void *) &utxline, 0, sizeof utxline);
strncpy (utxline.ut_line, line, sizeof utxline.ut_line);
utxline.ut_pid = getpid ();
} else {
utxline = *utmpx;
if (strncmp (utxline.ut_line, "/dev/", 5) == 0) {
memmove (utxline.ut_line, utxline.ut_line + 5,
sizeof utxline.ut_line - 5);
utxline.ut_line[sizeof utxline.ut_line - 5] = '\0';
}
}
if (! found_utmp) {
memset ((void *) &utline, 0, sizeof utline);
strncpy (utline.ut_line, utxline.ut_line,
sizeof utline.ut_line);
utline.ut_pid = utxline.ut_pid;
} else {
utline = *utmp;
if (strncmp (utline.ut_line, "/dev/", 5) == 0) {
memmove (utline.ut_line, utline.ut_line + 5,
sizeof utline.ut_line - 5);
utline.ut_line[sizeof utline.ut_line - 5] = '\0';
}
}
/*
* Fill in the fields in the utmpx entry and write it out. Do
* the utmp entry at the same time to make sure things don't
* get messed up.
*/
strncpy (utxline.ut_user, name, sizeof utxline.ut_user);
strncpy (utline.ut_user, name, sizeof utline.ut_user);
utline.ut_type = utxline.ut_type = USER_PROCESS;
gettimeofday(&utxline.ut_tv, NULL);
utline.ut_time = utxline.ut_tv.tv_sec;
strncpy(utxline.ut_host, host ? host : "", sizeof utxline.ut_host);
pututxline (&utxline);
pututline (&utline);
updwtmpx(_WTMP_FILE "x", &utxline);
updwtmp(_WTMP_FILE, &utline);
utxent = utxline;
utent = utline;
}
#else /* !SVR4 */
void
setutmp(const char *name, const char *line)
{
struct utmp utmp;
int fd;
int found = 0;
if ((fd = open(_UTMP_FILE, O_RDWR)) < 0)
return;
#if !defined(SUN) && !defined(BSD) && !defined(SUN4) /* XXX */
while (!found && read(fd, (char *)&utmp, sizeof utmp) == sizeof utmp) {
if (! strncmp (line, utmp.ut_line, (int) sizeof utmp.ut_line))
found++;
}
#endif
if (! found) {
/*
* This is a brand-new entry. Clear it out and fill it in
* later.
*/
memzero(&utmp, sizeof utmp);
strncpy(utmp.ut_line, line, (int) sizeof utmp.ut_line);
}
/*
* Fill in the parts of the UTMP entry. BSD has just the name,
* while System V has the name, PID and a type.
*/
strncpy(utmp.ut_user, name, sizeof utent.ut_user);
#ifdef USER_PROCESS
utmp.ut_type = USER_PROCESS;
utmp.ut_pid = getpid ();
#endif
/*
* Put in the current time (common to everyone)
*/
(void) time (&utmp.ut_time);
#ifdef UT_HOST
/*
* Update the host name field for systems with networking support
*/
(void) strncpy (utmp.ut_host, utent.ut_host, (int) sizeof utmp.ut_host);
#endif
/*
* Locate the correct position in the UTMP file for this
* entry.
*/
#ifdef HAVE_TTYSLOT
(void) lseek (fd, (off_t) (sizeof utmp) * ttyslot (), SEEK_SET);
#else
if (found) /* Back up a splot */
lseek (fd, (off_t) - sizeof utmp, SEEK_CUR);
else /* Otherwise, go to the end of the file */
lseek (fd, (off_t) 0, SEEK_END);
#endif
/*
* Scribble out the new entry and close the file. We're done
* with UTMP, next we do WTMP (which is real easy, put it on
* the end of the file.
*/
(void) write (fd, (char *) &utmp, sizeof utmp);
(void) close (fd);
updwtmp(_WTMP_FILE, &utmp);
utent = utmp;
}
#endif /* SVR4 */

101
libmisc/valid.c Normal file
View File

@@ -0,0 +1,101 @@
/*
* Copyright 1989 - 1993, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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 "rcsid.h"
RCSID("$Id: valid.c,v 1.4 1999/03/07 19:14:44 marekm Exp $")
#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.
*/
int
valid(const char *password, const struct passwd *ent)
{
const char *encrypted;
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 (ent->pw_name && ! ent->pw_passwd[0]) {
if (! password[0])
return (1); /* user entered nothing */
else
return (0); /* user entered something! */
}
/*
* If there is no entry then we need a salt to use.
*/
if (ent->pw_name == (char *) 0 || ent->pw_passwd[0] == '\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 (ent->pw_name && strcmp(encrypted, ent->pw_passwd) == 0)
return (1);
else
return (0);
}

38
libmisc/xmalloc.c Normal file
View File

@@ -0,0 +1,38 @@
/* 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>
#include "rcsid.h"
RCSID("$Id: xmalloc.c,v 1.3 1998/12/28 20:34:56 marekm Exp $")
#include <stdio.h>
#include "defines.h"
extern char *malloc();
char *
xmalloc(size_t size)
{
char *ptr;
ptr = malloc(size);
if (!ptr && size) {
fprintf(stderr, _("malloc(%d) failed\n"), (int) size);
exit(13);
}
return ptr;
}
char *
xstrdup(const char *str)
{
return strcpy(xmalloc(strlen(str) + 1), str);
}