diff options
Diffstat (limited to 'contrib/libpam/modules')
121 files changed, 6959 insertions, 4594 deletions
diff --git a/contrib/libpam/modules/Makefile b/contrib/libpam/modules/Makefile index 0066fb473e0c..aece2068904c 100644 --- a/contrib/libpam/modules/Makefile +++ b/contrib/libpam/modules/Makefile @@ -1,89 +1,17 @@ -# $Id: Makefile,v 1.21 1997/04/05 06:44:43 morgan Exp morgan $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ # # Makefile # # This makefile controls the build process of shared and static PAM modules. # -# $Log: Makefile,v $ -# Revision 1.21 1997/04/05 06:44:43 morgan -# pam_env and pam_tally added -# -# Revision 1.20 1997/02/15 18:57:11 morgan -# fixed bash syntax -# -# Revision 1.19 1997/01/04 20:21:32 morgan -# moved responsibility of conditional compilation to modules (more flexible) -# -# Revision 1.18 1996/12/01 03:34:40 morgan -# update for .54 -# -# Revision 1.17 1996/11/10 20:20:15 morgan -# cross platform support and new modules -# -# Revision 1.16 1996/09/05 06:20:45 morgan -# added two modules: listfile and shells -# -# Revision 1.15 1996/08/09 05:38:28 morgan -# added new/proposed modules. -# fixed makefile installation dependencies -# -# Revision 1.14 1996/07/08 00:00:33 morgan -# added wheel and group modules # -MODDIRS=\ - pam_access \ - pam_afs \ - pam_afsauth \ - pam_afspass \ - pam_afstok \ - pam_cracklib \ - pam_deny \ - pam_desgold \ - pam_env \ - pam_filter \ - pam_ftp \ - pam_group \ - pam_kerberos \ - pam_krb4 \ - pam_lastlog \ - pam_listfile \ - pam_limits \ - pam_mail \ - pam_nologin \ - pam_opie \ - pam_passwd+ \ - pam_permit \ - pam_pwdb \ - pam_radius \ - pam_restrict \ - pam_rhosts \ - pam_rootok \ - pam_securetty \ - pam_shells \ - pam_sid \ - pam_skey \ - pam_skey2 \ - pam_stress \ - pam_syslog \ - pam_tally \ - pam_time \ - pam_unix \ - pam_warn \ - pam_wheel +include ../Make.Rules - -# //////////////////////////////////////////////////// -# // You should not modify anything below this line // -# //////////////////////////////////////////////////// - -dummy: - @echo "*** This is not a top-level Makefile! ***" - -# ----------------------------------------------------------- +MODDIRS=$(shell /bin/ls -d pam_*) all: - @echo modules for $(OS) are: + @echo modules sources available are: @ls -d $(MODDIRS) 2>/dev/null ; echo :-------- @echo ifdef STATIC @@ -98,6 +26,9 @@ endif } fi ; \ done +download: + @./download-all + install: for i in $(MODDIRS) ; do \ if [ -d $$i ]; then { \ @@ -123,10 +54,3 @@ clean: lclean } fi ; \ done -extraclean: lclean - for i in $(MODDIRS) ; do \ - if [ -d $$i ]; then \ - $(MAKE) -C $$i extraclean ; \ - fi ; \ - done - diff --git a/contrib/libpam/modules/README b/contrib/libpam/modules/README index 864159478c65..73d3cf0c2e49 100644 --- a/contrib/libpam/modules/README +++ b/contrib/libpam/modules/README @@ -1,7 +1,7 @@ This directory contains the modules. If you want to reserve a module name please email <pam-list@redhat.com> -and announce its name. Andrew Morgan, <morgan@parc.power.net>, will +and announce its name. Andrew Morgan, <morgan@linux.kernel.org>, will add it to the Makefile in the next release of Linux-PAM. As of Linux-PAM-0.40 modules can optionally conform to the static diff --git a/contrib/libpam/modules/Simple.Rules b/contrib/libpam/modules/Simple.Rules new file mode 100644 index 000000000000..954641c668a3 --- /dev/null +++ b/contrib/libpam/modules/Simple.Rules @@ -0,0 +1,92 @@ +# $Id: Simple.Rules,v 1.3 2001/02/22 04:55:41 agmorgan Exp $ +# +# For simple modules with no significant dependencies, set $(TITLE) +# and include this file. +# +# There are a few ways to customize this set of rules. Namely, define +# +# $(MODULE_SIMPLE_EXTRACLEAN) +# $(MODULE_SIMPLE_CLEAN) +# $(MODULE_SIMPLE_REMOVE) +# $(MODULE_SIMPLE_INSTALL) +# $(MODULE_SIMPLE_EXTRALIBS) - other things to link with the module +# $(MODULE_SIMPLE_EXTRAFILES) - other files to build (no .c suffix) +# + +LIBFILES = $(TITLE) $(MODULE_SIMPLE_EXTRAFILES) +LIBSRC = $(addsuffix .c,$(LIBFILES)) +LIBOBJ = $(addsuffix .o,$(LIBFILES)) +LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) +LIBOBJS = $(addprefix static/,$(LIBOBJ)) + +ifdef DYNAMIC +LIBSHARED = $(TITLE).so +endif + +ifdef STATIC +LIBSTATIC = lib$(TITLE).o +endif + +####################### don't edit below ####################### + +all: dirs $(LIBSHARED) $(LIBSTATIC) register + +dynamic/%.o : %.c + $(CC) $(CFLAGS) $(DYNAMIC) $(TARGET_ARCH) -c $< -o $@ + +static/%.o : %.c + $(CC) $(CFLAGS) $(STATIC) $(TARGET_ARCH) -c $< -o $@ + +dirs: +ifdef DYNAMIC + $(MKDIR) ./dynamic +endif +ifdef STATIC + $(MKDIR) ./static +endif + +register: +ifdef STATIC + ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) +endif + +ifdef DYNAMIC +$(LIBOBJD): $(LIBSRC) +endif + +ifdef DYNAMIC +$(LIBSHARED): $(LIBOBJD) + $(LD_D) -o $@ $(LIBOBJD) $(MODULE_SIMPLE_EXTRALIBS) $(NEED_LINK_LIB_C) + +endif + +ifdef STATIC +$(LIBOBJS): $(LIBSRC) +endif + +ifdef STATIC +$(LIBSTATIC): $(LIBOBJS) + $(LD) -r -o $@ $(LIBOBJS) $(MODULE_SIMPLE_EXTRALIBS) +endif + +install: all + $(MKDIR) $(FAKEROOT)$(SECUREDIR) +ifdef DYNAMIC + $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) +endif + $(MODULE_SIMPLE_INSTALL) + +remove: + rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so + $(MODULE_SIMPLE_REMOVE) + +clean: + rm -f $(LIBOBJD) $(LIBOBJS) core *~ + $(MODULE_SIMPLE_CLEAN) + rm -f *.a *.o *.so *.bak + rm -rf dynamic static + $(MODULE_SIMPLE_EXTRACLEAN) + +.c.o: + $(CC) $(CFLAGS) -c $< + diff --git a/contrib/libpam/modules/dont_makefile b/contrib/libpam/modules/dont_makefile index f256ce1b3a61..48307f02ecd4 100644 --- a/contrib/libpam/modules/dont_makefile +++ b/contrib/libpam/modules/dont_makefile @@ -1,4 +1,6 @@ ######################################################################### +# $Id: dont_makefile,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ +######################################################################### # This is a makefile that does nothing. It is designed to be included # by module Makefile-s when they are not compatable with the local # system @@ -7,7 +9,7 @@ all: @echo "This module will not be compiled on this system" -extraclean: clean +remove: clean install: clean diff --git a/contrib/libpam/modules/download-all b/contrib/libpam/modules/download-all new file mode 100755 index 000000000000..9b6cf6558136 --- /dev/null +++ b/contrib/libpam/modules/download-all @@ -0,0 +1,30 @@ +#!/bin/sh +# +# $Id: download-all,v 1.1.1.1 2000/06/20 22:11:29 agmorgan Exp $ +# +cat <<EOT +For a number of reasons it is not practical for Linux-PAM to be +distributed with every module out there. However, this shell script +is intended as a convenient way for users to download modules from the +'net in some semiautomated fashion. + +Please feel free to send (pam-list@redhat.com) snippets of code that +will help others to download and unpack your favorite module into the +Linux-PAM source tree. Especially welcome are snippets of the +following form: + +ncftp ftp://my.ftpsite.org/pub/fluff/pam_fluff.tar.gz +rm -fr pam_fluff +tar zvfx pam_fluff.tar.gz + +Cheers + +Andrew +morgan@linux.kernel.org +EOT + +# --- insert your snippets below --- + +# --- insert your snippets above --- + +exit 0 diff --git a/contrib/libpam/modules/install_conf b/contrib/libpam/modules/install_conf new file mode 100755 index 000000000000..80f6be292d19 --- /dev/null +++ b/contrib/libpam/modules/install_conf @@ -0,0 +1,49 @@ +#!/bin/bash + +FAKEROOT=$1 +CONFD=$1$2 +CONFILE=$1$3 +MODULE=$4 +CONF=$5 + +IGNORE_AGE=./.ignore_age +QUIET_INSTALL=../../.quiet_install + +echo + +if [ -f "$QUIET_INSTALL" ]; then + if [ ! -f "$CONFILE" ]; then + yes="y" + else + yes="skip" + fi +elif [ -f "$IGNORE_AGE" ]; then + echo "you don't want to be bothered with the age of your $CONFILE file" + yes="n" +elif [ ! -f "$CONFILE" ] || [ "$CONF" -nt "$CONFILE" ]; then + if [ -f "$CONFILE" ]; then + echo "An older $MODULE configuration file already exists ($CONFILE)" + echo "Do you wish to copy the $CONF file in this distribution" + echo "to $CONFILE ? (y/n) [skip] " + read yes + else + yes="y" + fi +else + yes="skip" +fi + +if [ "$yes" = "y" ]; then + mkdir -p $CONFD + echo " copying $CONF to $CONFILE" + cp $CONF $CONFILE +else + echo " Skipping $CONF installation" + if [ "$yes" = "n" ]; then + touch "$IGNORE_AGE" + fi +fi + +echo + +exit 0 diff --git a/contrib/libpam/modules/pam_access/Makefile b/contrib/libpam/modules/pam_access/Makefile index a3d684bb7179..88c02fee7b54 100644 --- a/contrib/libpam/modules/pam_access/Makefile +++ b/contrib/libpam/modules/pam_access/Makefile @@ -1,111 +1,21 @@ -# $Id: Makefile,v 1.1 1997/06/23 00:39:42 morgan Exp morgan $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.1 1997/06/23 00:39:42 morgan -# Initial revision -# -# - -TITLE=pam_access -CONFD=$(CONFIGED)/security -export CONFD -CONFILE=$(CONFD)/access.conf -export CONFILE - -# Convenient defaults for compiling independently of the full source -# tree. -ifndef FULL_LINUX_PAM_SOURCE_TREE -export DYNAMIC=-DPAM_DYNAMIC -export CC=gcc -export CFLAGS=-O2 -Dlinux -DLINUX_PAM \ - -ansi -D_POSIX_SOURCE -Wall -Wwrite-strings \ - -Wpointer-arith -Wcast-qual -Wcast-align -Wtraditional \ - -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline \ - -Wshadow -pedantic -fPIC -export MKDIR=mkdir -p -export LD_D=gcc -shared -Xlinker -x -endif -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) +include ../../Make.Rules -DEFS=-DCONFILE=\"$(CONFILE)\" +TITLE=pam_access +LOCAL_CONFILE=./access.conf +INSTALLED_CONFILE=$(SCONFIGD)/access.conf +DEFS=-DDEFAULT_CONF_FILE=\"$(INSTALLED_CONFILE)\" CFLAGS += $(DEFS) -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - $(MKDIR) $(FAKEROOT)$(SCONFIGED) - bash -f ./install_conf - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - rm -f $(FAKEROOT)$(CONFILE) - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - rm -f ./.ignore_age - -extraclean: clean - rm -f *.a *.o *.so *.bak +MODULE_SIMPLE_INSTALL=bash -f ../install_conf "$(FAKEROOT)" "$(SCONFIGD)" "$(INSTALLED_CONFILE)" "$(TITLE)" "$(LOCAL_CONFILE)" +MODULE_SIMPLE_REMOVE=rm -f $(FAKEROOT)$(INSTALLED_CONFILE) +MODULE_SIMPLE_CLEAN=rm -f ./.ignore_age -.c.o: - $(CC) $(CFLAGS) -c $< +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_access/README b/contrib/libpam/modules/pam_access/README index df10c269ec04..ddd4725f0e04 100644 --- a/contrib/libpam/modules/pam_access/README +++ b/contrib/libpam/modules/pam_access/README @@ -1,4 +1,8 @@ -# Description of its configuration file (/etc/security/access.conf): +# Description of its configuration file +# +# (The default config file is "/etc/security/access.conf". This +# default can be overridden with a module config argument +# 'accessfile=<full-path>'): # # Login access control table. # diff --git a/contrib/libpam/modules/pam_access/pam_access.c b/contrib/libpam/modules/pam_access/pam_access.c index 121333928a26..87ad708d81ed 100644 --- a/contrib/libpam/modules/pam_access/pam_access.c +++ b/contrib/libpam/modules/pam_access/pam_access.c @@ -5,12 +5,27 @@ * (I took login_access from logdaemon-5.6 and converted it to PAM * using parts of pam_time code.) * + ************************************************************************ + * Copyright message from logdaemon-5.6 (original file name DISCLAIMER) + ************************************************************************ + * 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 linux -# define _GNU_SOURCE -# include <features.h> -#endif +#include <security/_pam_aconf.h> #include <stdio.h> #include <stdlib.h> @@ -46,21 +61,6 @@ extern int gethostname(char *name, size_t len); #include <security/_pam_macros.h> #include <security/pam_modules.h> -/* --- static functions for checking whether the user should be let in --- */ - -static void _log_err(const char *format, ... ) -{ - va_list args; - - va_start(args, format); - openlog("pam_access", LOG_CONS|LOG_PID, LOG_AUTH); - vsyslog(LOG_ERR, format, args); - va_end(args); - closelog(); -} - -#define PAM_ACCESS_CONFIG CONFILE - int strcasecmp(const char *s1, const char *s2); /* login_access.c from logdaemon-5.6 with several changes by A.Nogin: */ @@ -79,10 +79,16 @@ int strcasecmp(const char *s1, const char *s2); #define MAXHOSTNAMELEN 256 #endif +#ifdef DEFAULT_CONF_FILE +# define PAM_ACCESS_CONFIG DEFAULT_CONF_FILE +#else +# define PAM_ACCESS_CONFIG "/etc/security/access.conf" +#endif + /* Delimiters for fields and for lists of users, ttys or hosts. */ -static char fs[] = ":"; /* field separator */ -static char sep[] = ", \t"; /* list-element separator */ +static const char fs[] = ":"; /* field separator */ +static const char sep[] = ", \t"; /* list-element separator */ /* Constants to be used in assignments only, not in comparisons... */ @@ -96,8 +102,50 @@ static char sep[] = ", \t"; /* list-element separator */ struct login_info { struct passwd *user; char *from; + const char *config_file; + const char *service; }; +/* --- static functions for checking whether the user should be let in --- */ + +static void _log_err(const char *format, ... ) +{ + va_list args; + + va_start(args, format); + openlog("pam_access", LOG_CONS|LOG_PID, LOG_AUTH); + vsyslog(LOG_ERR, format, args); + va_end(args); + closelog(); +} + +/* Parse module config arguments */ + +static int parse_args(struct login_info *loginfo, int argc, const char **argv) +{ + int i; + + for (i=0; i<argc; ++i) { + if (!strncmp("accessfile=", argv[i], 11)) { + FILE *fp = fopen(11 + argv[i], "r"); + + if (fp) { + loginfo->config_file = 11 + argv[i]; + fclose(fp); + } else { + _log_err("for service [%s] failed to open accessfile=[%s]" + , loginfo->service, 11 + argv[i]); + return 0; + } + + } else { + _log_err("unrecognized option [%s]", argv[i]); + } + } + + return 1; /* OK */ +} + typedef int match_func (char *, struct login_info *); static int list_match (char *, struct login_info *, @@ -108,23 +156,16 @@ static int string_match (char *, char *); /* login_access - match username/group and host/tty with access control file */ -static int login_access(struct passwd *user, char *from) +static int login_access(struct login_info *item) { - struct login_info item; 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 */ + 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 */ - - /* - * Bundle up the arguments to avoid unnecessary clumsiness lateron. - */ - item.user = user; - item.from = from; + int lineno = 0; /* for diagnostics */ /* * Process the table one line at a time and stop at the first match. @@ -134,12 +175,12 @@ static int login_access(struct passwd *user, char *from) * non-existing table means no access control. */ - if ((fp = fopen(PAM_ACCESS_CONFIG, "r"))!=NULL) { + if ((fp = fopen(item->config_file, "r"))!=NULL) { while (!match && fgets(line, sizeof(line), fp)) { lineno++; if (line[end = strlen(line) - 1] != '\n') { _log_err("%s: line %d: missing newline or line too long", - PAM_ACCESS_CONFIG, lineno); + item->config_file, lineno); continue; } if (line[0] == '#') @@ -153,19 +194,21 @@ static int login_access(struct passwd *user, char *from) || !(users = strtok((char *) 0, fs)) || !(froms = strtok((char *) 0, fs)) || strtok((char *) 0, fs)) { - _log_err("%s: line %d: bad field count", PAM_ACCESS_CONFIG, lineno); + _log_err("%s: line %d: bad field count", + item->config_file, lineno); continue; } if (perm[0] != '+' && perm[0] != '-') { - _log_err("%s: line %d: bad first field", PAM_ACCESS_CONFIG, lineno); + _log_err("%s: line %d: bad first field", + item->config_file, lineno); continue; } - match = (list_match(froms, &item, from_match) - && list_match(users, &item, user_match)); + match = (list_match(froms, item, from_match) + && list_match(users, item, user_match)); } (void) fclose(fp); } else if (errno != ENOENT) { - _log_err("cannot open %s: %m", PAM_ACCESS_CONFIG); + _log_err("cannot open %s: %m", item->config_file); } return (match == 0 || (line[0] == '+')); } @@ -356,10 +399,17 @@ int strcasecmp(const char *s1, const char *s2) PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc ,const char **argv) { - const char *user=NULL; + struct login_info loginfo; + const char *user=NULL, *service=NULL; char *from=NULL; struct passwd *user_pw; + if ((pam_get_item(pamh, PAM_SERVICE, (const void **)&service) + != PAM_SUCCESS) || (service == NULL) || (*service == ' ')) { + _log_err("cannot find the service name"); + return PAM_ABORT; + } + /* set username */ if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS || user == NULL @@ -398,8 +448,27 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc } } + if ((user_pw=getpwnam(user))==NULL) return (PAM_USER_UNKNOWN); - if (login_access(user_pw,from)) return (PAM_SUCCESS); else { + + /* + * Bundle up the arguments to avoid unnecessary clumsiness later on. + */ + loginfo.user = user_pw; + loginfo.from = from; + loginfo.service = service; + loginfo.config_file = PAM_ACCESS_CONFIG; + + /* parse the argument list */ + + if (!parse_args(&loginfo, argc, argv)) { + _log_err("failed to parse the module arguments"); + return PAM_ABORT; + } + + if (login_access(&loginfo)) { + return (PAM_SUCCESS); + } else { _log_err("access denied for user `%s' from `%s'",user,from); return (PAM_PERM_DENIED); } diff --git a/contrib/libpam/modules/pam_cracklib/Makefile b/contrib/libpam/modules/pam_cracklib/Makefile index 668f2f846296..371ac0a86c3e 100644 --- a/contrib/libpam/modules/pam_cracklib/Makefile +++ b/contrib/libpam/modules/pam_cracklib/Makefile @@ -1,110 +1,32 @@ # +# $Id: Makefile,v 1.3 2001/02/10 22:15:23 agmorgan Exp $ +# # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# Created by Cristian Gafton <gafton@redhat.com> 1996/09/10 +# Created by Andrew Morgan <morgan@kernel.org> 2000/10/08 # -ifndef FULL_LINUX_PAM_SOURCE_TREE -# -# here you should make default variable defines... -# -MKDIR=mkdir -p -LD_D=gcc -shared -Xlinker -x -INSTALL=install -SECUREDIR=/usr/lib/security -# -HAVE_CRACKLIB=yes -endif - -ifeq ($(HAVE_CRACKLIB),yes) +include ../../Make.Rules TITLE=pam_cracklib -CRACKLIB=-lcrack -CRACKLIB_DICTPATH=/usr/lib/cracklib_dict -# -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) +ifeq ($(HAVE_LIBCRACK),yes) +BUILD_THIS_MODULE=yes +MODULE_SIMPLE_EXTRALIBS=-lcrack -ifdef CRACKLIB_DICTPATH +# These two should really be provided by ../../pam_aconf.h CFLAGS+=-DCRACKLIB_DICTPATH=\"$(CRACKLIB_DICTPATH)\" -endif - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) +ifeq ($(HAVE_LIBCRYPT),yes) + MODULE_SIMPLE_EXTRALIBS += -lcrypt endif -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) Makefile - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) $(CRACKLIB) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) endif -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ *.so - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< - +ifeq ($(BUILD_THIS_MODULE),yes) + include ../Simple.Rules else - -include ../dont_makefile - + include ../dont_makefile endif diff --git a/contrib/libpam/modules/pam_cracklib/README b/contrib/libpam/modules/pam_cracklib/README index e4b02731b523..69662f7385b3 100644 --- a/contrib/libpam/modules/pam_cracklib/README +++ b/contrib/libpam/modules/pam_cracklib/README @@ -13,9 +13,25 @@ RECOGNIZED ARGUMENTS: retry=N Prompt user at most N times before returning with error. Default N=1. + difok=N How many characters can be the same in the new + password relative to the old + difignore=N How many characters long should the password be + before we ignore difok. + + minlen=N The minimum simplicity count for a good password. + + dcredit=N + ucredit=N + lcredit=N + ocredit=N Weight, digits, upper, lower, other characters with + count N. Use these values to compute the + 'unsimplicity' of the password. + + use_authtok Get the proposed password from PAM_AUTHTOK + MODULE SERVICES PROVIDED: passwd chauthtok AUTHOR: - Cristian Gafton <gafton@sorosis.ro> + Cristian Gafton <gafton@redhat.com> diff --git a/contrib/libpam/modules/pam_cracklib/pam_cracklib.c b/contrib/libpam/modules/pam_cracklib/pam_cracklib.c index 3400dfb25209..07725db7ee7b 100644 --- a/contrib/libpam/modules/pam_cracklib/pam_cracklib.c +++ b/contrib/libpam/modules/pam_cracklib/pam_cracklib.c @@ -29,8 +29,12 @@ * S.A.G. in the section on the cracklib module. */ +#include <security/_pam_aconf.h> + #include <stdio.h> -#define __USE_BSD +#ifdef HAVE_CRYPT_H +# include <crypt.h> +#endif #include <unistd.h> #include <stdlib.h> #include <string.h> @@ -43,7 +47,7 @@ extern char *FascistCheck(char *pw, const char *dictpath); #ifndef CRACKLIB_DICTPATH -#define CRACKLIB_DICTPATH "/usr/lib/cracklib_dict" +#define CRACKLIB_DICTPATH "/usr/share/dict/cracklib_dict" #endif #define PROMPT1 "New %s password: " @@ -82,20 +86,31 @@ static void _pam_log(int err, const char *format, ...) /* argument parsing */ #define PAM_DEBUG_ARG 0x0001 -/* module data - AGM: please remove these static variables... PAM was - * designed to be reentrant based soley on a unique pamh... this - * breaks that. */ - -static int retry_times = 0; -static int diff_ok = 10; -static int min_length = 9; -static int dig_credit = 1; -static int up_credit = 1; -static int low_credit = 1; -static int oth_credit = 1; -static char prompt_type[BUFSIZ]; +struct cracklib_options { + int retry_times; + int diff_ok; + int diff_ignore; + int min_length; + int dig_credit; + int up_credit; + int low_credit; + int oth_credit; + int use_authtok; + char prompt_type[BUFSIZ]; +}; -static int _pam_parse(int argc, const char **argv) +#define CO_RETRY_TIMES 1 +#define CO_DIFF_OK 10 +#define CO_DIFF_IGNORE 23 +#define CO_MIN_LENGTH 9 +# define CO_MIN_LENGTH_BASE 5 +#define CO_DIG_CREDIT 1 +#define CO_UP_CREDIT 1 +#define CO_LOW_CREDIT 1 +#define CO_OTH_CREDIT 1 +#define CO_USE_AUTHTOK 0 + +static int _pam_parse(struct cracklib_options *opt, int argc, const char **argv) { int ctrl=0; @@ -108,35 +123,41 @@ static int _pam_parse(int argc, const char **argv) if (!strcmp(*argv,"debug")) ctrl |= PAM_DEBUG_ARG; else if (!strncmp(*argv,"type=",5)) - strcpy(prompt_type, *argv+5); + strcpy(opt->prompt_type, *argv+5); else if (!strncmp(*argv,"retry=",6)) { - retry_times = strtol(*argv+6,&ep,10); - if (!ep || (retry_times < 1)) - retry_times = 1; + opt->retry_times = strtol(*argv+6,&ep,10); + if (!ep || (opt->retry_times < 1)) + opt->retry_times = CO_RETRY_TIMES; } else if (!strncmp(*argv,"difok=",6)) { - diff_ok = strtol(*argv+6,&ep,10); - if (!ep || (diff_ok < 0)) - diff_ok = 10; + opt->diff_ok = strtol(*argv+6,&ep,10); + if (!ep || (opt->diff_ok < 0)) + opt->diff_ok = CO_DIFF_OK; + } else if (!strncmp(*argv,"difignore=",10)) { + opt->diff_ignore = strtol(*argv+10,&ep,10); + if (!ep || (opt->diff_ignore < 0)) + opt->diff_ignore = CO_DIFF_IGNORE; } else if (!strncmp(*argv,"minlen=",7)) { - min_length = strtol(*argv+7,&ep,10); - if (!ep || (min_length < 5)) - min_length = 5; + opt->min_length = strtol(*argv+7,&ep,10); + if (!ep || (opt->min_length < CO_MIN_LENGTH_BASE)) + opt->min_length = CO_MIN_LENGTH_BASE; } else if (!strncmp(*argv,"dcredit=",8)) { - dig_credit = strtol(*argv+8,&ep,10); - if (!ep || (dig_credit < 0)) - dig_credit = 0; + opt->dig_credit = strtol(*argv+8,&ep,10); + if (!ep || (opt->dig_credit < 0)) + opt->dig_credit = 0; } else if (!strncmp(*argv,"ucredit=",8)) { - up_credit = strtol(*argv+8,&ep,10); - if (!ep || (up_credit < 0)) - up_credit = 0; + opt->up_credit = strtol(*argv+8,&ep,10); + if (!ep || (opt->up_credit < 0)) + opt->up_credit = 0; } else if (!strncmp(*argv,"lcredit=",8)) { - low_credit = strtol(*argv+8,&ep,10); - if (!ep || (low_credit < 0)) - low_credit = 0; + opt->low_credit = strtol(*argv+8,&ep,10); + if (!ep || (opt->low_credit < 0)) + opt->low_credit = 0; } else if (!strncmp(*argv,"ocredit=",8)) { - oth_credit = strtol(*argv+8,&ep,10); - if (!ep || (oth_credit < 0)) - oth_credit = 0; + opt->oth_credit = strtol(*argv+8,&ep,10); + if (!ep || (opt->oth_credit < 0)) + opt->oth_credit = 0; + } else if (!strncmp(*argv,"use_authtok",11)) { + opt->use_authtok = 1; } else { _pam_log(LOG_ERR,"pam_parse: unknown option; %s",*argv); } @@ -216,32 +237,36 @@ static int palindrome(const char *old, const char *new) } /* - * more than half of the characters are different ones. - * or at least diff_ok are different - * NOTE that the defaults are NOT the same as befor this - * change. as long as there are at least 10 different bytes - * in a new password it will now pass even if the password - * is longer than 20 bytes (MD5) + * This is a reasonably severe check for a different selection of characters + * in the old and new passwords. */ -static int similiar(const char *old, const char *new) +static int similar(struct cracklib_options *opt, + const char *old, const char *new) { - int i, j; + int i, j; - for (i = j = 0;new[i] && old[i];i++) - if (strchr (new, old[i])) - j++; + for (i = j = 0; old[i]; i++) { + if (strchr (new, old[i])) { + j++; + } + } - if (j >= diff_ok || i >= j * 2) - return 0; + if (((i-j) >= opt->diff_ok) + || (strlen(new) >= (j * 2)) + || (strlen(new) >= opt->diff_ignore)) { + /* passwords are not very similar */ + return 0; + } - return 1; + /* passwords are too similar */ + return 1; } /* * a nice mix of characters. */ -static int simple(const char *old, const char *new) +static int simple(struct cracklib_options *opt, const char *old, const char *new) { int digits = 0; int uppers = 0; @@ -269,19 +294,19 @@ static int simple(const char *old, const char *new) * defaults cause the effect to be the same as before the change */ - if (digits > dig_credit) - digits = dig_credit; + if (digits > opt->dig_credit) + digits = opt->dig_credit; - if (uppers > up_credit) - uppers = up_credit; + if (uppers > opt->up_credit) + uppers = opt->up_credit; - if (lowers > low_credit) - lowers = low_credit; + if (lowers > opt->low_credit) + lowers = opt->low_credit; - if (others > oth_credit) - others = oth_credit; + if (others > opt->oth_credit) + others = opt->oth_credit; - size = min_length; + size = opt->min_length; size -= digits; size -= uppers; size -= lowers; @@ -302,7 +327,7 @@ static char * str_lower(char *string) return string; } -static const char * password_check(const char *old, const char *new) +static const char * password_check(struct cracklib_options *opt, const char *old, const char *new) { const char *msg = NULL; char *oldmono, *newmono, *wrapped; @@ -324,10 +349,10 @@ static const char * password_check(const char *old, const char *new) if (!msg && strcmp(oldmono, newmono) == 0) msg = "case changes only"; - if (!msg && similiar(oldmono, newmono)) - msg = "is too similiar to the old one"; + if (!msg && similar(opt, oldmono, newmono)) + msg = "is too similar to the old one"; - if (!msg && simple(old, new)) + if (!msg && simple(opt, old, new)) msg = "is too simple"; if (!msg && strstr(wrapped, newmono)) @@ -344,12 +369,51 @@ static const char * password_check(const char *old, const char *new) } +#define OLD_PASSWORDS_FILE "/etc/security/opasswd" + +static const char * check_old_password(const char *forwho, const char *newpass) +{ + static char buf[16384]; + char *s_luser, *s_uid, *s_npas, *s_pas; + const char *msg = NULL; + FILE *opwfile; + + opwfile = fopen(OLD_PASSWORDS_FILE, "r"); + if (opwfile == NULL) + return NULL; + + while (fgets(buf, 16380, opwfile)) { + if (!strncmp(buf, forwho, strlen(forwho))) { + buf[strlen(buf)-1] = '\0'; + s_luser = strtok(buf, ":,"); + s_uid = strtok(NULL, ":,"); + s_npas = strtok(NULL, ":,"); + s_pas = strtok(NULL, ":,"); + while (s_pas != NULL) { + if (!strcmp(crypt(newpass, s_pas), s_pas)) { + msg = "has been already used"; + break; + } + s_pas = strtok(NULL, ":,"); + } + break; + } + } + fclose(opwfile); + + return msg; +} + + static int _pam_unix_approve_pass(pam_handle_t *pamh, unsigned int ctrl, + struct cracklib_options *opt, const char *pass_old, const char *pass_new) { const char *msg = NULL; + const char *user; + int retval; if (pass_new == NULL || (pass_old && !strcmp(pass_old,pass_new))) { if (ctrl && PAM_DEBUG_ARG) @@ -364,7 +428,18 @@ static int _pam_unix_approve_pass(pam_handle_t *pamh, * if one wanted to hardwire authentication token strength * checking this would be the place */ - msg = password_check(pass_old,pass_new); + msg = password_check(opt, pass_old,pass_new); + if (!msg) { + retval = pam_get_item(pamh, PAM_USER, (const void **)&user); + if (retval != PAM_SUCCESS) { + if (ctrl & PAM_DEBUG_ARG) { + _pam_log(LOG_ERR,"Can not get username"); + return PAM_AUTHTOK_ERR; + } + } + msg = check_old_password(user, pass_new); + } + if (msg) { char remark[BUFSIZ]; @@ -387,14 +462,24 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) { unsigned int ctrl; + struct cracklib_options options; + + options.retry_times = CO_RETRY_TIMES; + options.diff_ok = CO_DIFF_OK; + options.diff_ignore = CO_DIFF_IGNORE; + options.min_length = CO_MIN_LENGTH; + options.dig_credit = CO_DIG_CREDIT; + options.up_credit = CO_UP_CREDIT; + options.low_credit = CO_LOW_CREDIT; + options.oth_credit = CO_OTH_CREDIT; + options.use_authtok = CO_USE_AUTHTOK; + memset(options.prompt_type, 0, BUFSIZ); - retry_times = 1; - memset(prompt_type,0,sizeof(prompt_type)); - ctrl = _pam_parse(argc, argv); + ctrl = _pam_parse(&options, argc, argv); D(("called.")); - if (!prompt_type[0]) - strcpy(prompt_type,"UNIX"); + if (!options.prompt_type[0]) + strcpy(options.prompt_type,"UNIX"); if (flags & PAM_PRELIM_CHECK) { /* Check for passwd dictionary */ @@ -421,7 +506,6 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, } else if (flags & PAM_UPDATE_AUTHTOK) { int retval; char *token1, *token2, *oldtoken; - const char *item; struct pam_message msg[1],*pmsg[1]; struct pam_response *resp; const char *cracklib_dictpath = CRACKLIB_DICTPATH; @@ -443,7 +527,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, */ token1 = token2 = NULL; - if (!retry_times) { + if (!options.retry_times) { D(("returning %s because maxtries reached", pam_strerror(pamh, retval))); return retval; @@ -457,33 +541,51 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, * set PAM_AUTHTOK and return */ - /* Prepare to ask the user for the first time */ - memset(prompt,0,sizeof(prompt)); - sprintf(prompt,PROMPT1,prompt_type); - pmsg[0] = &msg[0]; - msg[0].msg_style = PAM_PROMPT_ECHO_OFF; - msg[0].msg = prompt; - - resp = NULL; - retval = converse(pamh, ctrl, 1, pmsg, &resp); - if (resp != NULL) { - /* interpret the response */ - if (retval == PAM_SUCCESS) { /* a good conversation */ - token1 = x_strdup(resp[0].resp); - if (token1 == NULL) { - _pam_log(LOG_NOTICE, - "could not recover authentication token 1"); - retval = PAM_AUTHTOK_RECOVER_ERR; + if (options.use_authtok == 1) { + const char *item = NULL; + + retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **) &item); + if (retval != PAM_SUCCESS) { + /* very strange. */ + _pam_log(LOG_ALERT + ,"pam_get_item returned error to pam_cracklib" + ); + } else if (item != NULL) { /* we have a password! */ + token1 = x_strdup(item); + item = NULL; + } else { + retval = PAM_AUTHTOK_RECOVER_ERR; /* didn't work */ + } + + } else { + /* Prepare to ask the user for the first time */ + memset(prompt,0,sizeof(prompt)); + sprintf(prompt,PROMPT1,options.prompt_type); + pmsg[0] = &msg[0]; + msg[0].msg_style = PAM_PROMPT_ECHO_OFF; + msg[0].msg = prompt; + + resp = NULL; + retval = converse(pamh, ctrl, 1, pmsg, &resp); + if (resp != NULL) { + /* interpret the response */ + if (retval == PAM_SUCCESS) { /* a good conversation */ + token1 = x_strdup(resp[0].resp); + if (token1 == NULL) { + _pam_log(LOG_NOTICE, + "could not recover authentication token 1"); + retval = PAM_AUTHTOK_RECOVER_ERR; + } } + /* + * tidy up the conversation (resp_retcode) is ignored + */ + _pam_drop_reply(resp, 1); + } else { + retval = (retval == PAM_SUCCESS) ? + PAM_AUTHTOK_RECOVER_ERR:retval ; } - /* - * tidy up the conversation (resp_retcode) is ignored - */ - _pam_drop_reply(resp, 1); - } else { - retval = (retval == PAM_SUCCESS) ? - PAM_AUTHTOK_RECOVER_ERR:retval ; - } + } if (retval != PAM_SUCCESS) { if (ctrl && PAM_DEBUG_ARG) @@ -512,13 +614,14 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, /* check it for strength too... */ D(("for strength")); if (oldtoken) { - retval = _pam_unix_approve_pass(pamh,ctrl, + retval = _pam_unix_approve_pass(pamh,ctrl,&options, oldtoken,token1); - if (retval != PAM_SUCCESS) + if (retval != PAM_SUCCESS) { if (getuid() || (flags & PAM_CHANGE_EXPIRED_AUTHTOK)) retval = PAM_AUTHTOK_ERR; else retval = PAM_SUCCESS; + } } } } @@ -534,77 +637,81 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, } /* Now we have a good passwd. Ask for it once again */ - - bzero(prompt,sizeof(prompt)); - sprintf(prompt,PROMPT2,prompt_type); - pmsg[0] = &msg[0]; - msg[0].msg_style = PAM_PROMPT_ECHO_OFF; - msg[0].msg = prompt; - - resp = NULL; - retval = converse(pamh, ctrl, 1, pmsg, &resp); - if (resp != NULL) { - /* interpret the response */ - if (retval == PAM_SUCCESS) { /* a good conversation */ - token2 = x_strdup(resp[0].resp); - if (token2 == NULL) { - _pam_log(LOG_NOTICE, - "could not recover authentication token 2"); - retval = PAM_AUTHTOK_RECOVER_ERR; + + if (options.use_authtok == 0) { + bzero(prompt,sizeof(prompt)); + sprintf(prompt,PROMPT2,options.prompt_type); + pmsg[0] = &msg[0]; + msg[0].msg_style = PAM_PROMPT_ECHO_OFF; + msg[0].msg = prompt; + + resp = NULL; + retval = converse(pamh, ctrl, 1, pmsg, &resp); + if (resp != NULL) { + /* interpret the response */ + if (retval == PAM_SUCCESS) { /* a good conversation */ + token2 = x_strdup(resp[0].resp); + if (token2 == NULL) { + _pam_log(LOG_NOTICE, + "could not recover authentication token 2"); + retval = PAM_AUTHTOK_RECOVER_ERR; + } } + /* + * tidy up the conversation (resp_retcode) is ignored + */ + _pam_drop_reply(resp, 1); + } else { + retval = (retval == PAM_SUCCESS) ? + PAM_AUTHTOK_RECOVER_ERR:retval ; } - /* - * tidy up the conversation (resp_retcode) is ignored - */ - _pam_drop_reply(resp, 1); - } else { - retval = (retval == PAM_SUCCESS) ? - PAM_AUTHTOK_RECOVER_ERR:retval ; - } - if (retval != PAM_SUCCESS) { - if (ctrl && PAM_DEBUG_ARG) - _pam_log(LOG_DEBUG - ,"unable to obtain the password a second time"); - continue; - } + if (retval != PAM_SUCCESS) { + if (ctrl && PAM_DEBUG_ARG) + _pam_log(LOG_DEBUG + ,"unable to obtain the password a second time"); + continue; + } - /* Hopefully now token1 and token2 the same password ... */ - if (strcmp(token1,token2) != 0) { - /* tell the user */ - make_remark(pamh, ctrl, PAM_ERROR_MSG, MISTYPED_PASS); - token1 = _pam_delete(token1); - token2 = _pam_delete(token2); - pam_set_item(pamh, PAM_AUTHTOK, NULL); - if (ctrl & PAM_DEBUG_ARG) - _pam_log(LOG_NOTICE,"Password mistyped"); - retval = PAM_AUTHTOK_RECOVER_ERR; - continue; - } + /* Hopefully now token1 and token2 the same password ... */ + if (strcmp(token1,token2) != 0) { + /* tell the user */ + make_remark(pamh, ctrl, PAM_ERROR_MSG, MISTYPED_PASS); + token1 = _pam_delete(token1); + token2 = _pam_delete(token2); + pam_set_item(pamh, PAM_AUTHTOK, NULL); + if (ctrl & PAM_DEBUG_ARG) + _pam_log(LOG_NOTICE,"Password mistyped"); + retval = PAM_AUTHTOK_RECOVER_ERR; + continue; + } - /* Yes, the password was typed correct twice - * we store this password as an item - */ + /* Yes, the password was typed correct twice + * we store this password as an item + */ - retval = pam_set_item(pamh, PAM_AUTHTOK, token1); - /* clean it up */ - token1 = _pam_delete(token1); - token2 = _pam_delete(token2); - if ( - (retval != PAM_SUCCESS) || - ( - ( - retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&item) - ) != PAM_SUCCESS - ) - ) { - _pam_log(LOG_CRIT, "error manipulating password"); - continue; + { + const char *item = NULL; + + retval = pam_set_item(pamh, PAM_AUTHTOK, token1); + + /* clean up */ + token1 = _pam_delete(token1); + token2 = _pam_delete(token2); + + if ( (retval != PAM_SUCCESS) || + ((retval = pam_get_item(pamh, PAM_AUTHTOK, + (const void **)&item) + ) != PAM_SUCCESS) ) { + _pam_log(LOG_CRIT, "error manipulating password"); + continue; + } + item = NULL; /* break link to password */ + return PAM_SUCCESS; + } } - item = NULL; /* break link to password */ - return PAM_SUCCESS; - } while (retry_times--); + } while (options.retry_times--); } else { if (ctrl & PAM_DEBUG_ARG) diff --git a/contrib/libpam/modules/pam_deny/Makefile b/contrib/libpam/modules/pam_deny/Makefile index 02506cb38122..2fdd6e1111a5 100644 --- a/contrib/libpam/modules/pam_deny/Makefile +++ b/contrib/libpam/modules/pam_deny/Makefile @@ -1,125 +1,15 @@ # -# $Id: Makefile,v 1.7 1997/04/05 06:43:41 morgan Exp morgan $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.7 1997/04/05 06:43:41 morgan -# full-source-tree and fakeroot -# -# Revision 1.6 1997/02/15 19:04:27 morgan -# fixed email -# -# Revision 1.5 1996/11/10 20:11:48 morgan -# crossplatform support -# -# Revision 1.4 1996/09/05 06:50:12 morgan -# ld --> gcc -# -# Revision 1.3 1996/05/26 15:48:38 morgan -# make dynamic and static dirs -# -# Revision 1.2 1996/05/26 04:00:16 morgan -# changes for automated static/dynamic modules -# -# Revision 1.1 1996/03/16 17:47:36 morgan -# Initial revision -# -# -# Created by Andrew Morgan <morgan@parc.power.net> 1996/3/11 +# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27 # -# Convenient defaults for compiling independently of the full source -# tree. -ifndef FULL_LINUX_PAM_SOURCE_TREE -export DYNAMIC=-DPAM_DYNAMIC -export CC=gcc -export CFLAGS=-O2 -Dlinux -DLINUX_PAM \ - -ansi -D_POSIX_SOURCE -Wall -Wwrite-strings \ - -Wpointer-arith -Wcast-qual -Wcast-align -Wtraditional \ - -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline \ - -Wshadow -pedantic -fPIC -export MKDIR=mkdir -p -export LD_D=gcc -shared -Xlinker -x -endif - -# +include ../../Make.Rules TITLE=pam_deny -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak - -.c.o: - $(CC) $(CFLAGS) -c $< - +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_deny/README b/contrib/libpam/modules/pam_deny/README index 4f7f6de664fe..2eb96d4e35d1 100644 --- a/contrib/libpam/modules/pam_deny/README +++ b/contrib/libpam/modules/pam_deny/README @@ -1,4 +1,4 @@ -# $Id: README,v 1.1 1996/03/16 18:11:12 morgan Exp $ +# $Id: README,v 1.1.1.1 2000/06/20 22:11:33 agmorgan Exp $ # this module always fails, it ignores all options. diff --git a/contrib/libpam/modules/pam_deny/pam_deny.c b/contrib/libpam/modules/pam_deny/pam_deny.c index 76ba24d3fd90..8be1a8a87f55 100644 --- a/contrib/libpam/modules/pam_deny/pam_deny.c +++ b/contrib/libpam/modules/pam_deny/pam_deny.c @@ -1,23 +1,10 @@ /* pam_permit module */ /* - * $Id: pam_deny.c,v 1.4 1997/02/15 19:05:15 morgan Exp $ + * $Id: pam_deny.c,v 1.2 2000/12/04 19:02:34 baggins Exp $ * * Written by Andrew Morgan <morgan@parc.power.net> 1996/3/11 * - * $Log: pam_deny.c,v $ - * Revision 1.4 1997/02/15 19:05:15 morgan - * fixed email - * - * Revision 1.3 1996/06/02 08:06:19 morgan - * changes for new static protocol - * - * Revision 1.2 1996/05/26 04:01:12 morgan - * added static support - * - * Revision 1.1 1996/03/16 17:47:36 morgan - * Initial revision - * */ /* diff --git a/contrib/libpam/modules/pam_env/Makefile b/contrib/libpam/modules/pam_env/Makefile index df363bc9536b..189f1ee3fe6a 100644 --- a/contrib/libpam/modules/pam_env/Makefile +++ b/contrib/libpam/modules/pam_env/Makefile @@ -1,107 +1,22 @@ # -# $Id: Makefile,v 1.1 1997/04/05 06:42:35 morgan Exp morgan $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.1 1997/04/05 06:42:35 morgan -# Initial revision -# -# Revision 1.1 1997/01/04 20:32:52 morgan -# Initial revision -# -# Created by Andrew Morgan <morgan@parc.power.net> 1996/12/8 -# Adaptations by Dave Kinclea and Cristian Gafton -# - -TITLE=pam_env - -CONFD=$(CONFIGED)/security -export CONFD -CONFILE=$(CONFD)/pam_env.conf -export CONFILE - -#ifeq ($(HAVE_PWDBLIB),yes) -#CFLAGS += -DWANT_PWDB -#EXTRALIB = -lpwdb -#endif - -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ +include ../../Make.Rules -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) $(EXTRALIB) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) $(EXTRALIB) -endif - -install: all -ifdef DYNAMIC - $(MKDIR) $(FAKEROOT)$(SECUREDIR) - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - $(MKDIR) $(FAKEROOT)$(SCONFIGED) - bash -f ./install_conf - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ +TITLE=pam_env +LOCAL_CONFILE=./pam_env.conf-example +INSTALLED_CONFILE=$(SCONFIGD)/pam_env.conf -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* +DEFS=-DDEFAULT_CONF_FILE=\"$(INSTALLED_CONFILE)\" +CFLAGS += $(DEFS) -.c.o: - $(CC) $(CFLAGS) -c $< +MODULE_SIMPLE_INSTALL=bash -f ../install_conf "$(FAKEROOT)" "$(SCONFIGD)" "$(INSTALLED_CONFILE)" "$(TITLE)" "$(LOCAL_CONFILE)" +MODULE_SIMPLE_REMOVE=rm -f $(FAKEROOT)$(INSTALLED_CONFILE) +MODULE_SIMPLE_CLEAN=rm -f ./.ignore_age +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_env/README b/contrib/libpam/modules/pam_env/README index d6e959cdbee5..5053618a7835 100644 --- a/contrib/libpam/modules/pam_env/README +++ b/contrib/libpam/modules/pam_env/README @@ -1,6 +1,6 @@ -# $Date: 1997/04/05 06:42:35 $ -# $Author: morgan $ -# $Id: README,v 1.1 1997/04/05 06:42:35 morgan Exp $ +# $Date: 2000/06/20 22:11:33 $ +# $Author: agmorgan $ +# $Id: README,v 1.1.1.1 2000/06/20 22:11:33 agmorgan Exp $ # # This is the configuration file for pam_env, a PAM module to load in # a configurable list of environment variables for a diff --git a/contrib/libpam/modules/pam_env/pam_env.c b/contrib/libpam/modules/pam_env/pam_env.c index bd0879c52283..5f5aa815e6be 100644 --- a/contrib/libpam/modules/pam_env/pam_env.c +++ b/contrib/libpam/modules/pam_env/pam_env.c @@ -1,59 +1,21 @@ /* pam_mail module */ /* - * $Id: pam_env.c,v 1.1 1997/04/05 06:42:35 morgan Exp morgan $ + * $Id: pam_env.c,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ * * Written by Dave Kinchlea <kinch@kinch.ark.com> 1997/01/31 * Inspired by Andrew Morgan <morgan@parc.power.net, who also supplied the * template for this file (via pam_mail) - * - * $Log: pam_env.c,v $ - * Revision 1.1 1997/04/05 06:42:35 morgan - * Initial revision - * - * Revision 0.6 1997/02/04 17:58:27 kinch - * Debugging code cleaned up, lots added (whereever _log_err called) some removed - * - * Revision 0.5 1997/02/04 17:20:30 kinch - * Changed default config file - * Removed bogus message in pam_sm_authenticate() - * Added back support in pam_sm_session(), this could conceivably be used - * both as an auth_setcred and a session module - * - * Revision 0.4 1997/02/04 07:34:15 kinch - * Fixed dealing with escaped '$' and '@' characters - * This is now an pam_sm_setcred module to work closer to the RFC model - * though this whole thing seems to have little to do with Authentication - * - * Revision 0.3 1997/02/04 04:53:15 kinch - * Removed bogus space in PAM_ENV_SILENT - * Removed line that added a space when allowing for escaped newlines, that - * is not what we want at all, if we want a space, we can add one. - * Changed a PAM_ABORT to PAM_BUF_ERR for a malloc failure - * Changed bogus PAM_RUSER to PAM_RHOST - * - * Revision 0.2 1997/02/03 23:31:26 kinch - * Lots of D(()) debugging code added, probably too much actually. - * This now seems to work for all cases I can think of - * Lots of little code changes but nothing major and no function - * interface changes, largest change has to do with adding the - * logic to get "e hack to make it through all the code. Probably - * ought to have done this with a global flag for each of defval and - * override - it would have been cleaner. - * - * Revision 0.1 1997/02/03 01:39:06 kinch - * Initial code, it compiles cleanly but has not been tested at all. - * */ #ifndef DEFAULT_CONF_FILE #define DEFAULT_CONF_FILE "/etc/security/pam_env.conf" #endif -#ifdef linux -#define _GNU_SOURCE -#include <features.h> -#endif +#define DEFAULT_ETC_ENVFILE "/etc/environment" +#define DEFAULT_READ_ENVFILE 1 + +#include <security/_pam_aconf.h> #include <ctype.h> #include <errno.h> @@ -67,10 +29,6 @@ #include <sys/types.h> #include <unistd.h> -#ifdef WANT_PWDB -#include <pwdb/pwdb_public.h> -#endif - /* * here, we make a definition for the externally accessible function * in this file (this definition is required for static a module @@ -132,11 +90,13 @@ static void _log_err(int err, const char *format, ...) /* argument parsing */ -#define PAM_DEBUG_ARG 01 -#define PAM_NEW_CONF_FILE 02 -#define PAM_ENV_SILENT 04 +#define PAM_DEBUG_ARG 0x01 +#define PAM_NEW_CONF_FILE 0x02 +#define PAM_ENV_SILENT 0x04 +#define PAM_NEW_ENV_FILE 0x10 -static int _pam_parse(int flags, int argc, const char **argv, char **conffile) +static int _pam_parse(int flags, int argc, const char **argv, char **conffile, + char **envfile, int *readenv) { int ctrl=0; @@ -157,9 +117,19 @@ static int _pam_parse(int flags, int argc, const char **argv, char **conffile) _log_err(LOG_CRIT, "Configuration file specification missing argument - ignored"); } - } else { + } else if (!strncmp(*argv,"envfile=",8)) { + *envfile = x_strdup(8+*argv); + if (*envfile != NULL) { + D(("new Env File: %s", *envfile)); + ctrl |= PAM_NEW_ENV_FILE; + } else { + _log_err(LOG_CRIT, + "Env file specification missing argument - ignored"); + } + } else if (!strncmp(*argv,"readenv=",8)) + *readenv = atoi(8+*argv); + else _log_err(LOG_ERR,"pam_parse: unknown option; %s",*argv); - } } return ctrl; @@ -192,7 +162,7 @@ static int _parse_config_file(pam_handle_t *pamh, int ctrl, char **conffile) if ((conf = fopen(file,"r")) == NULL) { _log_err(LOG_ERR, "Unable to open config file: %s", strerror(errno)); - return PAM_ABORT; + return PAM_IGNORE; } /* _pam_assemble_line will provide a complete line from the config file, with all @@ -230,6 +200,88 @@ static int _parse_config_file(pam_handle_t *pamh, int ctrl, char **conffile) return (retval<0?PAM_ABORT:PAM_SUCCESS); } +static int _parse_env_file(pam_handle_t *pamh, int ctrl, char **env_file) +{ + int retval=PAM_SUCCESS, i, t; + const char *file; + char buffer[BUF_SIZE], *key, *mark; + FILE *conf; + + if (ctrl & PAM_NEW_ENV_FILE) + file = *env_file; + else + file = DEFAULT_ETC_ENVFILE; + + D(("Env file name is: %s", file)); + + if ((conf = fopen(file,"r")) == NULL) { + D(("Unable to open env file: %s", strerror(errno))); + return PAM_ABORT; + } + + while (_assemble_line(conf, buffer, BUF_SIZE) > 0) { + D(("Read line: %s", buffer)); + key = buffer; + + /* skip leading white space */ + key += strspn(key, " \n\t"); + + /* skip blanks lines and comments */ + if (!key || key[0] == '#') + continue; + + /* skip over "export " if present so we can be compat with + bash type declerations */ + if (strncmp(key, "export ", (size_t) 7) == 0) + key += 7; + + /* now find the end of value */ + mark = key; + while(mark[0] != '\n' && mark[0] != '#' && mark[0] != '\0') + mark++; + if (mark[0] != '\0') + mark[0] = '\0'; + + /* + * sanity check, the key must be alpha-numeric + */ + + for ( i = 0 ; key[i] != '=' && key[i] != '\0' ; i++ ) + if (!isalnum(key[i]) && key[i] != '_') { + D(("key is not alpha numeric - '%s', ignoring", key)); + continue; + } + + /* now we try to be smart about quotes around the value, + but not too smart, we can't get all fancy with escaped + values like bash */ + if (key[i] == '=' && (key[++i] == '\"' || key[i] == '\'')) { + for ( t = i+1 ; key[t] != '\0' ; t++) + if (key[t] != '\"' && key[t] != '\'') + key[i++] = key[t]; + else if (key[t+1] != '\0') + key[i++] = key[t]; + key[i] = '\0'; + } + + /* set the env var, if it fails, we break out of the loop */ + retval = pam_putenv(pamh, key); + if (retval != PAM_SUCCESS) { + D(("error setting env \"%s\"", key)); + break; + } + } + + (void) fclose(conf); + + /* tidy up */ + _pam_overwrite(*env_file); + _pam_drop(*env_file); + file = NULL; + D(("Exit.")); + return (retval<0?PAM_IGNORE:PAM_SUCCESS); +} + /* * This is where we read a line of the PAM config file. The line may be * preceeded by lines of comments and also extended with "\\\n" @@ -536,7 +588,7 @@ static int _expand_arg(pam_handle_t *pamh, char **value) _log_err(LOG_ERR, "Unterminated expandable variable: <%s>", orig-2); return PAM_ABORT; } - strcpy(tmpval, orig); + strncpy(tmpval, orig, (size_t) BUF_SIZE); orig=ptr; /* * so, we know we need to expand tmpval, it is either @@ -696,18 +748,21 @@ PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) { - int retval, ctrl; - char *conf_file=NULL; - + int retval, ctrl, readenv=DEFAULT_READ_ENVFILE; + char *conf_file=NULL, *env_file=NULL; + /* * this module sets environment variables read in from a file */ D(("Called.")); - ctrl = _pam_parse(flags, argc, argv, &conf_file); - + ctrl = _pam_parse(flags, argc, argv, &conf_file, &env_file, &readenv); + retval = _parse_config_file(pamh, ctrl, &conf_file); - + + if(readenv) + _parse_env_file(pamh, ctrl, &env_file); + /* indicate success or failure */ D(("Exit.")); @@ -726,18 +781,21 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh,int flags,int argc ,const char **argv) { - int retval, ctrl; - char *conf_file=NULL; + int retval, ctrl, readenv=DEFAULT_READ_ENVFILE; + char *conf_file=NULL, *env_file=NULL; /* * this module sets environment variables read in from a file */ D(("Called.")); - ctrl = _pam_parse(flags, argc, argv, &conf_file); + ctrl = _pam_parse(flags, argc, argv, &conf_file, &env_file, &readenv); retval = _parse_config_file(pamh, ctrl, &conf_file); + if(readenv) + _parse_env_file(pamh, ctrl, &env_file); + /* indicate success or failure */ D(("Exit.")); diff --git a/contrib/libpam/modules/pam_env/pam_env.conf-example b/contrib/libpam/modules/pam_env/pam_env.conf-example index 388e8b6b16d4..89637083be4e 100644 --- a/contrib/libpam/modules/pam_env/pam_env.conf-example +++ b/contrib/libpam/modules/pam_env/pam_env.conf-example @@ -1,6 +1,6 @@ -# $Date: 1997/04/05 06:42:35 $ -# $Author: morgan $ -# $Id: pam_env.conf-example,v 1.1 1997/04/05 06:42:35 morgan Exp $ +# $Date: 2000/06/20 22:11:35 $ +# $Author: agmorgan $ +# $Id: pam_env.conf-example,v 1.1.1.1 2000/06/20 22:11:35 agmorgan Exp $ # # This is the configuration file for pam_env, a PAM module to load in # a configurable list of environment variables for a diff --git a/contrib/libpam/modules/pam_filter/Makefile b/contrib/libpam/modules/pam_filter/Makefile index dbd6452ab285..1126aff9b301 100644 --- a/contrib/libpam/modules/pam_filter/Makefile +++ b/contrib/libpam/modules/pam_filter/Makefile @@ -1,24 +1,11 @@ # -# $Id: Makefile,v 1.10 1997/04/05 06:41:09 morgan Exp $ +# $Id: Makefile,v 1.3 2000/12/21 06:06:34 vorlon Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.10 1997/04/05 06:41:09 morgan -# fakeroot -# -# Revision 1.9 1997/02/15 18:58:48 morgan -# fixed bash syntax -# -# Revision 1.8 1997/01/04 20:24:29 morgan -# don't compile on solaris, make -> $(MAKE) -# -# Revision 1.7 1996/11/10 20:12:09 morgan -# cross platform support -# -# Created by Andrew Morgan <morgan@parc.power.net> 1996/3/11 +# Created by Andrew Morgan <morgan@linux.kernel.org> 1996/3/11 # ifeq ($(OS),solaris) @@ -27,12 +14,14 @@ include ../dont_makefile else +include ../../Make.Rules + TITLE=pam_filter FILTERS=upperLOWER FILTERSDIR=$(SUPLEMENTED)/pam_filter export FILTERSDIR -# +CFLAGS += -Iinclude LIBSRC = $(TITLE).c LIBOBJ = $(TITLE).o @@ -55,10 +44,6 @@ endif ####################### don't edit below ####################### -dummy: - @echo "**** This is not a top-level Makefile " - exit - # # this is where we compile this module # @@ -66,6 +51,7 @@ dummy: all: dirs $(LIBSHARED) $(LIBSTATIC) register filters dirs: + if [ ! -r include/security ]; then ln -sf . include/security ; fi ifdef DYNAMIC $(MKDIR) ./dynamic endif @@ -104,6 +90,15 @@ $(LIBSTATIC): $(LIBOBJS) $(LD) -r -o $@ $(LIBOBJS) endif +remove: + rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so + rm -f $(FAKEROOT)$(INCLUDED)/pam_filter.h + @for i in $(FILTERS) ; do \ + if [ -d $$i ]; then \ + $(MAKE) -C $$i remove ; \ + fi ; \ + done + install: all @for i in $(FILTERS) ; do \ if [ -d $$i ]; then \ @@ -117,34 +112,15 @@ endif $(MKDIR) $(FAKEROOT)$(INCLUDED) $(INSTALL) -m 644 include/pam_filter.h $(FAKEROOT)$(INCLUDED) -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - rm -f $(FAKEROOT)$(INCLUDED)/pam_filter.h - @for i in $(FILTERS) ; do \ - if [ -d $$i ]; then \ - $(MAKE) -C $$i remove ; \ - fi ; \ - done - -lclean: - rm -f $(LIBSHARED) $(LIBOBJD) $(LIBOBJS) core *~ - -clean: lclean +clean: @for i in $(FILTERS) ; do \ if [ -d $$i ]; then \ $(MAKE) -C $$i clean ; \ fi ; \ done - -extraclean: lclean - @rm -f *.a *.o *.so *.bak - for i in $(FILTERS) ; do \ - if [ -d $$i ]; then \ - $(MAKE) -C $$i extraclean ; \ - fi ; \ - done - -.c.o: - $(CC) $(CFLAGS) -c $< + rm -f $(LIBSHARED) $(LIBOBJD) $(LIBOBJS) core *~ + rm -f include/security + rm -fr dynamic static + rm -f *.a *.o *.so *.bak endif diff --git a/contrib/libpam/modules/pam_filter/README b/contrib/libpam/modules/pam_filter/README index 9d46a56e5c9c..12c4aeb5175b 100644 --- a/contrib/libpam/modules/pam_filter/README +++ b/contrib/libpam/modules/pam_filter/README @@ -1,5 +1,5 @@ # -# $Id: README,v 1.5 1996/12/01 02:53:08 morgan Exp $ +# $Id: README,v 1.1.1.1 2000/06/20 22:11:35 agmorgan Exp $ # # This describes the behavior of this module with respect to the # /etc/pam.conf file. diff --git a/contrib/libpam/modules/pam_filter/include/pam_filter.h b/contrib/libpam/modules/pam_filter/include/pam_filter.h index 3eb2730e768b..69e3a3e298ab 100644 --- a/contrib/libpam/modules/pam_filter/include/pam_filter.h +++ b/contrib/libpam/modules/pam_filter/include/pam_filter.h @@ -1,8 +1,8 @@ /* - * $Id: pam_filter.h,v 1.2 1997/02/15 19:09:09 morgan Exp $ + * $Id: pam_filter.h,v 1.1.1.1 2000/06/20 22:11:36 agmorgan Exp $ * * this file is associated with the Linux-PAM filter module. - * it was written by Andrew G. Morgan <morgan@parc.power.net> + * it was written by Andrew G. Morgan <morgan@linux.kernel.org> * */ diff --git a/contrib/libpam/modules/pam_filter/pam_filter.c b/contrib/libpam/modules/pam_filter/pam_filter.c index fc3d1f2b53fc..3ab2d8670646 100644 --- a/contrib/libpam/modules/pam_filter/pam_filter.c +++ b/contrib/libpam/modules/pam_filter/pam_filter.c @@ -1,24 +1,12 @@ /* - * $Id: pam_filter.c,v 1.9 1997/02/15 19:07:49 morgan Exp morgan $ - * - * $Log: pam_filter.c,v $ - * Revision 1.9 1997/02/15 19:07:49 morgan - * fixed email - * - * Revision 1.8 1996/11/10 20:59:23 morgan - * gcc warning removed - * - * Revision 1.7 1996/07/08 00:01:17 morgan - * set the PAM_TTY item now - * - * Revision 1.6 1996/06/02 08:08:19 morgan - * completely re-written - * + * $Id: pam_filter.c,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ * * written by Andrew Morgan <morgan@transmeta.com> with much help from * Richard Stevens' UNIX Network Programming book. */ +#include <security/_pam_aconf.h> + #include <stdlib.h> #include <syslog.h> #include <unistd.h> diff --git a/contrib/libpam/modules/pam_filter/upperLOWER/Makefile b/contrib/libpam/modules/pam_filter/upperLOWER/Makefile index 09b693bf6803..92da2479e0a8 100644 --- a/contrib/libpam/modules/pam_filter/upperLOWER/Makefile +++ b/contrib/libpam/modules/pam_filter/upperLOWER/Makefile @@ -1,44 +1,28 @@ # -# $Id: Makefile,v 1.5 1997/04/05 06:41:35 morgan Exp $ -# -# $Log: Makefile,v $ -# Revision 1.5 1997/04/05 06:41:35 morgan -# fakeroot -# -# Revision 1.4 1997/01/04 20:25:04 morgan -# removed need for make -# -# Revision 1.3 1996/11/10 20:13:08 morgan -# email address -# -# Revision 1.2 1996/11/10 20:12:24 morgan -# cross platform support -# -# Revision 1.1 1996/06/02 08:17:02 morgan -# Initial revision -# +# $Id: Makefile,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ # # This directory contains a pam_filter filter executable # -# Created by Andrew Morgan <morgan@parc.power.net> 1996/3/11 +# Created by Andrew Morgan <morgan@transmeta.com> 1996/3/11 # +include ../../../Make.Rules + TITLE=upperLOWER # +CFLAGS += -I../include + OBJS = $(TITLE).o ####################### don't edit below ####################### -dummy: - @echo "**** This is not a top-level Makefile " - all: $(TITLE) $(TITLE): $(OBJS) $(CC) -o $(TITLE) $(OBJS) - strip $(TITLE) + $(STRIP) $(TITLE) install: $(MKDIR) $(FAKEROOT)$(FILTERSDIR) @@ -50,9 +34,6 @@ remove: clean: rm -f $(TITLE) $(OBJS) core *~ -extraclean: clean - rm -f *.bak - .c.o: $(CC) $(CFLAGS) -c $< diff --git a/contrib/libpam/modules/pam_filter/upperLOWER/upperLOWER.c b/contrib/libpam/modules/pam_filter/upperLOWER/upperLOWER.c index b375c0794edf..6178c2797e2e 100644 --- a/contrib/libpam/modules/pam_filter/upperLOWER/upperLOWER.c +++ b/contrib/libpam/modules/pam_filter/upperLOWER/upperLOWER.c @@ -1,17 +1,14 @@ /* - * $Id: upperLOWER.c,v 1.1 1996/06/02 08:17:02 morgan Exp $ + * $Id: upperLOWER.c,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ * * This is a sample filter program, for use with pam_filter (a module * provided with Linux-PAM). This filter simply transposes upper and * lower case letters, it is intended for demonstration purposes and * it serves no purpose other than to annoy the user... - * - * $Log: upperLOWER.c,v $ - * Revision 1.1 1996/06/02 08:17:02 morgan - * Initial revision - * */ +#include <security/_pam_aconf.h> + #include <stdio.h> #include <syslog.h> #include <sys/time.h> @@ -52,7 +49,9 @@ static void do_transpose(char *buffer,int len) } } -int main(int argc, char **argv, char **envp) +extern char **environ; + +int main(int argc, char **argv) { char buffer[BUFSIZ]; fd_set readers; @@ -64,8 +63,8 @@ int main(int argc, char **argv, char **envp) int i; fprintf(stderr,"environment :[\r\n"); - for (i=0; envp[i]; ++i) { - fprintf(stderr,"-> %s\r\n",envp[i]); + for (i=0; environ[i]; ++i) { + fprintf(stderr,"-> %s\r\n",environ[i]); } fprintf(stderr,"]: end\r\n"); } diff --git a/contrib/libpam/modules/pam_ftp/Makefile b/contrib/libpam/modules/pam_ftp/Makefile index b5355c68b55e..456161bfe597 100644 --- a/contrib/libpam/modules/pam_ftp/Makefile +++ b/contrib/libpam/modules/pam_ftp/Makefile @@ -1,96 +1,15 @@ # -# $Id: Makefile,v 1.2 1997/04/05 06:40:33 morgan Exp $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.2 1997/04/05 06:40:33 morgan -# fakeroot +# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27 # -# Revision 1.1 1996/12/01 03:17:57 morgan -# Initial revision -# -# -# Created by Andrew Morgan <morgan@parc.power.net> 1996/11/14 -# - -TITLE=pam_ftp - -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### -dummy: +include ../../Make.Rules - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< +TITLE=pam_ftp +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_ftp/README b/contrib/libpam/modules/pam_ftp/README index 597f9120bd86..6d03330c10ed 100644 --- a/contrib/libpam/modules/pam_ftp/README +++ b/contrib/libpam/modules/pam_ftp/README @@ -1,20 +1,18 @@ -# $Id: README,v 1.1 1996/12/01 03:17:57 morgan Exp $ -# +This is the README for pam_ftp +------------------------------ -This module is an authentication module that does not authenticate. -Instead it always returns PAM_IGNORE, indicating that it does not want -to affect the authentication process. - -Its purpose is to log a message to the syslog indicating the -pam_item's available at the time it was invoked. It is a diagnostic -tool. +This module is an authentication module that does simple ftp +authentication. Recognized arguments: - none - -module services provided: + "debug" print debug messages + "users=" comma separated list of users which + could login only with email adress + "ignore" allow invalid email adresses - auth _authetication and _setcred (blank) +Options for: +auth: for authentication it provides pam_authenticate() and + pam_setcred() hooks. -Andrew Morgan +Thorsten Kukuk <kukuk@suse.de>, 17. June 1999 diff --git a/contrib/libpam/modules/pam_ftp/pam_ftp.c b/contrib/libpam/modules/pam_ftp/pam_ftp.c index ca2d41545e94..3fcbcec8cd54 100644 --- a/contrib/libpam/modules/pam_ftp/pam_ftp.c +++ b/contrib/libpam/modules/pam_ftp/pam_ftp.c @@ -1,17 +1,9 @@ /* pam_ftp module */ /* - * $Id: pam_ftp.c,v 1.2 1997/02/15 16:23:59 morgan Exp morgan $ - * - * Written by Andrew Morgan <morgan@parc.power.net> 1996/3/11 - * - * $Log: pam_ftp.c,v $ - * Revision 1.2 1997/02/15 16:23:59 morgan - * fixed logging to avoid a fixed buffer size - * - * Revision 1.1 1996/12/01 03:17:57 morgan - * Initial revision + * $Id: pam_ftp.c,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ * + * Written by Andrew Morgan <morgan@linux.kernel.org> 1996/3/11 * */ @@ -22,10 +14,7 @@ /* the following is a password that "can't be correct" */ #define BLOCK_PASSWORD "\177BAD PASSWPRD\177" -#ifdef linux -# define _GNU_SOURCE -# include <features.h> -#endif +#include <security/_pam_aconf.h> #include <stdio.h> #include <stdlib.h> @@ -76,7 +65,7 @@ static int converse(pam_handle_t *pamh, int nargs D(("returned from application's conversation function\n")); - if (retval != PAM_SUCCESS) { + if ((retval != PAM_SUCCESS) && (retval != PAM_CONV_AGAIN)) { _pam_log(LOG_DEBUG, "conversation failure [%s]" , pam_strerror(pamh, retval)); } @@ -211,24 +200,33 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc char *prompt=NULL; int i=0; - mesg[i] = &msg[i]; - msg[i].msg_style = PAM_PROMPT_ECHO_OFF; - if (anon) { - prompt = malloc(sizeof(PLEASE_ENTER_PASSWORD + strlen(user))); - sprintf(prompt, PLEASE_ENTER_PASSWORD, user); - msg[i].msg = prompt; + if (!anon) { + prompt = malloc(strlen(PLEASE_ENTER_PASSWORD) + strlen(user)); + if (prompt == NULL) { + D(("out of memory!?")); + return PAM_BUF_ERR; + } else { + sprintf(prompt, PLEASE_ENTER_PASSWORD, user); + msg[i].msg = prompt; + } } else { msg[i].msg = GUEST_LOGIN_PROMPT; } + msg[i].msg_style = PAM_PROMPT_ECHO_OFF; + mesg[i] = &msg[i]; + retval = converse(pamh, ++i, mesg, &resp); - _pam_overwrite(prompt); - _pam_drop(prompt); + if (prompt) { + _pam_overwrite(prompt); + _pam_drop(prompt); + } if (retval != PAM_SUCCESS) { if (resp != NULL) _pam_drop_reply(resp,i); - return PAM_AUTHINFO_UNAVAIL; + return ((retval == PAM_CONV_AGAIN) + ? PAM_INCOMPLETE:PAM_AUTHINFO_UNAVAIL); } if (anon) { @@ -238,11 +236,15 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc token = strtok(resp->resp, "@"); retval = pam_set_item(pamh, PAM_RUSER, token); - if (token && retval != PAM_SUCCESS) { + if ((token) && (retval == PAM_SUCCESS)) { token = strtok(NULL, "@"); retval = pam_set_item(pamh, PAM_RHOST, token); } } + + /* we are happy to grant annonymous access to the user */ + retval = PAM_SUCCESS; + } else { /* * we have a password so set AUTHTOK diff --git a/contrib/libpam/modules/pam_group/Makefile b/contrib/libpam/modules/pam_group/Makefile index 5db53ccf1133..afa888803315 100644 --- a/contrib/libpam/modules/pam_group/Makefile +++ b/contrib/libpam/modules/pam_group/Makefile @@ -1,114 +1,21 @@ -# -# $Id: Makefile,v 1.6 1997/04/05 06:39:56 morgan Exp morgan $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.6 1997/04/05 06:39:56 morgan -# fakeroot -# -# Revision 1.5 1997/01/04 20:28:47 morgan -# compile with and without libpwdb -# -# Revision 1.4 1996/11/10 20:13:18 morgan -# cross platform support -# -# Created by Andrew Morgan <morgan@parc.power.net> 1996/6/11 -# - -TITLE=pam_group -CONFD=$(CONFIGED)/security -export CONFD -CONFILE=$(CONFD)/group.conf -export CONFILE - -# -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) +include ../../Make.Rules -DEFS=-DCONFILE=\"$(CONFILE)\" -ifndef STATIC -ifeq ($(HAVE_PWDBLIB),yes) - DEFS+=-DWANT_PWDB - ELIBS=-lpwdb -endif -endif +TITLE=pam_group +LOCAL_CONFILE=./group.conf +INSTALLED_CONFILE=$(SCONFIGD)/group.conf +DEFS=-DDEFAULT_CONF_FILE=\"$(CONFILE)\" CFLAGS += $(DEFS) -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) $(ELIBS) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) $(ELIBS) -endif - -install: all -ifdef DYNAMIC - $(MKDIR) $(FAKEROOT)$(SECUREDIR) - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - $(MKDIR) $(FAKEROOT)$(SCONFIGED) - bash -f ./install_conf - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - rm -f $(FAKEROOT)$(CONFILE) - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - rm -f ./.ignore_age - -extraclean: clean - rm -f *.a *.o *.so *.bak - -.c.o: - $(CC) $(CFLAGS) -c $< +MODULE_SIMPLE_INSTALL=bash -f ../install_conf "$(FAKEROOT)" "$(SCONFIGD)" "$(INSTALLED_CONFILE)" "$(TITLE)" "$(LOCAL_CONFILE)" +MODULE_SIMPLE_REMOVE=rm -f $(FAKEROOT)$(INSTALLED_CONFILE) +MODULE_SIMPLE_CLEAN=rm -f ./.ignore_age +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_group/group.conf b/contrib/libpam/modules/pam_group/group.conf index bdd76adbe68f..e721b9907eea 100644 --- a/contrib/libpam/modules/pam_group/group.conf +++ b/contrib/libpam/modules/pam_group/group.conf @@ -10,7 +10,7 @@ # *** NOT inherently secure. If a user can create an executable that # *** is setgid a group that they are infrequently given membership # *** of, they can basically obtain group membership any time they -# *** like. Example: games are alowed between the hours of 6pm and 6am +# *** like. Example: games are allowed between the hours of 6pm and 6am # *** user joe logs in at 7pm writes a small C-program toplay.c that # *** invokes their favorite shell, compiles it and does # *** "chgrp games toplay; chmod g+s toplay". They are basically able diff --git a/contrib/libpam/modules/pam_group/pam_group.c b/contrib/libpam/modules/pam_group/pam_group.c index 9e2cf885e9cf..2d04119ad88a 100644 --- a/contrib/libpam/modules/pam_group/pam_group.c +++ b/contrib/libpam/modules/pam_group/pam_group.c @@ -1,32 +1,17 @@ /* pam_group module */ /* - * $Id: pam_group.c,v 1.7 1997/02/15 17:31:48 morgan Exp morgan $ + * $Id: pam_group.c,v 1.3 2000/11/26 07:32:39 agmorgan Exp $ * - * Written by Andrew Morgan <morgan@parc.power.net> 1996/7/6 - * - * $Log: pam_group.c,v $ - * Revision 1.7 1997/02/15 17:31:48 morgan - * time parsing more robust - * - * Revision 1.6 1997/01/04 21:57:49 morgan - * fixed warning about setgroups not being defined - * - * Revision 1.5 1997/01/04 20:26:49 morgan - * can be compiled with and without libpwdb. fixed buffer underwriting - * pays attention to PAM_CRED flags(!) - * - * Revision 1.4 1996/12/01 02:54:37 morgan - * mostly debugging now uses D(()) - * - * Revision 1.3 1996/11/10 21:01:22 morgan - * compatability and pam_get_user changes + * Written by Andrew Morgan <morgan@linux.kernel.org> 1996/7/6 */ const static char rcsid[] = -"$Id: pam_group.c,v 1.7 1997/02/15 17:31:48 morgan Exp morgan $;\n" +"$Id: pam_group.c,v 1.3 2000/11/26 07:32:39 agmorgan Exp $;\n" "Version 0.5 for Linux-PAM\n" -"Copyright (c) Andrew G. Morgan 1996 <morgan@parc.power.net>\n"; +"Copyright (c) Andrew G. Morgan 1996 <morgan@linux.kernel.org>\n"; + +#define _BSD_SOURCE #include <sys/file.h> #include <stdio.h> @@ -38,17 +23,16 @@ const static char rcsid[] = #include <syslog.h> #include <string.h> -#define __USE_BSD #include <grp.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> -#ifdef WANT_PWDB -#include <pwdb/pwdb_public.h> +#ifdef DEFAULT_CONF_FILE +# define PAM_GROUP_CONF DEFAULT_CONF_FILE /* from external define */ +#else +# define PAM_GROUP_CONF "/etc/security/group.conf" #endif - -#define PAM_GROUP_CONF CONFILE /* from external define */ #define PAM_GROUP_BUFLEN 1000 #define FIELD_SEPARATOR ';' /* this is new as of .02 */ @@ -137,6 +121,7 @@ static int read_field(int fd, char **buf, int *from, int *to) _log_err("error reading " PAM_GROUP_CONF); return -1; } else if (!i) { + close(fd); fd = -1; /* end of file reached */ } else *to += i; @@ -180,6 +165,8 @@ static int read_field(int fd, char **buf, int *from, int *to) if ((*buf)[i+1] == '\n') { shift_bytes(i + *buf, 2, *to - (i+2)); *to -= 2; + } else { + ++i; /* we don't escape non-newline characters */ } break; case '!': @@ -260,7 +247,7 @@ static int logic_member(const char *string, int *at) default: if (isalpha(c) || c == '*' || isdigit(c) || c == '_' - || c == '-' || c == '.') { + || c == '-' || c == '.' || c == '/') { token = 1; } else if (token) { --to; diff --git a/contrib/libpam/modules/pam_issue/Makefile b/contrib/libpam/modules/pam_issue/Makefile new file mode 100644 index 000000000000..1bd2be217db5 --- /dev/null +++ b/contrib/libpam/modules/pam_issue/Makefile @@ -0,0 +1,15 @@ +# +# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ +# +# This Makefile controls a build process of $(TITLE) module for +# Linux-PAM. You should not modify this Makefile (unless you know +# what you are doing!). +# +# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27 +# + +include ../../Make.Rules + +TITLE=pam_issue + +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_issue/pam_issue.c b/contrib/libpam/modules/pam_issue/pam_issue.c new file mode 100644 index 000000000000..2cb54bec77d6 --- /dev/null +++ b/contrib/libpam/modules/pam_issue/pam_issue.c @@ -0,0 +1,266 @@ +/* pam_issue module - a simple /etc/issue parser to set PAM_USER_PROMPT + * + * Copyright 1999 by Ben Collins <bcollins@debian.org> + * + * Needs to be called before any other auth modules so we can setup the + * user prompt before it's first used. Allows one argument option, which + * is the full path to a file to be used for issue (uses /etc/issue as a + * default) such as "issue=/etc/issue.telnet". + * + * We can also parse escapes within the the issue file (enabled by + * default, but can be disabled with the "noesc" option). It's the exact + * same parsing as util-linux's agetty program performs. + * + * Released under the GNU LGPL version 2 or later + */ + +#define _GNU_SOURCE +#define _BSD_SOURCE + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <time.h> +#include <fcntl.h> +#include <string.h> +#include <unistd.h> +#include <sys/utsname.h> +#include <utmp.h> +#include <malloc.h> + +#include <security/_pam_macros.h> + +#define PAM_SM_AUTH + +#include <security/pam_modules.h> + +static int _user_prompt_set = 0; + +char *do_prompt (FILE *); + +/* --- authentication management functions (only) --- */ + +PAM_EXTERN +int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + int retval = PAM_SUCCESS; + FILE *fd; + int parse_esc = 1; + char *prompt_tmp = NULL, *cur_prompt = NULL; + struct stat st; + char *issue_file = NULL; + + /* If we've already set the prompt, don't set it again */ + if(_user_prompt_set) + return PAM_IGNORE; + else + /* we set this here so if we fail below, we wont get further + than this next time around (only one real failure) */ + _user_prompt_set = 1; + + for ( ; argc-- > 0 ; ++argv ) { + if (!strncmp(*argv,"issue=",6)) { + issue_file = (char *) strdup(6+*argv); + if (issue_file != NULL) { + D(("set issue_file to: %s", issue_file)); + } else { + D(("failed to strdup issue_file - ignored")); + return PAM_IGNORE; + } + } else if (!strcmp(*argv,"noesc")) { + parse_esc = 0; + D(("turning off escape parsing by request")); + } else + D(("unknown option passed: %s", *argv)); + } + + if (issue_file == NULL) + issue_file = strdup("/etc/issue"); + + if ((fd = fopen(issue_file, "r")) != NULL) { + int tot_size = 0; + + if (stat(issue_file, &st) < 0) + return PAM_IGNORE; + + retval = pam_get_item(pamh, PAM_USER_PROMPT, (const void **) &cur_prompt); + if (retval != PAM_SUCCESS) + return PAM_IGNORE; + + /* first read in the issue file */ + + if (parse_esc) + prompt_tmp = do_prompt(fd); + else { + int count = 0; + prompt_tmp = malloc(st.st_size + 1); + if (prompt_tmp == NULL) return PAM_IGNORE; + memset (prompt_tmp, '\0', st.st_size + 1); + count = fread(prompt_tmp, sizeof(char *), st.st_size, fd); + prompt_tmp[st.st_size] = '\0'; + } + + fclose(fd); + + tot_size = strlen(prompt_tmp) + strlen(cur_prompt) + 1; + + /* + * alloc some extra space for the original prompt + * and postpend it to the buffer + */ + prompt_tmp = realloc(prompt_tmp, tot_size); + strcpy(prompt_tmp+strlen(prompt_tmp), cur_prompt); + + prompt_tmp[tot_size] = '\0'; + + retval = pam_set_item(pamh, PAM_USER_PROMPT, (const char *) prompt_tmp); + + free(issue_file); + free(prompt_tmp); + } else { + D(("could not open issue_file: %s", issue_file)); + return PAM_IGNORE; + } + + return retval; +} + +PAM_EXTERN +int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + return PAM_IGNORE; +} + +char *do_prompt(FILE *fd) +{ + int c, size = 1024; + char *issue = (char *)malloc(size); + char buf[1024]; + struct utsname uts; + + if (issue == NULL || fd == NULL) + return NULL; + + issue[0] = '\0'; /* zero this, for strcat to work on first buf */ + (void) uname(&uts); + + while ((c = getc(fd)) != EOF) { + if (c == '\\') { + c = getc(fd); + switch (c) { + case 's': + snprintf (buf, 1024, "%s", uts.sysname); + break; + case 'n': + snprintf (buf, 1024, "%s", uts.nodename); + break; + case 'r': + snprintf (buf, 1024, "%s", uts.release); + break; + case 'v': + snprintf (buf, 1024, "%s", uts.version); + break; + case 'm': + snprintf (buf, 1024, "%s", uts.machine); + break; + case 'o': + { + char domainname[256]; + + getdomainname(domainname, sizeof(domainname)); + domainname[sizeof(domainname)-1] = '\0'; + snprintf (buf, 1024, "%s", domainname); + } + break; + + case 'd': + case 't': + { + const char *weekday[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", + "Fri", "Sat" }; + const char *month[] = { + "Jan", "Feb", "Mar", "Apr", "May", + "Jun", "Jul", "Aug", "Sep", "Oct", + "Nov", "Dec" }; + time_t now; + struct tm *tm; + + (void) time (&now); + tm = localtime(&now); + + if (c == 'd') + snprintf (buf, 1024, "%s %s %d %d", + weekday[tm->tm_wday], month[tm->tm_mon], + tm->tm_mday, + tm->tm_year + 1900); + else + snprintf (buf, 1024, "%02d:%02d:%02d", + tm->tm_hour, tm->tm_min, tm->tm_sec); + } + break; + case 'l': + { + char *ttyn = ttyname(1); + if (!strncmp(ttyn, "/dev/", 5)) + ttyn += 5; + snprintf (buf, 1024, "%s", ttyn); + } + break; + case 'u': + case 'U': + { + int users = 0; + struct utmp *ut; + setutent(); + while ((ut = getutent())) + if (ut->ut_type == USER_PROCESS) + users++; + endutent(); + printf ("%d ", users); + if (c == 'U') + snprintf (buf, 1024, "%s", (users == 1) ? + " user" : " users"); + break; + } + default: + buf[0] = c; buf[1] = '\0'; + } + if ((strlen(issue) + strlen(buf)) < size + 1) { + size += strlen(buf) + 1; + issue = (char *) realloc (issue, size); + } + strcat(issue, buf); + } else { + buf[0] = c; buf[1] = '\0'; + if ((strlen(issue) + strlen(buf)) < size + 1) { + size += strlen(buf) + 1; + issue = (char *) realloc (issue, size); + } + strcat(issue, buf); + } + } + return issue; +} + +#ifdef PAM_STATIC + +/* static module data */ + +struct pam_module _pam_issue_modstruct = { + "pam_issue", + pam_sm_authenticate, + pam_sm_setcred, + NULL, + NULL, + NULL, + NULL, +}; + +#endif + +/* end of module definition */ diff --git a/contrib/libpam/modules/pam_lastlog/Makefile b/contrib/libpam/modules/pam_lastlog/Makefile index e51a72d31f50..e8062714af81 100644 --- a/contrib/libpam/modules/pam_lastlog/Makefile +++ b/contrib/libpam/modules/pam_lastlog/Makefile @@ -1,106 +1,19 @@ # -# $Id: Makefile,v 1.2 1997/04/05 06:17:14 morgan Exp morgan $ +# $Id: Makefile,v 1.3 2001/02/10 22:33:10 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.2 1997/04/05 06:17:14 morgan -# fakeroot fixed +# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27 # -# Revision 1.1 1997/01/04 20:29:28 morgan -# Initial revision -# -# -# -# Created by Andrew Morgan <morgan@parc.power.net> 1996/12/8 -# - -# Convenient defaults for compiling independently of the full source -# tree. -ifndef FULL_LINUX_PAM_SOURCE_TREE -export DYNAMIC=-DPAM_DYNAMIC -export CC=gcc -export CFLAGS=-O2 -Dlinux -DLINUX_PAM \ - -ansi -D_POSIX_SOURCE -Wall -Wwrite-strings \ - -Wpointer-arith -Wcast-qual -Wcast-align -Wtraditional \ - -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline \ - -Wshadow -pedantic -fPIC -export MKDIR=mkdir -p -export LD_D=gcc -shared -Xlinker -x -endif - -TITLE=pam_lastlog - -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - - -####################### don't edit below ####################### -all: dirs $(LIBSHARED) $(LIBSTATIC) register +include ../../Make.Rules -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) +ifeq ($(HAVE_LIBUTIL),yes) + MODULE_SIMPLE_EXTRALIBS += -lutil endif -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< +TITLE=pam_lastlog +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_lastlog/pam_lastlog.c b/contrib/libpam/modules/pam_lastlog/pam_lastlog.c index 96714f6bc16d..385d96405dd7 100644 --- a/contrib/libpam/modules/pam_lastlog/pam_lastlog.c +++ b/contrib/libpam/modules/pam_lastlog/pam_lastlog.c @@ -1,26 +1,17 @@ /* pam_lastlog module */ /* - * $Id: pam_lastlog.c,v 1.3 1997/04/05 06:18:21 morgan Exp morgan $ + * $Id: pam_lastlog.c,v 1.3 2001/02/10 22:33:10 agmorgan Exp $ * - * Written by Andrew Morgan <morgan@parc.power.net> 1996/3/11 + * Written by Andrew Morgan <morgan@linux.kernel.org> 1996/3/11 * * This module does the necessary work to display the last login * time+date for this user, it then updates this entry for the * present (login) service. - * - * $Log: pam_lastlog.c,v $ - * Revision 1.3 1997/04/05 06:18:21 morgan - * removed xstrdup - unused - * - * Revision 1.2 1997/02/15 17:18:21 morgan - * removed fixed buffer in logging - * - * Revision 1.1 1997/01/04 20:29:28 morgan - * Initial revision - * */ +#include <security/_pam_aconf.h> + #include <fcntl.h> #include <time.h> #ifdef HAVE_UTMP_H diff --git a/contrib/libpam/modules/pam_limits/Makefile b/contrib/libpam/modules/pam_limits/Makefile index f6a0e07ca48b..695bc02df2f5 100644 --- a/contrib/libpam/modules/pam_limits/Makefile +++ b/contrib/libpam/modules/pam_limits/Makefile @@ -1,102 +1,31 @@ # +# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ +# # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# Created by Cristian Gafton <gafton@redhat.com> 1996/09/10 -# - -ifeq ($(OS),linux) -ifeq ($(HAVE_PWDBLIB),yes) -TITLE=pam_limits -CONFD=$(CONFIGED)/security -export CONFD -CONFILE=$(CONFD)/limits.conf -export CONFILE - -CFLAGS+=-DLIMITS_FILE=\"$(CONFILE)\" - -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit -all: dirs $(LIBSHARED) $(LIBSTATIC) register +include ../../Make.Rules -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -lpwdb -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif +TITLE=pam_limits -install: all -ifdef DYNAMIC - $(MKDIR) $(FAKEROOT)$(SECUREDIR) - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - $(MKDIR) $(FAKEROOT)$(SCONFIGED) - bash -f ./install_conf +ifeq ($(OS),linux) -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so +LOCAL_CONFILE=./limits.skel +INSTALLED_CONFILE=$(SCONFIGD)/limits.conf -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ *.so +DEFS=-DDEFAULT_CONF_FILE=\"$(INSTALLED_CONFILE)\" +CFLAGS += $(DEFS) -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* +MODULE_SIMPLE_INSTALL=bash -f ../install_conf "$(FAKEROOT)" "$(SCONFIGD)" "$(INSTALLED_CONFILE)" "$(TITLE)" "$(LOCAL_CONFILE)" +MODULE_SIMPLE_REMOVE=rm -f $(FAKEROOT)$(INSTALLED_CONFILE) +MODULE_SIMPLE_CLEAN=rm -f ./.ignore_age -.c.o: - $(CC) $(CFLAGS) -c $< +include ../Simple.Rules else + include ../dont_makefile -endif -else -include ../dont_makefile + endif diff --git a/contrib/libpam/modules/pam_limits/README b/contrib/libpam/modules/pam_limits/README index 06a6857a8135..2398334b91e7 100644 --- a/contrib/libpam/modules/pam_limits/README +++ b/contrib/libpam/modules/pam_limits/README @@ -4,9 +4,10 @@ pam_limits module: THEORY OF OPERATION: -First, make a root-only-readable file (/etc/limits by default or LIMITS_FILE -defined Makefile) that describes the resource limits you wish to impose. No -limits are imposed on UID 0 accounts. +First, make a root-only-readable file (/etc/security/limits.conf by +default or INSTALLED_CONFILE defined Makefile) that describes the +resource limits you wish to impose. No limits are imposed on UID 0 +accounts. Each line describes a limit for a user in the form: @@ -18,9 +19,10 @@ Where: - a group name, with @group syntax - the wildcard *, for default entry -<type> can have the two values: - - "soft" for enforcinf the soft limits +<type> can have the three values: + - "soft" for enforcing the soft limits - "hard" for enforcing hard limits + - "-" for enforcing both soft and hard limits <item> can be one of the following: - core - limits the core file size (KB) @@ -35,15 +37,18 @@ Where: - as - address space limit - maxlogins - max number of logins for this user - maxsyslogins - max number of logins on the system - -To completely disable limits for a user (or a group), a single dash (-) -will do (Example: 'bin -', '@admin -'). Please remember that individual -limits have priority over group limits, so if you impose no limits for admin -group, but one of the members in this group have a limits line, the user -will have its limits set according to this line. + +Note, if you specify a type of '-' but neglect to supply the item and +value fields then the module will never enforce any limits on the +specified user/group etc. . + +Please remember that individual limits have priority over group +limits, so if you impose no limits for admin group, but one of the +members in this group has a limits line, the user will have its limits +set according to this line. Also, please note that all limit settings are set PER LOGIN. They are -not global, nor are they permanent (the session only) +not global, nor are they permanent (they apply for the session only). In the LIMITS_FILE, the # character introduces a comment - the rest of the line is ignored. @@ -68,6 +73,12 @@ ARGUMENTS RECOGNIZED: conf=/path/to/file the limits configuration file if different from the one set at compile time. + change_uid change real uid to the user for who the limits + are set up. Use this option if you have problems + like login not forking a shell for user who has + no processes. Be warned that something else + may break when you do this. + MODULE SERVICES PROVIDED: session _open_session and _close_session (blank) diff --git a/contrib/libpam/modules/pam_limits/limits.skel b/contrib/libpam/modules/pam_limits/limits.skel index ea57e42513e4..5ddd9b4c38e5 100644 --- a/contrib/libpam/modules/pam_limits/limits.skel +++ b/contrib/libpam/modules/pam_limits/limits.skel @@ -26,6 +26,7 @@ # - nproc - max number of processes # - as - address space limit # - maxlogins - max number of logins for this user +# - priority - the priority to run user process with # #<domain> <type> <item> <value> # diff --git a/contrib/libpam/modules/pam_limits/pam_limits.c b/contrib/libpam/modules/pam_limits/pam_limits.c index 179c43028b4e..7a5ec472579c 100644 --- a/contrib/libpam/modules/pam_limits/pam_limits.c +++ b/contrib/libpam/modules/pam_limits/pam_limits.c @@ -1,6 +1,8 @@ /* * pam_limits - impose resource limits when opening a user session * + * 1.6 - modified for PLD (added process priority settings) + * by Marcin Korzonek <mkorz@shadow.eu.org * 1.5 - Elliot Lee's "max system logins patch" * 1.4 - addressed bug in configuration file parser * 1.3 - modified the configuration file format @@ -15,9 +17,10 @@ #error THIS CODE IS KNOWN TO WORK ONLY ON LINUX !!! #endif +#include <security/_pam_aconf.h> + #include <stdio.h> #include <unistd.h> -#define __USE_POSIX2 #include <string.h> #include <ctype.h> #include <stdlib.h> @@ -26,11 +29,15 @@ #include <sys/types.h> #include <sys/stat.h> #include <sys/resource.h> + #include <utmp.h> #ifndef UT_USER /* some systems have ut_name instead of ut_user */ #define UT_USER ut_user #endif +#include <grp.h> +#include <pwd.h> + /* Module defines */ #define LINE_LENGTH 1024 @@ -39,23 +46,28 @@ #define LIMITS_DEF_DEFAULT 2 /* limit was set by an default entry */ #define LIMITS_DEF_NONE 3 /* this limit was not set yet */ -/* internal data */ -static char conf_file[BUFSIZ]; - struct user_limits_struct { int src_soft; int src_hard; struct rlimit limit; }; -static struct user_limits_struct limits[RLIM_NLIMITS]; -static int login_limit; /* the max logins limit */ -static int login_limit_def; /* which entry set the login limit */ -static int flag_numsyslogins; /* whether to limit logins only for a - specific user or to count all logins */ +/* internal data */ +struct pam_limit_s { + int login_limit; /* the max logins limit */ + int login_limit_def; /* which entry set the login limit */ + int flag_numsyslogins; /* whether to limit logins only for a + specific user or to count all logins */ + int priority; /* the priority to run user process with */ + struct user_limits_struct limits[RLIM_NLIMITS]; + char conf_file[BUFSIZ]; +}; #define LIMIT_LOGIN RLIM_NLIMITS+1 #define LIMIT_NUMSYSLOGINS RLIM_NLIMITS+2 + +#define LIMIT_PRI RLIM_NLIMITS+3 + #define LIMIT_SOFT 1 #define LIMIT_HARD 2 @@ -63,7 +75,6 @@ static int flag_numsyslogins; /* whether to limit logins only for a #include <security/pam_modules.h> #include <security/_pam_macros.h> -#include <pwdb/pwdb_map.h> /* logging */ static void _pam_log(int err, const char *format, ...) @@ -80,8 +91,9 @@ static void _pam_log(int err, const char *format, ...) /* argument parsing */ #define PAM_DEBUG_ARG 0x0001 +#define PAM_DO_SETREUID 0x0002 -static int _pam_parse(int argc, const char **argv) +static int _pam_parse(int argc, const char **argv, struct pam_limit_s *pl) { int ctrl=0; @@ -93,7 +105,9 @@ static int _pam_parse(int argc, const char **argv) if (!strcmp(*argv,"debug")) ctrl |= PAM_DEBUG_ARG; else if (!strncmp(*argv,"conf=",5)) - strcpy(conf_file,*argv+5); + strcpy(pl->conf_file,*argv+5); + else if (!strncmp(*argv,"change_uid",10)) + ctrl |= PAM_DO_SETREUID; else { _pam_log(LOG_ERR,"pam_parse: unknown option; %s",*argv); } @@ -104,15 +118,18 @@ static int _pam_parse(int argc, const char **argv) /* limits stuff */ -#ifndef LIMITS_FILE -#define LIMITS_FILE "/etc/security/limits.conf" +#ifdef DEFAULT_CONF_FILE +# define LIMITS_FILE DEFAULT_CONF_FILE +#else +# define LIMITS_FILE "/etc/security/limits.conf" #endif #define LIMIT_ERR 1 /* error setting a limit */ #define LOGIN_ERR 2 /* too many logins err */ /* Counts the number of user logins and check against the limit*/ -static int check_logins(const char *name, int limit, int ctrl) +static int check_logins(const char *name, int limit, int ctrl, + struct pam_limit_s *pl) { struct utmp *ut; unsigned int count; @@ -137,7 +154,7 @@ static int check_logins(const char *name, int limit, int ctrl) #endif if (ut->UT_USER[0] == '\0') continue; - if (!flag_numsyslogins + if (!pl->flag_numsyslogins && strncmp(name, ut->UT_USER, sizeof(ut->UT_USER)) != 0) continue; if (++count >= limit) @@ -212,65 +229,61 @@ static int is_on_group(const char *user_name, const char *group_name) return 0; } -static int init_limits(void) +static int init_limits(struct pam_limit_s *pl) { + int i; int retval = PAM_SUCCESS; D(("called.")); - retval |= getrlimit(RLIMIT_CPU, &limits[RLIMIT_CPU].limit); - limits[RLIMIT_CPU].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_CPU].src_hard = LIMITS_DEF_NONE; + for(i = 0; i < RLIM_NLIMITS; i++) + retval |= getrlimit(i, &pl->limits[i].limit); + + pl->limits[RLIMIT_CPU].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_CPU].src_hard = LIMITS_DEF_NONE; + + pl->limits[RLIMIT_FSIZE].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_FSIZE].src_hard = LIMITS_DEF_NONE; - retval |= getrlimit(RLIMIT_FSIZE, &limits[RLIMIT_FSIZE].limit); - limits[RLIMIT_FSIZE].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_FSIZE].src_hard = LIMITS_DEF_NONE; + pl->limits[RLIMIT_DATA].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_DATA].src_hard = LIMITS_DEF_NONE; - retval |= getrlimit(RLIMIT_DATA, &limits[RLIMIT_DATA].limit); - limits[RLIMIT_DATA].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_DATA].src_hard = LIMITS_DEF_NONE; + pl->limits[RLIMIT_STACK].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_STACK].src_hard = LIMITS_DEF_NONE; - retval |= getrlimit(RLIMIT_STACK, &limits[RLIMIT_STACK].limit); - limits[RLIMIT_STACK].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_STACK].src_hard = LIMITS_DEF_NONE; + pl->limits[RLIMIT_CORE].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_CORE].src_hard = LIMITS_DEF_NONE; - retval |= getrlimit(RLIMIT_CORE, &limits[RLIMIT_CORE].limit); - limits[RLIMIT_CORE].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_CORE].src_hard = LIMITS_DEF_NONE; + pl->limits[RLIMIT_RSS].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_RSS].src_hard = LIMITS_DEF_NONE; - retval |= getrlimit(RLIMIT_RSS, &limits[RLIMIT_RSS].limit); - limits[RLIMIT_RSS].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_RSS].src_hard = LIMITS_DEF_NONE; + pl->limits[RLIMIT_NPROC].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_NPROC].src_hard = LIMITS_DEF_NONE; - retval |= getrlimit(RLIMIT_NPROC, &limits[RLIMIT_NPROC].limit); - limits[RLIMIT_NPROC].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_NPROC].src_hard = LIMITS_DEF_NONE; + pl->limits[RLIMIT_NOFILE].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_NOFILE].src_hard = LIMITS_DEF_NONE; - retval |= getrlimit(RLIMIT_NOFILE, &limits[RLIMIT_NOFILE].limit); - limits[RLIMIT_NOFILE].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_NOFILE].src_hard = LIMITS_DEF_NONE; + pl->limits[RLIMIT_MEMLOCK].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_MEMLOCK].src_hard = LIMITS_DEF_NONE; - retval |= getrlimit(RLIMIT_MEMLOCK, &limits[RLIMIT_MEMLOCK].limit); - limits[RLIMIT_MEMLOCK].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_MEMLOCK].src_hard = LIMITS_DEF_NONE; + pl->limits[RLIMIT_AS].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_AS].src_hard = LIMITS_DEF_NONE; - retval |= getrlimit(RLIMIT_AS, &limits[RLIMIT_AS].limit); - limits[RLIMIT_AS].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_AS].src_hard = LIMITS_DEF_NONE; + pl->priority = 0; + pl->login_limit = -2; + pl->login_limit_def = LIMITS_DEF_NONE; - login_limit = -2; - login_limit_def = LIMITS_DEF_NONE; return retval; } static void process_limit(int source, const char *lim_type, const char *lim_item, const char *lim_value, - int ctrl) + int ctrl, struct pam_limit_s *pl) { int limit_item; int limit_type = 0; long limit_value; - char **endptr = (char **) &lim_value; + const char **endptr = &lim_value; const char *value_orig = lim_value; if (ctrl & PAM_DEBUG_ARG) @@ -299,10 +312,12 @@ static void process_limit(int source, const char *lim_type, limit_item = RLIMIT_AS; else if (strcmp(lim_item, "maxlogins") == 0) { limit_item = LIMIT_LOGIN; - flag_numsyslogins = 0; + pl->flag_numsyslogins = 0; } else if (strcmp(lim_item, "maxsyslogins") == 0) { limit_item = LIMIT_NUMSYSLOGINS; - flag_numsyslogins = 1; + pl->flag_numsyslogins = 1; + } else if (strcmp(lim_item, "priority") == 0) { + limit_item = LIMIT_PRI; } else { _pam_log(LOG_DEBUG,"unknown limit item '%s'", lim_item); return; @@ -349,38 +364,47 @@ static void process_limit(int source, const char *lim_type, break; } - if (limit_item != LIMIT_LOGIN && limit_item != LIMIT_NUMSYSLOGINS) { - if (limit_type & LIMIT_SOFT) - if (limits[limit_item].src_soft < source) + if (limit_item != LIMIT_LOGIN && limit_item != LIMIT_NUMSYSLOGINS + && limit_item != LIMIT_PRI + ) { + if (limit_type & LIMIT_SOFT) { + if (pl->limits[limit_item].src_soft < source) { return; - else { - limits[limit_item].limit.rlim_cur = limit_value; - limits[limit_item].src_soft = source; + } else { + pl->limits[limit_item].limit.rlim_cur = limit_value; + pl->limits[limit_item].src_soft = source; } - if (limit_type & LIMIT_HARD) - if (limits[limit_item].src_hard < source) + } + if (limit_type & LIMIT_HARD) { + if (pl->limits[limit_item].src_hard < source) { return; - else { - limits[limit_item].limit.rlim_max = limit_value; - limits[limit_item].src_hard = source; + } else { + pl->limits[limit_item].limit.rlim_max = limit_value; + pl->limits[limit_item].src_hard = source; } - } else - if (login_limit_def < source) - return; - else { - login_limit = limit_value; - login_limit_def = source; - } - - return; + } + } else + if (limit_item == LIMIT_PRI) { + /* additional check */ + pl->priority = ((limit_value>0)?limit_value:0); + } else { + if (pl->login_limit_def < source) { + return; + } else { + pl->login_limit = limit_value; + pl->login_limit_def = source; + } + } + return; } -static int parse_config_file(const char *uname, int ctrl) +static int parse_config_file(const char *uname, int ctrl, + struct pam_limit_s *pl) { FILE *fil; char buf[LINE_LENGTH]; -#define CONF_FILE (conf_file[0])?conf_file:LIMITS_FILE +#define CONF_FILE (pl->conf_file[0])?pl->conf_file:LIMITS_FILE /* check for the LIMITS_FILE */ if (ctrl & PAM_DEBUG_ARG) _pam_log(LOG_DEBUG,"reading settings from '%s'", CONF_FILE); @@ -428,6 +452,9 @@ static int parse_config_file(const char *uname, int ctrl) memset(value, 0, sizeof(value)); i = sscanf(buf,"%s%s%s%s", domain, ltype, item, value); + D(("scanned line[%d]: domain[%s], ltype[%s], item[%s], value[%s]", + i, domain, ltype, item, value)); + for(j=0; j < strlen(domain); j++) domain[j]=tolower(domain[j]); for(j=0; j < strlen(ltype); j++) @@ -439,36 +466,56 @@ static int parse_config_file(const char *uname, int ctrl) if (i == 4) { /* a complete line */ if (strcmp(uname, domain) == 0) /* this user have a limit */ - process_limit(LIMITS_DEF_USER, ltype, item, value, ctrl); + process_limit(LIMITS_DEF_USER, ltype, item, value, ctrl, pl); else if (domain[0]=='@') { if (is_on_group(uname, domain+1)) - process_limit(LIMITS_DEF_GROUP, ltype, item, value, ctrl); + process_limit(LIMITS_DEF_GROUP, ltype, item, value, ctrl, + pl); } else if (strcmp(domain, "*") == 0) - process_limit(LIMITS_DEF_DEFAULT, ltype, item, value, ctrl); - } else - _pam_log(LOG_DEBUG,"invalid line '%s'", buf); + process_limit(LIMITS_DEF_DEFAULT, ltype, item, value, ctrl, + pl); + } else if (i == 2 && ltype[0] == '-') { /* Probably a no-limit line */ + if (strcmp(uname, domain) == 0) { + _pam_log(LOG_DEBUG, "no limits for '%s'", uname); + fclose(fil); + return PAM_IGNORE; + } else if (domain[0] == '@' && is_on_group(uname, domain+1)) { + _pam_log(LOG_DEBUG, "no limits for '%s' in group '%s'", + uname, domain+1); + fclose(fil); + return PAM_IGNORE; + } + } else { + _pam_log(LOG_DEBUG,"invalid line '%s' - skipped", buf); + } } fclose(fil); return PAM_SUCCESS; } -static int setup_limits(const char * uname, int ctrl) +static int setup_limits(const char * uname, int ctrl, struct pam_limit_s *pl) { int i; int retval = PAM_SUCCESS; for (i=0; i<RLIM_NLIMITS; i++) { - if (limits[i].limit.rlim_cur > limits[i].limit.rlim_max) - limits[i].limit.rlim_cur = limits[i].limit.rlim_max; - retval |= setrlimit(i, &limits[i].limit); + if (pl->limits[i].limit.rlim_cur > pl->limits[i].limit.rlim_max) + pl->limits[i].limit.rlim_cur = pl->limits[i].limit.rlim_max; + retval |= setrlimit(i, &pl->limits[i].limit); } if (retval != PAM_SUCCESS) retval = LIMIT_ERR; - if (login_limit > 0) { - if (check_logins(uname, login_limit, ctrl) == LOGIN_ERR) + + retval=setpriority(PRIO_PROCESS, 0, pl->priority); + + if (retval != PAM_SUCCESS) + retval = LIMIT_ERR; + + if (pl->login_limit > 0) { + if (check_logins(uname, pl->login_limit, ctrl, pl) == LOGIN_ERR) retval |= LOGIN_ERR; - } else if (login_limit == 0) + } else if (pl->login_limit == 0) retval |= LOGIN_ERR; return retval; } @@ -481,12 +528,13 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, char *user_name; struct passwd *pwd; int ctrl; - + struct pam_limit_s pl; + D(("called.")); - memset(conf_file, 0, sizeof(conf_file)); - - ctrl = _pam_parse(argc, argv); + memset(&pl, 0, sizeof(pl)); + + ctrl = _pam_parse(argc, argv, &pl); retval = pam_get_item( pamh, PAM_USER, (void*) &user_name ); if ( user_name == NULL || retval != PAM_SUCCESS ) { _pam_log(LOG_CRIT, "open_session - error recovering username"); @@ -511,19 +559,25 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, return PAM_SUCCESS; } - retval = init_limits(); + retval = init_limits(&pl); if (retval != PAM_SUCCESS) { - _pam_log(LOG_WARNING, "can not initialize"); + _pam_log(LOG_WARNING, "cannot initialize"); return PAM_IGNORE; } - retval = parse_config_file(pwd->pw_name,ctrl); + retval = parse_config_file(pwd->pw_name, ctrl, &pl); + if (retval == PAM_IGNORE) { + D(("the configuration file has an applicable '<domain> -' entry")); + return PAM_SUCCESS; + } if (retval != PAM_SUCCESS) { _pam_log(LOG_WARNING, "error parsing the configuration file"); return PAM_IGNORE; } - - retval = setup_limits(pwd->pw_name, ctrl); + + if (ctrl & PAM_DO_SETREUID) + setreuid(pwd->pw_uid, -1); + retval = setup_limits(pwd->pw_name, ctrl, &pl); if (retval & LOGIN_ERR) { printf("\nToo many logins for '%s'\n",pwd->pw_name); sleep(2); diff --git a/contrib/libpam/modules/pam_listfile/Makefile b/contrib/libpam/modules/pam_listfile/Makefile index 02940390b333..c5447c949cf7 100644 --- a/contrib/libpam/modules/pam_listfile/Makefile +++ b/contrib/libpam/modules/pam_listfile/Makefile @@ -1,84 +1,15 @@ # +# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ +# # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # - -TITLE=pam_listfile - +# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27 # -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit +include ../../Make.Rules -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< +TITLE=pam_listfile +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_listfile/pam_listfile.c b/contrib/libpam/modules/pam_listfile/pam_listfile.c index e54b12aaec0c..2f4f3d0bf98a 100644 --- a/contrib/libpam/modules/pam_listfile/pam_listfile.c +++ b/contrib/libpam/modules/pam_listfile/pam_listfile.c @@ -1,39 +1,16 @@ /* - * $Id: pam_listfile.c,v 1.6 1997/04/05 06:38:35 morgan Exp $ - * - * $Log: pam_listfile.c,v $ - * Revision 1.6 1997/04/05 06:38:35 morgan - * reformat mostly - * - * Revision 1.5 1997/02/15 17:29:41 morgan - * removed fixed length buffer in logging - * - * Revision 1.4 1997/01/04 20:32:10 morgan - * ammendments for pam_listfile handling - * - * Revision 1.3 1996/11/10 21:02:08 morgan - * compiles with .53 - * - * Revision 1.2 1996/09/05 06:22:58 morgan - * Michael's patches + * $Id: pam_listfile.c,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ * */ /* - * by Elliot Lee <sopwith@redhat.com>, Red Hat Software. - * July 25, 1996. - * This code shamelessly ripped from the pam_rootok module. + * by Elliot Lee <sopwith@redhat.com>, Red Hat Software. July 25, 1996. + * log refused access error christopher mccrory <chrismcc@netus.com> 1998/7/11 + * + * This code began life as the pam_rootok module. */ -#ifdef linux -# define _SVID_SOURCE -# define _BSD_SOURCE -# define __USE_BSD -# define __USE_SVID -# define __USE_MISC -# define _GNU_SOURCE -# include <features.h> -#endif +#include <security/_pam_aconf.h> #include <stdio.h> #include <stdlib.h> @@ -64,15 +41,15 @@ /* some syslogging */ +#define LOCAL_LOG_PREFIX "PAM-listfile: " + static void _pam_log(int err, const char *format, ...) { va_list args; - + va_start(args, format); - openlog("PAM-listfile", LOG_CONS|LOG_PID, LOG_AUTH); - vsyslog(err, format, args); + vsyslog(LOG_AUTH | err, format, args); va_end(args); - closelog(); } /* checks if a user is on a list of members */ @@ -223,36 +200,41 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar strncpy(apply_val,myval,sizeof(apply_val)-1); } } else { - _pam_log(LOG_ERR,"Unknown option: %s",mybuf); + _pam_log(LOG_ERR,LOCAL_LOG_PREFIX "Unknown option: %s",mybuf); return onerr; } } if(!citem) { - _pam_log(LOG_ERR,"Unknown item or item not specified"); + _pam_log(LOG_ERR, + LOCAL_LOG_PREFIX "Unknown item or item not specified"); return onerr; } else if(!ifname) { - _pam_log(LOG_ERR,"List filename not specified"); + _pam_log(LOG_ERR,LOCAL_LOG_PREFIX "List filename not specified"); return onerr; } else if(sense == 2) { - _pam_log(LOG_ERR,"Unknown sense or sense not specified"); + _pam_log(LOG_ERR, + LOCAL_LOG_PREFIX "Unknown sense or sense not specified"); return onerr; } else if( (apply_type==APPLY_TYPE_NONE) || ((apply_type!=APPLY_TYPE_NULL) && (*apply_val=='\0')) ) { - _pam_log(LOG_ERR,"Invalid usage for apply= parameter"); + _pam_log(LOG_ERR, + LOCAL_LOG_PREFIX "Invalid usage for apply= parameter"); return onerr; } /* Check if it makes sense to use the apply= parameter */ if (apply_type != APPLY_TYPE_NULL) { if((citem==PAM_USER) || (citem==PAM_RUSER)) { - _pam_log(LOG_WARNING,"Non-sense use for apply= parameter"); + _pam_log(LOG_WARNING, + LOCAL_LOG_PREFIX "Non-sense use for apply= parameter"); apply_type=APPLY_TYPE_NULL; } if(extitem && (extitem==EI_GROUP)) { - _pam_log(LOG_WARNING,"Non-sense use for apply= parameter"); + _pam_log(LOG_WARNING, + LOCAL_LOG_PREFIX "Non-sense use for apply= parameter"); apply_type=APPLY_TYPE_NULL; } } @@ -269,7 +251,8 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar if(strcmp(user_name, apply_val)) { /* Does not apply to this user */ #ifdef DEBUG - _pam_log(LOG_DEBUG,"don't apply: apply=%s, user=%s", + _pam_log(LOG_DEBUG, + LOCAL_LOG_PREFIX "don't apply: apply=%s, user=%s", apply_val,user_name); #endif /* DEBUG */ return PAM_IGNORE; @@ -278,7 +261,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar if(!is_on_group(user_name,apply_val)) { /* Not a member of apply= group */ #ifdef DEBUG - _pam_log(LOG_DEBUG,"don't apply: %s not a member of group %s", + _pam_log(LOG_DEBUG, + LOCAL_LOG_PREFIX + "don't apply: %s not a member of group %s", user_name,apply_val); #endif /* DEBUG */ return PAM_IGNORE; @@ -331,18 +316,21 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar endpwent(); break; default: - _pam_log(LOG_ERR,"Internal weirdness, unknown extended item %d", + _pam_log(LOG_ERR, + LOCAL_LOG_PREFIX + "Internal weirdness, unknown extended item %d", extitem); return onerr; } } #ifdef DEBUG - _pam_log(LOG_INFO,"Got file = %s, item = %d, value = %s, sense = %d", + _pam_log(LOG_INFO, + LOCAL_LOG_PREFIX + "Got file = %s, item = %d, value = %s, sense = %d", ifname, citem, citemp, sense); #endif if(lstat(ifname,&fileinfo)) { - _pam_log(LOG_ERR, - "Couldn't open %s",ifname); + _pam_log(LOG_ERR,LOCAL_LOG_PREFIX "Couldn't open %s",ifname); return onerr; } @@ -350,7 +338,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar || !S_ISREG(fileinfo.st_mode)) { /* If the file is world writable or is not a normal file, return error */ - _pam_log(LOG_ERR, + _pam_log(LOG_ERR,LOCAL_LOG_PREFIX "%s is either world writable or not a normal file", ifname); return PAM_AUTH_ERR; @@ -360,7 +348,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar if(inf == NULL) { /* Check that we opened it successfully */ if (onerr == PAM_SERVICE_ERR) { /* Only report if it's an error... */ - _pam_log(LOG_ERR, "Error opening %s", ifname); + _pam_log(LOG_ERR,LOCAL_LOG_PREFIX "Error opening %s", ifname); } return onerr; } @@ -394,19 +382,24 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar } fclose(inf); free(ifname); - if(retval) { + if ((sense && retval) || (!sense && !retval)) { #ifdef DEBUG - syslog(LOG_INFO,"Returning %d, retval = %d", - sense?PAM_AUTH_ERR:PAM_SUCCESS, retval); + _pam_log(LOG_INFO, LOCAL_LOG_PREFIX + "Returning PAM_SUCCESS, retval = %d", retval); #endif - return sense?PAM_SUCCESS:PAM_AUTH_ERR; + return PAM_SUCCESS; } else { + const char *service, *user_name; #ifdef DEBUG - syslog(LOG_INFO,"Returning %d, retval = %d", - sense?PAM_SUCCESS:PAM_AUTH_ERR, retval); + _pam_log(LOG_INFO,LOCAL_LOG_PREFIX + "Returning PAM_AUTH_ERR, retval = %d", retval); #endif - return sense?PAM_AUTH_ERR:PAM_SUCCESS; + (void) pam_get_item(pamh, PAM_SERVICE, (const void **)&service); + (void) pam_get_user(pamh, &user_name, NULL); + _pam_log(LOG_ALERT,LOCAL_LOG_PREFIX "Refused user %s for service %s", + user_name, service); + return PAM_AUTH_ERR; } } diff --git a/contrib/libpam/modules/pam_mail/Makefile b/contrib/libpam/modules/pam_mail/Makefile index 5a402ea4015b..2d9b8e9a30a3 100644 --- a/contrib/libpam/modules/pam_mail/Makefile +++ b/contrib/libpam/modules/pam_mail/Makefile @@ -1,107 +1,15 @@ # -# $Id: Makefile,v 1.3 1997/04/05 06:37:45 morgan Exp $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.3 1997/04/05 06:37:45 morgan -# fakeroot +# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27 # -# Revision 1.2 1997/02/15 16:07:22 morgan -# optional libpwdb compilation -# -# Revision 1.1 1997/01/04 20:32:52 morgan -# Initial revision -# -# -# -# Created by Andrew Morgan <morgan@parc.power.net> 1996/12/8 -# - -TITLE=pam_mail - -ifndef STATIC -ifeq ($(HAVE_PWDBLIB),yes) -CFLAGS += -DWANT_PWDB -EXTRALIB = -lpwdb -endif -endif - -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif +include ../../Make.Rules -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) $(EXTRALIB) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) $(EXTRALIB) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< +TITLE=pam_mail +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_mail/README b/contrib/libpam/modules/pam_mail/README new file mode 100644 index 000000000000..155bd1db66dc --- /dev/null +++ b/contrib/libpam/modules/pam_mail/README @@ -0,0 +1,17 @@ +This is the README for pam_mail +------------------------------- + +This PAM module tells the User that he has new/unread email. + +Options for: +auth: for authentication it provides pam_authenticate() and + pam_setcred() hooks. + + "debug" write more information to syslog + "dir=maildir" users mailbox is maildir/<login> + "hash=count" mail directory hash depth + "close" print message also on logout + "nopen" print message not on login + "noenv" don't set the MAIL environment variable + "empty" also print message if user has no mail + diff --git a/contrib/libpam/modules/pam_mail/pam_mail.c b/contrib/libpam/modules/pam_mail/pam_mail.c index 15160f3d5208..df00315ab304 100644 --- a/contrib/libpam/modules/pam_mail/pam_mail.c +++ b/contrib/libpam/modules/pam_mail/pam_mail.c @@ -1,29 +1,14 @@ /* pam_mail module */ /* - * $Id: pam_mail.c,v 1.2 1997/02/15 16:06:14 morgan Exp morgan $ + * $Id: pam_mail.c,v 1.3 2000/12/04 20:59:13 baggins Exp $ * - * Written by Andrew Morgan <morgan@parc.power.net> 1996/3/11 + * Written by Andrew Morgan <morgan@linux.kernel.org> 1996/3/11 * $HOME additions by David Kinchlea <kinch@kinch.ark.com> 1997/1/7 - * - * $Log: pam_mail.c,v $ - * Revision 1.2 1997/02/15 16:06:14 morgan - * session -> setcred, also added "~"=$HOME - * - * Revision 1.1 1997/01/04 20:33:02 morgan - * Initial revision + * mailhash additions by Chris Adams <cadams@ro.com> 1998/7/11 */ -#define DEFAULT_MAIL_DIRECTORY "/var/spool/mail" -#define MAIL_FILE_FORMAT "%s/%s" -#define MAIL_ENV_NAME "MAIL" -#define MAIL_ENV_FORMAT MAIL_ENV_NAME "=%s" -#define YOUR_MAIL_FORMAT "You have %s mail in %s" - -#ifdef linux -# define _GNU_SOURCE -# include <features.h> -#endif +#include <security/_pam_aconf.h> #include <ctype.h> #include <pwd.h> @@ -35,11 +20,20 @@ #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> +#include <dirent.h> #ifdef WANT_PWDB #include <pwdb/pwdb_public.h> #endif +#define DEFAULT_MAIL_DIRECTORY PAM_PATH_MAILDIR +#define MAIL_FILE_FORMAT "%s%s/%s" +#define MAIL_ENV_NAME "MAIL" +#define MAIL_ENV_FORMAT MAIL_ENV_NAME "=%s" +#define YOUR_MAIL_VERBOSE_FORMAT "You have %s mail in %s." +#define YOUR_MAIL_STANDARD_FORMAT "You have %smail." +#define NO_MAIL_STANDARD_FORMAT "No mail." + /* * here, we make a definition for the externally accessible function * in this file (this definition is required for static a module @@ -47,6 +41,7 @@ * modules include file to define the function prototypes. */ +#define PAM_SM_SESSION #define PAM_SM_AUTH #include <security/pam_modules.h> @@ -67,16 +62,19 @@ static void _log_err(int err, const char *format, ...) /* argument parsing */ -#define PAM_DEBUG_ARG 01 -#define PAM_NO_LOGIN 02 -#define PAM_LOGOUT_TOO 04 -#define PAM_NEW_MAIL_DIR 010 -#define PAM_MAIL_SILENT 020 -#define PAM_NO_ENV 040 -#define PAM_HOME_MAIL 0100 -#define PAM_EMPTY_TOO 0200 - -static int _pam_parse(int flags, int argc, const char **argv, char **maildir) +#define PAM_DEBUG_ARG 0x0001 +#define PAM_NO_LOGIN 0x0002 +#define PAM_LOGOUT_TOO 0x0004 +#define PAM_NEW_MAIL_DIR 0x0010 +#define PAM_MAIL_SILENT 0x0020 +#define PAM_NO_ENV 0x0040 +#define PAM_HOME_MAIL 0x0100 +#define PAM_EMPTY_TOO 0x0200 +#define PAM_STANDARD_MAIL 0x0400 +#define PAM_QUIET_MAIL 0x1000 + +static int _pam_parse(int flags, int argc, const char **argv, char **maildir, + int *hashcount) { int ctrl=0; @@ -84,6 +82,8 @@ static int _pam_parse(int flags, int argc, const char **argv, char **maildir) ctrl |= PAM_MAIL_SILENT; } + *hashcount = 0; + /* step through arguments */ for (; argc-- > 0; ++argv) { @@ -91,6 +91,10 @@ static int _pam_parse(int flags, int argc, const char **argv, char **maildir) if (!strcmp(*argv,"debug")) ctrl |= PAM_DEBUG_ARG; + else if (!strcmp(*argv,"quiet")) + ctrl |= PAM_QUIET_MAIL; + else if (!strcmp(*argv,"standard")) + ctrl |= PAM_STANDARD_MAIL | PAM_EMPTY_TOO; else if (!strncmp(*argv,"dir=",4)) { *maildir = x_strdup(4+*argv); if (*maildir != NULL) { @@ -100,6 +104,12 @@ static int _pam_parse(int flags, int argc, const char **argv, char **maildir) _log_err(LOG_CRIT, "failed to duplicate mail directory - ignored"); } + } else if (!strncmp(*argv,"hash=",5)) { + char *ep = NULL; + *hashcount = strtol(*argv+5,&ep,10); + if (!ep || (*hashcount < 0)) { + *hashcount = 0; + } } else if (!strcmp(*argv,"close")) { ctrl |= PAM_LOGOUT_TOO; } else if (!strcmp(*argv,"nopen")) { @@ -113,6 +123,11 @@ static int _pam_parse(int flags, int argc, const char **argv, char **maildir) } } + if ((*hashcount != 0) && !(ctrl & PAM_NEW_MAIL_DIR)) { + *maildir = x_strdup(DEFAULT_MAIL_DIRECTORY); + ctrl |= PAM_NEW_MAIL_DIR; + } + return ctrl; } @@ -150,8 +165,8 @@ static int converse(pam_handle_t *pamh, int ctrl, int nargs return retval; /* propagate error status */ } -static int get_folder(pam_handle_t *pamh, int ctrl - , char **path_mail, char **folder_p) +static int get_folder(pam_handle_t *pamh, int ctrl, + char **path_mail, char **folder_p, int hashcount) { int retval; const char *user, *path; @@ -184,6 +199,9 @@ static int get_folder(pam_handle_t *pamh, int ctrl return PAM_ABORT; } ctrl |= PAM_HOME_MAIL; + if (hashcount != 0) { + _log_err(LOG_ALERT, "can't do hash= and home directory mail"); + } } } else { path = DEFAULT_MAIL_DIRECTORY; @@ -195,14 +213,29 @@ static int get_folder(pam_handle_t *pamh, int ctrl folder = malloc(sizeof(MAIL_FILE_FORMAT) +strlen(pwd->pw_dir)+strlen(path)); } else { - folder = malloc(sizeof(MAIL_FILE_FORMAT)+strlen(path)+strlen(user)); + folder = malloc(sizeof(MAIL_FILE_FORMAT)+strlen(path)+strlen(user) + +2*hashcount); } if (folder != NULL) { if (ctrl & PAM_HOME_MAIL) { - sprintf(folder, MAIL_FILE_FORMAT, pwd->pw_dir, path); + sprintf(folder, MAIL_FILE_FORMAT, pwd->pw_dir, "", path); } else { - sprintf(folder, MAIL_FILE_FORMAT, path, user); + int i; + char *hash = malloc(2*hashcount+1); + + if (hash) { + for (i = 0; i < hashcount; i++) { + hash[2*i] = '/'; + hash[2*i+1] = user[i]; + } + hash[2*i] = '\0'; + sprintf(folder, MAIL_FILE_FORMAT, path, hash, user); + _pam_overwrite(hash); + _pam_drop(hash); + } else { + sprintf(folder, "error"); + } } D(("folder =[%s]", folder)); } @@ -226,17 +259,52 @@ static int get_folder(pam_handle_t *pamh, int ctrl static const char *get_mail_status(int ctrl, const char *folder) { - const char *type; + const char *type = NULL; + static char dir[256]; struct stat mail_st; - - if (stat(folder, &mail_st) == 0 && mail_st.st_size > 0) { - type = (mail_st.st_atime < mail_st.st_mtime) ? "new":"old" ; - } else if (ctrl & PAM_EMPTY_TOO) { - type = "no"; - } else { - type = NULL; + struct dirent **namelist; + int i; + + if (stat(folder, &mail_st) == 0) { + if (S_ISDIR(mail_st.st_mode)) { /* Assume Maildir format */ + sprintf(dir, "%.250s/new", folder); + i = scandir(dir, &namelist, 0, alphasort); + if (i > 2) { + type = "new"; + while (--i) + free(namelist[i]); + } else { + while (--i >= 0) + free(namelist[i]); + sprintf(dir, "%.250s/cur", folder); + i = scandir(dir, &namelist, 0, alphasort); + if (i > 2) { + type = "old"; + while (--i) + free(namelist[i]); + } else if (ctrl & PAM_EMPTY_TOO) { + while (--i >= 0) + free(namelist[i]); + type = "no"; + } else { + type = NULL; + } + } + } else { + if (mail_st.st_size > 0) { + if (mail_st.st_atime < mail_st.st_mtime) /* new */ + type = (ctrl & PAM_STANDARD_MAIL) ? "new " : "new"; + else /* old */ + type = (ctrl & PAM_STANDARD_MAIL) ? "" : "old"; + } else if (ctrl & PAM_EMPTY_TOO) { + type = "no"; + } else { + type = NULL; + } + } } + memset(dir, 0, 256); memset(&mail_st, 0, sizeof(mail_st)); D(("user has %s mail in %s folder", type, folder)); return type; @@ -247,17 +315,29 @@ static int report_mail(pam_handle_t *pamh, int ctrl { int retval; - if (!(ctrl & PAM_MAIL_SILENT)) { + if (!(ctrl & PAM_MAIL_SILENT) || ((ctrl & PAM_QUIET_MAIL) && strcmp(type, "new"))) { char *remark; - remark = malloc(sizeof(YOUR_MAIL_FORMAT)+strlen(type)+strlen(folder)); + if (ctrl & PAM_STANDARD_MAIL) + if (!strcmp(type, "no")) + remark = malloc(strlen(NO_MAIL_STANDARD_FORMAT)+1); + else + remark = malloc(strlen(YOUR_MAIL_STANDARD_FORMAT)+strlen(type)+1); + else + remark = malloc(strlen(YOUR_MAIL_VERBOSE_FORMAT)+strlen(type)+strlen(folder)+1); if (remark == NULL) { retval = PAM_BUF_ERR; } else { struct pam_message msg[1], *mesg[1]; struct pam_response *resp=NULL; - sprintf(remark, YOUR_MAIL_FORMAT, type, folder); + if (ctrl & PAM_STANDARD_MAIL) + if (!strcmp(type, "no")) + sprintf(remark, NO_MAIL_STANDARD_FORMAT); + else + sprintf(remark, YOUR_MAIL_STANDARD_FORMAT, type); + else + sprintf(remark, YOUR_MAIL_VERBOSE_FORMAT, type, folder); mesg[0] = &msg[0]; msg[0].msg_style = PAM_TEXT_INFO; @@ -279,28 +359,51 @@ static int report_mail(pam_handle_t *pamh, int ctrl return retval; } -/* --- authentication management functions (only) --- */ +static int _do_mail(pam_handle_t *, int, int, const char **, int); -/* - * Cannot use mail to authenticate yourself - */ +/* --- authentication functions --- */ PAM_EXTERN -int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc - ,const char **argv) +int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc, + const char **argv) { return PAM_IGNORE; } -/* - * MAIL is a "credential" - */ +/* Checking mail as part of authentication */ +PAM_EXTERN +int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + if (!(flags & (PAM_ESTABLISH_CRED|PAM_DELETE_CRED))) + return PAM_IGNORE; + return _do_mail(pamh,flags,argc,argv,(flags & PAM_ESTABLISH_CRED)); +} + +/* --- session management functions --- */ + +PAM_EXTERN +int pam_sm_close_session(pam_handle_t *pamh,int flags,int argc + ,const char **argv) +{ + return _do_mail(pamh,flags,argc,argv,0);; +} +/* Checking mail as part of the session management */ PAM_EXTERN -int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc - , const char **argv) +int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, + const char **argv) { - int retval, ctrl; + return _do_mail(pamh,flags,argc,argv,1); +} + + +/* --- The Beaf (Tm) --- */ + +static int _do_mail(pam_handle_t *pamh, int flags, int argc, + const char **argv, int est) +{ + int retval, ctrl, hashcount; char *path_mail=NULL, *folder; const char *type; @@ -309,17 +412,16 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc * the user has any new mail. */ - ctrl = _pam_parse(flags, argc, argv, &path_mail); + ctrl = _pam_parse(flags, argc, argv, &path_mail, &hashcount); /* Do we have anything to do? */ - if (!(flags & (PAM_ESTABLISH_CRED|PAM_DELETE_CRED))) { + if (flags & PAM_SILENT) return PAM_SUCCESS; - } /* which folder? */ - retval = get_folder(pamh, ctrl, &path_mail, &folder); + retval = get_folder(pamh, ctrl, &path_mail, &folder, hashcount); if (retval != PAM_SUCCESS) { D(("failed to find folder")); return retval; @@ -327,7 +429,7 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc /* set the MAIL variable? */ - if (!(ctrl & PAM_NO_ENV) && (flags & PAM_ESTABLISH_CRED)) { + if (!(ctrl & PAM_NO_ENV) && est) { char *tmp; tmp = malloc(strlen(folder)+sizeof(MAIL_ENV_FORMAT)); @@ -357,24 +459,20 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc * OK. we've got the mail folder... what about its status? */ - if (((flags & PAM_ESTABLISH_CRED) && !(ctrl & PAM_NO_LOGIN)) - || ((flags & PAM_DELETE_CRED) && (ctrl & PAM_LOGOUT_TOO))) { + if ((est && !(ctrl & PAM_NO_LOGIN)) + || (!est && (ctrl & PAM_LOGOUT_TOO))) { type = get_mail_status(ctrl, folder); if (type != NULL) { retval = report_mail(pamh, ctrl, type, folder); type = NULL; } } - - /* - * Delete environment variable? - */ - - if (flags & PAM_DELETE_CRED) { + + /* Delete environment variable? */ + if (!est) (void) pam_putenv(pamh, MAIL_ENV_NAME); - } - _pam_overwrite(folder); /* clean up */ + _pam_overwrite(folder); /* clean up */ _pam_drop(folder); /* indicate success or failure */ @@ -391,8 +489,8 @@ struct pam_module _pam_mail_modstruct = { pam_sm_authenticate, pam_sm_setcred, NULL, - NULL, - NULL, + pam_sm_open_session, + pam_sm_close_session, NULL, }; diff --git a/contrib/libpam/modules/pam_mkhomedir/Makefile b/contrib/libpam/modules/pam_mkhomedir/Makefile new file mode 100644 index 000000000000..f017f4a469ec --- /dev/null +++ b/contrib/libpam/modules/pam_mkhomedir/Makefile @@ -0,0 +1,15 @@ +# +# $Id: Makefile,v 1.3 2000/11/19 23:54:04 agmorgan Exp $ +# +# This Makefile controls a build process of $(TITLE) module for +# Linux-PAM. You should not modify this Makefile (unless you know +# what you are doing!). +# +# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27 +# + +include ../../Make.Rules + +TITLE=pam_mkhomedir + +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_mkhomedir/pam_mkhomedir.c b/contrib/libpam/modules/pam_mkhomedir/pam_mkhomedir.c new file mode 100644 index 000000000000..ec05993dfa1e --- /dev/null +++ b/contrib/libpam/modules/pam_mkhomedir/pam_mkhomedir.c @@ -0,0 +1,370 @@ +/* PAM Make Home Dir module + + This module will create a users home directory if it does not exist + when the session begins. This allows users to be present in central + database (such as nis, kerb or ldap) without using a distributed + file system or pre-creating a large number of directories. + + Here is a sample /etc/pam.d/login file for Debian GNU/Linux + 2.1: + + auth requisite pam_securetty.so + auth sufficient pam_ldap.so + auth required pam_pwdb.so + auth optional pam_group.so + auth optional pam_mail.so + account requisite pam_time.so + account sufficient pam_ldap.so + account required pam_pwdb.so + session required pam_mkhomedir.so skel=/etc/skel/ umask=0022 + session required pam_pwdb.so + session optional pam_lastlog.so + password required pam_pwdb.so + + Released under the GNU LGPL version 2 or later + Originally written by Jason Gunthorpe <jgg@debian.org> Feb 1999 + Structure taken from pam_lastlogin by Andrew Morgan + <morgan@parc.power.net> 1996 + */ + +/* I want snprintf dammit */ +#define _GNU_SOURCE 1 +#include <stdarg.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <pwd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <dirent.h> + +/* + * here, we make a definition for the externally accessible function + * in this file (this definition is required for static a module + * but strongly encouraged generally) it is used to instruct the + * modules include file to define the function prototypes. + */ + +#define PAM_SM_SESSION + +#include <security/pam_modules.h> +#include <security/_pam_macros.h> + +/* argument parsing */ +#define MKHOMEDIR_DEBUG 020 /* keep quiet about things */ +#define MKHOMEDIR_QUIET 040 /* keep quiet about things */ + +static unsigned int UMask = 0022; +static char SkelDir[BUFSIZ] = "/etc/skel"; + +/* some syslogging */ +static void _log_err(int err, const char *format, ...) +{ + va_list args; + + va_start(args, format); + openlog("PAM-mkhomedir", LOG_CONS|LOG_PID, LOG_AUTH); + vsyslog(err, format, args); + va_end(args); + closelog(); +} + +static int _pam_parse(int flags, int argc, const char **argv) +{ + int ctrl = 0; + + /* does the appliction require quiet? */ + if ((flags & PAM_SILENT) == PAM_SILENT) + ctrl |= MKHOMEDIR_QUIET; + + /* step through arguments */ + for (; argc-- > 0; ++argv) + { + if (!strcmp(*argv, "silent")) + { + ctrl |= MKHOMEDIR_QUIET; + } + else if (!strncmp(*argv,"umask=",6)) + UMask = strtol(*argv+6,0,0); + else if (!strncmp(*argv,"skel=",5)) + strcpy(SkelDir,*argv+5); + else + { + _log_err(LOG_ERR, "unknown option; %s", *argv); + } + } + + D(("ctrl = %o", ctrl)); + return ctrl; +} + +/* This common function is used to send a message to the applications + conversion function. Our only use is to ask the application to print + an informative message that we are creating a home directory */ +static int converse(pam_handle_t * pamh, int ctrl, int nargs + ,struct pam_message **message + ,struct pam_response **response) +{ + int retval; + struct pam_conv *conv; + + D(("begin to converse")); + + retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv); + if (retval == PAM_SUCCESS) + { + + retval = conv->conv(nargs, (const struct pam_message **) message + ,response, conv->appdata_ptr); + + D(("returned from application's conversation function")); + + if (retval != PAM_SUCCESS && (ctrl & MKHOMEDIR_DEBUG)) + { + _log_err(LOG_DEBUG, "conversation failure [%s]" + ,pam_strerror(pamh, retval)); + } + + } + else + { + _log_err(LOG_ERR, "couldn't obtain coversation function [%s]" + ,pam_strerror(pamh, retval)); + } + + D(("ready to return from module conversation")); + + return retval; /* propagate error status */ +} + +/* Ask the application to display a short text string for us. */ +static int make_remark(pam_handle_t * pamh, int ctrl, const char *remark) +{ + int retval; + + if ((ctrl & MKHOMEDIR_QUIET) != MKHOMEDIR_QUIET) + { + struct pam_message msg[1], *mesg[1]; + struct pam_response *resp = NULL; + + mesg[0] = &msg[0]; + msg[0].msg_style = PAM_TEXT_INFO; + msg[0].msg = remark; + + retval = converse(pamh, ctrl, 1, mesg, &resp); + + msg[0].msg = NULL; + if (resp) + { + _pam_drop_reply(resp, 1); + } + } + else + { + D(("keeping quiet")); + retval = PAM_SUCCESS; + } + + D(("returning %s", pam_strerror(pamh, retval))); + return retval; +} + +/* Do the actual work of creating a home dir */ +static int create_homedir(pam_handle_t * pamh, int ctrl, + const struct passwd *pwd) +{ + char *remark; + DIR *D; + struct dirent *Dir; + + /* Some scratch space */ + remark = malloc(BUFSIZ); + if (remark == NULL) + { + D(("no memory for last login remark")); + return PAM_BUF_ERR; + } + + /* Mention what is happening, if the notification fails that is OK */ + if (snprintf(remark,BUFSIZ,"Creating home directory '%s'.", + pwd->pw_dir) == -1) + return PAM_PERM_DENIED; + + make_remark(pamh, ctrl, remark); + + /* Crete the home directory */ + if (mkdir(pwd->pw_dir,0700) != 0) + { + free(remark); + _log_err(LOG_DEBUG, "unable to create home directory %s",pwd->pw_dir); + return PAM_PERM_DENIED; + } + if (chmod(pwd->pw_dir,0777 & (~UMask)) != 0 || + chown(pwd->pw_dir,pwd->pw_uid,pwd->pw_gid) != 0) + { + free(remark); + _log_err(LOG_DEBUG, "unable to chance perms on home directory %s",pwd->pw_dir); + return PAM_PERM_DENIED; + } + + /* See if we need to copy the skel dir over. */ + if (SkelDir[0] == 0) + { + free(remark); + return PAM_SUCCESS; + } + + /* Scan the directory */ + D = opendir(SkelDir); + if (D == 0) + { + free(remark); + _log_err(LOG_DEBUG, "unable to read directory %s",SkelDir); + return PAM_PERM_DENIED; + } + + for (Dir = readdir(D); Dir != 0; Dir = readdir(D)) + { + int SrcFd; + int DestFd; + int Res; + struct stat St; + + /* Skip some files.. */ + if (strcmp(Dir->d_name,".") == 0 || + strcmp(Dir->d_name,"..") == 0) + continue; + + /* Check if it is a directory */ + snprintf(remark,BUFSIZ,"%s/%s",SkelDir,Dir->d_name); + if (stat(remark,&St) != 0) + continue; + if (S_ISDIR(St.st_mode)) + { + snprintf(remark,BUFSIZ,"%s/%s",pwd->pw_dir,Dir->d_name); + if (mkdir(remark,(St.st_mode | 0222) & (~UMask)) != 0 || + chmod(remark,(St.st_mode | 0222) & (~UMask)) != 0 || + chown(remark,pwd->pw_uid,pwd->pw_gid) != 0) + { + free(remark); + _log_err(LOG_DEBUG, "unable to change perms on copy %s",remark); + return PAM_PERM_DENIED; + } + continue; + } + + /* Open the source file */ + if ((SrcFd = open(remark,O_RDONLY)) < 0 || fstat(SrcFd,&St) != 0) + { + free(remark); + _log_err(LOG_DEBUG, "unable to open src file %s",remark); + return PAM_PERM_DENIED; + } + stat(remark,&St); + + /* Open the dest file */ + snprintf(remark,BUFSIZ,"%s/%s",pwd->pw_dir,Dir->d_name); + if ((DestFd = open(remark,O_WRONLY | O_TRUNC | O_CREAT,0600)) < 0) + { + close(SrcFd); + free(remark); + _log_err(LOG_DEBUG, "unable to open dest file %s",remark); + return PAM_PERM_DENIED; + } + + /* Set the proper ownership and permissions for the module. We make + the file a+w and then mask it with the set mask. This preseves + execute bits */ + if (fchmod(DestFd,(St.st_mode | 0222) & (~UMask)) != 0 || + fchown(DestFd,pwd->pw_uid,pwd->pw_gid) != 0) + { + free(remark); + _log_err(LOG_DEBUG, "unable to chang perms on copy %s",remark); + return PAM_PERM_DENIED; + } + + /* Copy the file */ + do + { + Res = read(SrcFd,remark,BUFSIZ); + if (Res < 0 || write(DestFd,remark,Res) != Res) + { + close(SrcFd); + close(DestFd); + free(remark); + _log_err(LOG_DEBUG, "unable to perform IO"); + return PAM_PERM_DENIED; + } + } + while (Res != 0); + close(SrcFd); + close(DestFd); + } + + free(remark); + return PAM_SUCCESS; +} + +/* --- authentication management functions (only) --- */ + +PAM_EXTERN +int pam_sm_open_session(pam_handle_t * pamh, int flags, int argc + ,const char **argv) +{ + int retval, ctrl; + const char *user; + const struct passwd *pwd; + struct stat St; + + /* Parse the flag values */ + ctrl = _pam_parse(flags, argc, argv); + + /* Determine the user name so we can get the home directory */ + retval = pam_get_item(pamh, PAM_USER, (const void **) &user); + if (retval != PAM_SUCCESS || user == NULL || *user == '\0') + { + _log_err(LOG_NOTICE, "user unknown"); + return PAM_USER_UNKNOWN; + } + + /* Get the password entry */ + pwd = getpwnam(user); + if (pwd == NULL) + { + D(("couldn't identify user %s", user)); + return PAM_CRED_INSUFFICIENT; + } + + /* Stat the home directory, if something exists then we assume it is + correct and return a success*/ + if (stat(pwd->pw_dir,&St) == 0) + return PAM_SUCCESS; + + return create_homedir(pamh,ctrl,pwd); +} + +/* Ignore */ +PAM_EXTERN +int pam_sm_close_session(pam_handle_t * pamh, int flags, int argc + ,const char **argv) +{ + return PAM_SUCCESS; +} + +#ifdef PAM_STATIC + +/* static module data */ +struct pam_module _pam_mkhomedir_modstruct = +{ + "pam_mkhomedir", + NULL, + NULL, + NULL, + pam_sm_open_session, + pam_sm_close_session, + NULL, +}; + +#endif diff --git a/contrib/libpam/modules/pam_motd/Makefile b/contrib/libpam/modules/pam_motd/Makefile new file mode 100644 index 000000000000..fb83807a36da --- /dev/null +++ b/contrib/libpam/modules/pam_motd/Makefile @@ -0,0 +1,15 @@ +# +# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ +# +# This Makefile controls a build process of $(TITLE) module for +# Linux-PAM. You should not modify this Makefile (unless you know +# what you are doing!). +# +# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27 +# + +include ../../Make.Rules + +TITLE=pam_motd + +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_motd/pam_motd.c b/contrib/libpam/modules/pam_motd/pam_motd.c new file mode 100644 index 000000000000..2434b2986c9b --- /dev/null +++ b/contrib/libpam/modules/pam_motd/pam_motd.c @@ -0,0 +1,119 @@ +/* pam_motd module */ + +/* + * Modified for pam_motd by Ben Collins <bcollins@debian.org> + * + * Based off of: + * $Id: pam_motd.c,v 1.1.1.1 2000/06/20 22:11:46 agmorgan Exp $ + * + * Written by Michael K. Johnson <johnsonm@redhat.com> 1996/10/24 + * + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <pwd.h> + +#include <security/_pam_macros.h> +/* + * here, we make a definition for the externally accessible function + * in this file (this definition is required for static a module + * but strongly encouraged generally) it is used to instruct the + * modules include file to define the function prototypes. + */ + +#define PAM_SM_SESSION +#define DEFAULT_MOTD "/etc/motd" + +#include <security/pam_modules.h> + +/* --- session management functions (only) --- */ + +PAM_EXTERN +int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + return PAM_IGNORE; +} + +PAM_EXTERN +int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + int retval = PAM_IGNORE; + int fd; + char *mtmp=NULL, *motd_path=NULL; + struct pam_conv *conversation; + struct pam_message message; + struct pam_message *pmessage = &message; + struct pam_response *resp = NULL; + struct stat st; + + if (flags & PAM_SILENT) { + return retval; + } + + for (; argc-- > 0; ++argv) { + if (!strncmp(*argv,"motd=",5)) { + motd_path = (char *) strdup(5+*argv); + if (motd_path != NULL) { + D(("set motd path: %s", motd_path)); + } else { + D(("failed to duplicate motd path - ignored")); + } + } + } + + if (motd_path == NULL) + motd_path = DEFAULT_MOTD; + + message.msg_style = PAM_TEXT_INFO; + + if ((fd = open(motd_path, O_RDONLY, 0)) >= 0) { + /* fill in message buffer with contents of motd */ + if ((fstat(fd, &st) < 0) || !st.st_size) + return retval; + message.msg = mtmp = malloc(st.st_size+1); + /* if malloc failed... */ + if (!message.msg) return retval; + read(fd, mtmp, st.st_size); + if (mtmp[st.st_size-1] == '\n') + mtmp[st.st_size-1] = '\0'; + else + mtmp[st.st_size] = '\0'; + close(fd); + /* Use conversation function to give user contents of motd */ + pam_get_item(pamh, PAM_CONV, (const void **)&conversation); + conversation->conv(1, (const struct pam_message **)&pmessage, + &resp, conversation->appdata_ptr); + free(mtmp); + if (resp) + _pam_drop_reply(resp, 1); + } + + return retval; +} + + +#ifdef PAM_STATIC + +/* static module data */ + +struct pam_module _pam_motd_modstruct = { + "pam_motd", + NULL, + NULL, + NULL, + pam_sm_open_session, + pam_sm_close_session, + NULL, +}; + +#endif + +/* end of module definition */ diff --git a/contrib/libpam/modules/pam_nologin/Makefile b/contrib/libpam/modules/pam_nologin/Makefile index 0769bb993120..2ad38ffd9609 100644 --- a/contrib/libpam/modules/pam_nologin/Makefile +++ b/contrib/libpam/modules/pam_nologin/Makefile @@ -1,86 +1,15 @@ # +# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ +# # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# Michael K. Johnson <johnsonm@redhat.com> 1996/10/24 +# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27 # -TITLE=pam_nologin - -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit +include ../../Make.Rules -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - mkdir -p ./dynamic -endif -ifdef STATIC - mkdir -p ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - mkdir -p $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - install -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< +TITLE=pam_nologin +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_nologin/README b/contrib/libpam/modules/pam_nologin/README index ab7ccd7d9803..9b00e6923868 100644 --- a/contrib/libpam/modules/pam_nologin/README +++ b/contrib/libpam/modules/pam_nologin/README @@ -1,4 +1,4 @@ -# $Id: README,v 1.1 1996/10/25 03:19:36 morgan Exp $ +# $Id: README,v 1.1.1.1 2000/06/20 22:11:46 agmorgan Exp $ # This module always lets root in; it lets other users in only if the file diff --git a/contrib/libpam/modules/pam_nologin/pam_nologin.c b/contrib/libpam/modules/pam_nologin/pam_nologin.c index 2788dcf8f39a..1359c18bfaf6 100644 --- a/contrib/libpam/modules/pam_nologin/pam_nologin.c +++ b/contrib/libpam/modules/pam_nologin/pam_nologin.c @@ -1,24 +1,10 @@ /* pam_nologin module */ /* - * $Id: pam_nologin.c,v 1.4 1997/04/05 06:36:47 morgan Exp morgan $ + * $Id: pam_nologin.c,v 1.2 2000/12/04 19:02:34 baggins Exp $ * * Written by Michael K. Johnson <johnsonm@redhat.com> 1996/10/24 * - * $Log: pam_nologin.c,v $ - * Revision 1.4 1997/04/05 06:36:47 morgan - * display message when the user is unknown - * - * Revision 1.3 1996/12/01 03:00:54 morgan - * added prototype to conversation, gave static structure name of module - * - * Revision 1.2 1996/11/10 21:02:31 morgan - * compile against .53 - * - * Revision 1.1 1996/10/25 03:19:36 morgan - * Initial revision - * - * */ #include <stdio.h> diff --git a/contrib/libpam/modules/pam_permit/Makefile b/contrib/libpam/modules/pam_permit/Makefile index 823b62472e35..49f3b3dd5e20 100644 --- a/contrib/libpam/modules/pam_permit/Makefile +++ b/contrib/libpam/modules/pam_permit/Makefile @@ -1,126 +1,15 @@ # -# $Id: Makefile,v 1.8 1997/04/05 06:33:25 morgan Exp morgan $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.8 1997/04/05 06:33:25 morgan -# fakeroot -# -# Revision 1.7 1997/02/15 19:02:27 morgan -# updated email address -# -# Revision 1.6 1996/11/10 20:14:34 morgan -# cross platform support -# -# Revision 1.5 1996/09/05 06:32:45 morgan -# ld --> gcc -# -# Revision 1.4 1996/05/26 15:49:25 morgan -# make dynamic and static dirs -# -# Revision 1.3 1996/05/26 04:04:26 morgan -# automated static support -# -# Revision 1.2 1996/03/16 17:56:38 morgan -# tidied up -# -# -# Created by Andrew Morgan <morgan@parc.power.net> 1996/3/11 +# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27 # -# Convenient defaults for compiling independently of the full source -# tree. -ifndef FULL_LINUX_PAM_SOURCE_TREE -export DYNAMIC=-DPAM_DYNAMIC -export CC=gcc -export CFLAGS=-O2 -Dlinux -DLINUX_PAM \ - -ansi -D_POSIX_SOURCE -Wall -Wwrite-strings \ - -Wpointer-arith -Wcast-qual -Wcast-align -Wtraditional \ - -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline \ - -Wshadow -pedantic -fPIC -export MKDIR=mkdir -p -export LD_D=gcc -shared -Xlinker -x -endif - -# -# +include ../../Make.Rules TITLE=pam_permit -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(TARGET_ARCH) -c $< -o $@ - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) -endif - -ifdef DYNAMIC -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) -endif - -ifdef STATIC -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak - -.c.o: - $(CC) $(CFLAGS) -c $< - +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_permit/README b/contrib/libpam/modules/pam_permit/README index da179a34829c..52e7364e8753 100644 --- a/contrib/libpam/modules/pam_permit/README +++ b/contrib/libpam/modules/pam_permit/README @@ -1,4 +1,4 @@ -# $Id: README,v 1.1 1996/03/16 18:12:51 morgan Exp $ +# $Id: README,v 1.1.1.1 2000/06/20 22:11:46 agmorgan Exp $ # this module always returns PAM_SUCCESS, it ignores all options. diff --git a/contrib/libpam/modules/pam_permit/pam_permit.c b/contrib/libpam/modules/pam_permit/pam_permit.c index 1bdd5644a63b..46e36eb97c24 100644 --- a/contrib/libpam/modules/pam_permit/pam_permit.c +++ b/contrib/libpam/modules/pam_permit/pam_permit.c @@ -1,20 +1,10 @@ /* pam_permit module */ /* - * $Id: pam_permit.c,v 1.5 1997/02/15 19:03:15 morgan Exp $ + * $Id: pam_permit.c,v 1.2 2000/12/04 19:02:34 baggins Exp $ * * Written by Andrew Morgan <morgan@parc.power.net> 1996/3/11 * - * $Log: pam_permit.c,v $ - * Revision 1.5 1997/02/15 19:03:15 morgan - * fixed email address - * - * Revision 1.4 1997/02/15 16:03:10 morgan - * force a name for user - * - * Revision 1.3 1996/06/02 08:10:14 morgan - * updated for new static protocol - * */ #define DEFAULT_USER "nobody" diff --git a/contrib/libpam/modules/pam_pwdb/BUGS b/contrib/libpam/modules/pam_pwdb/BUGS index 397f367b5372..d51686e51d76 100644 --- a/contrib/libpam/modules/pam_pwdb/BUGS +++ b/contrib/libpam/modules/pam_pwdb/BUGS @@ -1,8 +1,3 @@ -$Id: BUGS,v 1.2 1996/09/05 06:36:16 morgan Exp $ - -$Log: BUGS,v $ -Revision 1.2 1996/09/05 06:36:16 morgan -revised for .52 to be released - +$Id: BUGS,v 1.2 2000/12/04 19:02:34 baggins Exp $ As of Linux-PAM-0.52 this is new. No known bugs yet. diff --git a/contrib/libpam/modules/pam_pwdb/CHANGELOG b/contrib/libpam/modules/pam_pwdb/CHANGELOG index 0cb21879120b..a36140319933 100644 --- a/contrib/libpam/modules/pam_pwdb/CHANGELOG +++ b/contrib/libpam/modules/pam_pwdb/CHANGELOG @@ -1,4 +1,4 @@ -$Header: /home/morgan/pam/Linux-PAM-0.52/modules/pam_unix/RCS/CHANGELOG,v 1.1 1996/08/29 13:23:29 morgan Exp $ +$Id: CHANGELOG,v 1.1.1.1 2000/06/20 22:11:46 agmorgan Exp $ Tue Apr 23 12:28:09 EDT 1996 (Alexander O. Yuriev alex@bach.cis.temple.edu) diff --git a/contrib/libpam/modules/pam_pwdb/Makefile b/contrib/libpam/modules/pam_pwdb/Makefile index 7428bb439040..ec66f9e8269c 100644 --- a/contrib/libpam/modules/pam_pwdb/Makefile +++ b/contrib/libpam/modules/pam_pwdb/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.7 1997/04/05 06:28:50 morgan Exp morgan $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ # # This Makefile controls a build process of the pam_unix module # for Linux-PAM. You should not modify this Makefile. @@ -7,42 +7,20 @@ # <morgan@parc.power.net> 1996/11/6 # -# -# Note, the STATIC module is commented out because it doesn't work. -# please fix! -# +include ../../Make.Rules -ifndef FULL_LINUX_PAM_SOURCE_TREE -export DYNAMIC=-DPAM_DYNAMIC -export CC=gcc -export CFLAGS=-O2 -Dlinux -DLINUX_PAM \ - -ansi -D_POSIX_SOURCE -Wall -Wwrite-strings \ - -Wpointer-arith -Wcast-qual -Wcast-align -Wtraditional \ - -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline \ - -Wshadow -pedantic -fPIC -export MKDIR=mkdir -p -export LD_D=gcc -shared -Xlinker -x -export HAVE_PWDBLIB=yes -endif +ifeq ($(HAVE_LIBPWDB),yes) -ifeq ($(HAVE_PWDBLIB),yes) +EXTRALS += -lpwdb +EXTRAS += -DCHKPWD_HELPER=\"$(SUPLEMENTED)/$(CHKPWD)\" + +ifeq ($(HAVE_LIBCRYPT),yes) + EXTRALS += -lcrypt +endif TITLE=pam_pwdb CHKPWD=pwdb_chkpwd -# compilation flags -EXTRAS= -# extra object files -PLUS= -# extra files that may be needed to be created -CREATE= - -# NOTE: this module links dynamically to the libpwdb library. -EXTRALS += -lpwdb -EXTRAS += -DCHKPWD_HELPER=\"$(SUPLEMENTED)/$(CHKPWD)\" - -########################### don't edit below ########################## - LIBSRC = $(TITLE).c LIBOBJ = $(TITLE).o LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) @@ -50,7 +28,7 @@ LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) LIBDEPS = pam_unix_acct.-c pam_unix_auth.-c pam_unix_passwd.-c \ pam_unix_sess.-c pam_unix_pwupd.-c support.-c bigcrypt.-c -PLUS += md5.o md5_crypt.o +PLUS += md5_good.o md5_broken.o md5_crypt_good.o md5_crypt_broken.o CFLAGS += $(EXTRAS) ifdef DYNAMIC @@ -73,11 +51,28 @@ info: @echo "*** Building PAM_pwdb module..." @echo -$(CHKPWD): pwdb_chkpwd.o md5.o md5_crypt.o +$(CHKPWD): pwdb_chkpwd.o md5_good.o md5_broken.o \ + md5_crypt_good.o md5_crypt_broken.o $(CC) -o $(CHKPWD) $^ -lpwdb pwdb_chkpwd.o: pwdb_chkpwd.c pam_unix_md.-c bigcrypt.-c +md5_good.o: md5.c + $(CC) $(CFLAGS) $(CPPFLAGS) -DHIGHFIRST -D'MD5Name(x)=Good##x' \ + $(TARGET_ARCH) -c $< -o $@ + +md5_broken.o: md5.c + $(CC) $(CFLAGS) $(CPPFLAGS) -D'MD5Name(x)=Broken##x' \ + $(TARGET_ARCH) -c $< -o $@ + +md5_crypt_good.o: md5_crypt.c + $(CC) $(CFLAGS) $(CPPFLAGS) -D'MD5Name(x)=Good##x' \ + $(TARGET_ARCH) -c $< -o $@ + +md5_crypt_broken.o: md5_crypt.c + $(CC) $(CFLAGS) $(CPPFLAGS) -D'MD5Name(x)=Broken##x' \ + $(TARGET_ARCH) -c $< -o $@ + dirs: ifdef DYNAMIC @$(MKDIR) ./dynamic @@ -111,7 +106,7 @@ ifdef DYNAMIC $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) endif $(MKDIR) $(FAKEROOT)$(SUPLEMENTED) - $(INSTALL) -m 4555 -o root -g root $(CHKPWD) $(FAKEROOT)$(SUPLEMENTED) + $(INSTALL) -m 4555 $(CHKPWD) $(FAKEROOT)$(SUPLEMENTED) remove: rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so @@ -119,37 +114,11 @@ remove: clean: rm -f $(CHKPWD) $(LIBOBJD) $(LIBOBJS) $(MOREDELS) core *~ *.o *.so - -extraclean: clean rm -f *.a *.o *.so *.bak + rm -fr dynamic static else include ../dont_makefile endif - -##################################################################### -# $Log: Makefile,v $ -# Revision 1.7 1997/04/05 06:28:50 morgan -# fakeroot -# -# Revision 1.6 1997/02/15 17:25:32 morgan -# update for .56 . extra commands for new helper binary -# -# Revision 1.5 1997/01/04 20:39:08 morgan -# conditional on having libpwdb -# -# Revision 1.4 1996/12/01 03:02:03 morgan -# changed banner, removed linking libraries -# -# Revision 1.3 1996/11/10 20:14:42 morgan -# cross platform support -# -# Revision 1.2 1996/09/05 06:36:49 morgan -# options added and use of LD altered -# -# Revision 1.1 1996/08/29 13:23:29 morgan -# Initial revision -# -# diff --git a/contrib/libpam/modules/pam_pwdb/README b/contrib/libpam/modules/pam_pwdb/README index 351a706008e9..4f420855cded 100644 --- a/contrib/libpam/modules/pam_pwdb/README +++ b/contrib/libpam/modules/pam_pwdb/README @@ -7,7 +7,7 @@ passwords. the license suggests -- use at your own risk.] So far as I am concerned this module is now pretty stable. If you find -any bugs, PLEASE tell me! <morgan@parc.power.net> +any bugs, PLEASE tell me! <morgan@linux.kernel.org> Options recognized by this module are as follows: @@ -38,4 +38,4 @@ should read the source to find the appropriate #define that you will need. --------------------- -Andrew Morgan <morgan@parc.power.net> +Andrew Morgan <morgan@linux.kernel.org> diff --git a/contrib/libpam/modules/pam_pwdb/TODO b/contrib/libpam/modules/pam_pwdb/TODO index 23eb4c163d08..520a262ec13c 100644 --- a/contrib/libpam/modules/pam_pwdb/TODO +++ b/contrib/libpam/modules/pam_pwdb/TODO @@ -1,4 +1,4 @@ -$Id: TODO,v 1.3 1996/11/10 21:03:21 morgan Exp $ +$Id: TODO,v 1.1.1.1 2000/06/20 22:11:47 agmorgan Exp $ * get NIS working * .. including "nonis" argument diff --git a/contrib/libpam/modules/pam_pwdb/md5.c b/contrib/libpam/modules/pam_pwdb/md5.c index fdfbdd88f389..4428294178ff 100644 --- a/contrib/libpam/modules/pam_pwdb/md5.c +++ b/contrib/libpam/modules/pam_pwdb/md5.c @@ -1,4 +1,4 @@ -/* $Id: md5.c,v 1.1 1996/09/05 06:43:31 morgan Exp $ +/* $Id: md5.c,v 1.2 2000/12/04 19:02:34 baggins Exp $ * * This code implements the MD5 message-digest algorithm. * The algorithm is due to Ron Rivest. This code was @@ -15,10 +15,6 @@ * needed on buffers full of bytes, and then call MD5Final, which * will fill a supplied 16-byte array with the digest. * - * $Log: md5.c,v $ - * Revision 1.1 1996/09/05 06:43:31 morgan - * Initial revision - * */ #include <string.h> @@ -27,13 +23,13 @@ #ifndef HIGHFIRST #define byteReverse(buf, len) /* Nothing */ #else -void byteReverse(unsigned char *buf, unsigned longs); +static void byteReverse(unsigned char *buf, unsigned longs); #ifndef ASM_MD5 /* * Note: this code is harmless on little-endian machines. */ -void byteReverse(unsigned char *buf, unsigned longs) +static void byteReverse(unsigned char *buf, unsigned longs) { uint32 t; do { @@ -50,7 +46,7 @@ void byteReverse(unsigned char *buf, unsigned longs) * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * initialization constants. */ -void MD5Init(struct MD5Context *ctx) +void MD5Name(MD5Init)(struct MD5Context *ctx) { ctx->buf[0] = 0x67452301U; ctx->buf[1] = 0xefcdab89U; @@ -65,7 +61,7 @@ void MD5Init(struct MD5Context *ctx) * Update context to reflect the concatenation of another buffer full * of bytes. */ -void MD5Update(struct MD5Context *ctx, unsigned const char *buf, unsigned len) +void MD5Name(MD5Update)(struct MD5Context *ctx, unsigned const char *buf, unsigned len) { uint32 t; @@ -90,7 +86,7 @@ void MD5Update(struct MD5Context *ctx, unsigned const char *buf, unsigned len) } memcpy(p, buf, t); byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32 *) ctx->in); + MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); buf += t; len -= t; } @@ -99,7 +95,7 @@ void MD5Update(struct MD5Context *ctx, unsigned const char *buf, unsigned len) while (len >= 64) { memcpy(ctx->in, buf, 64); byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32 *) ctx->in); + MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); buf += 64; len -= 64; } @@ -113,7 +109,7 @@ void MD5Update(struct MD5Context *ctx, unsigned const char *buf, unsigned len) * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ -void MD5Final(unsigned char digest[16], struct MD5Context *ctx) +void MD5Name(MD5Final)(unsigned char digest[16], struct MD5Context *ctx) { unsigned count; unsigned char *p; @@ -134,7 +130,7 @@ void MD5Final(unsigned char digest[16], struct MD5Context *ctx) /* Two lots of padding: Pad the first block to 64 bytes */ memset(p, 0, count); byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32 *) ctx->in); + MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); /* Now fill the next block with 56 bytes */ memset(ctx->in, 0, 56); @@ -148,7 +144,7 @@ void MD5Final(unsigned char digest[16], struct MD5Context *ctx) ((uint32 *) ctx->in)[14] = ctx->bits[0]; ((uint32 *) ctx->in)[15] = ctx->bits[1]; - MD5Transform(ctx->buf, (uint32 *) ctx->in); + MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); byteReverse((unsigned char *) ctx->buf, 4); memcpy(digest, ctx->buf, 16); memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ @@ -173,7 +169,7 @@ void MD5Final(unsigned char digest[16], struct MD5Context *ctx) * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ -void MD5Transform(uint32 buf[4], uint32 const in[16]) +void MD5Name(MD5Transform)(uint32 buf[4], uint32 const in[16]) { register uint32 a, b, c, d; diff --git a/contrib/libpam/modules/pam_pwdb/md5.h b/contrib/libpam/modules/pam_pwdb/md5.h index 4949ade27e1f..75c4dbac85e1 100644 --- a/contrib/libpam/modules/pam_pwdb/md5.h +++ b/contrib/libpam/modules/pam_pwdb/md5.h @@ -1,11 +1,7 @@ #ifndef MD5_H #define MD5_H -#ifdef __alpha typedef unsigned int uint32; -#else -typedef unsigned long uint32; -#endif struct MD5Context { uint32 buf[4]; @@ -13,13 +9,17 @@ struct MD5Context { unsigned char in[64]; }; -void MD5Init(struct MD5Context *); -void MD5Update(struct MD5Context *, unsigned const char *, unsigned); -void MD5Final(unsigned char digest[16], struct MD5Context *); -void MD5Transform(uint32 buf[4], uint32 const in[16]); -int i64c(int i); +void GoodMD5Init(struct MD5Context *); +void GoodMD5Update(struct MD5Context *, unsigned const char *, unsigned); +void GoodMD5Final(unsigned char digest[16], struct MD5Context *); +void GoodMD5Transform(uint32 buf[4], uint32 const in[16]); +void BrokenMD5Init(struct MD5Context *); +void BrokenMD5Update(struct MD5Context *, unsigned const char *, unsigned); +void BrokenMD5Final(unsigned char digest[16], struct MD5Context *); +void BrokenMD5Transform(uint32 buf[4], uint32 const in[16]); -char *crypt_md5(const char *pw, const char *salt); +char *Goodcrypt_md5(const char *pw, const char *salt); +char *Brokencrypt_md5(const char *pw, const char *salt); /* * This is needed to make RSAREF happy on some MS-DOS compilers. diff --git a/contrib/libpam/modules/pam_pwdb/md5_crypt.c b/contrib/libpam/modules/pam_pwdb/md5_crypt.c index 88be13b7f001..826087f28093 100644 --- a/contrib/libpam/modules/pam_pwdb/md5_crypt.c +++ b/contrib/libpam/modules/pam_pwdb/md5_crypt.c @@ -1,4 +1,4 @@ -/* $Id: md5_crypt.c,v 1.1 1996/09/05 06:43:31 morgan Exp $ +/* $Id: md5_crypt.c,v 1.2 2000/12/04 19:02:34 baggins Exp $ * * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): @@ -9,10 +9,6 @@ * * Origin: Id: crypt.c,v 1.3 1995/05/30 05:42:22 rgrimes Exp * - * $Log: md5_crypt.c,v $ - * Revision 1.1 1996/09/05 06:43:31 morgan - * Initial revision - * */ #include <string.h> @@ -31,34 +27,12 @@ to64(char *s, unsigned long v, int n) } /* - * i64c - convert an integer to a radix 64 character - */ -int i64c(int i) -{ - if (i < 0) - return ('.'); - else if (i > 63) - return ('z'); - if (i == 0) - return ('.'); - if (i == 1) - return ('/'); - if (i >= 2 && i <= 11) - return ('0' - 2 + i); - if (i >= 12 && i <= 37) - return ('A' - 12 + i); - if (i >= 38 && i <= 63) - return ('a' - 38 + i); - return ('\0'); -} - -/* * UNIX password * * Use MD5 for what it is best at... */ -char * crypt_md5(const char *pw, const char *salt) +char * MD5Name(crypt_md5)(const char *pw, const char *salt) { const char *magic = "$1$"; /* This string is magic for this algorithm. Having @@ -84,25 +58,25 @@ char * crypt_md5(const char *pw, const char *salt) /* get the length of the true salt */ sl = ep - sp; - MD5Init(&ctx); + MD5Name(MD5Init)(&ctx); /* The password first, since that is what is most unknown */ - MD5Update(&ctx,(unsigned const char *)pw,strlen(pw)); + MD5Name(MD5Update)(&ctx,(unsigned const char *)pw,strlen(pw)); /* Then our magic string */ - MD5Update(&ctx,(unsigned const char *)magic,strlen(magic)); + MD5Name(MD5Update)(&ctx,(unsigned const char *)magic,strlen(magic)); /* Then the raw salt */ - MD5Update(&ctx,(unsigned const char *)sp,sl); + MD5Name(MD5Update)(&ctx,(unsigned const char *)sp,sl); /* Then just as many characters of the MD5(pw,salt,pw) */ - MD5Init(&ctx1); - MD5Update(&ctx1,(unsigned const char *)pw,strlen(pw)); - MD5Update(&ctx1,(unsigned const char *)sp,sl); - MD5Update(&ctx1,(unsigned const char *)pw,strlen(pw)); - MD5Final(final,&ctx1); + MD5Name(MD5Init)(&ctx1); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)sp,sl); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); + MD5Name(MD5Final)(final,&ctx1); for(pl = strlen(pw); pl > 0; pl -= 16) - MD5Update(&ctx,(unsigned const char *)final,pl>16 ? 16 : pl); + MD5Name(MD5Update)(&ctx,(unsigned const char *)final,pl>16 ? 16 : pl); /* Don't leave anything around in vm they could use. */ memset(final,0,sizeof final); @@ -110,16 +84,16 @@ char * crypt_md5(const char *pw, const char *salt) /* Then something really weird... */ for (j=0,i = strlen(pw); i ; i >>= 1) if(i&1) - MD5Update(&ctx, (unsigned const char *)final+j, 1); + MD5Name(MD5Update)(&ctx, (unsigned const char *)final+j, 1); else - MD5Update(&ctx, (unsigned const char *)pw+j, 1); + MD5Name(MD5Update)(&ctx, (unsigned const char *)pw+j, 1); /* Now make the output string */ strcpy(passwd,magic); strncat(passwd,sp,sl); strcat(passwd,"$"); - MD5Final(final,&ctx); + MD5Name(MD5Final)(final,&ctx); /* * and now, just to make sure things don't run too fast @@ -127,23 +101,23 @@ char * crypt_md5(const char *pw, const char *salt) * need 30 seconds to build a 1000 entry dictionary... */ for(i=0;i<1000;i++) { - MD5Init(&ctx1); + MD5Name(MD5Init)(&ctx1); if(i & 1) - MD5Update(&ctx1,(unsigned const char *)pw,strlen(pw)); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); else - MD5Update(&ctx1,(unsigned const char *)final,16); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)final,16); if(i % 3) - MD5Update(&ctx1,(unsigned const char *)sp,sl); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)sp,sl); if(i % 7) - MD5Update(&ctx1,(unsigned const char *)pw,strlen(pw)); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); if(i & 1) - MD5Update(&ctx1,(unsigned const char *)final,16); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)final,16); else - MD5Update(&ctx1,(unsigned const char *)pw,strlen(pw)); - MD5Final(final,&ctx1); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); + MD5Name(MD5Final)(final,&ctx1); } p = passwd + strlen(passwd); diff --git a/contrib/libpam/modules/pam_pwdb/pam_pwdb.c b/contrib/libpam/modules/pam_pwdb/pam_pwdb.c index a612f74037b4..8c75ac232e18 100644 --- a/contrib/libpam/modules/pam_pwdb/pam_pwdb.c +++ b/contrib/libpam/modules/pam_pwdb/pam_pwdb.c @@ -1,5 +1,5 @@ /* - * $Id: pam_pwdb.c,v 1.3 1997/01/04 20:38:33 morgan Exp morgan $ + * $Id: pam_pwdb.c,v 1.3 2000/11/19 23:54:04 agmorgan Exp $ * * This is the single file that will be compiled for pam_unix. * it includes each of the modules that have beed defined in the .-c @@ -13,37 +13,14 @@ * See the end of this file for Copyright information. */ -/* - * $Log: pam_pwdb.c,v $ - * Revision 1.3 1997/01/04 20:38:33 morgan - * this is not the unix module! - * - * Revision 1.2 1996/12/01 03:03:43 morgan - * debugging code uses _pam_malloc - * - * Revision 1.1 1996/11/10 21:21:24 morgan - * Initial revision - * - * Revision 1.3 1996/09/05 06:44:33 morgan - * more debugging, fixed static structure name - * - * Revision 1.2 1996/09/01 01:05:12 morgan - * Cristian Gafton's patches. - * - * Revision 1.1 1996/08/29 13:22:19 morgan - * Initial revision - * - */ - static const char rcsid[] = -"$Id: pam_pwdb.c,v 1.3 1997/01/04 20:38:33 morgan Exp morgan $\n" +"$Id: pam_pwdb.c,v 1.3 2000/11/19 23:54:04 agmorgan Exp $\n" " - PWDB Pluggable Authentication module. <morgan@linux.kernel.org>" ; -#ifdef linux -# define _GNU_SOURCE -# include <features.h> -#endif +/* #define DEBUG */ + +#include <security/_pam_aconf.h> #include <sys/types.h> #include <stdarg.h> @@ -56,9 +33,6 @@ static const char rcsid[] = #include <fcntl.h> #include <ctype.h> -#define _SVID_SOURCE -#define __USE_BSD -#define _BSD_COMPAT #include <sys/time.h> #include <unistd.h> @@ -100,6 +74,13 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags retval = _unix_auth( pamh, ctrl ); pwdb_end(); + if ( on(UNIX_LIKE_AUTH, ctrl) ) { + D(("recording return code for next time [%d]", retval)); + pam_set_data(pamh, "pwdb_setcred_return", (void *) retval, NULL); + } + + D(("done. [%s]", pam_strerror(pamh, retval))); + return retval; } @@ -113,9 +94,17 @@ PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags pwdb_start(); ctrl = set_ctrl(flags, argc, argv); - retval = _unix_set_credentials(pamh, ctrl) ; + retval = _unix_set_credentials(pamh, ctrl); pwdb_end(); + if ( on(UNIX_LIKE_AUTH, ctrl) ) { + int *pretval = &retval; + + D(("recovering return code from auth call")); + pam_get_data(pamh, "pwdb_setcred_return", (const void **) pretval); + D(("recovered data indicates that old retval was %d", retval)); + } + return retval; } @@ -203,6 +192,8 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, retval = _unix_chauthtok(pamh, ctrl); pwdb_end(); + D(("done.")); + return retval; } diff --git a/contrib/libpam/modules/pam_pwdb/pam_unix_acct.-c b/contrib/libpam/modules/pam_pwdb/pam_unix_acct.-c index dbd13855ed3c..adcb6538624f 100644 --- a/contrib/libpam/modules/pam_pwdb/pam_unix_acct.-c +++ b/contrib/libpam/modules/pam_pwdb/pam_unix_acct.-c @@ -1,31 +1,11 @@ /* - * $Id: pam_unix_acct.-c,v 1.6 1997/01/04 20:37:15 morgan Exp morgan $ - * - * $Log: pam_unix_acct.-c,v $ - * Revision 1.6 1997/01/04 20:37:15 morgan - * extra debugging - * - * Revision 1.5 1996/12/01 03:05:54 morgan - * debugging with _pam_macros.h - * - * Revision 1.4 1996/11/10 21:03:57 morgan - * pwdb conversion - * - * Revision 1.3 1996/09/05 06:45:45 morgan - * tidied shadow acct management - * - * Revision 1.2 1996/09/01 01:13:14 morgan - * Cristian Gafton's patches - * - * Revision 1.1 1996/08/29 13:27:51 morgan - * Initial revision - * + * $Id: pam_unix_acct.-c,v 1.2 2000/12/04 19:02:34 baggins Exp $ * * See end of file for copyright information */ static const char rcsid_acct[] = -"$Id: pam_unix_acct.-c,v 1.6 1997/01/04 20:37:15 morgan Exp morgan $\n" +"$Id: pam_unix_acct.-c,v 1.2 2000/12/04 19:02:34 baggins Exp $\n" " - PAM_PWDB account management <gafton@redhat.com>"; /* the shadow suite has accout managment.. */ diff --git a/contrib/libpam/modules/pam_pwdb/pam_unix_auth.-c b/contrib/libpam/modules/pam_pwdb/pam_unix_auth.-c index 4a1eed0d6387..31230394c65f 100644 --- a/contrib/libpam/modules/pam_pwdb/pam_unix_auth.-c +++ b/contrib/libpam/modules/pam_pwdb/pam_unix_auth.-c @@ -1,25 +1,11 @@ /* - * $Id: pam_unix_auth.-c,v 1.4 1996/12/01 03:05:54 morgan Exp $ + * $Id: pam_unix_auth.-c,v 1.1.1.1 2000/06/20 22:11:49 agmorgan Exp $ * - * $Log: pam_unix_auth.-c,v $ - * Revision 1.4 1996/12/01 03:05:54 morgan - * debugging with _pam_macros.h - * - * Revision 1.3 1996/11/10 21:04:29 morgan - * pwdb conversion - * - * Revision 1.2 1996/09/05 06:46:53 morgan - * fixed comments. Added check for null passwd. - * changed data item name - * - * Revision 1.1 1996/08/29 13:27:51 morgan - * Initial revision - * * See end of file for Copyright information. */ static const char rcsid_auth[] = -"$Id: pam_unix_auth.-c,v 1.4 1996/12/01 03:05:54 morgan Exp $: pam_unix_auth.-c,v 1.2 1996/09/05 06:46:53 morgan Exp morgan $\n" +"$Id: pam_unix_auth.-c,v 1.1.1.1 2000/06/20 22:11:49 agmorgan Exp $: pam_unix_auth.-c,v 1.2 1996/09/05 06:46:53 morgan Exp morgan $\n" " - PAM_PWDB authentication functions. <morgan@parc.power.net>"; /* @@ -42,8 +28,15 @@ static int _unix_auth(pam_handle_t *pamh, unsigned int ctrl) retval = _unix_get_user(pamh, ctrl, NULL, &name); if (retval != PAM_SUCCESS ) { - if ( on(UNIX_DEBUG,ctrl) ) { - _log_err(LOG_DEBUG, "auth could not identify user"); + if (retval != PAM_CONV_AGAIN) { + if ( on(UNIX_DEBUG,ctrl) ) { + _log_err(LOG_DEBUG, "auth could not identify user"); + } + } else { + D(("pam_get_user/conv() function is not ready yet")); + /* it is safe to resume this function so we translate this + retval to the value that indicates we're happy to resume. */ + retval = PAM_INCOMPLETE; } return retval; } @@ -60,18 +53,27 @@ static int _unix_auth(pam_handle_t *pamh, unsigned int ctrl) retval = _unix_read_password(pamh, ctrl, NULL, "Password: ", NULL , _UNIX_AUTHTOK, &p); - if (retval != PAM_SUCCESS ) { - _log_err(LOG_CRIT, "auth could not identify password for [%s]" - , name); + if (retval != PAM_SUCCESS) { + if (retval != PAM_CONV_AGAIN) { + _log_err(LOG_CRIT, "auth could not identify password for [%s]" + , name); + } else { + D(("conversation function is not ready yet")); + /* it is safe to resume this function so we translate this + retval to the value that indicates we're happy to resume. */ + retval = PAM_INCOMPLETE; + } name = NULL; return retval; } + D(("user=%s, password=[%s]", name, p)); /* verify the password of this user */ - retval = _unix_verify_password(pamh, name, p, ctrl); name = p = NULL; + D(("done [%d]", retval)); + return retval; } diff --git a/contrib/libpam/modules/pam_pwdb/pam_unix_md.-c b/contrib/libpam/modules/pam_pwdb/pam_unix_md.-c index cd90b0ff339b..d9b2c51b205a 100644 --- a/contrib/libpam/modules/pam_pwdb/pam_unix_md.-c +++ b/contrib/libpam/modules/pam_pwdb/pam_unix_md.-c @@ -25,7 +25,7 @@ struct cfns { #define N_MDS 1 const static struct cfns cfn_list[N_MDS] = { - { "$1$", 3, crypt_md5 }, + { "$1$", 3, Goodcrypt_md5 }, }; static char *_pam_md(const char *key, const char *salt) @@ -53,3 +53,21 @@ static char *_pam_md(const char *key, const char *salt) return x; /* this must be deleted elsewhere */ } +#ifndef PWDB_NO_MD_COMPAT +static char *_pam_md_compat(const char *key, const char *salt) +{ + char *x,*e=NULL; + + D(("called with key='%s', salt='%s'", key, salt)); + + if ( !strncmp("$1$", salt, 3) ) { + e = Brokencrypt_md5(key, salt); + x = x_strdup(e); /* put e in malloc()ed memory */ + _pam_overwrite(e); /* clean up */ + } else { + x = x_strdup("*"); + } + + return x; /* this must be deleted elsewhere */ +} +#endif /* PWDB_NO_MD_COMPAT */ diff --git a/contrib/libpam/modules/pam_pwdb/pam_unix_passwd.-c b/contrib/libpam/modules/pam_pwdb/pam_unix_passwd.-c index 402f7f349f88..eb43bcfa713f 100644 --- a/contrib/libpam/modules/pam_pwdb/pam_unix_passwd.-c +++ b/contrib/libpam/modules/pam_pwdb/pam_unix_passwd.-c @@ -1,29 +1,7 @@ -/* $Id: pam_unix_passwd.-c,v 1.6 1997/04/05 06:31:06 morgan Exp morgan $ */ - -/* - * $Log: pam_unix_passwd.-c,v $ - * Revision 1.6 1997/04/05 06:31:06 morgan - * mostly a reformat. - * - * Revision 1.5 1996/12/01 03:05:54 morgan - * debugging with _pam_macros.h - * - * Revision 1.4 1996/11/10 21:04:51 morgan - * pwdb conversion - * - * Revision 1.3 1996/09/05 06:48:15 morgan - * A lot has changed. I'd recommend you study the diff. - * - * Revision 1.2 1996/09/01 16:33:27 morgan - * Cristian Gafton's changes - * - * Revision 1.1 1996/08/29 13:21:27 morgan - * Initial revision - * - */ +/* $Id: pam_unix_passwd.-c,v 1.2 2000/12/04 19:02:34 baggins Exp $ */ static const char rcsid_pass[] = -"$Id: pam_unix_passwd.-c,v 1.6 1997/04/05 06:31:06 morgan Exp morgan $\n" +"$Id: pam_unix_passwd.-c,v 1.2 2000/12/04 19:02:34 baggins Exp $\n" " - PAM_PWDB password module <morgan@parc.power.net>" ; @@ -42,6 +20,28 @@ static const char rcsid_pass[] = /* Implementation */ /* + * i64c - convert an integer to a radix 64 character + */ +static int i64c(int i) +{ + if (i < 0) + return ('.'); + else if (i > 63) + return ('z'); + if (i == 0) + return ('.'); + if (i == 1) + return ('/'); + if (i >= 2 && i <= 11) + return ('0' - 2 + i); + if (i >= 12 && i <= 37) + return ('A' - 12 + i); + if (i >= 38 && i <= 63) + return ('a' - 38 + i); + return ('\0'); +} + +/* * FUNCTION: _pam_unix_chauthtok() * * this function works in two passes. The first, when UNIX__PRELIM is @@ -259,15 +259,15 @@ static int _unix_chauthtok(pam_handle_t *pamh, unsigned int ctrl) unsigned char tmp[16]; int i; - MD5Init(&ctx); + GoodMD5Init(&ctx); gettimeofday(&tv, (struct timezone *) 0); - MD5Update(&ctx, (void *) &tv, sizeof tv); + GoodMD5Update(&ctx, (void *) &tv, sizeof tv); i = getpid(); - MD5Update(&ctx, (void *) &i, sizeof i); + GoodMD5Update(&ctx, (void *) &i, sizeof i); i = clock(); - MD5Update(&ctx, (void *) &i, sizeof i); - MD5Update(&ctx, result, sizeof result); - MD5Final(tmp, &ctx); + GoodMD5Update(&ctx, (void *) &i, sizeof i); + GoodMD5Update(&ctx, result, sizeof result); + GoodMD5Final(tmp, &ctx); strcpy(cp, "$1$"); /* magic for the MD5 */ cp += strlen(cp); for (i = 0; i < 8; i++) diff --git a/contrib/libpam/modules/pam_pwdb/pam_unix_pwupd.-c b/contrib/libpam/modules/pam_pwdb/pam_unix_pwupd.-c index d50031dcb919..a1fc65ff5163 100644 --- a/contrib/libpam/modules/pam_pwdb/pam_unix_pwupd.-c +++ b/contrib/libpam/modules/pam_pwdb/pam_unix_pwupd.-c @@ -1,19 +1,7 @@ /* - * $Id: pam_unix_pwupd.-c,v 1.4 1997/01/04 20:35:32 morgan Exp morgan $ + * $Id: pam_unix_pwupd.-c,v 1.1.1.1 2000/06/20 22:11:51 agmorgan Exp $ * * This file contains the routines to update the passwd databases. - * - * $Log: pam_unix_pwupd.-c,v $ - * Revision 1.4 1997/01/04 20:35:32 morgan - * minor comment change - * - * Revision 1.3 1996/12/01 03:05:54 morgan - * debugging with _pam_macros.h - * - * Revision 1.2 1996/11/10 21:05:09 morgan - * pwdb conversion - * - * */ /* Implementation */ diff --git a/contrib/libpam/modules/pam_pwdb/pam_unix_sess.-c b/contrib/libpam/modules/pam_pwdb/pam_unix_sess.-c index 49ce96cbd16c..395bd9bba3a7 100644 --- a/contrib/libpam/modules/pam_pwdb/pam_unix_sess.-c +++ b/contrib/libpam/modules/pam_pwdb/pam_unix_sess.-c @@ -1,25 +1,11 @@ /* - * $Id: pam_unix_sess.-c,v 1.4 1996/12/01 03:05:54 morgan Exp morgan $ - * - * $Log: pam_unix_sess.-c,v $ - * Revision 1.4 1996/12/01 03:05:54 morgan - * debugging with _pam_macros.h - * - * Revision 1.3 1996/11/10 21:05:33 morgan - * pwdb conversion - * - * Revision 1.2 1996/09/05 06:49:02 morgan - * more informative logging - * - * Revision 1.1 1996/08/29 13:27:51 morgan - * Initial revision - * + * $Id: pam_unix_sess.-c,v 1.2 2000/12/04 19:02:34 baggins Exp $ * * See end for Copyright information */ static const char rcsid_sess[] = -"$Id: pam_unix_sess.-c,v 1.4 1996/12/01 03:05:54 morgan Exp morgan $\n" +"$Id: pam_unix_sess.-c,v 1.2 2000/12/04 19:02:34 baggins Exp $\n" " - PAM_PWDB session management. morgan@parc.power.net"; /* Define internal functions */ diff --git a/contrib/libpam/modules/pam_pwdb/pwdb_chkpwd.c b/contrib/libpam/modules/pam_pwdb/pwdb_chkpwd.c index 6332eaa7e865..3b3c1d5f0f51 100644 --- a/contrib/libpam/modules/pam_pwdb/pwdb_chkpwd.c +++ b/contrib/libpam/modules/pam_pwdb/pwdb_chkpwd.c @@ -1,5 +1,5 @@ /* - * $Id: pwdb_chkpwd.c,v 1.1 1997/02/15 17:26:18 morgan Exp $ + * $Id: pwdb_chkpwd.c,v 1.3 2001/02/11 06:33:53 agmorgan Exp $ * * This program is designed to run setuid(root) or with sufficient * privilege to read all of the unix password databases. It is designed @@ -11,19 +11,9 @@ * * Copyright information is located at the end of the file. * - * $Log: pwdb_chkpwd.c,v $ - * Revision 1.1 1997/02/15 17:26:18 morgan - * Initial revision - * - * Revision 1.1 1996/11/10 21:20:51 morgan - * Initial revision - * */ -#ifdef linux -# define _GNU_SOURCE -# include <features.h> -#endif +#include <security/_pam_aconf.h> #include <stdarg.h> #include <stdio.h> @@ -54,6 +44,7 @@ static void _log_err(int err, const char *format, ...) closelog(); } +#define PWDB_NO_MD_COMPAT #include "pam_unix_md.-c" static int _unix_verify_passwd(const char *salt, const char *p) @@ -92,12 +83,12 @@ static int _unix_verify_passwd(const char *salt, const char *p) return retval; } -void main(void) +int main(int argc, char **argv) { const struct pwdb *pw=NULL; const struct pwdb_entry *pwe=NULL; char pass[MAXPASS+1]; - int npass; + int npass, force_failure=0; int retval=UNIX_FAILED; /* @@ -129,14 +120,26 @@ void main(void) retval = UNIX_FAILED; } if (retval != UNIX_FAILED) { - retval = pwdb_locate("user", PWDB_DEFAULT, PWDB_NAME_UNKNOWN - , getuid(), &pw); + retval = pwdb_locate("user", PWDB_DEFAULT, PWDB_NAME_UNKNOWN, + getuid(), &pw); } if (retval != PWDB_SUCCESS) { _log_err(LOG_ALERT, "could not identify user"); while (pwdb_end() != PWDB_SUCCESS); exit(UNIX_FAILED); } + if (argc == 2) { + if (pwdb_get_entry(pw, "user", &pwe) == PWDB_SUCCESS) { + if (pwe == NULL) { + force_failure = 1; + } else { + if (strcmp((const char *) pwe->value, argv[1])) { + force_failure = 1; + } + pwdb_entry_delete(&pwe); + } + } + } /* read the password from stdin (a pipe from the pam_pwdb module) */ @@ -167,6 +170,10 @@ void main(void) memset(pass, '\0', MAXPASS); /* clear memory of the password */ while (pwdb_end() != PWDB_SUCCESS); + if ((retval != UNIX_FAILED) && force_failure) { + retval = UNIX_FAILED; + } + /* return pass or fail */ exit(retval); diff --git a/contrib/libpam/modules/pam_pwdb/support.-c b/contrib/libpam/modules/pam_pwdb/support.-c index 71e212d64195..2b80f960cde7 100644 --- a/contrib/libpam/modules/pam_pwdb/support.-c +++ b/contrib/libpam/modules/pam_pwdb/support.-c @@ -1,18 +1,5 @@ /* - * $Id: support.-c,v 1.7 1997/04/05 06:32:06 morgan Exp morgan $ - * - * $Log: support.-c,v $ - * Revision 1.7 1997/04/05 06:32:06 morgan - * new option and also deleted _readto - * - * Revision 1.6 1997/02/15 17:27:20 morgan - * added helper binary to password checking - * - * Revision 1.5 1996/12/01 03:05:54 morgan - * debugging with _pam_macros.h - * - * Revision 1.4 1996/11/10 21:06:07 morgan - * pwdb conversion + * $Id: support.-c,v 1.3 2001/02/11 06:33:53 agmorgan Exp $ * * Copyright information at end of file. */ @@ -91,8 +78,9 @@ typedef struct { #define UNIX_NODELAY 18 /* admin does not want a fail-delay */ #define UNIX_UNIX 19 /* wish to use /etc/passwd for pwd */ #define UNIX_BIGCRYPT 20 /* use DEC-C2 crypt()^x function */ +#define UNIX_LIKE_AUTH 21 /* need to auth for setcred to work */ /* -------------- */ -#define UNIX_CTRLS_ 21 /* number of ctrl arguments defined */ +#define UNIX_CTRLS_ 22 /* number of ctrl arguments defined */ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = { @@ -118,8 +106,9 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = { /* UNIX__SET_DB */ { NULL, _ALL_ON_, 0100000 }, /* UNIX_DEBUG */ { "debug", _ALL_ON_, 0200000 }, /* UNIX_NODELAY */ { "nodelay", _ALL_ON_, 0400000 }, -/* UNIX_UNIX */ { "unix", _ALL_ON_^(050000), 01000000 }, +/* UNIX_UNIX */ { "unix", _ALL_ON_^(050000), 01000000 }, /* UNIX_BIGCRYPT */ { "bigcrypt", _ALL_ON_^(020000), 02000000 }, +/* UNIX_LIKE_AUTH */ { "likeauth", _ALL_ON_, 04000000 }, }; #define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag) @@ -161,7 +150,7 @@ static int converse(pam_handle_t *pamh, int ctrl, int nargs , pam_strerror(pamh, retval)); } - } else { + } else if (retval != PAM_CONV_AGAIN) { _log_err(LOG_ERR, "couldn't obtain coversation function [%s]" , pam_strerror(pamh, retval)); } @@ -322,13 +311,13 @@ static void _cleanup_failures(pam_handle_t *pamh, void *fl, int err) if ( !quiet && !err ) { /* under advisement from Sun,may go away */ /* log the number of authentication failures */ - if ( failure->count != 0 ) { + if ( failure->count > 1 ) { (void) pam_get_item(pamh, PAM_SERVICE , (const void **)&service); _log_err(LOG_NOTICE - , "%d authentication failure%s; %s(uid=%d) -> " + , "%d more authentication failure%s; %s(uid=%d) -> " "%s for %s service" - , failure->count, failure->count==1 ? "":"s" + , failure->count-1, failure->count==2 ? "":"s" , failure->name , failure->id , failure->user @@ -356,7 +345,8 @@ static void _cleanup_failures(pam_handle_t *pamh, void *fl, int err) #include <sys/types.h> #include <sys/wait.h> -static int pwdb_run_helper_binary(pam_handle_t *pamh, const char *passwd) +static int pwdb_run_helper_binary(pam_handle_t *pamh, const char *passwd, + const char *user) { int retval, child, fds[2]; @@ -370,7 +360,7 @@ static int pwdb_run_helper_binary(pam_handle_t *pamh, const char *passwd) /* fork */ child = fork(); if (child == 0) { - static char *args[] = { NULL, NULL }; + static char *args[] = { NULL, NULL, NULL }; static char *envp[] = { NULL }; /* XXX - should really tidy up PAM here too */ @@ -382,6 +372,8 @@ static int pwdb_run_helper_binary(pam_handle_t *pamh, const char *passwd) /* exec binary helper */ args[0] = x_strdup(CHKPWD_HELPER); + args[1] = x_strdup(user); + execve(CHKPWD_HELPER, args, envp); /* should not get here: exit with error */ @@ -389,13 +381,14 @@ static int pwdb_run_helper_binary(pam_handle_t *pamh, const char *passwd) exit(PWDB_SUCCESS+1); } else if (child > 0) { /* wait for child */ - close(fds[0]); if (passwd != NULL) { /* send the password to the child */ write(fds[1], passwd, strlen(passwd)+1); passwd = NULL; } else { write(fds[1], "", 1); /* blank password */ } + close(fds[0]); /* we close this after the write because we want + to avoid a possible SIGPIPE. */ close(fds[1]); (void) waitpid(child, &retval, 0); /* wait for helper to complete */ retval = (retval == PWDB_SUCCESS) ? PAM_SUCCESS:PAM_AUTH_ERR; @@ -408,8 +401,8 @@ static int pwdb_run_helper_binary(pam_handle_t *pamh, const char *passwd) return retval; } -static int _unix_verify_password(pam_handle_t *pamh, const char *name - , const char *p, unsigned int ctrl) +static int _unix_verify_password(pam_handle_t *pamh, const char *name, + const char *p, unsigned int ctrl) { const struct pwdb *pw=NULL; const struct pwdb_entry *pwe=NULL; @@ -418,6 +411,7 @@ static int _unix_verify_password(pam_handle_t *pamh, const char *name char *pp; char *data_name; int retval; + int verify_result; D(("called")); @@ -474,7 +468,7 @@ static int _unix_verify_password(pam_handle_t *pamh, const char *name if (geteuid()) { /* we are not root perhaps this is the reason? Run helper */ D(("running helper binary")); - retval = pwdb_run_helper_binary(pamh, p); + retval = pwdb_run_helper_binary(pamh, p, name); } else { retval = PAM_AUTHINFO_UNAVAIL; _log_err(LOG_ALERT, "get passwd; %s", pwdb_strerror(retval)); @@ -491,33 +485,56 @@ static int _unix_verify_password(pam_handle_t *pamh, const char *name * clear text... */ - if ( ( !salt ) && ( !p ) ) { + data_name = (char *) malloc(sizeof(FAIL_PREFIX)+strlen(name)); + if ( data_name == NULL ) { + _log_err(LOG_CRIT, "no memory for data-name"); + } + strcpy(data_name, FAIL_PREFIX); + strcpy(data_name + sizeof(FAIL_PREFIX)-1, name); - /* the stored password is NULL */ + if ( !( (salt && *salt) || (p && *p) ) ) { - (void) pwdb_entry_delete(&pwe); - (void) pwdb_delete(&pw); + D(("two null passwords to compare")); + /* the stored password is NULL */ + pp = NULL; if ( off(UNIX__NONULL, ctrl ) ) { /* this means we've succeeded */ - return PAM_SUCCESS; + verify_result = PAM_SUCCESS; } else { - return PAM_AUTH_ERR; + verify_result = PAM_AUTH_ERR; } - } - pp = _pam_md(p, salt); - p = NULL; /* no longer needed here */ + } else if ( !( salt && p ) ) { - data_name = (char *) malloc(sizeof(FAIL_PREFIX)+strlen(name)); - if ( data_name == NULL ) { - _log_err(LOG_CRIT, "no memory for data-name"); - } - strcpy(data_name, FAIL_PREFIX); - strcpy(data_name + sizeof(FAIL_PREFIX)-1, name); + D(("one of the two to compare are NULL")); + + pp = NULL; + verify_result = PAM_AUTH_ERR; + + } else { - /* the moment of truth -- do we agree with the password? */ + pp = _pam_md(p, salt); - if ( strcmp( pp, salt ) == 0 ) { + /* the moment of truth -- do we agree with the password? */ + D(("comparing state of pp[%s] and salt[%s]", pp, salt)); + + if ( strcmp( pp, salt ) == 0 ) { + verify_result = PAM_SUCCESS; + } else { + _pam_delete(pp); + pp = _pam_md_compat(p, salt); + if ( strcmp( pp, salt ) == 0 ) { + verify_result = PAM_SUCCESS; + } else { + verify_result = PAM_AUTH_ERR; + } + } + + p = NULL; /* no longer needed here */ + + } + + if ( verify_result == PAM_SUCCESS ) { retval = PAM_SUCCESS; if (data_name) { /* reset failures */ @@ -538,7 +555,11 @@ static int _unix_verify_password(pam_handle_t *pamh, const char *name if (new != NULL) { - /* any previous failures for this user ? */ + new->user = x_strdup(name); + new->id = getuid(); + new->name = x_strdup(getlogin() ? getlogin():"" ); + + /* any previous failures for this user ? */ pam_get_data(pamh, data_name, (const void **)&old ); if (old != NULL) { @@ -547,11 +568,19 @@ static int _unix_verify_password(pam_handle_t *pamh, const char *name retval = PAM_MAXTRIES; } } else { + const char *service=NULL; + (void) pam_get_item(pamh, PAM_SERVICE + , (const void **)&service); + _log_err(LOG_NOTICE + , "authentication failure; %s(uid=%d) -> " + "%s for %s service" + , new->name + , new->id + , new->user + , service == NULL ? "**unknown**":service + ); new->count = 1; } - new->user = x_strdup(name); - new->id = getuid(); - new->name = x_strdup(getlogin() ? getlogin():"" ); pam_set_data(pamh, data_name, new, _cleanup_failures); @@ -568,6 +597,8 @@ static int _unix_verify_password(pam_handle_t *pamh, const char *name _pam_delete(data_name); _pam_delete(pp); + D(("done [%d].", retval)); + return retval; } @@ -596,8 +627,9 @@ static int _unix_get_user(pam_handle_t *pamh, unsigned int ctrl * alphanumeric character. */ - if (!isalnum(**user)) { - if (on(UNIX_DEBUG,ctrl) || **user) { + if (*user == NULL || !isalnum(**user)) { + D(("bad username")); + if (on(UNIX_DEBUG,ctrl)) { _log_err(LOG_ERR, "bad username [%s]", *user); } return PAM_USER_UNKNOWN; @@ -872,7 +904,7 @@ static int _pam_unix_approve_pass(pam_handle_t *pamh } /* ****************************************************************** * - * Copyright (c) Andrew G. Morgan, <morgan@parc.power.net> 1996. + * Copyright (c) Andrew G. Morgan 1996-8. * Copyright (c) Alex O. Yuriev, 1996. * Copyright (c) Cristian Gafton 1996. * diff --git a/contrib/libpam/modules/pam_radius/Makefile b/contrib/libpam/modules/pam_radius/Makefile index a74b911f4e3b..aa149d3ee9b5 100644 --- a/contrib/libpam/modules/pam_radius/Makefile +++ b/contrib/libpam/modules/pam_radius/Makefile @@ -8,13 +8,15 @@ # STATIC modules are not supported # +include ../../Make.Rules + TITLE=pam_radius CONFD=$(CONFIGED)/security export CONFD CONFILE=$(CONFD)/radius.conf export CONFILE -ifeq ($(HAVE_PWDBLIB),yes) +ifeq ($(HAVE_LIBPWDB),yes) # @@ -41,11 +43,6 @@ endif ####################### don't edit below ####################### -dummy: - - @echo "**** This is not a top-level Makefile " - exit - all: dirs $(LIBSHARED) $(LIBSTATIC) register dirs: @@ -85,9 +82,8 @@ remove: clean: rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean rm -f *.a *.o *.so *.bak dynamic/* static/* + rm -rf dynamic static .c.o: $(CC) $(CFLAGS) -c $< diff --git a/contrib/libpam/modules/pam_radius/pam_radius.h b/contrib/libpam/modules/pam_radius/pam_radius.h index 72b1da8aa0cb..67230243eed8 100644 --- a/contrib/libpam/modules/pam_radius/pam_radius.h +++ b/contrib/libpam/modules/pam_radius/pam_radius.h @@ -1,12 +1,17 @@ +/* + * $Id: pam_radius.h,v 1.2 2000/11/19 23:54:05 agmorgan Exp $ + */ #ifndef PAM_RADIUS_H #define PAM_RADIUS_H -#define _GNU_SOURCE -#include <features.h> +#include <security/_pam_aconf.h> #include <stdio.h> + +#ifndef __USE_POSIX2 #define __USE_POSIX2 +#endif /* __USE_POSIX2 */ #include <stdlib.h> diff --git a/contrib/libpam/modules/pam_rhosts/Makefile b/contrib/libpam/modules/pam_rhosts/Makefile index 93addbb68119..d12e00c0680e 100644 --- a/contrib/libpam/modules/pam_rhosts/Makefile +++ b/contrib/libpam/modules/pam_rhosts/Makefile @@ -1,94 +1,15 @@ -# This Makefile controls a build process of the pam_rhosts modules -# for Linux-PAM. You should not modify this Makefile. +# +# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $ +# +# This Makefile controls a build process of $(TITLE) module for +# Linux-PAM. You should not modify this Makefile (unless you know +# what you are doing!). +# +# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27 +# -LIBAUTHOBJ = pam_rhosts_auth.o -LIBAUTHSRC = pam_rhosts_auth.c -LIBSESSOBJ = -LIBSESSSRC = -LIBPASSWDSRC = -LIBPASSWDOBJ = -LIBOBJ = $(LIBAUTHOBJ) $(LIBSESSOBJ) $(LIBPASSWDOBJ) -LIBSRC = $(LIBAUTHSRC) $(LIBSESSSRC) $(LIBPASSWDSRC) +include ../../Make.Rules -ifdef STATIC -LIBSTATIC = libpam_rhosts.o -LIBOBJS = $(addprefix static/,$(LIBOBJ)) -endif +TITLE=pam_rhosts_auth -ifdef DYNAMIC -LIBSESSSH = -LIBAUTHSH = pam_rhosts_auth.so -LIBPASSWDSH = -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBSHARED = $(LIBSESSSH) $(LIBAUTHSH) $(LIBPASSWDSH) -endif - -####################### don't edit below ####################### - -dummy: - @echo "**** This is not a top-level Makefile " - exit - - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; \ - ./register_static pam_rhosts_auth pam_rhosts/libpam_rhosts.o ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -endif - -ifdef DYNAMIC -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -endif - -ifdef STATIC -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) - -endif - -#.c.o: -# $(CC) -c $(CFLAGS) $< - -install: all -ifdef DYNAMIC - $(MKDIR) $(FAKEROOT)$(SECUREDIR) - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -# tidy up - -remove: - cd $(FAKEROOT)$(SECUREDIR) && rm -f $(LIBSHARED) - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) a.out core *~ - -extraclean: - rm -f *.a *.out *.o *.so *.bak dynamic/* static/* - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_rhosts/pam_rhosts_auth.c b/contrib/libpam/modules/pam_rhosts/pam_rhosts_auth.c index 10dfcf797119..b633a52989d7 100644 --- a/contrib/libpam/modules/pam_rhosts/pam_rhosts_auth.c +++ b/contrib/libpam/modules/pam_rhosts/pam_rhosts_auth.c @@ -46,6 +46,10 @@ #include <endian.h> #endif +#ifdef NEED_FSUID_H +#include <sys/fsuid.h> +#endif /* NEED_FSUID_H */ + #include <sys/types.h> #include <sys/uio.h> #include <string.h> @@ -103,6 +107,7 @@ int innetgr(const char *, const char *, const char *,const char *); struct _options { int opt_no_hosts_equiv; + int opt_hosts_equiv_rootok; int opt_no_rhosts; int opt_debug; int opt_nowarn; @@ -111,6 +116,8 @@ struct _options { int opt_promiscuous; int opt_suppress; int opt_private_group; + int opt_no_uid_check; + const char *superuser; const char *last_error; }; @@ -133,6 +140,11 @@ static void set_option (struct _options *opts, const char *arg) return; } + if (strcmp(arg, "hosts_equiv_rootok") == 0) { + opts->opt_hosts_equiv_rootok = 1; + return; + } + if (strcmp(arg, "no_rhosts") == 0) { opts->opt_no_rhosts = 1; return; @@ -165,6 +177,15 @@ static void set_option (struct _options *opts, const char *arg) return; } + if (strcmp(arg, "no_uid_check") == 0) { + opts->opt_no_uid_check = 1; /* NIS optimization */ + return; + } + + if (strcmp(arg, "superuser=") == 0) { + opts->superuser = arg+sizeof("superuser=")-1; + return; + } /* * All other options are ignored at the present time. */ @@ -444,7 +465,7 @@ pam_iruserok(pam_handle_t *pamh, int answer; char pbuf[MAXPATHLEN]; /* potential buffer overrun */ - if ( !superuser && !opts->opt_no_hosts_equiv ) { + if ((!superuser||opts->opt_hosts_equiv_rootok) && !opts->opt_no_hosts_equiv ) { /* try to open system hosts.equiv file */ hostf = fopen (_PATH_HEQUIV, "r"); @@ -677,8 +698,12 @@ static int _pam_auth_rhosts (pam_handle_t *pamh, break; } + if (opts.superuser && !strcmp(opts.superuser, luser)) { + as_root = 1; + } + /* check if the luser uid == 0... --cristiang */ - { + if (! opts.opt_no_uid_check) { struct passwd *luser_pwd; luser_pwd = getpwnam(luser); @@ -759,30 +784,3 @@ struct pam_module _pam_rhosts_auth_modstruct = { }; #endif - -/* - * $Log: pam_rhosts_auth.c,v $ - * Revision 1.12 1997/09/27 14:34:01 morgan - * fixed comment and renamed iruserok to pam_iruserok. - * - * Revision 1.11 1997/04/05 06:26:39 morgan - * fairly major fixes and enhancements (see CHANGELOG for 0.57 release) - * - * Revision 1.10 1997/02/09 02:09:30 morgan - * - implementation of 'debug' argument (Cristian Gafton) - * - we check for uid=0 accounts instead of hardcoded 'root' (Cristian Gafton) - * - * Revision 1.9 1996/12/01 03:09:47 morgan - * *** empty log message *** - * - * Revision 1.8 1996/11/12 06:08:59 morgan - * Oliver Crow's "rootok" patch plus a little clean up of set_option - * (AGM) - * - * Revision 1.7 1996/11/10 20:15:56 morgan - * cross platform support - * - * Revision 1.6 1996/08/09 05:46:29 morgan - * removed code for manually setting the remote username etc.. - * - */ diff --git a/contrib/libpam/modules/pam_rootok/Makefile b/contrib/libpam/modules/pam_rootok/Makefile index b37870801193..b908b1157ac2 100644 --- a/contrib/libpam/modules/pam_rootok/Makefile +++ b/contrib/libpam/modules/pam_rootok/Makefile @@ -1,111 +1,15 @@ # -# $Id: Makefile,v 1.7 1997/04/05 06:25:20 morgan Exp $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.7 1997/04/05 06:25:20 morgan -# fakeroot +# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27 # -# Revision 1.6 1997/02/15 19:15:50 morgan -# fixed email -# -# Revision 1.5 1996/11/10 20:16:10 morgan -# cross platform support -# -# Revision 1.4 1996/09/05 06:29:36 morgan -# ld --> gcc -# -# Revision 1.3 1996/05/26 15:47:46 morgan -# make dynamic/static dirs! -# -# Revision 1.2 1996/05/26 04:04:53 morgan -# automated static support -# -# Revision 1.1 1996/05/05 17:14:15 morgan -# Initial revision -# -# -# Created by Andrew Morgan <morgan@parc.power.net> 1996/5/5 -# - -TITLE=pam_rootok - -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif +include ../../Make.Rules -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< +TITLE=pam_rootok +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_rootok/README b/contrib/libpam/modules/pam_rootok/README index d7010dd9738d..eee59ff02b0c 100644 --- a/contrib/libpam/modules/pam_rootok/README +++ b/contrib/libpam/modules/pam_rootok/README @@ -1,4 +1,4 @@ -# $Id: README,v 1.1 1996/05/10 04:15:31 morgan Exp $ +# $Id: README,v 1.1.1.1 2000/06/20 22:11:56 agmorgan Exp $ # this module is an authentication module that performs one task: if the diff --git a/contrib/libpam/modules/pam_rootok/pam_rootok.c b/contrib/libpam/modules/pam_rootok/pam_rootok.c index 21327d42e5ea..54795e3c2b3d 100644 --- a/contrib/libpam/modules/pam_rootok/pam_rootok.c +++ b/contrib/libpam/modules/pam_rootok/pam_rootok.c @@ -1,22 +1,13 @@ /* pam_rootok module */ /* - * $Id: pam_rootok.c,v 1.5 1997/02/15 17:32:47 morgan Exp $ - * - * Written by Andrew Morgan <morgan@parc.power.net> 1996/3/11 - * - * $Log: pam_rootok.c,v $ - * Revision 1.5 1997/02/15 17:32:47 morgan - * removed fixed syslog buffer - * - * Revision 1.4 1996/12/01 03:10:14 morgan - * reformatted - * - * Revision 1.3 1996/06/02 08:11:01 morgan - * updated for new static protocol + * $Id: pam_rootok.c,v 1.1.1.1 2000/06/20 22:11:56 agmorgan Exp $ * + * Written by Andrew Morgan <morgan@linux.kernel.org> 1996/3/11 */ +#define _GNU_SOURCE + #include <stdio.h> #include <unistd.h> #include <syslog.h> diff --git a/contrib/libpam/modules/pam_securetty/Makefile b/contrib/libpam/modules/pam_securetty/Makefile index d8a09ea13377..8ac853c595ff 100644 --- a/contrib/libpam/modules/pam_securetty/Makefile +++ b/contrib/libpam/modules/pam_securetty/Makefile @@ -1,83 +1,15 @@ # +# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $ +# # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # - -TITLE=pam_securetty - +# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27 # -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit +include ../../Make.Rules -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* +TITLE=pam_securetty -.c.o: - $(CC) $(CFLAGS) -c $< +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_securetty/pam_securetty.c b/contrib/libpam/modules/pam_securetty/pam_securetty.c index 369fb03dd060..9e6121e8be97 100644 --- a/contrib/libpam/modules/pam_securetty/pam_securetty.c +++ b/contrib/libpam/modules/pam_securetty/pam_securetty.c @@ -8,18 +8,10 @@ * July 25, 1996. * This code shamelessly ripped from the pam_rootok module. * Slight modifications AGM. 1996/12/3 - * $Log: pam_securetty.c,v $ - * Revision 1.7 1997/04/05 06:24:23 morgan - * changed return value on user unknown error - * - * Revision 1.6 1997/02/15 17:30:36 morgan - * removed fixed length syslog buffer - * - * Revision 1.5 1997/02/09 02:22:24 morgan - * added "debug" flag handling (Cristian Gafton) - * */ +#define _GNU_SOURCE + #include <stdio.h> #include <stdlib.h> #include <sys/types.h> @@ -28,7 +20,7 @@ #include <syslog.h> #include <stdarg.h> #include <pwd.h> -#include <strings.h> +#include <string.h> #define PAM_SM_AUTH @@ -97,13 +89,20 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc /* parse the arguments */ ctrl = _pam_parse(argc, argv); - retval = pam_get_item(pamh,PAM_USER,(const void **)&username); - if (retval == PAM_SUCCESS) - retval = pam_get_item(pamh,PAM_TTY,(const void **)&uttyname); + retval = pam_get_user(pamh, &username, NULL); + if (retval != PAM_SUCCESS || username == NULL) { + if (ctrl & PAM_DEBUG_ARG) { + _pam_log(LOG_WARNING, "cannot determine username"); + } + return (retval == PAM_CONV_AGAIN + ? PAM_INCOMPLETE:PAM_SERVICE_ERR); + } + + retval = pam_get_item(pamh, PAM_TTY, (const void **)&uttyname); if (retval != PAM_SUCCESS || uttyname == NULL) { - /* If we couldn't get the username or the tty return error */ - if (ctrl & PAM_DEBUG_ARG) - _pam_log(LOG_WARNING, "can not determine tty I'm running on !"); + if (ctrl & PAM_DEBUG_ARG) { + _pam_log(LOG_WARNING, "cannot determine user's tty"); + } return PAM_SERVICE_ERR; } @@ -111,36 +110,24 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc if (strncmp(TTY_PREFIX, uttyname, sizeof(TTY_PREFIX)-1) == 0) uttyname += sizeof(TTY_PREFIX)-1; - /* If we didn't get a username, get one */ - if(!username || (strlen(username) <= 0)) { - /* Don't let them use a NULL username... */ - (void) pam_set_item(pamh, PAM_USER, NULL); - pam_get_user(pamh,&username,NULL); - if (retval != PAM_SUCCESS || username == NULL || *username == '\0') { - if (ctrl & PAM_DEBUG_ARG) - _pam_log(LOG_WARNING, - "can not determine username for this service!"); - return PAM_SERVICE_ERR; - } - } - user_pwd = getpwnam(username); - if (user_pwd == NULL) + if (user_pwd == NULL) { return PAM_IGNORE; - else if (user_pwd->pw_uid != 0) /* If the user is not root, - securetty's does not apply to them */ + } else if (user_pwd->pw_uid != 0) { /* If the user is not root, + securetty's does not apply + to them */ return PAM_SUCCESS; + } - if(stat(SECURETTY_FILE,&ttyfileinfo)) { - _pam_log(LOG_NOTICE, - "Couldn't open " SECURETTY_FILE); + if (stat(SECURETTY_FILE, &ttyfileinfo)) { + _pam_log(LOG_NOTICE, "Couldn't open " SECURETTY_FILE); return PAM_SUCCESS; /* for compatibility with old securetty handling, this needs to succeed. But we still log the error. */ } - if((ttyfileinfo.st_mode & S_IWOTH) - || !S_ISREG(ttyfileinfo.st_mode)) { + if ((ttyfileinfo.st_mode & S_IWOTH) + || !S_ISREG(ttyfileinfo.st_mode)) { /* If the file is world writable or is not a normal file, return error */ _pam_log(LOG_ERR, SECURETTY_FILE diff --git a/contrib/libpam/modules/pam_shells/Makefile b/contrib/libpam/modules/pam_shells/Makefile index 121b19a00863..f1d7ff515187 100644 --- a/contrib/libpam/modules/pam_shells/Makefile +++ b/contrib/libpam/modules/pam_shells/Makefile @@ -1,84 +1,15 @@ # +# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $ +# # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # - -TITLE=pam_shells - +# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27 # -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit +include ../../Make.Rules -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< +TITLE=pam_shells +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_shells/pam_shells.c b/contrib/libpam/modules/pam_shells/pam_shells.c index edc9134b3274..36dd1a917e4e 100644 --- a/contrib/libpam/modules/pam_shells/pam_shells.c +++ b/contrib/libpam/modules/pam_shells/pam_shells.c @@ -1,4 +1,4 @@ -/* pam_securetty module */ +/* pam_shells module */ #define SHELL_FILE "/etc/shells" @@ -8,6 +8,8 @@ * This code shamelessly ripped from the pam_securetty module. */ +#define _BSD_SOURCE + #include <pwd.h> #include <stdarg.h> #include <stdio.h> @@ -71,21 +73,21 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc userShell = pw->pw_shell; if(stat(SHELL_FILE,&sb)) { - _pam_log(LOG_ERR, SHELL_FILE, " cannot be stat'd (it probably does " - "not exist)"); + _pam_log(LOG_ERR, + "%s cannot be stat'd (it probably does not exist)", SHELL_FILE); return PAM_AUTH_ERR; /* must have /etc/shells */ } if((sb.st_mode & S_IWOTH) || !S_ISREG(sb.st_mode)) { - _pam_log(LOG_ERR, - SHELL_FILE " is either world writable or not a normal file"); - return PAM_AUTH_ERR; + _pam_log(LOG_ERR, + "%s is either world writable or not a normal file", SHELL_FILE); + return PAM_AUTH_ERR; } shellFile = fopen(SHELL_FILE,"r"); if(shellFile == NULL) { /* Check that we opened it successfully */ - _pam_log(LOG_ERR, - "Error opening " SHELL_FILE); + _pam_log(LOG_ERR, + "Error opening %s", SHELL_FILE); return PAM_SERVICE_ERR; } /* There should be no more errors from here on */ diff --git a/contrib/libpam/modules/pam_stress/Makefile b/contrib/libpam/modules/pam_stress/Makefile index 52e8e21881a3..3512c853aef9 100644 --- a/contrib/libpam/modules/pam_stress/Makefile +++ b/contrib/libpam/modules/pam_stress/Makefile @@ -1,109 +1,15 @@ # -# $Id: Makefile,v 1.7 1997/04/05 06:23:08 morgan Exp $ -# -# Created by Andrew Morgan <morgan@parc.power.net> 1996/3/11 +# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.7 1997/04/05 06:23:08 morgan -# fakeroot -# -# Revision 1.6 1997/02/15 19:05:55 morgan -# fixed email -# -# Revision 1.5 1996/11/10 20:17:55 morgan -# cross platform support -# -# Revision 1.4 1996/09/05 06:31:09 morgan -# ld --> gcc -# -# Revision 1.3 1996/05/26 15:50:43 morgan -# make dynamic and static dirs -# -# Revision 1.2 1996/05/26 04:11:56 morgan -# automated static support -# -# +# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27 # -TITLE=pam_stress - -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif +include ../../Make.Rules -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak - -.c.o: - $(CC) $(CFLAGS) -c $< +TITLE=pam_stress +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_stress/README b/contrib/libpam/modules/pam_stress/README index 1cb7c14b73c3..b4273f501ff4 100644 --- a/contrib/libpam/modules/pam_stress/README +++ b/contrib/libpam/modules/pam_stress/README @@ -1,5 +1,5 @@ # -# $Id: README,v 1.7 1997/02/15 19:07:08 morgan Exp $ +# $Id: README,v 1.1.1.1 2000/06/20 22:11:57 agmorgan Exp $ # # This describes the behavior of this module with respect to the # /etc/pam.conf file. diff --git a/contrib/libpam/modules/pam_stress/pam_stress.c b/contrib/libpam/modules/pam_stress/pam_stress.c index 501541850461..52d9e8041ec8 100644 --- a/contrib/libpam/modules/pam_stress/pam_stress.c +++ b/contrib/libpam/modules/pam_stress/pam_stress.c @@ -1,34 +1,18 @@ /* pam_stress module */ -/* $Id: pam_stress.c,v 1.12 1997/02/15 19:06:30 morgan Exp morgan $ - * - * created by Andrew Morgan <morgan@parc.power.net> 1996/3/12 - * - * $Log: pam_stress.c,v $ - * Revision 1.12 1997/02/15 19:06:30 morgan - * fixed email - * - * Revision 1.11 1997/02/15 17:33:24 morgan - * removed fixed syslog buffer - * - * Revision 1.10 1996/12/01 03:11:35 morgan - * using _pam_macros.h now - * - * Revision 1.9 1996/11/10 20:18:10 morgan - * changes for .53 compilation - * - * Revision 1.8 1996/09/05 06:31:59 morgan - * changed return value of wipe_up from int to void - * - * Revision 1.7 1996/06/02 08:12:28 morgan - * updated for new static protocol, added STRESS to various user prompts - * and added rootok flag for pam_sm_chauthtok to look out for +/* $Id: pam_stress.c,v 1.2 2000/11/19 23:54:05 agmorgan Exp $ * + * created by Andrew Morgan <morgan@linux.kernel.org> 1996/3/12 */ +#include <security/_pam_aconf.h> + #include <stdlib.h> #include <stdio.h> + +#define __USE_BSD #include <syslog.h> + #include <stdarg.h> #include <string.h> #include <unistd.h> diff --git a/contrib/libpam/modules/pam_tally/Makefile b/contrib/libpam/modules/pam_tally/Makefile index ec17ff31fa8e..032b93416bd9 100644 --- a/contrib/libpam/modules/pam_tally/Makefile +++ b/contrib/libpam/modules/pam_tally/Makefile @@ -1,20 +1,19 @@ # -# $Id: Makefile,v 1.1 1997/04/05 06:19:04 morgan Exp $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $ # -# This Makefile controls a build process of $(TITLE) module for -# Linux-PAM. You should not modify this Makefile (unless you know -# what you are doing!). -# -# $Log: Makefile,v $ -# Revision 1.1 1997/04/05 06:19:04 morgan -# Initial revision +# This Makefile controls a build process of $(TITLE) module and +# application for Linux-PAM. You should not modify this Makefile +# (unless you know what you are doing!). # # +include ../../Make.Rules + TITLE=pam_tally # -## Should add some more rules to make the application too. +## Additional rules for making (and moving) the application added. +## Assuming that all modules' applications are called $TITLE # LIBSRC = $(TITLE).c @@ -22,6 +21,11 @@ LIBOBJ = $(TITLE).o LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) LIBOBJS = $(addprefix static/,$(LIBOBJ)) +APPSRC = $(TITLE)_app.c +APPOBJ = $(TITLE)_app.o +APPOBJD = $(addprefix dynamic/,$(APPOBJ)) +APPOBJS = $(addprefix static/,$(APPOBJ)) + dynamic/%.o : %.c $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ @@ -37,14 +41,12 @@ ifdef STATIC LIBSTATIC = lib$(TITLE).o endif -####################### don't edit below ####################### +APPLICATION = $(TITLE) +APPMODE = 755 -dummy: - - @echo "**** This is not a top-level Makefile " - exit +####################### don't edit below ####################### -all: dirs $(LIBSHARED) $(LIBSTATIC) register +all: dirs $(LIBSHARED) $(LIBSTATIC) register $(APPLICATION) dirs: ifdef DYNAMIC @@ -62,8 +64,12 @@ endif ifdef DYNAMIC $(LIBOBJD): $(LIBSRC) -$(LIBSHARED): $(LIBOBJD) +$(LIBSHARED): $(LIBOBJD) $(LD_D) -o $@ $(LIBOBJD) + +$(APPLICATION): $(APPOBJD) + $(CC) $(CFLAGS) -o $@ $< $(LOADLIBES) + endif ifdef STATIC @@ -71,6 +77,9 @@ $(LIBOBJS): $(LIBSRC) $(LIBSTATIC): $(LIBOBJS) $(LD) -r -o $@ $(LIBOBJS) + +$(APPLICATION): $(APPOBJS) + $(CC) $(CFLAGS) -o $@ $< $(LOADLIBES) endif install: all @@ -78,16 +87,17 @@ install: all ifdef DYNAMIC $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) endif + $(MKDIR) $(FAKEROOT)$(SUPLEMENTED) +# $(INSTALL) -m $(APPMODE) $(APPLICATION) $(FAKEROOT)$(SUPLEMENTED) remove: rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so + rm -f $(FAKEROOT)$(SUPLEMENTED)/$(TITLE) clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ + rm -f $(LIBOBJD) $(LIBOBJS) $(APPOBJD) $(APPOBJS) core *~ + rm -f *.a *.o *.so *.bak dynamic/* static/* $(APPLICATION) + rm -rf dynamic static -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: +.c.o: $(CC) $(CFLAGS) -c $< - diff --git a/contrib/libpam/modules/pam_tally/README b/contrib/libpam/modules/pam_tally/README index aaa8512bade4..b58b24e45793 100644 --- a/contrib/libpam/modules/pam_tally/README +++ b/contrib/libpam/modules/pam_tally/README @@ -1,4 +1,3 @@ - SUMMARY: pam_tally: @@ -12,10 +11,12 @@ SUMMARY: * file=/where/to/keep/counts (default /var/log/faillog) (auth) + Authentication phase increments attempted login counter. * no_magic_root (root DOES increment counter. Use for daemon-based stuff, like telnet/rsh/login) (account) + Account phase can deny access and/or reset attempts counter. * deny=n (deny access if tally for this user exceeds n; The presence of deny=n changes the default for reset/no_reset to reset, unless the user trying to @@ -34,11 +35,54 @@ SUMMARY: This is the default unless deny exists and the user attempting access is NOT magic root. - Also checks to make sure that the list file is a plain + * per_user (If /var/log/faillog contains a non-zero + .fail_max field for this user then use it + instead of deny=n parameter) + + * no_lock_time (Don't use .fail_locktime filed in + /var/log/faillog for this user) + + Also checks to make sure that the counts file is a plain file and not world writable. - - Tim Baverstock <warwick@mmm.co.uk>, Multi Media Machine Ltd. - v0.1 5 March 1997 + - Tim Baverstock <warwick@sable.demon.co.uk>, v0.1 5 March 1997 + +LONGER: + +pam_tally comes in two parts: pam_tally.so and pam_tally. + +pam_tally.so sits in a pam config file, in the auth and account sections. + +In the auth section, it increments a per-uid counter for each attempted +login, in the account section, it denies access if attempted logins +exceed some threashold and/or resets that counter to zero on successful +login. + +Root is treated specially: + +1. When a process already running as root tries to access some service, the +access is `magic', and bypasses pam_tally's checks: handy for `su'ing from +root into an account otherwise blocked. However, for services like telnet or +login which always effectively run from the root account, root (ie everyone) +shouldn't be granted this magic status, and the flag `no_magic_root' should +be set in this situation, as noted in the summary above. [This option may +be obsolete, with `sufficient root' processing.] + +2. Normally, failed attempts to access root will NOT cause the root +account to become blocked, to prevent denial-of-service: if your users aren't +given shell accounts and root may only login via `su' or at the machine +console (not telnet/rsh, etc), this is safe. If you really want root to be +blocked for some given service, use even_deny_root_account. + +pam_tally is an (optional) application which can be used to interrogate and +manipulate the counter file. It can display users' counts, set individual +counts, or clear all counts. Setting artificially high counts may be useful +for blocking users without changing their passwords. I found it useful to +clear all counts every midnight from a cron.. + +The counts file is organised as a binary-word array, indexed by uid. You +can probably make sense of it with `od', if you don't want to use the +supplied appliction. BUGS: diff --git a/contrib/libpam/modules/pam_tally/faillog.h b/contrib/libpam/modules/pam_tally/faillog.h new file mode 100644 index 000000000000..0f16261bbd9c --- /dev/null +++ b/contrib/libpam/modules/pam_tally/faillog.h @@ -0,0 +1,55 @@ +/* + * 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. + */ + +/* + * faillog.h - login failure logging file format + * + * $Id: faillog.h,v 1.1.1.1 2000/06/20 22:11:59 agmorgan Exp $ + * + * The login failure file is maintained by login(1) and faillog(8) + * Each record in the file represents a separate UID and the file + * is indexed in that fashion. + */ + +#ifndef _FAILLOG_H +#define _FAILLOG_H + +struct faillog { + short fail_cnt; /* failures since last success */ + short fail_max; /* failures before turning account off */ + char fail_line[12]; /* last failure occured here */ + time_t fail_time; /* last failure occured then */ + /* + * If nonzero, the account will be re-enabled if there are no + * failures for fail_locktime seconds since last failure. + */ + long fail_locktime; +}; + +#endif diff --git a/contrib/libpam/modules/pam_tally/pam_tally.c b/contrib/libpam/modules/pam_tally/pam_tally.c index a1b65c04e958..23067f794e6a 100644 --- a/contrib/libpam/modules/pam_tally/pam_tally.c +++ b/contrib/libpam/modules/pam_tally/pam_tally.c @@ -1,7 +1,7 @@ /* * pam_tally.c * - * Revision history? :) 0.1 + * $Id: pam_tally.c,v 1.5 2001/01/20 22:21:22 agmorgan Exp $ */ @@ -11,21 +11,20 @@ * Stuff stolen from pam_rootok and pam_listfile */ -#ifdef linux -# define _GNU_SOURCE -# include <features.h> -#endif +#include <security/_pam_aconf.h> #include <stdio.h> -#include <strings.h> +#include <string.h> #include <unistd.h> #include <stdarg.h> #include <syslog.h> #include <pwd.h> +#include <time.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/param.h> +#include "faillog.h" #ifndef TRUE #define TRUE 1L @@ -67,6 +66,13 @@ enum TALLY_RESET { # define FILENAME_MAX MAXPATHLEN #endif +struct fail_s { + struct faillog fs_faillog; +#ifndef MAIN + time_t fs_fail_time; +#endif /* ndef MAIN */ +}; + /*---------------------------------------------------------------------*/ /* some syslogging */ @@ -131,19 +137,23 @@ static int pam_get_uid( pam_handle_t *pamh, uid_t *uid, const char **userp ) static int get_tally( tally_t *tally, uid_t uid, const char *filename, - FILE **TALLY ) + FILE **TALLY, + struct fail_s *fsp) { struct stat fileinfo; int lstat_ret = lstat(filename,&fileinfo); if ( lstat_ret && *tally!=TALLY_HI ) { - if ( ( *TALLY=fopen(filename, "a") ) ) { - /* Create file, or append-open in pathological case. */ + int oldmask = umask(077); + *TALLY=fopen(filename, "a"); + /* Create file, or append-open in pathological case. */ + umask(oldmask); + if ( !*TALLY ) { _pam_log(LOG_ALERT, "Couldn't create %s",filename); return PAM_AUTH_ERR; } + lstat_ret = fstat(fileno(*TALLY),&fileinfo); fclose(*TALLY); - lstat_ret = lstat(filename,&fileinfo); } if ( lstat_ret ) { @@ -171,14 +181,18 @@ static int get_tally( tally_t *tally, return PAM_AUTH_ERR; } - if ( fseek( *TALLY, uid * sizeof (tally_t), SEEK_SET ) ) { - _pam_log(LOG_ALERT, "fseek failed %s", filename); - return PAM_AUTH_ERR; - } - - if ( ( fread(tally, sizeof(tally_t), 1, *TALLY) )==0 ) { - *tally=0; /* Assuming a gappy filesystem */ + if ( fseek( *TALLY, uid * sizeof(struct faillog), SEEK_SET ) ) { + _pam_log(LOG_ALERT, "fseek failed %s", filename); + return PAM_AUTH_ERR; + } + + + if (( fread((char *) &fsp->fs_faillog, + sizeof(struct faillog), 1, *TALLY) )==0 ) { + *tally=0; /* Assuming a gappy filesystem */ } + *tally = fsp->fs_faillog.fail_cnt; + return PAM_SUCCESS; } @@ -189,16 +203,18 @@ static int get_tally( tally_t *tally, static int set_tally( tally_t tally, uid_t uid, const char *filename, - FILE **TALLY ) + FILE **TALLY, + struct fail_s *fsp) { if ( tally!=TALLY_HI ) { - if ( fseek( *TALLY, uid * sizeof(tally_t), SEEK_SET ) ) { - _pam_log(LOG_ALERT, "fseek failed %s", filename); - return PAM_AUTH_ERR; + if ( fseek( *TALLY, uid * sizeof(struct faillog), SEEK_SET ) ) { + _pam_log(LOG_ALERT, "fseek failed %s", filename); + return PAM_AUTH_ERR; } - - if ( fwrite(&tally, sizeof(tally_t), 1, *TALLY)==0 ) { + fsp->fs_faillog.fail_cnt = tally; + if (fwrite((char *) &fsp->fs_faillog, + sizeof(struct faillog), 1, *TALLY)==0 ) { _pam_log(LOG_ALERT, "tally update (fputc) failed.", filename); return PAM_AUTH_ERR; } @@ -284,12 +300,37 @@ static int tally_bump (int inc, FILE *TALLY = NULL; const char - *user = NULL; + *user = NULL, + *remote_host = NULL, + *cur_tty = NULL; + struct fail_s fs, *fsp = &fs; int i=pam_get_uid(pamh, &uid, &user); if ( i != PAM_SUCCESS ) RETURN_ERROR( i ); - i=get_tally( &tally, uid, filename, &TALLY ); + i=get_tally( &tally, uid, filename, &TALLY, fsp ); + + /* to remember old fail time (for locktime) */ + fsp->fs_fail_time = fsp->fs_faillog.fail_time; + fsp->fs_faillog.fail_time = (time_t) time( (time_t *) 0); + (void) pam_get_item(pamh, PAM_RHOST, (const void **)&remote_host); + if (!remote_host) + { + (void) pam_get_item(pamh, PAM_TTY, (const void **)&cur_tty); + if (!cur_tty) + strcpy(fsp->fs_faillog.fail_line, "unknown"); + else { + strncpy(fsp->fs_faillog.fail_line, cur_tty, + (size_t)sizeof(fsp->fs_faillog.fail_line)); + fsp->fs_faillog.fail_line[sizeof(fsp->fs_faillog.fail_line)-1] = 0; + } + } + else + { + strncpy(fsp->fs_faillog.fail_line, remote_host, + (size_t)sizeof(fsp->fs_faillog.fail_line)); + fsp->fs_faillog.fail_line[sizeof(fsp->fs_faillog.fail_line)-1] = 0; + } if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); RETURN_ERROR( i ); } if ( no_magic_root || getuid() ) { /* no_magic_root kills uid test */ @@ -303,7 +344,7 @@ static int tally_bump (int inc, } } - i=set_tally( tally, uid, filename, &TALLY ); + i=set_tally( tally, uid, filename, &TALLY, fsp ); if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); RETURN_ERROR( i ); } } @@ -370,6 +411,8 @@ PAM_FUNCTION( pam_sm_acct_mgmt ) { char no_magic_root = FALSE, even_deny_root_account = FALSE; + char per_user = FALSE; /* if true then deny=.fail_max for user */ + char no_lock_time = FALSE; /* if true then don't use .fail_locktime */ const char *user = NULL; @@ -424,6 +467,14 @@ PAM_FUNCTION( pam_sm_acct_mgmt ) { else if ( ! strcmp( *argv, "onerr=succeed" ) ) { fail_on_error=FALSE; } + else if ( ! strcmp( *argv, "per_user" ) ) + { + per_user = TRUE; + } + else if ( ! strcmp( *argv, "no_lock_time") ) + { + no_lock_time = TRUE; + } else { _pam_log(LOG_ERR, MODULE_NAME ": unknown option; %s",*argv); } @@ -431,17 +482,38 @@ PAM_FUNCTION( pam_sm_acct_mgmt ) { } { + struct fail_s fs, *fsp = &fs; FILE *TALLY=0; int i=pam_get_uid(pamh, &uid, &user); if ( i != PAM_SUCCESS ) RETURN_ERROR( i ); - i=get_tally( &tally, uid, filename, &TALLY ); + i=get_tally( &tally, uid, filename, &TALLY, fsp ); if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); RETURN_ERROR( i ); } if ( no_magic_root || getuid() ) { /* no_magic_root kills uid test */ /* To deny or not to deny; that is the question */ + /* if there's .fail_max entry and per_user=TRUE then deny=.fail_max */ + + if ( (fsp->fs_faillog.fail_max) && (per_user) ) { + deny = fsp->fs_faillog.fail_max; + } + if (fsp->fs_faillog.fail_locktime && fsp->fs_fail_time + && (!no_lock_time) ) + { + if ( (fsp->fs_faillog.fail_locktime + fsp->fs_fail_time) + > (time_t)time((time_t)0) ) + { + _pam_log(LOG_NOTICE, + "user %s ("UID_FMT") has time limit [%lds left]" + " since last failure.", + user,uid, + fsp->fs_fail_time+fsp->fs_faillog.fail_locktime + -(time_t)time((time_t)0)); + return PAM_AUTH_ERR; + } + } if ( ( deny != 0 ) && /* deny==0 means no deny */ ( tally > deny ) && /* tally>deny means exceeded */ @@ -467,8 +539,12 @@ PAM_FUNCTION( pam_sm_acct_mgmt ) { if ( reset == TALLY_RESET_RESET ) { tally=0; } } - - i=set_tally( tally, uid, filename, &TALLY ); + if (tally == 0) + { + fsp->fs_faillog.fail_time = (time_t) 0; + strcpy(fsp->fs_faillog.fail_line, ""); + } + i=set_tally( tally, uid, filename, &TALLY, fsp ); if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); RETURN_ERROR( i ); } } @@ -557,6 +633,8 @@ static int getopts( int argc, char **argv ) { int main ( int argc, char **argv ) { + struct fail_s fs, *fsp = &fs; + if ( ! getopts( argc, argv+1 ) ) { printf("%s: [--file rooted-filename] [--user username] " "[--reset[=n]] [--quiet]\n", @@ -564,6 +642,8 @@ int main ( int argc, char **argv ) { exit(0); } + umask(077); + /* * Major difference between individual user and all users: * --user just handles one user, just like PAM. @@ -580,7 +660,7 @@ int main ( int argc, char **argv ) { exit(0); } - i=get_tally( &tally, uid, cline_filename, &TALLY ); + i=get_tally( &tally, uid, cline_filename, &TALLY, fsp ); if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); fprintf(stderr,"%s: %s\n",*argv,pam_errors(i)); @@ -591,7 +671,7 @@ int main ( int argc, char **argv ) { printf("User %s\t("UID_FMT")\t%s "TALLY_FMT"\n",cline_user,uid, (cline_reset!=TALLY_HI)?"had":"has",tally); - i=set_tally( cline_reset, uid, cline_filename, &TALLY ); + i=set_tally( cline_reset, uid, cline_filename, &TALLY, fsp ); if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); fprintf(stderr,"%s: %s\n",*argv,pam_errors(i)); @@ -606,7 +686,13 @@ int main ( int argc, char **argv ) { for ( ; !feof(TALLY); uid++ ) { tally_t tally; struct passwd *pw; - if ( ! fread(&tally, sizeof(tally_t), 1, TALLY) || ! tally ) continue; + if ( ! fread((char *) &fsp->fs_faillog, + sizeof (struct faillog), 1, TALLY) + || ! fsp->fs_faillog.fail_cnt ) { + tally=fsp->fs_faillog.fail_cnt; + continue; + } + tally = fsp->fs_faillog.fail_cnt; if ( ( pw=getpwuid(uid) ) ) { printf("User %s\t("UID_FMT")\t%s "TALLY_FMT"\n",pw->pw_name,uid, diff --git a/contrib/libpam/modules/pam_tally/pam_tally_app.c b/contrib/libpam/modules/pam_tally/pam_tally_app.c new file mode 100644 index 000000000000..9e6e1fafd062 --- /dev/null +++ b/contrib/libpam/modules/pam_tally/pam_tally_app.c @@ -0,0 +1,7 @@ +/* + # This seemed like such a good idea at the time. :) + */ + +#define MAIN +#include "pam_tally.c" + diff --git a/contrib/libpam/modules/pam_time/Makefile b/contrib/libpam/modules/pam_time/Makefile index bc297d4f9853..4aa4e2761ee0 100644 --- a/contrib/libpam/modules/pam_time/Makefile +++ b/contrib/libpam/modules/pam_time/Makefile @@ -1,121 +1,21 @@ -# -# $Id: Makefile,v 1.6 1997/04/05 06:22:32 morgan Exp morgan $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.6 1997/04/05 06:22:32 morgan -# fakeroot -# -# Revision 1.5 1997/02/15 19:16:16 morgan -# fixed email -# -# Revision 1.4 1996/11/10 20:18:21 morgan -# cross platform support -# -# Revision 1.3 1996/09/05 06:27:37 morgan -# ld --> gcc -# -# Revision 1.2 1996/08/09 05:48:19 morgan -# inherit installation files from parent -# -# Revision 1.1 1996/07/07 23:42:48 morgan -# Initial revision -# -# Revision 1.1 1996/06/24 05:48:49 morgan -# Initial revision -# -# -# Created by Andrew Morgan <morgan@parc.power.net> 1996/6/11 -# - -TITLE=pam_time -CONFD=$(CONFIGED)/security -export CONFD -CONFILE=$(CONFD)/time.conf -export CONFILE -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) +include ../../Make.Rules -DEFS=-DCONFILE=\"$(CONFILE)\" +TITLE=pam_time +LOCAL_CONFILE=./time.conf +INSTALLED_CONFILE=$(SCONFIGD)/time.conf +DEFS=-DDEFAULT_CONF_FILE=\"$(INSTALLED_CONFILE)\" CFLAGS += $(DEFS) -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all -ifdef DYNAMIC - $(MKDIR) $(FAKEROOT)$(SECUREDIR) - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - $(MKDIR) $(FAKEROOT)$(SCONFIGED) - bash -f ./install_conf - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - rm -f $(FAKEROOT)$(CONFILE) - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - rm -f ./.ignore_age - -extraclean: clean - rm -f *.a *.o *.so *.bak - -.c.o: - $(CC) $(CFLAGS) -c $< +MODULE_SIMPLE_INSTALL=bash -f ../install_conf "$(FAKEROOT)" "$(SCONFIGD)" "$(INSTALLED_CONFILE)" "$(TITLE)" "$(LOCAL_CONFILE)" +MODULE_SIMPLE_REMOVE=rm -f $(FAKEROOT)$(INSTALLED_CONFILE) +MODULE_SIMPLE_CLEAN=rm -f ./.ignore_age +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_time/README b/contrib/libpam/modules/pam_time/README index 0c3f976b4012..0228b907fc21 100644 --- a/contrib/libpam/modules/pam_time/README +++ b/contrib/libpam/modules/pam_time/README @@ -1,4 +1,4 @@ -$Id: README,v 1.3 1997/01/04 20:42:43 morgan Exp $ +$Id: README,v 1.2 2000/12/04 19:02:35 baggins Exp $ This is a help file for the pam_time module. It explains the need for pam_time and also the syntax of the /etc/security/time.conf file. @@ -28,10 +28,3 @@ unrecognised rules are ignored (but an error is logged to syslog(3)) -------------------- Bugs to Andrew <morgan@parc.power.net> or the list <pam-list@redhat.com> - -######################################################################## -# $Log: README,v $ -# Revision 1.3 1997/01/04 20:42:43 morgan -# I want email on parc now -# -#
\ No newline at end of file diff --git a/contrib/libpam/modules/pam_time/pam_time.c b/contrib/libpam/modules/pam_time/pam_time.c index 489c1d734ae0..a517abf0e3d2 100644 --- a/contrib/libpam/modules/pam_time/pam_time.c +++ b/contrib/libpam/modules/pam_time/pam_time.c @@ -1,25 +1,19 @@ /* pam_time module */ /* - * $Id: pam_time.c,v 1.7 1997/02/15 17:32:21 morgan Exp $ + * $Id: pam_time.c,v 1.3 2000/11/26 07:32:39 agmorgan Exp $ * - * Written by Andrew Morgan <morgan@parc.power.net> 1996/6/22 + * Written by Andrew Morgan <morgan@linux.kernel.org> 1996/6/22 * (File syntax and much other inspiration from the shadow package * shadow-960129) - * - * $Log: pam_time.c,v $ - * Revision 1.7 1997/02/15 17:32:21 morgan - * time parsing more robust - * - * Revision 1.6 1997/01/04 20:43:15 morgan - * fixed buffer underflow, reformatted to 4 spaces - * */ const static char rcsid[] = -"$Id: pam_time.c,v 1.7 1997/02/15 17:32:21 morgan Exp $;\n" +"$Id: pam_time.c,v 1.3 2000/11/26 07:32:39 agmorgan Exp $;\n" "\t\tVersion 0.22 for Linux-PAM\n" -"Copyright (C) Andrew G. Morgan 1996 <morgan@parc.power.net>\n"; +"Copyright (C) Andrew G. Morgan 1996 <morgan@linux.kernel.org>\n"; + +#include <security/_pam_aconf.h> #include <sys/file.h> #include <stdio.h> @@ -34,7 +28,11 @@ const static char rcsid[] = #include <sys/stat.h> #include <fcntl.h> -#define PAM_TIME_CONF CONFILE /* from external define */ +#ifdef DEFAULT_CONF_FILE +# define PAM_TIME_CONF DEFAULT_CONF_FILE /* from external define */ +#else +# define PAM_TIME_CONF "/etc/security/time.conf" +#endif #define PAM_TIME_BUFLEN 1000 #define FIELD_SEPARATOR ';' /* this is new as of .02 */ @@ -124,6 +122,7 @@ static int read_field(int fd, char **buf, int *from, int *to) _log_err("error reading " PAM_TIME_CONF); return -1; } else if (!i) { + close(fd); fd = -1; /* end of file reached */ } else *to += i; @@ -167,6 +166,8 @@ static int read_field(int fd, char **buf, int *from, int *to) if ((*buf)[i+1] == '\n') { shift_bytes(i + *buf, 2, *to - (i+2)); *to -= 2; + } else { + ++i; /* we don't escape non-newline characters */ } break; case '!': @@ -248,7 +249,7 @@ static int logic_member(const char *string, int *at) default: if (isalpha(c) || c == '*' || isdigit(c) || c == '_' - || c == '-' || c == '.') { + || c == '-' || c == '.' || c == '/') { token = 1; } else if (token) { --to; diff --git a/contrib/libpam/modules/pam_unix/CHANGELOG b/contrib/libpam/modules/pam_unix/CHANGELOG index 37e4c8501c9d..509ce0a31a62 100644 --- a/contrib/libpam/modules/pam_unix/CHANGELOG +++ b/contrib/libpam/modules/pam_unix/CHANGELOG @@ -1,6 +1,55 @@ -$Id: CHANGELOG,v 1.1 1996/11/09 19:42:41 morgan Exp $ +$Id: CHANGELOG,v 1.1.1.1 2000/06/20 22:12:01 agmorgan Exp $ -$Log: CHANGELOG,v $ -Revision 1.1 1996/11/09 19:42:41 morgan -Initial revision +* Mon Aug 16 1999 Jan Rêkorajski <baggins@pld.org.pl> +- fixed reentrancy problems + +* Sun Jul 4 21:03:42 PDT 1999 + +- temporarily removed the crypt16 stuff. I'm really paranoid about + crypto stuff and exporting it, and there are a few too many 's-box' + references in the code for my liking.. + +* Wed Jun 30 1999 Steve Langasek <vorlon@netexpress.net> +- further NIS+ fixes + +* Sun Jun 27 1999 Steve Langasek <vorlon@netexpress.net> +- fix to uid-handling code for NIS+ + +* Sat Jun 26 1999 Jan Rêkorajski <baggins@mimuw.edu.pl> +- merged MD5 fix and early failure syslog + by Andrey Vladimirovich Savochkin <saw@msu.ru> +- minor fixes +- added signal handler to unix_chkpwd + +* Fri Jun 25 1999 Stephen Langasek <vorlon@netexpress.net> +- reorganized the code to let it build as separate C files + +* Sun Jun 20 1999 Jan Rêkorajski <baggins@mimuw.edu.pl> +- fixes in pam_unix_auth, it incorrectly saved and restored return + value when likeauth option was used + +* Tue Jun 15 1999 Jan Rêkorajski <baggins@mimuw.edu.pl> +- added NIS+ support + +* Mon Jun 14 1999 Jan Rêkorajski <baggins@mimuw.edu.pl> +- total rewrite based on pam_pwdb module, now there is ONE pam_unix.so + module, it accepts the same options as pam_pwdb - all of them correctly ;) + (pam_pwdb dosn't understand what DISALLOW_NULL_AUTHTOK means) + +* Tue Apr 20 1999 Jan Rêkorajski <baggins@mimuw.edu.pl> +- Arghhh, pam_unix_passwd was not updating /etc/shadow when used with + pam_cracklib. + +* Mon Apr 19 1999 Jan Rêkorajski <baggins@mimuw.edu.pl> +- added "remember=XXX" option that means 'remember XXX old passwords' + Old passwords are stored in /etc/security/opasswd, there can be + maximum of 400 passwords per user. + +* Sat Mar 27 1999 Jan Rêkorajski <baggins@mimuw.edu.pl> +- added crypt16 to pam_unix_auth and pam_unix_passwd (check only, this algorithm + is too lame to use it in real life) + +* Sun Mar 21 1999 Jan Rêkorajski <baggins@mimuw.edu.pl> +- pam_unix_auth now correctly behave when user has NULL AUTHTOK +- pam_unix_auth returns PAM_PERM_DENIED when seteuid fails diff --git a/contrib/libpam/modules/pam_unix/Makefile b/contrib/libpam/modules/pam_unix/Makefile index ad1f47f185e4..9329aa6e1006 100644 --- a/contrib/libpam/modules/pam_unix/Makefile +++ b/contrib/libpam/modules/pam_unix/Makefile @@ -1,100 +1,91 @@ -# $Header$ +# $Id: Makefile,v 1.3 2001/02/11 06:33:53 agmorgan Exp $ # # This Makefile controls a build process of the pam_unix modules # for Linux-PAM. You should not modify this Makefile. # -# $Log$ -# Revision 1.1.1.2 1998/06/03 03:43:56 adam -# Import from archive -# -# Revision 1.3 1998/05/31 23:48:13 adam -# Link crypt library as necessary. -# -# Revision 1.3 1997/04/05 06:20:58 morgan -# fakeroot and also lockpwdf is in libc now -# -# Revision 1.2 1996/11/10 20:18:59 morgan -# cross platform support -# -# Revision 1.1 1996/11/09 19:44:16 morgan -# Initial revision -# -# + +include ../../Make.Rules ######################################################################## # some options... uncomment to take effect ######################################################################## -# do you want shadow? -USE_SHADOW=-D"HAVE_SHADOW_H" - +# Unless someone wants to work out how to make this work with the new +# autoconf stuff, you should use a separate module for this type of thing +# pam_cracklib perhaps..? # do you want cracklib? -ifeq ($(HAVE_CRACKLIB),yes) -USE_CRACKLIB=-D"USE_CRACKLIB" -endif +#ifeq ($(HAVE_CRACKLIB),yes) +#USE_CRACKLIB=-D"USE_CRACKLIB" +#endif # do you want to use lckpwdf? +ifeq ($(WITH_LCKPWDF),yes) USE_LCKPWDF=-D"USE_LCKPWDF" - # do you need to include the locking functions in the source? -#NEED_LCKPWDF=-D"NEED_LCKPWDF" - -######################################################################## - -CFLAGS += $(USE_SHADOW) $(USE_CRACKLIB) $(USE_LCKPWDF) $(NEED_LCKPWDF) +ifeq ($(HAVE_LCKPWDF),no) + NEED_LCKPWDF=-D"NEED_LCKPWDF" +endif +endif -ifdef DYNAMIC -LIBSESSSH = pam_unix_session.so -LIBAUTHSH = pam_unix_auth.so -LIBPASSWDSH = pam_unix_passwd.so -LIBACCOUNT = pam_unix_acct.so +ifeq ($(HAVE_LIBNSL),yes) + LIBNSL = -lnsl endif -ifdef STATIC -LIBSTATIC = libpam_unix.o +ifeq ($(HAVE_LIBCRYPT),yes) + LIBCRYPT=-lcrypt endif +CHKPWD=unix_chkpwd + +EXTRAS += -DCHKPWD_HELPER=\"$(SUPLEMENTED)/$(CHKPWD)\" + +######################################################################## + +CFLAGS += $(USE_CRACKLIB) $(USE_LCKPWDF) $(NEED_LCKPWDF) $(EXTRAS) +LDLIBS = $(EXTRALS) + ifdef USE_CRACKLIB CRACKLIB = -lcrack endif -LIBAUTHOBJ = pam_unix_auth.o support.o -LIBAUTHSRC = pam_unix_auth.c support.c -LIBSESSOBJ = pam_unix_sess.o -LIBSESSSRC = pam_unix_sess.c -LIBPASSWDSRC = pam_unix_passwd.c -LIBPASSWDOBJ = pam_unix_passwd.o -LIBACCOUNTSRC = pam_unix_acct.c -LIBACCOUNTOBJ = pam_unix_acct.o -LIBOBJ = $(LIBAUTHOBJ) $(LIBSESSOBJ) $(LIBPASSWDOBJ) $(LIBACCOUNTOBJ) -LIBSRC = $(LIBAUTHSRC) $(LIBSESSSRC) $(LIBPASSWDSRC) $(LIBACCOUNTSRC) - -LIBSHARED = $(LIBSESSSH) $(LIBAUTHSH) $(LIBPASSWDSH) $(LIBACCOUNT) +LIBOBJ = pam_unix_auth.o pam_unix_acct.o pam_unix_sess.o pam_unix_passwd.o \ + support.o +LIBSRC = pam_unix_auth.c pam_unix_acct.c pam_unix_sess.c pam_unix_passwd.c \ + support.c LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) LIBOBJS = $(addprefix static/,$(LIBOBJ)) -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) -c $< -o $@ +PLUS = md5_good.o md5_broken.o md5_crypt_good.o md5_crypt_broken.o \ + yppasswd_xdr.o bigcrypt.o -static/%.o: %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) -c $< -o $@ +ifdef DYNAMIC +LIBSHARED = pam_unix.so +endif +ifdef STATIC +LIBSTATIC = libpam_unix.o +endif ########################### don't edit below ####################### -dummy: +all: dirs info $(PLUS) $(LIBSHARED) $(LIBSTATIC) $(CHKPWD) register + +dynamic/%.o : %.c + $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ +static/%.o: %.c + $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +dummy: @echo "**** This is not a top-level Makefile " exit info: @echo - @echo "*** Building pam-unix(alpha) module of the framework..." + @echo "*** Building pam-unix module of the framework..." @echo -all: dirs info $(LIBSHARED) $(LIBSTATIC) register - dirs: ifdef DYNAMIC mkdir -p ./dynamic @@ -105,50 +96,71 @@ endif register: ifdef STATIC - ( cd .. ; \ - ./register_static pam_unix_auth pam_unix/$(LIBSTATIC) ; \ - ./register_static pam_unix_acct "" ; \ + ( cd .. ; ./register_static pam_unix_auth pam_unix/$(LIBSTATIC) ; \ + ./register_static pam_unix_acct "" ; \ + ./register_static pam_unix_session "" ; \ + ./register_static pam_unix_passwd "" ; \ ) endif ifdef DYNAMIC $(LIBOBJD): $(LIBSRC) -$(LIBAUTHSH): $(LIBAUTHSRC) $(LIBOBJD) - $(LD_D) -o $@ $(addprefix dynamic/,$(LIBAUTHOBJ)) -lcrypt - -$(LIBSESSSH): $(LIBSESSSRC) $(LIBOBJD) - $(LD_D) -o $@ $(addprefix dynamic/,$(LIBSESSOBJ)) - -$(LIBPASSWDSH): $(LIBPASSWDSRC) $(LIBOBJD) - $(LD_D) -o $@ $(addprefix dynamic/,$(LIBPASSWDOBJ)) $(CRACKLIB) -lcrypt - -$(LIBACCOUNT): $(LIBACCOUNTSRC) $(LIBOBJD) - $(LD_D) -o $@ $(addprefix dynamic/,$(LIBACCOUNTOBJ)) +$(LIBSHARED): $(LIBOBJD) + $(LD_D) -o $@ $(LIBOBJD) $(PLUS) $(CRACKLIB) $(LDLIBS) $(LIBNSL) $(LIBCRYPT) endif - ifdef STATIC $(LIBOBJS): $(LIBSRC) $(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) + $(LD) -r -o $@ $(LIBOBJS) $(PLUS) $(CRACKLIB) $(LDLIBS) $(LIBNSL) $(LIBCRYPT) endif +$(CHKPWD): unix_chkpwd.o md5_good.o md5_broken.o \ + md5_crypt_good.o md5_crypt_broken.o \ + bigcrypt.o + $(CC) -o $(CHKPWD) $^ $(LDLIBS) $(LIBCRYPT) + +unix_chkpwd.o: unix_chkpwd.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +md5_good.o: md5.c + $(CC) $(CFLAGS) $(CPPFLAGS) -DHIGHFIRST -D'MD5Name(x)=Good##x' \ + $(TARGET_ARCH) -c $< -o $@ + +md5_broken.o: md5.c + $(CC) $(CFLAGS) $(CPPFLAGS) -D'MD5Name(x)=Broken##x' \ + $(TARGET_ARCH) -c $< -o $@ + +md5_crypt_good.o: md5_crypt.c + $(CC) $(CFLAGS) $(CPPFLAGS) -D'MD5Name(x)=Good##x' \ + $(TARGET_ARCH) -c $< -o $@ + +md5_crypt_broken.o: md5_crypt.c + $(CC) $(CFLAGS) $(CPPFLAGS) -D'MD5Name(x)=Broken##x' \ + $(TARGET_ARCH) -c $< -o $@ + install: all mkdir -p $(FAKEROOT)$(SECUREDIR) ifdef DYNAMIC install -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) + for x in pam_unix_auth pam_unix_acct pam_unix_passwd pam_unix_session;\ + do ln -sf $(LIBSHARED) $(FAKEROOT)$(SECUREDIR)/$$x.so ; done endif + $(MKDIR) $(FAKEROOT)$(SUPLEMENTED) + install -m 4555 $(CHKPWD) $(FAKEROOT)$(SUPLEMENTED) remove: - cd $(FAKEROOT)$(SECUREDIR) && rm -f $(LIBSHARED) + rm -f $(FAKEROOT)$(SECUREDIR)/$(LIBSHARED) + for x in pam_unix_auth pam_unix_acct pam_unix_passwd pam_unix_session;\ + do rm -f $(FAKEROOT)$(SECUREDIR)/$$x.so ; done + rm -f $(FAKEROOT)$(SUPLEMENTED)/$(CHKPWD) clean: - rm -f $(LIBOBJD) $(LIBOBJS) a.out core *~ - -extraclean: clean - rm -f *.a *.out *.o *.so *.bak + rm -f $(LIBOBJD) $(LIBOBJS) $(CHKPWD) *.o *.so core + rm -f *~ *.a *.out *.bak + rm -rf dynamic static .c.o: $(CC) -c $(CFLAGS) $< diff --git a/contrib/libpam/modules/pam_unix/README b/contrib/libpam/modules/pam_unix/README index 082e99697da2..ad4bc35e488a 100644 --- a/contrib/libpam/modules/pam_unix/README +++ b/contrib/libpam/modules/pam_unix/README @@ -1,39 +1,39 @@ -This is the README for pam_unix in Linux-PAM-0.53. +This is the README for pam_unix in Linux-PAM-0.67. -------------------------------------------------- -pam_unix comes as four separate modules: +pam_unix now comes as one module pam_unix.so. +The following links are left for compatibility with old versions: pam_unix_auth: authentication module providing - pam_authenticate() and pam_setcred() hooks - - NO options are recognized. Credential facilities are trivial - (function simply returns) - + pam_authenticate() and pam_setcred() hooks pam_unix_sess: session module, providing session logging - - "debug" and "trace" arguments are accepted, which indicate the - logging-level for syslog. - - "debug" -> LOG_DEBUG [ also default ] - "trace" -> LOG_AUTHPRIV - pam_unix_acct: account management, providing shadow account - managment features, password aging etc.. - - NO options are recognized. Account managment trivial without - shadow active. - + managment features, password aging etc.. pam_unix_passwd: password updating facilities providing - cracklib password strength checking facilities. - - if compiled, the default behavior is to check passwords - strictly using CrackLib. This behavior can be turned off - with the argument - - "strict=false" + cracklib password strength checking facilities. + +The following options are recognized: + debug - log more debugging info + audit - a little more extreme than debug + use_first_pass - don 't prompt the user for passwords + take them from PAM_ items instead + try_first_pass - don 't prompt the user for the passwords + unless PAM_(OLD)AUTHTOK is unset + use_authtok - like try_first_pass, but * fail * if the new + PAM_AUTHTOK has not been previously set. + (intended for stacking password modules only) + not_set_pass - don 't set the PAM_ items with the passwords + used by this module. + shadow - try to maintian a shadow based system. + md5 - when a user changes their password next, + encrypt it with the md5 algorithm. + bigcrypt - when a user changes their password next, + excrypt it with the DEC C2 - algorithm(0). + nodelay - used to prevent failed authentication + resulting in a delay of about 1 second. + nis - use NIS RPC for setting new password + remember=X - remember X old passwords, they are kept in + /etc/security/opasswd in MD5 crypted form invalid arguments are logged to syslog. ------------------------------- -- Andrew 1996/11/9 ------------------------------- diff --git a/contrib/libpam/modules/pam_unix/bigcrypt.c b/contrib/libpam/modules/pam_unix/bigcrypt.c new file mode 100644 index 000000000000..b1568d6b340a --- /dev/null +++ b/contrib/libpam/modules/pam_unix/bigcrypt.c @@ -0,0 +1,119 @@ +/* + * This function implements the "bigcrypt" algorithm specifically for + * Linux-PAM. + * + * This algorithm is algorithm 0 (default) shipped with the C2 secure + * implementation of Digital UNIX. + * + * Disclaimer: This work is not based on the source code to Digital + * UNIX, nor am I connected to Digital Equipment Corp, in any way + * other than as a customer. This code is based on published + * interfaces and reasonable guesswork. + * + * Description: The cleartext is divided into blocks of SEGMENT_SIZE=8 + * characters or less. Each block is encrypted using the standard UNIX + * libc crypt function. The result of the encryption for one block + * provides the salt for the suceeding block. + * + * Restrictions: The buffer used to hold the encrypted result is + * statically allocated. (see MAX_PASS_LEN below). This is necessary, + * as the returned pointer points to "static data that are overwritten + * by each call", (XPG3: XSI System Interface + Headers pg 109), and + * this is a drop in replacement for crypt(); + * + * Andy Phillips <atp@mssl.ucl.ac.uk> + */ + +#include <string.h> +#include <security/_pam_macros.h> + +char *crypt(const char *key, const char *salt); +char *bigcrypt(const char *key, const char *salt); + +/* + * Max cleartext password length in segments of 8 characters this + * function can deal with (16 segments of 8 chars= max 128 character + * password). + */ + +#define MAX_PASS_LEN 16 +#define SEGMENT_SIZE 8 +#define SALT_SIZE 2 +#define KEYBUF_SIZE ((MAX_PASS_LEN*SEGMENT_SIZE)+SALT_SIZE) +#define ESEGMENT_SIZE 11 +#define CBUF_SIZE ((MAX_PASS_LEN*ESEGMENT_SIZE)+SALT_SIZE+1) + +char *bigcrypt(const char *key, const char *salt) +{ + static char dec_c2_cryptbuf[CBUF_SIZE]; /* static storage area */ + + unsigned long int keylen, n_seg, j; + char *cipher_ptr, *plaintext_ptr, *tmp_ptr, *salt_ptr; + char keybuf[KEYBUF_SIZE + 1]; + + D(("called with key='%s', salt='%s'.", key, salt)); + + /* reset arrays */ + memset(keybuf, 0, KEYBUF_SIZE + 1); + memset(dec_c2_cryptbuf, 0, CBUF_SIZE); + + /* fill KEYBUF_SIZE with key */ + strncpy(keybuf, key, KEYBUF_SIZE); + + /* deal with case that we are doing a password check for a + conventially encrypted password: the salt will be + SALT_SIZE+ESEGMENT_SIZE long. */ + if (strlen(salt) == (SALT_SIZE + ESEGMENT_SIZE)) + keybuf[SEGMENT_SIZE] = '\0'; /* terminate password early(?) */ + + keylen = strlen(keybuf); + + if (!keylen) { + n_seg = 1; + } else { + /* work out how many segments */ + n_seg = 1 + ((keylen - 1) / SEGMENT_SIZE); + } + + if (n_seg > MAX_PASS_LEN) + n_seg = MAX_PASS_LEN; /* truncate at max length */ + + /* set up some pointers */ + cipher_ptr = dec_c2_cryptbuf; + plaintext_ptr = keybuf; + + /* do the first block with supplied salt */ + tmp_ptr = crypt(plaintext_ptr, salt); /* libc crypt() */ + + /* and place in the static area */ + strncpy(cipher_ptr, tmp_ptr, 13); + cipher_ptr += ESEGMENT_SIZE + SALT_SIZE; + plaintext_ptr += SEGMENT_SIZE; /* first block of SEGMENT_SIZE */ + + /* change the salt (1st 2 chars of previous block) - this was found + by dowsing */ + + salt_ptr = cipher_ptr - ESEGMENT_SIZE; + + /* so far this is identical to "return crypt(key, salt);", if + there is more than one block encrypt them... */ + + if (n_seg > 1) { + for (j = 2; j <= n_seg; j++) { + + tmp_ptr = crypt(plaintext_ptr, salt_ptr); + + /* skip the salt for seg!=0 */ + strncpy(cipher_ptr, (tmp_ptr + SALT_SIZE), ESEGMENT_SIZE); + + cipher_ptr += ESEGMENT_SIZE; + plaintext_ptr += SEGMENT_SIZE; + salt_ptr = cipher_ptr - ESEGMENT_SIZE; + } + } + D(("key=|%s|, salt=|%s|\nbuf=|%s|\n", key, salt, dec_c2_cryptbuf)); + + /* this is the <NUL> terminated encrypted password */ + + return dec_c2_cryptbuf; +} diff --git a/contrib/libpam/modules/pam_unix/lckpwdf.-c b/contrib/libpam/modules/pam_unix/lckpwdf.-c new file mode 100644 index 000000000000..b5ff45850b4b --- /dev/null +++ b/contrib/libpam/modules/pam_unix/lckpwdf.-c @@ -0,0 +1,117 @@ +/* + * This is a hack, but until libc and glibc both include this function + * by default (libc only includes it if nys is not being used, at the + * moment, and glibc doesn't appear to have it at all) we need to have + * it here, too. :-( + * + * This should not become an official part of PAM. + * + * BEGIN_HACK + */ + +/* + * lckpwdf.c -- prevent simultaneous updates of password files + * + * Before modifying any of the password files, call lckpwdf(). It may block + * for up to 15 seconds trying to get the lock. Return value is 0 on success + * or -1 on failure. When you are done, call ulckpwdf() to release the lock. + * The lock is also released automatically when the process exits. Only one + * process at a time may hold the lock. + * + * These functions are supposed to be conformant with AT&T SVID Issue 3. + * + * Written by Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>, + * public domain. + */ + +#include <fcntl.h> +#include <signal.h> + +#define LOCKFILE "/etc/.pwd.lock" +#define TIMEOUT 15 + +static int lockfd = -1; + +static int set_close_on_exec(int fd) +{ + int flags = fcntl(fd, F_GETFD, 0); + if (flags == -1) + return -1; + flags |= FD_CLOEXEC; + return fcntl(fd, F_SETFD, flags); +} + +static int do_lock(int fd) +{ + struct flock fl; + + memset(&fl, 0, sizeof fl); + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + return fcntl(fd, F_SETLKW, &fl); +} + +static void alarm_catch(int sig) +{ +/* does nothing, but fcntl F_SETLKW will fail with EINTR */ +} + +static int lckpwdf(void) +{ + struct sigaction act, oldact; + sigset_t set, oldset; + + if (lockfd != -1) + return -1; + + lockfd = open(LOCKFILE, O_CREAT | O_WRONLY, 0600); + if (lockfd == -1) + return -1; + if (set_close_on_exec(lockfd) == -1) + goto cleanup_fd; + + memset(&act, 0, sizeof act); + act.sa_handler = alarm_catch; + act.sa_flags = 0; + sigfillset(&act.sa_mask); + if (sigaction(SIGALRM, &act, &oldact) == -1) + goto cleanup_fd; + + sigemptyset(&set); + sigaddset(&set, SIGALRM); + if (sigprocmask(SIG_UNBLOCK, &set, &oldset) == -1) + goto cleanup_sig; + + alarm(TIMEOUT); + if (do_lock(lockfd) == -1) + goto cleanup_alarm; + alarm(0); + sigprocmask(SIG_SETMASK, &oldset, NULL); + sigaction(SIGALRM, &oldact, NULL); + return 0; + + cleanup_alarm: + alarm(0); + sigprocmask(SIG_SETMASK, &oldset, NULL); + cleanup_sig: + sigaction(SIGALRM, &oldact, NULL); + cleanup_fd: + close(lockfd); + lockfd = -1; + return -1; +} + +static int ulckpwdf(void) +{ + unlink(LOCKFILE); + if (lockfd == -1) + return -1; + + if (close(lockfd) == -1) { + lockfd = -1; + return -1; + } + lockfd = -1; + return 0; +} +/* END_HACK */ diff --git a/contrib/libpam/modules/pam_unix/md5.c b/contrib/libpam/modules/pam_unix/md5.c new file mode 100644 index 000000000000..7ee9ed00cdea --- /dev/null +++ b/contrib/libpam/modules/pam_unix/md5.c @@ -0,0 +1,256 @@ +/* + * $Id: md5.c,v 1.1.1.1 2000/06/20 22:12:03 agmorgan Exp $ + * + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + * + */ + +#include <string.h> +#include "md5.h" + +#ifndef HIGHFIRST +#define byteReverse(buf, len) /* Nothing */ +#else +static void byteReverse(unsigned char *buf, unsigned longs); + +#ifndef ASM_MD5 +/* + * Note: this code is harmless on little-endian machines. + */ +static void byteReverse(unsigned char *buf, unsigned longs) +{ + uint32 t; + do { + t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32 *) buf = t; + buf += 4; + } while (--longs); +} +#endif +#endif + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void MD5Name(MD5Init)(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301U; + ctx->buf[1] = 0xefcdab89U; + ctx->buf[2] = 0x98badcfeU; + ctx->buf[3] = 0x10325476U; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void MD5Name(MD5Update)(struct MD5Context *ctx, unsigned const char *buf, unsigned len) +{ + uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void MD5Name(MD5Final)(unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((uint32 *) ctx->in)[14] = ctx->bits[0]; + ((uint32 *) ctx->in)[15] = ctx->bits[1]; + + MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +#ifndef ASM_MD5 + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +void MD5Name(MD5Transform)(uint32 buf[4], uint32 const in[16]) +{ + register uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478U, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756U, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070dbU, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceeeU, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0fafU, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62aU, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613U, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501U, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8U, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7afU, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1U, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7beU, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122U, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193U, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438eU, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821U, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562U, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340U, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51U, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aaU, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105dU, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453U, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681U, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8U, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6U, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6U, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87U, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14edU, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905U, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8U, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9U, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8aU, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942U, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681U, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122U, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380cU, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44U, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9U, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60U, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70U, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6U, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127faU, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085U, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05U, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039U, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5U, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8U, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665U, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244U, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97U, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7U, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039U, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3U, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92U, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47dU, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1U, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4fU, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0U, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314U, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1U, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82U, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235U, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bbU, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391U, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#endif diff --git a/contrib/libpam/modules/pam_unix/md5.h b/contrib/libpam/modules/pam_unix/md5.h new file mode 100644 index 000000000000..103f168a91c6 --- /dev/null +++ b/contrib/libpam/modules/pam_unix/md5.h @@ -0,0 +1,31 @@ + +#ifndef MD5_H +#define MD5_H + +typedef unsigned int uint32; + +struct MD5Context { + uint32 buf[4]; + uint32 bits[2]; + unsigned char in[64]; +}; + +void GoodMD5Init(struct MD5Context *); +void GoodMD5Update(struct MD5Context *, unsigned const char *, unsigned); +void GoodMD5Final(unsigned char digest[16], struct MD5Context *); +void GoodMD5Transform(uint32 buf[4], uint32 const in[16]); +void BrokenMD5Init(struct MD5Context *); +void BrokenMD5Update(struct MD5Context *, unsigned const char *, unsigned); +void BrokenMD5Final(unsigned char digest[16], struct MD5Context *); +void BrokenMD5Transform(uint32 buf[4], uint32 const in[16]); + +char *Goodcrypt_md5(const char *pw, const char *salt); +char *Brokencrypt_md5(const char *pw, const char *salt); + +/* + * This is needed to make RSAREF happy on some MS-DOS compilers. + */ + +typedef struct MD5Context MD5_CTX; + +#endif /* MD5_H */ diff --git a/contrib/libpam/modules/pam_unix/md5_crypt.c b/contrib/libpam/modules/pam_unix/md5_crypt.c new file mode 100644 index 000000000000..257e4bb6bd06 --- /dev/null +++ b/contrib/libpam/modules/pam_unix/md5_crypt.c @@ -0,0 +1,149 @@ +/* + * $Id: md5_crypt.c,v 1.1.1.1 2000/06/20 22:12:03 agmorgan Exp $ + * + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + * + * Origin: Id: crypt.c,v 1.3 1995/05/30 05:42:22 rgrimes Exp + * + */ + +#include <string.h> +#include "md5.h" + +static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ +"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static void to64(char *s, unsigned long v, int n) +{ + while (--n >= 0) { + *s++ = itoa64[v & 0x3f]; + v >>= 6; + } +} + +/* + * UNIX password + * + * Use MD5 for what it is best at... + */ + +char *MD5Name(crypt_md5)(const char *pw, const char *salt) +{ + const char *magic = "$1$"; + /* This string is magic for this algorithm. Having + * it this way, we can get get better later on */ + static char passwd[120], *p; + static const char *sp, *ep; + unsigned char final[16]; + int sl, pl, i, j; + MD5_CTX ctx, ctx1; + unsigned long l; + + /* Refine the Salt first */ + sp = salt; + + /* If it starts with the magic string, then skip that */ + if (!strncmp(sp, magic, strlen(magic))) + sp += strlen(magic); + + /* It stops at the first '$', max 8 chars */ + for (ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++) + continue; + + /* get the length of the true salt */ + sl = ep - sp; + + MD5Name(MD5Init)(&ctx); + + /* The password first, since that is what is most unknown */ + MD5Name(MD5Update)(&ctx,(unsigned const char *)pw,strlen(pw)); + + /* Then our magic string */ + MD5Name(MD5Update)(&ctx,(unsigned const char *)magic,strlen(magic)); + + /* Then the raw salt */ + MD5Name(MD5Update)(&ctx,(unsigned const char *)sp,sl); + + /* Then just as many characters of the MD5(pw,salt,pw) */ + MD5Name(MD5Init)(&ctx1); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)sp,sl); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); + MD5Name(MD5Final)(final,&ctx1); + for (pl = strlen(pw); pl > 0; pl -= 16) + MD5Name(MD5Update)(&ctx,(unsigned const char *)final,pl>16 ? 16 : pl); + + /* Don't leave anything around in vm they could use. */ + memset(final, 0, sizeof final); + + /* Then something really weird... */ + for (j = 0, i = strlen(pw); i; i >>= 1) + if (i & 1) + MD5Name(MD5Update)(&ctx, (unsigned const char *)final+j, 1); + else + MD5Name(MD5Update)(&ctx, (unsigned const char *)pw+j, 1); + + /* Now make the output string */ + strcpy(passwd, magic); + strncat(passwd, sp, sl); + strcat(passwd, "$"); + + MD5Name(MD5Final)(final,&ctx); + + /* + * and now, just to make sure things don't run too fast + * On a 60 Mhz Pentium this takes 34 msec, so you would + * need 30 seconds to build a 1000 entry dictionary... + */ + for (i = 0; i < 1000; i++) { + MD5Name(MD5Init)(&ctx1); + if (i & 1) + MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); + else + MD5Name(MD5Update)(&ctx1,(unsigned const char *)final,16); + + if (i % 3) + MD5Name(MD5Update)(&ctx1,(unsigned const char *)sp,sl); + + if (i % 7) + MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); + + if (i & 1) + MD5Name(MD5Update)(&ctx1,(unsigned const char *)final,16); + else + MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); + MD5Name(MD5Final)(final,&ctx1); + } + + p = passwd + strlen(passwd); + + l = (final[0] << 16) | (final[6] << 8) | final[12]; + to64(p, l, 4); + p += 4; + l = (final[1] << 16) | (final[7] << 8) | final[13]; + to64(p, l, 4); + p += 4; + l = (final[2] << 16) | (final[8] << 8) | final[14]; + to64(p, l, 4); + p += 4; + l = (final[3] << 16) | (final[9] << 8) | final[15]; + to64(p, l, 4); + p += 4; + l = (final[4] << 16) | (final[10] << 8) | final[5]; + to64(p, l, 4); + p += 4; + l = final[11]; + to64(p, l, 2); + p += 2; + *p = '\0'; + + /* Don't leave anything around in vm they could use. */ + memset(final, 0, sizeof final); + + return passwd; +} diff --git a/contrib/libpam/modules/pam_unix/pam_unix_acct.c b/contrib/libpam/modules/pam_unix/pam_unix_acct.c index 5c0546aa1f8f..178b6037465a 100644 --- a/contrib/libpam/modules/pam_unix/pam_unix_acct.c +++ b/contrib/libpam/modules/pam_unix/pam_unix_acct.c @@ -1,5 +1,6 @@ /* * Copyright Elliot Lee, 1996. All rights reserved. + * Copyright Jan Rêkorajski, 1999. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,73 +34,159 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* pam_unix_acct.c module, different track */ - -#ifdef linux -# define _GNU_SOURCE -# include <features.h> -#endif +#include <security/_pam_aconf.h> #include <stdlib.h> #include <stdio.h> #include <string.h> -#define __USE_MISC -#include <pwd.h> +#include <unistd.h> #include <sys/types.h> #include <syslog.h> -#include <unistd.h> -#ifdef HAVE_SHADOW_H +#include <pwd.h> #include <shadow.h> -#endif -#include <time.h> +#include <time.h> /* for time() */ -#define PAM_SM_ACCOUNT +#include <security/_pam_macros.h> -#ifndef LINUX -# include <security/pam_appl.h> -#endif +/* indicate that the following groups are defined */ + +#define PAM_SM_ACCOUNT -#define _PAM_EXTERN_FUNCTIONS #include <security/pam_modules.h> -PAM_EXTERN -int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, - int argc, const char **argv) +#ifndef LINUX_PAM +#include <security/pam_appl.h> +#endif /* LINUX_PAM */ + +#include "support.h" + +/* + * PAM framework looks for this entry-point to pass control to the + * account management module. + */ + +PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags, + int argc, const char **argv) { -#ifdef HAVE_SHADOW_H - const char *uname; - int retval; - time_t curdays; - struct spwd *spent; - struct passwd *pwent; - - setpwent(); - setspent(); - retval = pam_get_item(pamh,PAM_USER,(const void **)&uname); - if(retval != PAM_SUCCESS || uname == NULL) { - return PAM_SUCCESS; /* Couldn't get username, just ignore this - (i.e. they don't have any expiry info available */ - } - pwent = getpwnam(uname); - if(!pwent) - return PAM_USER_UNKNOWN; - if(strcmp(pwent->pw_passwd,"x")) - return PAM_SUCCESS; /* They aren't using shadow passwords & expiry - info */ - spent = getspnam(uname); - if(!spent) - return PAM_SUCCESS; /* Couldn't get username from shadow, just ignore this - (i.e. they don't have any expiry info available */ - curdays = time(NULL)/(60*60*24); - if((curdays > (spent->sp_lstchg + spent->sp_max + spent->sp_inact)) - && (spent->sp_max != -1) && (spent->sp_inact != -1)) - return PAM_ACCT_EXPIRED; - if((curdays > spent->sp_expire) && (spent->sp_expire != -1)) - return PAM_ACCT_EXPIRED; - endspent(); - endpwent(); -#endif - return PAM_SUCCESS; + unsigned int ctrl; + const char *uname; + int retval, daysleft; + time_t curdays; + struct spwd *spent; + struct passwd *pwent; + char buf[80]; + + D(("called.")); + + ctrl = _set_ctrl(pamh, flags, NULL, argc, argv); + + retval = pam_get_item(pamh, PAM_USER, (const void **) &uname); + D(("user = `%s'", uname)); + if (retval != PAM_SUCCESS || uname == NULL) { + _log_err(LOG_ALERT, pamh + ,"could not identify user (from uid=%d)" + ,getuid()); + return PAM_USER_UNKNOWN; + } + + pwent = getpwnam(uname); + if (!pwent) { + _log_err(LOG_ALERT, pamh + ,"could not identify user (from getpwnam(%s))" + ,uname); + return PAM_USER_UNKNOWN; + } + + if (!strcmp( pwent->pw_passwd, "*NP*" )) { /* NIS+ */ + uid_t save_euid, save_uid; + + save_euid = geteuid(); + save_uid = getuid(); + if (save_uid == pwent->pw_uid) + setreuid( save_euid, save_uid ); + else { + setreuid( 0, -1 ); + if (setreuid( -1, pwent->pw_uid ) == -1) { + setreuid( -1, 0 ); + setreuid( 0, -1 ); + if(setreuid( -1, pwent->pw_uid ) == -1) + return PAM_CRED_INSUFFICIENT; + } + } + spent = getspnam( uname ); + if (save_uid == pwent->pw_uid) + setreuid( save_uid, save_euid ); + else { + if (setreuid( -1, 0 ) == -1) + setreuid( save_uid, -1 ); + setreuid( -1, save_euid ); + } + + } else if (!strcmp( pwent->pw_passwd, "x" )) { + spent = getspnam(uname); + } else { + return PAM_SUCCESS; + } + + if (!spent) + return PAM_AUTHINFO_UNAVAIL; /* Couldn't get username from shadow */ + + curdays = time(NULL) / (60 * 60 * 24); + D(("today is %d, last change %d", curdays, spent->sp_lstchg)); + if ((curdays > spent->sp_expire) && (spent->sp_expire != -1) + && (spent->sp_lstchg != 0)) { + _log_err(LOG_NOTICE, pamh + ,"account %s has expired (account expired)" + ,uname); + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + "Your account has expired; please contact your system administrator"); + D(("account expired")); + return PAM_ACCT_EXPIRED; + } + if ((curdays > (spent->sp_lstchg + spent->sp_max + spent->sp_inact)) + && (spent->sp_max != -1) && (spent->sp_inact != -1) + && (spent->sp_lstchg != 0)) { + _log_err(LOG_NOTICE, pamh + ,"account %s has expired (failed to change password)" + ,uname); + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + "Your account has expired; please contact your system administrator"); + D(("account expired 2")); + return PAM_ACCT_EXPIRED; + } + D(("when was the last change")); + if (spent->sp_lstchg == 0) { + _log_err(LOG_NOTICE, pamh + ,"expired password for user %s (root enforced)" + ,uname); + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + "You are required to change your password immediately (root enforced)"); + D(("need a new password")); + return PAM_NEW_AUTHTOK_REQD; + } + if (((spent->sp_lstchg + spent->sp_max) < curdays) && (spent->sp_max != -1)) { + _log_err(LOG_DEBUG, pamh + ,"expired password for user %s (password aged)" + ,uname); + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + "You are required to change your password immediately (password aged)"); + D(("need a new password 2")); + return PAM_NEW_AUTHTOK_REQD; + } + if ((curdays > (spent->sp_lstchg + spent->sp_max - spent->sp_warn)) + && (spent->sp_max != -1) && (spent->sp_warn != -1)) { + daysleft = (spent->sp_lstchg + spent->sp_max) - curdays; + _log_err(LOG_DEBUG, pamh + ,"password for user %s will expire in %d days" + ,uname, daysleft); + snprintf(buf, 80, "Warning: your password will expire in %d day%.2s", + daysleft, daysleft == 1 ? "" : "s"); + _make_remark(pamh, ctrl, PAM_TEXT_INFO, buf); + } + + D(("all done")); + + return PAM_SUCCESS; } diff --git a/contrib/libpam/modules/pam_unix/pam_unix_auth.c b/contrib/libpam/modules/pam_unix/pam_unix_auth.c index 95f13d0abdc6..f08ea515b4d4 100644 --- a/contrib/libpam/modules/pam_unix/pam_unix_auth.c +++ b/contrib/libpam/modules/pam_unix/pam_unix_auth.c @@ -1,8 +1,7 @@ -/* $Header: /home/morgan/pam/Linux-PAM-0.59/modules/pam_unix/RCS/pam_unix_auth.c,v 1.1 1996/11/09 19:44:35 morgan Exp morgan $ */ - /* * Copyright Alexander O. Yuriev, 1996. All rights reserved. * NIS+ support by Thorsten Kukuk <kukuk@weber.uni-paderborn.de> + * Copyright Jan Rêkorajski, 1999. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,217 +34,145 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ - -/* - * $Log: pam_unix_auth.c,v $ - * - * Revision 1.9 1996/05/26 04:13:04 morgan - * added static support - * - * Revision 1.8 1996/05/21 03:51:58 morgan - * added "const" to rcsid[] definition - * - * Revision 1.7 1996/04/19 03:25:57 alex - * minor corrections. - * - * Revision 1.6 1996/04/17 01:05:05 alex - * _pam_auth_unix() cleaned up - non-authentication code is made into funcs - * and mostly moved out to support.c. - * - * Revision 1.5 1996/04/16 21:12:46 alex - * unix authentication works on Bach again. This is a tranitional stage. - * I really don't like that _pam_unix_auth() grew into a monster that does - * prompts etc etc. They should go into other functions. - * - * Revision 1.4 1996/04/07 08:06:12 morgan - * tidied up a little - * - * Revision 1.3 1996/04/07 07:34:07 morgan - * added conversation support. Now the module is capable of obtaining a - * username and a password all by itself. - * - * Revision 1.2 1996/03/29 02:31:19 morgan - * Marek Michalkiewicz's small patches for shadow support. - * - * Revision 1.1 1996/03/09 09:10:57 morgan - * Initial revision - * - */ -#ifdef linux -# define _GNU_SOURCE -# include <features.h> -#endif +/* #define DEBUG */ + +#include <security/_pam_aconf.h> -#include <stdlib.h> #include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> #include <string.h> -#define __USE_BSD #include <unistd.h> -#include <pwd.h> +#include <fcntl.h> +#include <ctype.h> #include <sys/types.h> +#include <sys/stat.h> -#ifndef NDEBUG - -#include <syslog.h> - -#endif /* NDEBUG */ - -#ifdef HAVE_SHADOW_H - -#include <shadow.h> - -#endif /* HAVE_SHADOW_H */ - -#ifndef LINUX - -#include <security/pam_appl.h> +/* indicate the following groups are defined */ -#endif /* LINUX */ +#define PAM_SM_AUTH #define _PAM_EXTERN_FUNCTIONS +#include <security/_pam_macros.h> #include <security/pam_modules.h> -static const char rcsid[] = "$Id: pam_unix_auth.c,v 1.1 1996/11/09 19:44:35 morgan Exp morgan $ pam_unix authentication functions. alex@bach.cis.temple.edu"; - -/* Define function phototypes */ - -extern char *crypt(const char *key, const char *salt); /* This should have - been in unistd.h - but it is not */ -extern int converse( pam_handle_t *pamh, - int nargs, - struct pam_message **message, - struct pam_response **response ); - -extern int _set_auth_tok( pam_handle_t *pamh, - int flags, int argc, - const char **argv ); - -static int _pam_auth_unix( pam_handle_t *pamh, - int flags, int argc, - const char **argv ); +#ifndef LINUX_PAM +#include <security/pam_appl.h> +#endif /* LINUX_PAM */ -static int _pam_set_credentials_unix ( pam_handle_t *pamh, - int flags, - int argc, - const char ** argv ) ; +#include "support.h" +/* + * PAM framework looks for these entry-points to pass control to the + * authentication module. + */ /* Fun starts here :) - * - * _pam_auth_unix() actually performs UNIX/shadow authentication + + * pam_sm_authenticate() performs UNIX/shadow authentication * - * First, if shadow support is available, attempt to perform - * authentication using shadow passwords. If shadow is not - * available, or user does not have a shadow password, fallback - * onto a normal UNIX authentication + * First, if shadow support is available, attempt to perform + * authentication using shadow passwords. If shadow is not + * available, or user does not have a shadow password, fallback + * onto a normal UNIX authentication */ -static int _pam_auth_unix( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ) +#define _UNIX_AUTHTOK "-UN*X-PASS" + +#define AUTH_RETURN \ +{ \ + if (on(UNIX_LIKE_AUTH, ctrl) && ret_data) { \ + D(("recording return code for next time [%d]", \ + retval)); \ + pam_set_data(pamh, "unix_setcred_return", \ + (void *) retval, NULL); \ + } \ + D(("done. [%s]", pam_strerror(pamh, retval))); \ + return retval; \ +} + +PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags + ,int argc, const char **argv) { - int retval; - struct passwd *pw; - const char *name; - char *p, *pp; - const char *salt; + unsigned int ctrl; + int retval, *ret_data = NULL; + const char *name, *p; -#ifdef HAVE_SHADOW_H + D(("called.")); - struct spwd *sp; + ctrl = _set_ctrl(pamh, flags, NULL, argc, argv); -#endif + /* Get a few bytes so we can pass our return value to + pam_sm_setcred(). */ + ret_data = malloc(sizeof(int)); /* get the user'name' */ - if ( (retval = pam_get_user( pamh, &name, "login: ") ) != PAM_SUCCESS ) - return retval; - - /* - * at some point we will have to make this module pay - * attention to arguments, like 'pam_first_pass' etc... - */ - - pw = getpwnam ( name ); + retval = pam_get_user(pamh, &name, "login: "); + if (retval == PAM_SUCCESS) { + /* + * Various libraries at various times have had bugs related to + * '+' or '-' as the first character of a user name. Don't take + * any chances here. Require that the username starts with an + * alphanumeric character. + */ + if (name == NULL || !isalnum(*name)) { + _log_err(LOG_ERR, pamh, "bad username [%s]", name); + retval = PAM_USER_UNKNOWN; + AUTH_RETURN + } + if (retval == PAM_SUCCESS && on(UNIX_DEBUG, ctrl)) + D(("username [%s] obtained", name)); + } else { + D(("trouble reading username")); + if (retval == PAM_CONV_AGAIN) { + D(("pam_get_user/conv() function is not ready yet")); + /* it is safe to resume this function so we translate this + * retval to the value that indicates we're happy to resume. + */ + retval = PAM_INCOMPLETE; + } + AUTH_RETURN + } - /* For NIS+, root cannot get password for lesser user */ - if (pw) { - uid_t save_euid, save_uid; + /* if this user does not have a password... */ - save_uid = getuid (); - save_euid = geteuid(); - if (setreuid (0,pw->pw_uid) >= 0) { - pw = getpwnam ( name ); - setreuid (save_uid,save_euid); - } + if (_unix_blankpasswd(ctrl, name)) { + D(("user '%s' has blank passwd", name)); + name = NULL; + retval = PAM_SUCCESS; + AUTH_RETURN } - - if ( pw && (!pw->pw_passwd || pw->pw_passwd[0] == '\0') && - !(flags & PAM_DISALLOW_NULL_AUTHTOK)) { - return PAM_SUCCESS; + /* get this user's authentication token */ + + retval = _unix_read_password(pamh, ctrl, NULL, "Password: ", NULL + ,_UNIX_AUTHTOK, &p); + if (retval != PAM_SUCCESS) { + if (retval != PAM_CONV_AGAIN) { + _log_err(LOG_CRIT, pamh, "auth could not identify password for [%s]" + ,name); + } else { + D(("conversation function is not ready yet")); + /* + * it is safe to resume this function so we translate this + * retval to the value that indicates we're happy to resume. + */ + retval = PAM_INCOMPLETE; + } + name = NULL; + AUTH_RETURN } - pam_get_item( pamh, PAM_AUTHTOK, (void*) &p ); - - if ( !p ) - { - retval = _set_auth_tok( pamh, flags, argc, argv ); - if ( retval != PAM_SUCCESS ) - return retval; - } - - /* - We have to call pam_get_item() again because value of p should - change - */ - - pam_get_item( pamh, PAM_AUTHTOK, (void*) &p ); + D(("user=%s, password=[%s]", name, p)); + /* verify the password of this user */ + retval = _unix_verify_password(pamh, name, p, ctrl); + name = p = NULL; - if (pw) - { - -#ifdef HAVE_SHADOW_H - - /* - * Support for shadow passwords on Linux and SVR4-based - * systems. Shadow passwords are optional on Linux - if - * there is no shadow password, use the non-shadow one. - */ - - sp = getspnam( name ); - if (sp && (!strcmp(pw->pw_passwd,"x"))) - { - /* TODO: check if password has expired etc. */ - salt = sp->sp_pwdp; - } - else -#endif - salt = pw->pw_passwd; - } - else - return PAM_USER_UNKNOWN; - - /* The 'always-encrypt' method does not make sense in PAM - because the framework requires return of a different - error code for non-existant users -- alex */ - - if ( ( !pw->pw_passwd ) && ( !p ) ) - if ( flags && PAM_DISALLOW_NULL_AUTHTOK ) - return PAM_SUCCESS; - else - return PAM_AUTH_ERR; - - pp = crypt(p, salt); - - if ( strcmp( pp, salt ) == 0 ) - return PAM_SUCCESS; - - return PAM_AUTH_ERR; + AUTH_RETURN } + /* * The only thing _pam_set_credentials_unix() does is initialization of * UNIX group IDs. @@ -255,45 +182,35 @@ static int _pam_auth_unix( pam_handle_t *pamh, * warned you. -- AOY */ -static int _pam_set_credentials_unix ( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ) - -{ /* FIX ME: incorrect error code */ - - return PAM_SUCCESS; /* This is a wrong result code. From what I - remember from reafing one of the guides - there's an error-level saying 'N/A func' - -- AOY - */ -} - -/* - * PAM framework looks for these entry-points to pass control to the - * authentication module. - */ - -PAM_EXTERN -int pam_sm_authenticate( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ) -{ - return _pam_auth_unix( pamh, flags, argc, argv ); -} - -PAM_EXTERN -int pam_sm_setcred( pam_handle_t *pamh, - int flags, - int argc, - const char **argv) +PAM_EXTERN int pam_sm_setcred(pam_handle_t * pamh, int flags + ,int argc, const char **argv) { - return _pam_set_credentials_unix ( pamh, flags, argc, argv ) ; + unsigned int ctrl; + int retval; + + D(("called.")); + + /* FIXME: it shouldn't be necessary to parse the arguments again. The + only argument we need is UNIX_LIKE_AUTH: if it was set, + pam_get_data will succeed. If it wasn't, it will fail, and we + return PAM_SUCCESS. -SRL */ + ctrl = _set_ctrl(pamh, flags, NULL, argc, argv); + retval = PAM_SUCCESS; + + if (on(UNIX_LIKE_AUTH, ctrl)) { + int *pretval = NULL; + + D(("recovering return code from auth call")); + pam_get_data(pamh, "unix_setcred_return", (const void **) pretval); + if(pretval) { + retval = *pretval; + free(pretval); + D(("recovered data indicates that old retval was %d", retval)); + } + } + return retval; } - -/* static module data */ #ifdef PAM_STATIC struct pam_module _pam_unix_auth_modstruct = { "pam_unix_auth", diff --git a/contrib/libpam/modules/pam_unix/pam_unix_passwd.c b/contrib/libpam/modules/pam_unix/pam_unix_passwd.c index de1345e85285..3fe8a27a6997 100644 --- a/contrib/libpam/modules/pam_unix/pam_unix_passwd.c +++ b/contrib/libpam/modules/pam_unix/pam_unix_passwd.c @@ -1,8 +1,7 @@ - -/* Main coding by Elliot Lee <sopwith@redhat.com>, Red Hat Software. - Copyright (C) 1996. */ - /* + * Main coding by Elliot Lee <sopwith@redhat.com>, Red Hat Software. + * Copyright (C) 1996. + * Copyright (c) Jan Rêkorajski, 1999. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -16,13 +15,13 @@ * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. - * + * * ALTERNATIVELY, this product may be distributed under the terms of * the GNU Public License, in which case the provisions of the GPL are * required INSTEAD OF the above restrictions. (This clause is * necessary due to a potential bad interaction between the GPL and * the restrictions contained in a BSD-style copyright.) - * + * * THIS SOFTWARE IS PROVIDED ``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 @@ -36,778 +35,970 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - How it works: - Gets in username (has to be done) from the calling program - Does authentication of user (only if we are not running as root) - Gets new password/checks for sanity - Sets it. - */ - -#define PAM_SM_PASSWORD - -/* #define DEBUG 1 */ +#include <security/_pam_aconf.h> #include <stdio.h> -#include <sys/time.h> -#define _BSD_SOURCE -#define _SVID_SOURCE +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <malloc.h> +#include <unistd.h> #include <errno.h> -#define __USE_BSD -#define _BSD_SOURCE -#include <pwd.h> #include <sys/types.h> +#include <pwd.h> +#include <syslog.h> +#include <shadow.h> +#include <time.h> /* for time() */ +#include <fcntl.h> +#include <ctype.h> +#include <sys/time.h> +#include <sys/stat.h> +#include <rpc/rpc.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> -/* why not defined? */ -void setpwent(void); -void endpwent(void); -int chmod(const char *path, mode_t mode); -struct passwd *fgetpwent(FILE *stream); -int putpwent(const struct passwd *p, FILE *stream); - -#include <unistd.h> -char *crypt(const char *key, const char *salt); #ifdef USE_CRACKLIB #include <crack.h> #endif -#include <ctype.h> -#include <stdlib.h> -#include <stdio.h> -#include <syslog.h> -#include <string.h> -#include <stdarg.h> -#include <malloc.h> + #include <security/_pam_macros.h> -#ifndef LINUX /* AGM added this as of 0.2 */ -#include <security/pam_appl.h> -#endif /* ditto */ +/* indicate the following groups are defined */ + +#define PAM_SM_PASSWORD + #include <security/pam_modules.h> -#ifdef HAVE_SHADOW_H -#include <shadow.h> -#endif -#define MAX_PASSWD_TRIES 3 -#define OLD_PASSWORD_PROMPT "Password: " -#define NEW_PASSWORD_PROMPT "New password: " -#define AGAIN_PASSWORD_PROMPT "New password (again): " -#define PW_TMPFILE "/etc/npasswd" -#define SH_TMPFILE "/etc/nshadow" -#define CRACKLIB_DICTS "/usr/lib/cracklib_dict" - -/* Various flags for the getpass routine to send back in... */ -#define PPW_EXPIRED 1 -#define PPW_EXPIRING 2 -#define PPW_WILLEXPIRE 4 -#define PPW_NOSUCHUSER 8 -#define PPW_SHADOW 16 -#define PPW_TOOEARLY 32 -#define PPW_ERROR 64 - -#ifndef DO_TEST -#define STATIC static -#else -#define STATIC -#endif -/* Sets a password for the specified user to the specified password - Returns flags PPW_*, or'd. */ -STATIC int _do_setpass(char *forwho, char *towhat, int flags); -/* Gets a password for the specified user - Returns flags PPW_*, or'd. */ -STATIC int _do_getpass(char *forwho, char **theirpass); -/* Checks whether the password entered is same as listed in the database - 'entered' should not be crypt()'d or anything (it should be as the - user entered it...), 'listed' should be as it is listed in the - password database file */ -STATIC int _do_checkpass(const char *entered, char *listed); - -/* sends a one-way message to the user, either error or info... */ -STATIC int conv_sendmsg(struct pam_conv *aconv, const char *message, int style); -/* sends a message and returns the results of the conversation */ -STATIC int conv_getitem(struct pam_conv *aconv, char *message, int style, - char **result); - -PAM_EXTERN -int pam_sm_chauthtok( pam_handle_t *pamh, - int flags, - int argc, - const char **argv); - -static void _pam_log(int err, const char *format, ...) -{ - va_list args; +#ifndef LINUX_PAM +#include <security/pam_appl.h> +#endif /* LINUX_PAM */ - va_start(args, format); - openlog("PAM-unix_passwd", LOG_CONS|LOG_PID, LOG_AUTH); - vsyslog(err, format, args); - va_end(args); - closelog(); -} +#include "yppasswd.h" +#include "md5.h" +#include "support.h" + +#if !((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1)) +extern int getrpcport(const char *host, unsigned long prognum, + unsigned long versnum, unsigned int proto); +#endif /* GNU libc 2.1 */ + +/* + * PAM framework looks for these entry-points to pass control to the + * password changing module. + */ #ifdef NEED_LCKPWDF -/* This is a hack, but until libc and glibc both include this function - * by default (libc only includes it if nys is not being used, at the - * moment, and glibc doesn't appear to have it at all) we need to have - * it here, too. :-( - * - * This should not become an official part of PAM. - * - * BEGIN_HACK -*/ +#include "./lckpwdf.-c" +#endif + +extern char *bigcrypt(const char *key, const char *salt); /* - * lckpwdf.c -- prevent simultaneous updates of password files - * - * Before modifying any of the password files, call lckpwdf(). It may block - * for up to 15 seconds trying to get the lock. Return value is 0 on success - * or -1 on failure. When you are done, call ulckpwdf() to release the lock. - * The lock is also released automatically when the process exits. Only one - * process at a time may hold the lock. - * - * These functions are supposed to be conformant with AT&T SVID Issue 3. - * - * Written by Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>, - * public domain. + How it works: + Gets in username (has to be done) from the calling program + Does authentication of user (only if we are not running as root) + Gets new password/checks for sanity + Sets it. */ -#include <fcntl.h> -#include <signal.h> +/* passwd/salt conversion macros */ -#define LOCKFILE "/etc/.pwd.lock" -#define TIMEOUT 15 +#define ascii_to_bin(c) ((c)>='a'?(c-59):(c)>='A'?((c)-53):(c)-'.') +#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.') -static int lockfd = -1; +/* data tokens */ -static int -set_close_on_exec(int fd) +#define _UNIX_OLD_AUTHTOK "-UN*X-OLD-PASS" +#define _UNIX_NEW_AUTHTOK "-UN*X-NEW-PASS" + +#define MAX_PASSWD_TRIES 3 +#define PW_TMPFILE "/etc/npasswd" +#define SH_TMPFILE "/etc/nshadow" +#define CRACKLIB_DICTS "/usr/share/dict/cracklib_dict" +#define OPW_TMPFILE "/etc/security/nopasswd" +#define OLD_PASSWORDS_FILE "/etc/security/opasswd" + +/* + * i64c - convert an integer to a radix 64 character + */ +static int i64c(int i) { - int flags = fcntl(fd, F_GETFD, 0); - if (flags == -1) - return -1; - flags |= FD_CLOEXEC; - return fcntl(fd, F_SETFD, flags); + if (i < 0) + return ('.'); + else if (i > 63) + return ('z'); + if (i == 0) + return ('.'); + if (i == 1) + return ('/'); + if (i >= 2 && i <= 11) + return ('0' - 2 + i); + if (i >= 12 && i <= 37) + return ('A' - 12 + i); + if (i >= 38 && i <= 63) + return ('a' - 38 + i); + return ('\0'); } -static int -do_lock(int fd) +static char *crypt_md5_wrapper(const char *pass_new) { - struct flock fl; + /* + * Code lifted from Marek Michalkiewicz's shadow suite. (CG) + * removed use of static variables (AGM) + */ + + struct timeval tv; + MD5_CTX ctx; + unsigned char result[16]; + char *cp = (char *) result; + unsigned char tmp[16]; + int i; + char *x, *e = NULL; + + GoodMD5Init(&ctx); + gettimeofday(&tv, (struct timezone *) 0); + GoodMD5Update(&ctx, (void *) &tv, sizeof tv); + i = getpid(); + GoodMD5Update(&ctx, (void *) &i, sizeof i); + i = clock(); + GoodMD5Update(&ctx, (void *) &i, sizeof i); + GoodMD5Update(&ctx, result, sizeof result); + GoodMD5Final(tmp, &ctx); + strcpy(cp, "$1$"); /* magic for the MD5 */ + cp += strlen(cp); + for (i = 0; i < 8; i++) + *cp++ = i64c(tmp[i] & 077); + *cp = '\0'; + + /* no longer need cleartext */ + e = Goodcrypt_md5(pass_new, (const char *) result); + x = x_strdup(e); /* put e in malloc()ed memory */ + _pam_overwrite(e); /* clean up */ + + return x; +} - memset(&fl, 0, sizeof fl); - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - return fcntl(fd, F_SETLKW, &fl); +static char *getNISserver(pam_handle_t *pamh) +{ + char *master; + char *domainname; + int port, err; + + if ((err = yp_get_default_domain(&domainname)) != 0) { + _log_err(LOG_WARNING, pamh, "can't get local yp domain: %s\n", + yperr_string(err)); + return NULL; + } + if ((err = yp_master(domainname, "passwd.byname", &master)) != 0) { + _log_err(LOG_WARNING, pamh, "can't find the master ypserver: %s\n", + yperr_string(err)); + return NULL; + } + port = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP); + if (port == 0) { + _log_err(LOG_WARNING, pamh, + "yppasswdd not running on NIS master host\n"); + return NULL; + } + if (port >= IPPORT_RESERVED) { + _log_err(LOG_WARNING, pamh, + "yppasswd daemon running on illegal port.\n"); + return NULL; + } + return master; } -static void -alarm_catch(int sig) +static int check_old_password(const char *forwho, const char *newpass) { -/* does nothing, but fcntl F_SETLKW will fail with EINTR */ + static char buf[16384]; + char *s_luser, *s_uid, *s_npas, *s_pas; + int retval = PAM_SUCCESS; + FILE *opwfile; + + opwfile = fopen(OLD_PASSWORDS_FILE, "r"); + if (opwfile == NULL) + return PAM_AUTHTOK_ERR; + + while (fgets(buf, 16380, opwfile)) { + if (!strncmp(buf, forwho, strlen(forwho))) { + buf[strlen(buf) - 1] = '\0'; + s_luser = strtok(buf, ":,"); + s_uid = strtok(NULL, ":,"); + s_npas = strtok(NULL, ":,"); + s_pas = strtok(NULL, ":,"); + while (s_pas != NULL) { + if (!strcmp(Goodcrypt_md5(newpass, s_pas), s_pas)) { + retval = PAM_AUTHTOK_ERR; + break; + } + s_pas = strtok(NULL, ":,"); + } + break; + } + } + fclose(opwfile); + + return retval; } -static int lckpwdf(void) +static int save_old_password(const char *forwho, const char *oldpass, int howmany) { - struct sigaction act, oldact; - sigset_t set, oldset; - - if (lockfd != -1) - return -1; - - lockfd = open(LOCKFILE, O_CREAT | O_WRONLY, 0600); - if (lockfd == -1) - return -1; - if (set_close_on_exec(lockfd) == -1) - goto cleanup_fd; - - memset(&act, 0, sizeof act); - act.sa_handler = alarm_catch; - act.sa_flags = 0; - sigfillset(&act.sa_mask); - if (sigaction(SIGALRM, &act, &oldact) == -1) - goto cleanup_fd; - - sigemptyset(&set); - sigaddset(&set, SIGALRM); - if (sigprocmask(SIG_UNBLOCK, &set, &oldset) == -1) - goto cleanup_sig; - - alarm(TIMEOUT); - if (do_lock(lockfd) == -1) - goto cleanup_alarm; - alarm(0); - sigprocmask(SIG_SETMASK, &oldset, NULL); - sigaction(SIGALRM, &oldact, NULL); - return 0; - -cleanup_alarm: - alarm(0); - sigprocmask(SIG_SETMASK, &oldset, NULL); -cleanup_sig: - sigaction(SIGALRM, &oldact, NULL); -cleanup_fd: - close(lockfd); - lockfd = -1; - return -1; + static char buf[16384]; + static char nbuf[16384]; + char *s_luser, *s_uid, *s_npas, *s_pas, *pass; + int retval = 0, npas; + FILE *pwfile, *opwfile; + int err = 0; + int oldmask; + int found = 0; + struct passwd *pwd = NULL; + + if (howmany < 0) + return retval; + + if (oldpass == NULL) + return retval; + + oldmask = umask(077); + pwfile = fopen(OPW_TMPFILE, "w"); + umask(oldmask); + opwfile = fopen(OLD_PASSWORDS_FILE, "r"); + if (pwfile == NULL || opwfile == NULL) + return PAM_AUTHTOK_ERR; + chown(OPW_TMPFILE, 0, 0); + chmod(OPW_TMPFILE, 0600); + + while (fgets(buf, 16380, opwfile)) { + if (!strncmp(buf, forwho, strlen(forwho))) { + buf[strlen(buf) - 1] = '\0'; + s_luser = strtok(buf, ":"); + s_uid = strtok(NULL, ":"); + s_npas = strtok(NULL, ":"); + s_pas = strtok(NULL, ":"); + npas = strtol(s_npas, NULL, 10) + 1; + while (npas > howmany) { + s_pas = strpbrk(s_pas, ","); + if (s_pas != NULL) + s_pas++; + npas--; + } + pass = crypt_md5_wrapper(oldpass); + if (s_pas == NULL) + sprintf(nbuf, "%s:%s:%d:%s\n", s_luser, s_uid, npas, pass); + else + sprintf(nbuf, "%s:%s:%d:%s,%s\n", s_luser, s_uid, npas, s_pas, pass); + if (fputs(nbuf, pwfile) < 0) { + retval = PAM_AUTHTOK_ERR; + err = 1; + break; + } + found = 1; + } else if (fputs(buf, pwfile) < 0) { + retval = PAM_AUTHTOK_ERR; + err = 1; + break; + } + } + fclose(opwfile); + if (!found) { + pwd = getpwnam(forwho); + if (pwd == NULL) { + retval = PAM_AUTHTOK_ERR; + err = 1; + } else { + pass = crypt_md5_wrapper(oldpass); + sprintf(nbuf, "%s:%d:1:%s\n", forwho, pwd->pw_uid, pass); + if (fputs(nbuf, pwfile) < 0) { + retval = PAM_AUTHTOK_ERR; + err = 1; + } + } + } + if (fclose(pwfile)) { + fprintf(stderr, "error writing entries to old passwords file: %s\n", + strerror(errno)); + retval = PAM_AUTHTOK_ERR; + err = 1; + } + if (!err) + rename(OPW_TMPFILE, OLD_PASSWORDS_FILE); + else + unlink(OPW_TMPFILE); + + return retval; } -static int -ulckpwdf(void) +static int _update_passwd(const char *forwho, const char *towhat) { - unlink(LOCKFILE); - if (lockfd == -1) - return -1; + struct passwd *tmpent = NULL; + FILE *pwfile, *opwfile; + int retval = 0; + int err = 0; + int oldmask; + + oldmask = umask(077); + pwfile = fopen(PW_TMPFILE, "w"); + umask(oldmask); + opwfile = fopen("/etc/passwd", "r"); + if (pwfile == NULL || opwfile == NULL) + return PAM_AUTHTOK_ERR; + chown(PW_TMPFILE, 0, 0); + chmod(PW_TMPFILE, 0644); + tmpent = fgetpwent(opwfile); + while (tmpent) { + if (!strcmp(tmpent->pw_name, forwho)) { + tmpent->pw_passwd = towhat; + } + if (putpwent(tmpent, pwfile)) { + fprintf(stderr, "error writing entry to password file: %s\n", + strerror(errno)); + err = 1; + retval = PAM_AUTHTOK_ERR; + break; + } + tmpent = fgetpwent(opwfile); + } + fclose(opwfile); - if (close(lockfd) == -1) { - lockfd = -1; - return -1; + if (fclose(pwfile)) { + fprintf(stderr, "error writing entries to password file: %s\n", + strerror(errno)); + retval = PAM_AUTHTOK_ERR; + err = 1; } - lockfd = -1; - return 0; + if (!err) + rename(PW_TMPFILE, "/etc/passwd"); + else + unlink(PW_TMPFILE); + + return retval; } -/* END_HACK */ -#endif -#define PAM_FAIL_CHECK if(retval != PAM_SUCCESS) { return retval; } +static int _update_shadow(const char *forwho, char *towhat) +{ + struct spwd *spwdent = NULL, *stmpent = NULL; + FILE *pwfile, *opwfile; + int retval = 0; + int err = 0; + int oldmask; + + spwdent = getspnam(forwho); + if (spwdent == NULL) + return PAM_USER_UNKNOWN; + oldmask = umask(077); + pwfile = fopen(SH_TMPFILE, "w"); + umask(oldmask); + opwfile = fopen("/etc/shadow", "r"); + if (pwfile == NULL || opwfile == NULL) + return PAM_AUTHTOK_ERR; + chown(SH_TMPFILE, 0, 0); + chmod(SH_TMPFILE, 0600); + stmpent = fgetspent(opwfile); + while (stmpent) { + if (!strcmp(stmpent->sp_namp, forwho)) { + stmpent->sp_pwdp = towhat; + stmpent->sp_lstchg = time(NULL) / (60 * 60 * 24); + + D(("Set password %s for %s", stmpent->sp_pwdp, forwho)); + } + if (putspent(stmpent, pwfile)) { + fprintf(stderr, "error writing entry to shadow file: %s\n", + strerror(errno)); + err = 1; + retval = PAM_AUTHTOK_ERR; + break; + } + stmpent = fgetspent(opwfile); + } + fclose(opwfile); + + if (fclose(pwfile)) { + fprintf(stderr, "error writing entries to shadow file: %s\n", + strerror(errno)); + retval = PAM_AUTHTOK_ERR; + err = 1; + } + if (!err) + rename(SH_TMPFILE, "/etc/shadow"); + else + unlink(SH_TMPFILE); + + return retval; +} -PAM_EXTERN -int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) +static int _do_setpass(pam_handle_t* pamh, const char *forwho, char *fromwhat, + char *towhat, unsigned int ctrl, int remember) { - char *usrname, *curpass, *newpass; /* pointers to the username, - current password, and new password */ - - struct pam_conv *appconv; /* conversation with the app */ - struct pam_message msg, *pmsg; /* Misc for conversations */ - struct pam_response *resp; - - int retval=0; /* Gets the return values for all our function calls */ - unsigned int pflags=0; /* Holds the flags from our getpass & setpass - functions */ - - const char *cmiscptr; /* Utility variables, used for different purposes at - different times */ - char *miscptr; /* Utility variables, used for different purposes at - different times */ - unsigned int miscint; - int fascist = 1; /* Be fascist by default. If compiled with cracklib, - call cracklib. Otherwise just check length... */ - - char argbuf[256],argval[256]; - int i; - - - retval = pam_get_item(pamh,PAM_CONV,(const void **) &appconv); - PAM_FAIL_CHECK; - - retval = pam_get_item(pamh,PAM_USER,(const void **) &usrname); - PAM_FAIL_CHECK; - if(flags & PAM_PRELIM_CHECK) { - pflags = _do_getpass(usrname,&miscptr); - if(pflags & PPW_NOSUCHUSER) - return PAM_USER_UNKNOWN; - else if(pflags & ~(PPW_SHADOW|PPW_EXPIRING|PPW_WILLEXPIRE)) - return PAM_AUTHTOK_ERR; - else - return PAM_SUCCESS; - } /* else... */ + struct passwd *pwd = NULL; + int retval = 0; + + D(("called")); + + setpwent(); + pwd = getpwnam(forwho); + endpwent(); + + if (pwd == NULL) + return PAM_AUTHTOK_ERR; + + if (on(UNIX_NIS, ctrl)) { + struct timeval timeout; + struct yppasswd yppwd; + CLIENT *clnt; + char *master; + int status; + int err = 0; + + /* Make RPC call to NIS server */ + if ((master = getNISserver(pamh)) == NULL) + return PAM_TRY_AGAIN; + + /* Initialize password information */ + yppwd.newpw.pw_passwd = pwd->pw_passwd; + yppwd.newpw.pw_name = pwd->pw_name; + yppwd.newpw.pw_uid = pwd->pw_uid; + yppwd.newpw.pw_gid = pwd->pw_gid; + yppwd.newpw.pw_gecos = pwd->pw_gecos; + yppwd.newpw.pw_dir = pwd->pw_dir; + yppwd.newpw.pw_shell = pwd->pw_shell; + yppwd.oldpass = fromwhat; + yppwd.newpw.pw_passwd = towhat; + + D(("Set password %s for %s", yppwd.newpw.pw_passwd, forwho)); + + /* The yppasswd.x file said `unix authentication required', + * so I added it. This is the only reason it is in here. + * My yppasswdd doesn't use it, but maybe some others out there + * do. --okir + */ + clnt = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp"); + clnt->cl_auth = authunix_create_default(); + memset((char *) &status, '\0', sizeof(status)); + timeout.tv_sec = 25; + timeout.tv_usec = 0; + err = clnt_call(clnt, YPPASSWDPROC_UPDATE, + (xdrproc_t) xdr_yppasswd, (char *) &yppwd, + (xdrproc_t) xdr_int, (char *) &status, + timeout); + + if (err) { + clnt_perrno(err); + retval = PAM_TRY_AGAIN; + } else if (status) { + fprintf(stderr, "Error while changing NIS password.\n"); + retval = PAM_TRY_AGAIN; + } + printf("\nThe password has%s been changed on %s.\n", + (err || status) ? " not" : "", master); + + auth_destroy(clnt->cl_auth); + clnt_destroy(clnt); + if ((err || status) != 0) { + retval = PAM_TRY_AGAIN; + } #ifdef DEBUG - fprintf(stderr,"Got username of %s\n",usrname); + sleep(5); #endif - if((usrname == NULL) || (strlen(usrname) < 1)) { - /* The app is supposed to get us the username! */ - retval = PAM_USER_UNKNOWN; - PAM_FAIL_CHECK; - } - - for(i=0; i < argc; i++) { - { - char *tmp = x_strdup(argv[i]); - strncpy(argbuf,strtok(tmp ,"="),255); - strncpy(argval,strtok(NULL,"="),255); - free(tmp); - } - - /* For PC functionality use "strict" -- historically "fascist" */ - if(!strcmp(argbuf,"strict") || !strcmp(argbuf, "fascist")) - - if(!strcmp(argval,"true")) - fascist = 1; - else if(!strcmp(argval,"false")) - fascist = 0; - else - return PAM_SERVICE_ERR; - else { - _pam_log(LOG_ERR,"Unknown option: %s",argbuf); - return PAM_SERVICE_ERR; - } - } - - - /* Now we have all the initial information we need from the app to - set things up (we assume that getting the username succeeded...) */ - retval = pam_get_item(pamh,PAM_OLDAUTHTOK,(const void **) &curpass); - PAM_FAIL_CHECK; - if(getuid()) { /* If this is being run by root, we don't need to get their - old password. - note */ - /* If we haven't been given a password yet, prompt for one... */ - miscint=0; - while((curpass == NULL) && (miscint++ < MAX_PASSWD_TRIES)) { - pflags = _do_getpass(usrname,&miscptr); - if(pflags & PPW_NOSUCHUSER) - return PAM_USER_UNKNOWN; /* If the user that was passed in doesn't - exist, say so and exit (app passes in - username) */ - - /* Get the password from the user... */ - pmsg = &msg; - - msg.msg_style = PAM_PROMPT_ECHO_OFF; - msg.msg = OLD_PASSWORD_PROMPT; - resp = NULL; - - retval = appconv->conv(1, (const struct pam_message **) &pmsg, - &resp, appconv->appdata_ptr); - - PAM_FAIL_CHECK; - curpass = resp->resp; - free (resp); - if(_do_checkpass(curpass?curpass:"",miscptr)) { - int abortme = 0; - - /* password is incorrect... */ - if (curpass && curpass[0] == '\0') { - /* ...and it was zero-length; user wishes to abort change */ - abortme = 1; - } - if (curpass) { free (curpass); } - curpass = NULL; - if (abortme) { - conv_sendmsg(appconv,"Password change aborted.",PAM_ERROR_MSG); - return PAM_AUTHTOK_ERR; - } - } - } - - if(curpass == NULL) - return PAM_AUTH_ERR; /* They didn't seem to enter the right password - for three tries - error */ - pam_set_item(pamh, PAM_OLDAUTHTOK, (void *)curpass); - } else { -#ifdef DEBUG - fprintf(stderr,"I am ROOT!\n"); -#endif - pflags = _do_getpass(usrname,&curpass); - if(curpass == NULL) - curpass = x_strdup(""); - } - if(pflags & PPW_TOOEARLY) { - conv_sendmsg(appconv,"You must wait longer to change your password", - PAM_ERROR_MSG); - return PAM_AUTHTOK_ERR; - } - if(pflags & PPW_WILLEXPIRE) - conv_sendmsg(appconv,"Your password is about to expire",PAM_TEXT_INFO); - else if(pflags & PPW_EXPIRED) - return PAM_ACCT_EXPIRED; /* If their account has expired, we can't auth - them to change their password */ - if(!(pflags & PPW_EXPIRING) && (flags & PAM_CHANGE_EXPIRED_AUTHTOK)) - return PAM_SUCCESS; - /* If we haven't been given a password yet, prompt for one... */ - miscint=0; - pam_get_item(pamh,PAM_AUTHTOK,(const void **)&newpass); - cmiscptr = NULL; - while((newpass == NULL) && (miscint++ < MAX_PASSWD_TRIES)) { - - /* Get the password from the user... */ - pmsg = &msg; - - msg.msg_style = PAM_PROMPT_ECHO_OFF; - msg.msg = NEW_PASSWORD_PROMPT; - resp = NULL; - - retval = appconv->conv(1, (const struct pam_message **) &pmsg, - &resp, appconv->appdata_ptr); - - PAM_FAIL_CHECK; - newpass = resp->resp; - free (resp); + return retval; + } + /* first, save old password */ + if (save_old_password(forwho, fromwhat, remember)) { + return PAM_AUTHTOK_ERR; + } + if (on(UNIX_SHADOW, ctrl) || (strcmp(pwd->pw_passwd, "x") == 0)) { + retval = _update_shadow(forwho, towhat); + if (retval == PAM_SUCCESS) + retval = _update_passwd(forwho, "x"); + } else { + retval = _update_passwd(forwho, towhat); + } -#ifdef DEBUG - if(newpass) - fprintf(stderr,"Got password of %s\n",newpass); - else - fprintf(stderr,"No new password...\n"); -#endif - if (newpass[0] == '\0') { free (newpass); newpass = (char *) 0; } - cmiscptr=NULL; - if(newpass) { + return retval; +} + +static int _unix_verify_shadow(const char *user, unsigned int ctrl) +{ + struct passwd *pwd = NULL; /* Password and shadow password */ + struct spwd *spwdent = NULL; /* file entries for the user */ + time_t curdays; + int retval = PAM_SUCCESS; + + /* UNIX passwords area */ + setpwent(); + pwd = getpwnam(user); /* Get password file entry... */ + endpwent(); + if (pwd == NULL) + return PAM_AUTHINFO_UNAVAIL; /* We don't need to do the rest... */ + + if (strcmp(pwd->pw_passwd, "x") == 0) { + /* ...and shadow password file entry for this user, if shadowing + is enabled */ + setspent(); + spwdent = getspnam(user); + endspent(); + + if (spwdent == NULL) + return PAM_AUTHINFO_UNAVAIL; + } else { + if (strcmp(pwd->pw_passwd,"*NP*") == 0) { /* NIS+ */ + uid_t save_uid; + + save_uid = geteuid(); + seteuid (pwd->pw_uid); + spwdent = getspnam( user ); + seteuid (save_uid); + + if (spwdent == NULL) + return PAM_AUTHINFO_UNAVAIL; + } else + spwdent = NULL; + } + + if (spwdent != NULL) { + /* We have the user's information, now let's check if their account + has expired (60 * 60 * 24 = number of seconds in a day) */ + + if (off(UNIX__IAMROOT, ctrl)) { + /* Get the current number of days since 1970 */ + curdays = time(NULL) / (60 * 60 * 24); + if ((curdays < (spwdent->sp_lstchg + spwdent->sp_min)) + && (spwdent->sp_min != -1)) + retval = PAM_AUTHTOK_ERR; + else if ((curdays > (spwdent->sp_lstchg + spwdent->sp_max + spwdent->sp_inact)) + && (spwdent->sp_max != -1) && (spwdent->sp_inact != -1) + && (spwdent->sp_lstchg != 0)) + /* + * Their password change has been put off too long, + */ + retval = PAM_ACCT_EXPIRED; + else if ((curdays > spwdent->sp_expire) && (spwdent->sp_expire != -1) + && (spwdent->sp_lstchg != 0)) + /* + * OR their account has just plain expired + */ + retval = PAM_ACCT_EXPIRED; + } + } + return retval; +} + +static int _pam_unix_approve_pass(pam_handle_t * pamh + ,unsigned int ctrl + ,const char *pass_old + ,const char *pass_new) +{ + const char *user; + const char *remark = NULL; + int retval = PAM_SUCCESS; + + D(("&new=%p, &old=%p", pass_old, pass_new)); + D(("new=[%s]", pass_new)); + D(("old=[%s]", pass_old)); + + if (pass_new == NULL || (pass_old && !strcmp(pass_old, pass_new))) { + if (on(UNIX_DEBUG, ctrl)) { + _log_err(LOG_DEBUG, pamh, "bad authentication token"); + } + _make_remark(pamh, ctrl, PAM_ERROR_MSG, pass_new == NULL ? + "No password supplied" : "Password unchanged"); + return PAM_AUTHTOK_ERR; + } + /* + * if one wanted to hardwire authentication token strength + * checking this would be the place - AGM + */ + + retval = pam_get_item(pamh, PAM_USER, (const void **) &user); + if (retval != PAM_SUCCESS) { + if (on(UNIX_DEBUG, ctrl)) { + _log_err(LOG_ERR, pamh, "Can not get username"); + return PAM_AUTHTOK_ERR; + } + } + if (off(UNIX__IAMROOT, ctrl)) { #ifdef USE_CRACKLIB - if(fascist && getuid()) - cmiscptr = FascistCheck(newpass,CRACKLIB_DICTS); + remark = FascistCheck(pass_new, CRACKLIB_DICTS); + D(("called cracklib [%s]", remark)); #else - if(fascist && getuid() && strlen(newpass) < 6) - cmiscptr = "You must choose a longer password"; + if (strlen(pass_new) < 6) + remark = "You must choose a longer password"; + D(("lenth check [%s]", remark)); #endif - if(curpass) - if(!strcmp(curpass,newpass)) { - cmiscptr="You must choose a new password."; - newpass=NULL; + if (on(UNIX_REMEMBER_PASSWD, ctrl)) + if ((retval = check_old_password(user, pass_new)) != PAM_SUCCESS) + remark = "Password has been already used. Choose another."; } - } else { - /* We want to abort the password change */ - conv_sendmsg(appconv,"Password change aborted",PAM_ERROR_MSG); - return PAM_AUTHTOK_ERR; - } - if(!cmiscptr) { - /* We ask them to enter their password again... */ - /* Get the password from the user... */ - pmsg = &msg; - - msg.msg_style = PAM_PROMPT_ECHO_OFF; - msg.msg = AGAIN_PASSWORD_PROMPT; - resp = NULL; - - retval = appconv->conv(1, (const struct pam_message **) &pmsg, - &resp, appconv->appdata_ptr); - - PAM_FAIL_CHECK; - miscptr = resp->resp; - free (resp); - if (miscptr[0] == '\0') { free (miscptr); miscptr = (char *) 0; } - if(!miscptr) { /* Aborting password change... */ - conv_sendmsg(appconv,"Password change aborted",PAM_ERROR_MSG); - return PAM_AUTHTOK_ERR; - } - if(!strcmp(newpass,miscptr)) { - miscptr=NULL; - break; - } - conv_sendmsg(appconv,"You must enter the same password twice.", - PAM_ERROR_MSG); - miscptr=NULL; - newpass=NULL; - } - else { - conv_sendmsg(appconv,cmiscptr,PAM_ERROR_MSG); - newpass = NULL; - } - } - if(cmiscptr) { - /* conv_sendmsg(appconv,cmiscptr,PAM_ERROR_MSG); */ - return PAM_AUTHTOK_ERR; - } else if(newpass == NULL) - return PAM_AUTHTOK_ERR; /* They didn't seem to enter the right password - for three tries - error */ -#ifdef DEBUG - printf("Changing password for sure!\n"); -#endif - /* From now on, we are bound and determined to get their password - changed :-) */ - pam_set_item(pamh, PAM_AUTHTOK, (void *)newpass); - retval = _do_setpass(usrname,newpass,pflags); -#ifdef DEBUG - fprintf(stderr,"retval was %d\n",retval); -#endif - if(retval & ~PPW_SHADOW) { - conv_sendmsg(appconv,"Error: Password NOT changed",PAM_ERROR_MSG); - return PAM_AUTHTOK_ERR; - } else { - conv_sendmsg(appconv,"Password changed",PAM_TEXT_INFO); - return PAM_SUCCESS; - } + if (remark) { + _make_remark(pamh, ctrl, PAM_ERROR_MSG, remark); + retval = PAM_AUTHTOK_ERR; + } + return retval; } -/* _do_checkpass() returns 0 on success, non-0 on failure */ -STATIC int _do_checkpass(const char *entered, char *listed) + +PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, + int argc, const char **argv) { - char salt[3]; - if ((strlen(listed) == 0) &&(strlen(entered) == 0)) { - /* no password in database; no password entered */ - return (0); - } - salt[0]=listed[0]; salt[1]=listed[1]; salt[2]='\0'; - return strcmp(crypt(entered,salt),listed); -} + unsigned int ctrl, lctrl; + int retval, i; + int remember = -1; -STATIC char mksalt(int seed) { - int num = seed % 64; - - if (num < 26) - return 'a' + num; - else if (num < 52) - return 'A' + (num - 26); - else if (num < 62) - return '0' + (num - 52); - else if (num == 63) - return '.'; - else - return '/'; -} + /* <DO NOT free() THESE> */ + const char *user; + char *pass_old, *pass_new; + /* </DO NOT free() THESE> */ -STATIC int _do_setpass(char *forwho, char *towhat,int flags) -{ - struct passwd *pwd=NULL, *tmpent=NULL; - FILE *pwfile,*opwfile; - char thesalt[3]; - int retval=0; - struct timeval time1; - int err = 0; -#ifdef HAVE_SHADOW_H - struct spwd *spwdent=NULL, *stmpent=NULL; + D(("called.")); + +#ifdef USE_LCKPWDF + /* our current locking system requires that we lock the + entire password database. This avoids both livelock + and deadlock. */ + /* These values for the number of attempts and the sleep time + are, of course, completely arbitrary. + My reading of the PAM docs is that, once pam_chauthtok() has been + called with PAM_UPDATE_AUTHTOK, we are obliged to take any + reasonable steps to make sure the token is updated; so retrying + for 1/10 sec. isn't overdoing it. + The other possibility is to call lckpwdf() on the first + pam_chauthtok() pass, and hold the lock until released in the + second pass--but is this guaranteed to work? -SRL */ + i=0; + while((retval = lckpwdf()) != 0 && i < 100) { + usleep(1000); + } + if(retval != 0) { + return PAM_AUTHTOK_LOCK_BUSY; + } #endif - if(flags & PPW_SHADOW) { retval |= PPW_SHADOW; } - gettimeofday(&time1, NULL); - srand(time1.tv_usec); - thesalt[0]=mksalt(rand()); - thesalt[1]=mksalt(rand()); - thesalt[2]='\0'; - - /* lock the entire password subsystem */ + ctrl = _set_ctrl(pamh, flags, &remember, argc, argv); + + /* + * First get the name of a user + */ + retval = pam_get_user(pamh, &user, "Username: "); + if (retval == PAM_SUCCESS) { + /* + * Various libraries at various times have had bugs related to + * '+' or '-' as the first character of a user name. Don't take + * any chances here. Require that the username starts with an + * alphanumeric character. + */ + if (user == NULL || !isalnum(*user)) { + _log_err(LOG_ERR, pamh, "bad username [%s]", user); #ifdef USE_LCKPWDF - lckpwdf(); + ulckpwdf(); #endif - setpwent(); - pwd = getpwnam(forwho); -#ifdef DEBUG - printf("Got %p, for %s (salt %s)\n",pwd, - forwho,thesalt); + return PAM_USER_UNKNOWN; + } + if (retval == PAM_SUCCESS && on(UNIX_DEBUG, ctrl)) + _log_err(LOG_DEBUG, pamh, "username [%s] obtained", + user); + } else { + if (on(UNIX_DEBUG, ctrl)) + _log_err(LOG_DEBUG, pamh, + "password - could not identify user"); +#ifdef USE_LCKPWDF + ulckpwdf(); #endif - if(pwd == NULL) - return PPW_NOSUCHUSER; - endpwent(); - -#ifdef HAVE_SHADOW_H - if(flags & PPW_SHADOW) { - spwdent = getspnam(forwho); - if(spwdent == NULL) - return PPW_NOSUCHUSER; - spwdent->sp_pwdp = towhat; - spwdent->sp_lstchg = time(NULL)/(60*60*24); - pwfile = fopen(SH_TMPFILE,"w"); - opwfile = fopen("/etc/shadow","r"); - if(pwfile == NULL || opwfile == NULL) - return PPW_ERROR; - chown(SH_TMPFILE,0,0); - chmod(SH_TMPFILE,0600); - stmpent=fgetspent(opwfile); - while(stmpent) { - if(!strcmp(stmpent->sp_namp,forwho)) { - stmpent->sp_pwdp = crypt(towhat,thesalt); - stmpent->sp_lstchg = time(NULL)/(60*60*24); -#ifdef DEBUG - fprintf(stderr,"Set password %s for %s\n",stmpent->sp_pwdp, - forwho); + return retval; + } + + D(("Got username of %s", user)); + + /* + * This is not an AUTH module! + */ + if (on(UNIX__NONULL, ctrl)) + set(UNIX__NULLOK, ctrl); + + if (on(UNIX__PRELIM, ctrl)) { + /* + * obtain and verify the current password (OLDAUTHTOK) for + * the user. + */ + char *Announce; + + D(("prelim check")); + + if (_unix_blankpasswd(ctrl, user)) { +#ifdef USE_LCKPWDF + ulckpwdf(); #endif - } - if (putspent(stmpent,pwfile)) { - fprintf(stderr, "error writing entry to shadow file: %s\n", - strerror(errno)); - err = 1; - retval = PPW_ERROR; - break; - } - stmpent=fgetspent(opwfile); - } - fclose(opwfile); - - if (fclose(pwfile)) { - fprintf(stderr, "error writing entries to shadow file: %s\n", - strerror(errno)); - retval = PPW_ERROR; - err = 1; - } - - if (!err) - rename(SH_TMPFILE,"/etc/shadow"); - else - unlink(SH_TMPFILE); - } else { - pwd->pw_passwd = towhat; - pwfile = fopen(PW_TMPFILE,"w"); - opwfile = fopen("/etc/passwd","r"); - if(pwfile == NULL || opwfile == NULL) - return PPW_ERROR; - chown(PW_TMPFILE,0,0); - chmod(PW_TMPFILE,0644); - tmpent=fgetpwent(opwfile); - while(tmpent) { - if(!strcmp(tmpent->pw_name,forwho)) { - tmpent->pw_passwd = crypt(towhat,thesalt); - } - if (putpwent(tmpent,pwfile)) { - fprintf(stderr, "error writing entry to password file: %s\n", - strerror(errno)); - err = 1; - retval = PPW_ERROR; - break; - } - tmpent=fgetpwent(opwfile); - } - fclose(opwfile); - - if (fclose(pwfile)) { - fprintf(stderr, "error writing entries to password file: %s\n", - strerror(errno)); - retval = PPW_ERROR; - err = 1; - } - - if (!err) - rename(PW_TMPFILE,"/etc/passwd"); - else - unlink(PW_TMPFILE); - } -#else - pwd->pw_passwd = towhat; - pwfile = fopen(PW_TMPFILE,"w"); - opwfile = fopen("/etc/passwd","r"); - if(pwfile == NULL || opwfile == NULL) - return PPW_ERROR; - chown(PW_TMPFILE,0,0); - chmod(PW_TMPFILE,0644); - tmpent=fgetpwent(opwfile); - while(tmpent) { - if(!strcmp(tmpent->pw_name,forwho)) { - tmpent->pw_passwd = crypt(towhat,thesalt); - } - if (putpwent(tmpent,pwfile)) { - fprintf(stderr, "error writing entry to shadow file: %s\n", - strerror(errno)); - err = 1; - retval = PPW_ERROR; - break; - } - tmpent=fgetpwent(opwfile); - } - fclose(opwfile); - - if (fclose(pwfile)) { - fprintf(stderr, "error writing entries to password file: %s\n", - strerror(errno)); - retval = PPW_ERROR; - err = 1; - } - - if (!err) - rename(PW_TMPFILE,"/etc/passwd"); - else - unlink(PW_TMPFILE); + return PAM_SUCCESS; + } else if (off(UNIX__IAMROOT, ctrl)) { + + /* instruct user what is happening */ +#define greeting "Changing password for " + Announce = (char *) malloc(sizeof(greeting) + strlen(user)); + if (Announce == NULL) { + _log_err(LOG_CRIT, pamh, + "password - out of memory"); +#ifdef USE_LCKPWDF + ulckpwdf(); #endif - /* unlock the entire password subsystem */ + return PAM_BUF_ERR; + } + (void) strcpy(Announce, greeting); + (void) strcpy(Announce + sizeof(greeting) - 1, user); +#undef greeting + + lctrl = ctrl; + set(UNIX__OLD_PASSWD, lctrl); + retval = _unix_read_password(pamh, lctrl + ,Announce + ,"(current) UNIX password: " + ,NULL + ,_UNIX_OLD_AUTHTOK + ,(const char **) &pass_old); + free(Announce); + + if (retval != PAM_SUCCESS) { + _log_err(LOG_NOTICE, pamh + ,"password - (old) token not obtained"); #ifdef USE_LCKPWDF - ulckpwdf(); + ulckpwdf(); #endif - return retval; -} - -STATIC int _do_getpass(char *forwho, char **theirpass) -{ - struct passwd *pwd=NULL; /* Password and shadow password */ -#ifdef HAVE_SHADOW_H - struct spwd *spwdent=NULL; /* file entries for the user */ - time_t curdays; + return retval; + } + /* verify that this is the password for this user */ + + retval = _unix_verify_password(pamh, user, pass_old, ctrl); + } else { + D(("process run by root so do nothing this time around")); + pass_old = NULL; + retval = PAM_SUCCESS; /* root doesn't have too */ + } + + if (retval != PAM_SUCCESS) { + D(("Authentication failed")); + pass_old = NULL; +#ifdef USE_LCKPWDF + ulckpwdf(); #endif - int retval=0; - /* UNIX passwords area */ - setpwent(); - pwd = getpwnam(forwho); /* Get password file entry... */ - endpwent(); - if(pwd == NULL) - return PPW_NOSUCHUSER; /* We don't need to do the rest... */ -#ifdef HAVE_SHADOW_H - if(!strcmp(pwd->pw_passwd,"x")) { - /* ...and shadow password file entry for this user, if shadowing - is enabled */ - retval |= PPW_SHADOW; - setspent(); - spwdent = getspnam(forwho); - endspent(); - if(spwdent == NULL) - return PPW_NOSUCHUSER; - *theirpass = x_strdup(spwdent->sp_pwdp); - - /* We have the user's information, now let's check if their account - has expired (60 * 60 * 24 = number of seconds in a day) */ - - /* Get the current number of days since 1970 */ - curdays = time(NULL)/(60*60*24); - if((curdays < (spwdent->sp_lstchg + spwdent->sp_min)) - && (spwdent->sp_min != -1)) - retval |= PPW_TOOEARLY; - else if((curdays - > (spwdent->sp_lstchg + spwdent->sp_max + spwdent->sp_inact)) - && (spwdent->sp_max != -1) && (spwdent->sp_inact != -1)) - /* Their password change has been put off too long, - OR their account has just plain expired */ - retval |= PPW_EXPIRED; - else if((curdays > (spwdent->sp_lstchg + spwdent->sp_max)) - && (spwdent->sp_max != -1)) - /* Their passwd needs to be changed */ - retval |= PPW_EXPIRING; - else if((curdays > (spwdent->sp_lstchg - + spwdent->sp_max - spwdent->sp_warn)) - && (spwdent->sp_max != -1) && (spwdent->sp_warn != -1)) - retval |= PPW_WILLEXPIRE; -/* if(spwdent->sp_lstchg < 0) - retval &= ~(PPW_WILLEXPIRE | PPW_EXPIRING | PPW_EXPIRED); - if(spwdent->sp_max < 0) - retval &= ~(PPW_EXPIRING | PPW_EXPIRED); */ - } else { - *theirpass = (char *)x_strdup(pwd->pw_passwd); - } - -#else - *theirpass = (char *) x_strdup(pwd->pw_passwd); + return retval; + } + retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old); + pass_old = NULL; + if (retval != PAM_SUCCESS) { + _log_err(LOG_CRIT, pamh, + "failed to set PAM_OLDAUTHTOK"); + } + retval = _unix_verify_shadow(user, ctrl); + if (retval == PAM_AUTHTOK_ERR) { + if (off(UNIX__IAMROOT, ctrl)) + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + "You must wait longer to change your password"); + else + retval = PAM_SUCCESS; + } + } else if (on(UNIX__UPDATE, ctrl)) { + /* + * tpass is used below to store the _pam_md() return; it + * should be _pam_delete()'d. + */ + + char *tpass = NULL; + int retry = 0; + + /* + * obtain the proposed password + */ + + D(("do update")); + + /* + * get the old token back. NULL was ok only if root [at this + * point we assume that this has already been enforced on a + * previous call to this function]. + */ + + if (off(UNIX_NOT_SET_PASS, ctrl)) { + retval = pam_get_item(pamh, PAM_OLDAUTHTOK + ,(const void **) &pass_old); + } else { + retval = pam_get_data(pamh, _UNIX_OLD_AUTHTOK + ,(const void **) &pass_old); + if (retval == PAM_NO_MODULE_DATA) { + retval = PAM_SUCCESS; + pass_old = NULL; + } + } + D(("pass_old [%s]", pass_old)); + + if (retval != PAM_SUCCESS) { + _log_err(LOG_NOTICE, pamh, "user not authenticated"); +#ifdef USE_LCKPWDF + ulckpwdf(); +#endif + return retval; + } + retval = _unix_verify_shadow(user, ctrl); + if (retval != PAM_SUCCESS) { + _log_err(LOG_NOTICE, pamh, "user not authenticated 2"); +#ifdef USE_LCKPWDF + ulckpwdf(); +#endif + return retval; + } + D(("get new password now")); + + lctrl = ctrl; + + if (on(UNIX_USE_AUTHTOK, lctrl)) { + set(UNIX_USE_FIRST_PASS, lctrl); + } + retry = 0; + retval = PAM_AUTHTOK_ERR; + while ((retval != PAM_SUCCESS) && (retry++ < MAX_PASSWD_TRIES)) { + /* + * use_authtok is to force the use of a previously entered + * password -- needed for pluggable password strength checking + */ + + retval = _unix_read_password(pamh, lctrl + ,NULL + ,"Enter new UNIX password: " + ,"Retype new UNIX password: " + ,_UNIX_NEW_AUTHTOK + ,(const char **) &pass_new); + + if (retval != PAM_SUCCESS) { + if (on(UNIX_DEBUG, ctrl)) { + _log_err(LOG_ALERT, pamh + ,"password - new password not obtained"); + } + pass_old = NULL; /* tidy up */ +#ifdef USE_LCKPWDF + ulckpwdf(); +#endif + return retval; + } + D(("returned to _unix_chauthtok")); + + /* + * At this point we know who the user is and what they + * propose as their new password. Verify that the new + * password is acceptable. + */ + + if (pass_new[0] == '\0') { /* "\0" password = NULL */ + pass_new = NULL; + } + retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new); + } + + if (retval != PAM_SUCCESS) { + _log_err(LOG_NOTICE, pamh, + "new password not acceptable"); + _pam_overwrite(pass_new); + _pam_overwrite(pass_old); + pass_new = pass_old = NULL; /* tidy up */ +#ifdef USE_LCKPWDF + ulckpwdf(); +#endif + return retval; + } + /* + * By reaching here we have approved the passwords and must now + * rebuild the password database file. + */ + + /* + * First we encrypt the new password. + */ + + if (on(UNIX_MD5_PASS, ctrl)) { + tpass = crypt_md5_wrapper(pass_new); + } else { + /* + * Salt manipulation is stolen from Rick Faith's passwd + * program. Sorry Rick :) -- alex + */ + + time_t tm; + char salt[3]; + + time(&tm); + salt[0] = bin_to_ascii(tm & 0x3f); + salt[1] = bin_to_ascii((tm >> 6) & 0x3f); + salt[2] = '\0'; + + if (off(UNIX_BIGCRYPT, ctrl) && strlen(pass_new) > 8) { + /* + * to avoid using the _extensions_ of the bigcrypt() + * function we truncate the newly entered password + */ + char *temp = malloc(9); + char *e; + + if (temp == NULL) { + _log_err(LOG_CRIT, pamh, + "out of memory for password"); + _pam_overwrite(pass_new); + _pam_overwrite(pass_old); + pass_new = pass_old = NULL; /* tidy up */ +#ifdef USE_LCKPWDF + ulckpwdf(); #endif + return PAM_BUF_ERR; + } + /* copy first 8 bytes of password */ + strncpy(temp, pass_new, 8); + temp[8] = '\0'; + + /* no longer need cleartext */ + e = bigcrypt(temp, salt); + tpass = x_strdup(e); + + _pam_overwrite(e); + _pam_delete(temp); /* tidy up */ + } else { + char *e; + + /* no longer need cleartext */ + e = bigcrypt(pass_new, salt); + tpass = x_strdup(e); + + _pam_overwrite(e); + } + } + + D(("password processed")); + + /* update the password database(s) -- race conditions..? */ + + retval = _do_setpass(pamh, user, pass_old, tpass, ctrl, + remember); + _pam_overwrite(pass_new); + _pam_overwrite(pass_old); + _pam_delete(tpass); + pass_old = pass_new = NULL; + } else { /* something has broken with the module */ + _log_err(LOG_ALERT, pamh, + "password received unknown request"); + retval = PAM_ABORT; + } - return retval; -} + D(("retval was %d", retval)); -STATIC int conv_sendmsg(struct pam_conv *aconv, const char *message, int style) -{ - struct pam_message msg,*pmsg; - struct pam_response *resp; - int retval; - - /* Get the password from the user... */ - pmsg = &msg; - - msg.msg_style = style; - msg.msg = message; - resp = NULL; - - retval = aconv->conv(1, (const struct pam_message **) &pmsg, - &resp, aconv->appdata_ptr); - if (resp) { - _pam_drop_reply(resp, 1); - } - return retval; +#ifdef USE_LCKPWDF + ulckpwdf(); +#endif + return retval; } -STATIC int conv_getitem(struct pam_conv *aconv, char *message, int style, - char **result) -{ - struct pam_message msg,*pmsg; - struct pam_response *resp; - int retval; - - D(("called.")); - - /* Get the password from the user... */ - pmsg = &msg; - msg.msg_style = style; - msg.msg = message; - resp = NULL; - - retval = aconv->conv(1, (const struct pam_message **) &pmsg, - &resp, aconv->appdata_ptr); - if(retval != PAM_SUCCESS) - return retval; - if(resp != NULL) { - *result = resp->resp; free(resp); - return PAM_SUCCESS; - } - else - return PAM_SERVICE_ERR; -} +/* static module data */ +#ifdef PAM_STATIC +struct pam_module _pam_unix_passwd_modstruct = { + "pam_unix_passwd", + NULL, + NULL, + NULL, + NULL, + NULL, + pam_sm_chauthtok, +}; +#endif + diff --git a/contrib/libpam/modules/pam_unix/pam_unix_sess.c b/contrib/libpam/modules/pam_unix/pam_unix_sess.c index 319b2ed6288e..d0785006772c 100644 --- a/contrib/libpam/modules/pam_unix/pam_unix_sess.c +++ b/contrib/libpam/modules/pam_unix/pam_unix_sess.c @@ -1,9 +1,8 @@ -/* - * $Header: /home/morgan/pam/Linux-PAM-0.53/modules/pam_unix/RCS/pam_unix_sess.c,v 1.1 1996/11/09 19:44:35 morgan Exp $ - */ - /* + * $Id: pam_unix_sess.c,v 1.3 2000/12/20 05:15:05 vorlon Exp $ + * * Copyright Alexander O. Yuriev, 1996. All rights reserved. + * Copyright Jan Rêkorajski, 1999. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,145 +36,106 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * $Log: pam_unix_sess.c,v $ - * Revision 1.1 1996/11/09 19:44:35 morgan - * Initial revision - * - * Revision 1.4 1996/05/21 03:55:17 morgan - * added "const" to definition of rcsid[] - * - * Revision 1.3 1996/04/23 16:32:28 alex - * nothing really got changed. - * - * Revision 1.2 1996/04/19 03:23:33 alex - * session code implemented. account management moved into pam_unix_acct.c - * - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <pwd.h> +#include <security/_pam_aconf.h> -#ifndef LINUX /* AGM added this as of 0.2 */ +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <syslog.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> - #include <security/pam_appl.h> +/* indicate the following groups are defined */ -#endif /* ditto */ +#define PAM_SM_SESSION +#include <security/_pam_macros.h> #include <security/pam_modules.h> -#include <syslog.h> -#include <unistd.h> -#ifndef LOG_AUTHPRIV -#define LOG_AUTHPRIV LOG_AUTH -#endif - -static const char rcsid[] = "$Id: pam_unix_sess.c,v 1.1 1996/11/09 19:44:35 morgan Exp $ pam_unix session management. alex@bach.cis.temple.edu"; - -/* Define internal functions */ -static int _get_log_level( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ); - -int _pam_unix_open_session( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ); +#ifndef LINUX_PAM +#include <security/pam_appl.h> +#endif /* LINUX_PAM */ -int _pam_unix_close_session( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ); +#include "support.h" -/* Implementation */ +/* + * PAM framework looks for these entry-points to pass control to the + * session module. + */ -static int _get_log_level( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ) +PAM_EXTERN int pam_sm_open_session(pam_handle_t * pamh, int flags, + int argc, const char **argv) { - int i = argc; - int log_level = LOG_DEBUG; - - while ( i-- ) - { - if ( strcmp( *argv, "debug" ) == 0 ) - log_level = LOG_DEBUG; - else if ( strcmp ( *argv, "trace" ) == 0 ) - log_level = LOG_AUTHPRIV; - argv++; - } - - return log_level; -} + char *user_name, *service; + unsigned int ctrl; + int retval; + + D(("called.")); + + ctrl = _set_ctrl(pamh, flags, NULL, argc, argv); + + retval = pam_get_item(pamh, PAM_USER, (void *) &user_name); + if (user_name == NULL || retval != PAM_SUCCESS) { + _log_err(LOG_CRIT, pamh, + "open_session - error recovering username"); + return PAM_SESSION_ERR; /* How did we get authenticated with + no username?! */ + } + retval = pam_get_item(pamh, PAM_SERVICE, (void *) &service); + if (service == NULL || retval != PAM_SUCCESS) { + _log_err(LOG_CRIT, pamh, + "open_session - error recovering service"); + return PAM_SESSION_ERR; + } + _log_err(LOG_INFO, pamh, "session opened for user %s by %s(uid=%d)" + ,user_name + ,PAM_getlogin() == NULL ? "" : PAM_getlogin(), getuid()); -int _pam_unix_open_session( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ) -{ - int log_level; - char *user_name, *service; - - - log_level = _get_log_level( pamh, flags, argc, argv ); - - pam_get_item( pamh, PAM_USER, (void*) &user_name ); - if ( !user_name ) - return PAM_CONV_ERR; /* How did we get authenticated with - no username?! */ - - pam_get_item( pamh, PAM_SERVICE, (void*) &service ); - if ( !service ) - return PAM_CONV_ERR; - - syslog ( log_level, - "pam_unix authentication session started, user %s, service %s\n", - user_name, service ); - return PAM_SUCCESS; } -int _pam_unix_close_session( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ) +PAM_EXTERN int pam_sm_close_session(pam_handle_t * pamh, int flags, + int argc, const char **argv) { - int log_level; - char *user_name, *service; - - log_level = _get_log_level( pamh, flags, argc, argv ); - - pam_get_item( pamh, PAM_USER, (void*) &user_name ); - if ( !user_name ) - return PAM_CONV_ERR; /* How did we get authenticated with - no username?! */ - - pam_get_item( pamh, PAM_SERVICE, (void*) &service ); - if ( !service ) - return PAM_CONV_ERR; - - syslog ( log_level, - "pam_unix authentication session finished, user %s, service %s\n", - user_name, service ); - - return PAM_SUCCESS; -} + char *user_name, *service; + unsigned int ctrl; + int retval; + + D(("called.")); + + ctrl = _set_ctrl(pamh, flags, NULL, argc, argv); + + retval = pam_get_item(pamh, PAM_USER, (void *) &user_name); + if (user_name == NULL || retval != PAM_SUCCESS) { + _log_err(LOG_CRIT, pamh, + "close_session - error recovering username"); + return PAM_SESSION_ERR; /* How did we get authenticated with + no username?! */ + } + retval = pam_get_item(pamh, PAM_SERVICE, (void *) &service); + if (service == NULL || retval != PAM_SUCCESS) { + _log_err(LOG_CRIT, pamh, + "close_session - error recovering service"); + return PAM_SESSION_ERR; + } + _log_err(LOG_INFO, pamh, "session closed for user %s" + ,user_name); -int pam_sm_open_session( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ) -{ - return _pam_unix_open_session( pamh, flags, argc, argv ) ; + return PAM_SUCCESS; } -int pam_sm_close_session(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - return _pam_unix_close_session( pamh, flags, argc, argv ) ; -} +/* static module data */ +#ifdef PAM_STATIC +struct pam_module _pam_unix_session_modstruct = { + "pam_unix_session", + NULL, + NULL, + NULL, + pam_sm_open_session, + pam_sm_close_session, + NULL, +}; +#endif diff --git a/contrib/libpam/modules/pam_unix/support.c b/contrib/libpam/modules/pam_unix/support.c index a2fafcd2c13e..f7d221f18006 100644 --- a/contrib/libpam/modules/pam_unix/support.c +++ b/contrib/libpam/modules/pam_unix/support.c @@ -1,152 +1,882 @@ /* - * $Header: /home/morgan/pam/Linux-PAM-0.53/modules/pam_unix/RCS/support.c,v 1.1 1996/11/09 19:44:35 morgan Exp $ + * $Id: support.c,v 1.8 2001/02/11 06:33:53 agmorgan Exp $ + * + * Copyright information at end of file. */ - + +#define _BSD_SOURCE + +#include <stdlib.h> +#include <unistd.h> +#include <stdarg.h> +#include <string.h> +#include <malloc.h> +#include <pwd.h> +#include <shadow.h> +#include <limits.h> +#include <utmp.h> + +#include <security/_pam_macros.h> +#include <security/pam_modules.h> + +#include "md5.h" +#include "support.h" + +extern char *crypt(const char *key, const char *salt); +extern char *bigcrypt(const char *key, const char *salt); + +/* syslogging function for errors and other information */ + +void _log_err(int err, pam_handle_t *pamh, const char *format,...) +{ + char *service = NULL; + char logname[256]; + va_list args; + + pam_get_item(pamh, PAM_SERVICE, (const void **) &service); + if (service) { + strncpy(logname, service, sizeof(logname)); + logname[sizeof(logname) - 1 - strlen("(pam_unix)")] = '\0'; + strncat(logname, "(pam_unix)", strlen("(pam_unix)")); + } else { + strncpy(logname, "pam_unix", sizeof(logname) - 1); + } + + va_start(args, format); + openlog(logname, LOG_CONS | LOG_PID, LOG_AUTH); + vsyslog(err, format, args); + va_end(args); + closelog(); +} + +/* this is a front-end for module-application conversations */ + +static int converse(pam_handle_t * pamh, int ctrl, int nargs + ,struct pam_message **message + ,struct pam_response **response) +{ + int retval; + struct pam_conv *conv; + + D(("begin to converse")); + + retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv); + if (retval == PAM_SUCCESS) { + + retval = conv->conv(nargs, (const struct pam_message **) message + ,response, conv->appdata_ptr); + + D(("returned from application's conversation function")); + + if (retval != PAM_SUCCESS && on(UNIX_DEBUG, ctrl)) { + _log_err(LOG_DEBUG, pamh, "conversation failure [%s]" + ,pam_strerror(pamh, retval)); + } + } else if (retval != PAM_CONV_AGAIN) { + _log_err(LOG_ERR, pamh + ,"couldn't obtain coversation function [%s]" + ,pam_strerror(pamh, retval)); + } + D(("ready to return from module conversation")); + + return retval; /* propagate error status */ +} + +int _make_remark(pam_handle_t * pamh, unsigned int ctrl + ,int type, const char *text) +{ + int retval = PAM_SUCCESS; + + if (off(UNIX__QUIET, ctrl)) { + struct pam_message *pmsg[1], msg[1]; + struct pam_response *resp; + + pmsg[0] = &msg[0]; + msg[0].msg = text; + msg[0].msg_style = type; + + resp = NULL; + retval = converse(pamh, ctrl, 1, pmsg, &resp); + + if (resp) { + _pam_drop_reply(resp, 1); + } + } + return retval; +} + + /* + * Beacause getlogin() is braindead and sometimes it just + * doesn't work, we reimplement it here. + */ +char *PAM_getlogin(void) +{ + struct utmp *ut, line; + char *curr_tty, *retval; + static char curr_user[sizeof(ut->ut_user) + 4]; + + retval = NULL; + + curr_tty = ttyname(0); + if (curr_tty != NULL) { + D(("PAM_getlogin ttyname: %s", curr_tty)); + curr_tty += 5; + setutent(); + strncpy(line.ut_line, curr_tty, sizeof line.ut_line); + if ((ut = getutline(&line)) != NULL) { + strncpy(curr_user, ut->ut_user, sizeof(ut->ut_user)); + retval = curr_user; + } + endutent(); + } + D(("PAM_getlogin retval: %s", retval)); + + return retval; +} + /* - * Copyright Andrew Morgan, 1996. All rights reserved. - * Modified by Alexander O. Yuriev - * - * 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, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * ALTERNATIVELY, this product may be distributed under the terms of - * the GNU Public License, in which case the provisions of the GPL are - * required INSTEAD OF the above restrictions. (This clause is - * necessary due to a potential bad interaction between the GPL and - * the restrictions contained in a BSD-style copyright.) - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + * set the control flags for the UNIX module. */ +int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int argc, + const char **argv) +{ + unsigned int ctrl; + + D(("called.")); + + ctrl = UNIX_DEFAULTS; /* the default selection of options */ + + /* set some flags manually */ + + if (getuid() == 0 && !(flags & PAM_CHANGE_EXPIRED_AUTHTOK)) { + D(("IAMROOT")); + set(UNIX__IAMROOT, ctrl); + } + if (flags & PAM_UPDATE_AUTHTOK) { + D(("UPDATE_AUTHTOK")); + set(UNIX__UPDATE, ctrl); + } + if (flags & PAM_PRELIM_CHECK) { + D(("PRELIM_CHECK")); + set(UNIX__PRELIM, ctrl); + } + if (flags & PAM_DISALLOW_NULL_AUTHTOK) { + D(("DISALLOW_NULL_AUTHTOK")); + set(UNIX__NONULL, ctrl); + } + if (flags & PAM_SILENT) { + D(("SILENT")); + set(UNIX__QUIET, ctrl); + } + /* now parse the arguments to this module */ + + while (argc-- > 0) { + int j; + + D(("pam_unix arg: %s", *argv)); + + for (j = 0; j < UNIX_CTRLS_; ++j) { + if (unix_args[j].token + && !strncmp(*argv, unix_args[j].token, strlen(unix_args[j].token))) { + break; + } + } + + if (j >= UNIX_CTRLS_) { + _log_err(LOG_ERR, pamh, + "unrecognized option [%s]", *argv); + } else { + ctrl &= unix_args[j].mask; /* for turning things off */ + ctrl |= unix_args[j].flag; /* for turning things on */ + + if (remember != NULL) { + if (j == UNIX_REMEMBER_PASSWD) { + *remember = strtol(*argv + 9, NULL, 10); + if ((*remember == LONG_MIN) || (*remember == LONG_MAX)) + *remember = -1; + if (*remember > 400) + *remember = 400; + } + } + } + + ++argv; /* step to next argument */ + } + + /* auditing is a more sensitive version of debug */ + + if (on(UNIX_AUDIT, ctrl)) { + set(UNIX_DEBUG, ctrl); + } + /* return the set of flags */ + + D(("done.")); + return ctrl; +} + +static void _cleanup(pam_handle_t * pamh, void *x, int error_status) +{ + _pam_delete(x); +} + +/* ************************************************************** * + * Useful non-trivial functions * + * ************************************************************** */ + + /* + * the following is used to keep track of the number of times a user fails + * to authenticate themself. + */ + +#define FAIL_PREFIX "-UN*X-FAIL-" +#define UNIX_MAX_RETRIES 3 + +struct _pam_failed_auth { + char *user; /* user that's failed to be authenticated */ + char *name; /* attempt from user with name */ + int uid; /* uid of calling user */ + int euid; /* euid of calling process */ + int count; /* number of failures so far */ +}; + +#ifndef PAM_DATA_REPLACE +#error "Need to get an updated libpam 0.52 or better" +#endif + +static void _cleanup_failures(pam_handle_t * pamh, void *fl, int err) +{ + int quiet; + const char *service = NULL; + const char *ruser = NULL; + const char *rhost = NULL; + const char *tty = NULL; + struct _pam_failed_auth *failure; + + D(("called")); + + quiet = err & PAM_DATA_SILENT; /* should we log something? */ + err &= PAM_DATA_REPLACE; /* are we just replacing data? */ + failure = (struct _pam_failed_auth *) fl; + + if (failure != NULL) { + + if (!quiet && !err) { /* under advisement from Sun,may go away */ + + /* log the number of authentication failures */ + if (failure->count > 1) { + (void) pam_get_item(pamh, PAM_SERVICE, + (const void **)&service); + (void) pam_get_item(pamh, PAM_RUSER, + (const void **)&ruser); + (void) pam_get_item(pamh, PAM_RHOST, + (const void **)&rhost); + (void) pam_get_item(pamh, PAM_TTY, + (const void **)&tty); + _log_err(LOG_NOTICE, pamh, + "%d more authentication failure%s; " + "logname=%s uid=%d euid=%d " + "tty=%s ruser=%s rhost=%s " + "%s%s", + failure->count - 1, failure->count == 2 ? "" : "s", + failure->name, failure->uid, failure->euid, + tty ? tty : "", ruser ? ruser : "", + rhost ? rhost : "", + (failure->user && failure->user[0] != '\0') + ? " user=" : "", failure->user + ); + + if (failure->count > UNIX_MAX_RETRIES) { + _log_err(LOG_ALERT, pamh + ,"service(%s) ignoring max retries; %d > %d" + ,service == NULL ? "**unknown**" : service + ,failure->count + ,UNIX_MAX_RETRIES); + } + } + } + _pam_delete(failure->user); /* tidy up */ + _pam_delete(failure->name); /* tidy up */ + free(failure); + } +} + /* - * $Log: support.c,v $ - * Revision 1.1 1996/11/09 19:44:35 morgan - * Initial revision - * - * Revision 1.1 1996/04/17 01:11:08 alex - * Initial revision + * _unix_blankpasswd() is a quick check for a blank password * + * returns TRUE if user does not have a password + * - to avoid prompting for one in such cases (CG) */ - -#include <stdlib.h> /* define NULL */ -#ifndef LINUX +int _unix_blankpasswd(unsigned int ctrl, const char *name) +{ + struct passwd *pwd = NULL; + struct spwd *spwdent = NULL; + char *salt = NULL; + int retval; - #include <security/pam_appl.h> + D(("called")); -#endif /* LINUX */ + /* + * This function does not have to be too smart if something goes + * wrong, return FALSE and let this case to be treated somewhere + * else (CG) + */ -#include <security/pam_modules.h> + if (on(UNIX__NONULL, ctrl)) + return 0; /* will fail but don't let on yet */ + + /* UNIX passwords area */ + pwd = getpwnam(name); /* Get password file entry... */ + + if (pwd != NULL) { + if (strcmp( pwd->pw_passwd, "*NP*" ) == 0) + { /* NIS+ */ + uid_t save_euid, save_uid; + + save_euid = geteuid(); + save_uid = getuid(); + if (save_uid == pwd->pw_uid) + setreuid( save_euid, save_uid ); + else { + setreuid( 0, -1 ); + if (setreuid( -1, pwd->pw_uid ) == -1) { + setreuid( -1, 0 ); + setreuid( 0, -1 ); + if(setreuid( -1, pwd->pw_uid ) == -1) + /* Will fail elsewhere. */ + return 0; + } + } + + spwdent = getspnam( name ); + if (save_uid == pwd->pw_uid) + setreuid( save_uid, save_euid ); + else { + if (setreuid( -1, 0 ) == -1) + setreuid( save_uid, -1 ); + setreuid( -1, save_euid ); + } + } else if (strcmp(pwd->pw_passwd, "x") == 0) { + /* + * ...and shadow password file entry for this user, + * if shadowing is enabled + */ + spwdent = getspnam(name); + } + if (spwdent) + salt = x_strdup(spwdent->sp_pwdp); + else + salt = x_strdup(pwd->pw_passwd); + } + /* Does this user have a password? */ + if (salt == NULL) { + retval = 0; + } else { + if (strlen(salt) == 0) + retval = 1; + else + retval = 0; + } + /* tidy up */ -#ifndef NDEBUG + if (salt) + _pam_delete(salt); - #include <syslog.h> + return retval; +} -#endif /* NDEBUG */ +/* + * verify the password of a user + */ + +#include <sys/types.h> +#include <sys/wait.h> + +static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd, + unsigned int ctrl, const char *user) +{ + int retval, child, fds[2]; + D(("called.")); + /* create a pipe for the password */ + if (pipe(fds) != 0) { + D(("could not make pipe")); + return PAM_AUTH_ERR; + } -/* Phototype declarations */ + /* fork */ + child = fork(); + if (child == 0) { + static char *envp[] = { NULL }; + char *args[] = { NULL, NULL, NULL }; -int converse( pam_handle_t *pamh, - int nargs, - struct pam_message **message, - struct pam_response **response ); + /* XXX - should really tidy up PAM here too */ -int _set_auth_tok( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ); + /* reopen stdin as pipe */ + close(fds[1]); + dup2(fds[0], STDIN_FILENO); -/* Implementation */ + /* exec binary helper */ + args[0] = x_strdup(CHKPWD_HELPER); + args[1] = x_strdup(user); -int converse( pam_handle_t *pamh, - int nargs, - struct pam_message **message, - struct pam_response **response ) + execve(CHKPWD_HELPER, args, envp); + /* should not get here: exit with error */ + D(("helper binary is not available")); + exit(PAM_AUTHINFO_UNAVAIL); + } else if (child > 0) { + /* wait for child */ + /* if the stored password is NULL */ + if (off(UNIX__NONULL, ctrl)) { /* this means we've succeeded */ + write(fds[1], "nullok\0\0", 8); + } else { + write(fds[1], "nonull\0\0", 8); + } + if (passwd != NULL) { /* send the password to the child */ + write(fds[1], passwd, strlen(passwd)+1); + passwd = NULL; + } else { + write(fds[1], "", 1); /* blank password */ + } + close(fds[0]); /* close here to avoid possible SIGPIPE above */ + close(fds[1]); + (void) waitpid(child, &retval, 0); /* wait for helper to complete */ + retval = (retval == 0) ? PAM_SUCCESS:PAM_AUTH_ERR; + } else { + D(("fork failed")); + retval = PAM_AUTH_ERR; + } + + D(("returning %d", retval)); + return retval; +} + +int _unix_verify_password(pam_handle_t * pamh, const char *name + ,const char *p, unsigned int ctrl) { + struct passwd *pwd = NULL; + struct spwd *spwdent = NULL; + char *salt = NULL; + char *pp = NULL; + char *data_name; int retval; - struct pam_conv *conv; - retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ; - if ( retval == PAM_SUCCESS ) - { - retval = conv->conv( nargs, - ( const struct pam_message ** ) message, - response, - conv->appdata_ptr ); - } + D(("called")); + +#ifdef HAVE_PAM_FAIL_DELAY + if (off(UNIX_NODELAY, ctrl)) { + D(("setting delay")); + (void) pam_fail_delay(pamh, 2000000); /* 2 sec delay for on failure */ + } +#endif + + /* locate the entry for this user */ + + D(("locating user's record")); + + /* UNIX passwords area */ + pwd = getpwnam(name); /* Get password file entry... */ + + if (pwd != NULL) { + if (strcmp( pwd->pw_passwd, "*NP*" ) == 0) + { /* NIS+ */ + uid_t save_euid, save_uid; + + save_euid = geteuid(); + save_uid = getuid(); + if (save_uid == pwd->pw_uid) + setreuid( save_euid, save_uid ); + else { + setreuid( 0, -1 ); + if (setreuid( -1, pwd->pw_uid ) == -1) { + setreuid( -1, 0 ); + setreuid( 0, -1 ); + if(setreuid( -1, pwd->pw_uid ) == -1) + return PAM_CRED_INSUFFICIENT; + } + } + + spwdent = getspnam( name ); + if (save_uid == pwd->pw_uid) + setreuid( save_uid, save_euid ); + else { + if (setreuid( -1, 0 ) == -1) + setreuid( save_uid, -1 ); + setreuid( -1, save_euid ); + } + } else if (strcmp(pwd->pw_passwd, "x") == 0) { + /* + * ...and shadow password file entry for this user, + * if shadowing is enabled + */ + spwdent = getspnam(name); + } + if (spwdent) + salt = x_strdup(spwdent->sp_pwdp); + else + salt = x_strdup(pwd->pw_passwd); + } + + data_name = (char *) malloc(sizeof(FAIL_PREFIX) + strlen(name)); + if (data_name == NULL) { + _log_err(LOG_CRIT, pamh, "no memory for data-name"); + } else { + strcpy(data_name, FAIL_PREFIX); + strcpy(data_name + sizeof(FAIL_PREFIX) - 1, name); + } + + retval = PAM_SUCCESS; + if (pwd == NULL || salt == NULL || !strcmp(salt, "x")) { + if (geteuid()) { + /* we are not root perhaps this is the reason? Run helper */ + D(("running helper binary")); + retval = _unix_run_helper_binary(pamh, p, ctrl, name); + if (pwd == NULL && !on(UNIX_AUDIT,ctrl) + && retval != PAM_SUCCESS) + { + name = NULL; + } + } else { + D(("user's record unavailable")); + if (on(UNIX_AUDIT, ctrl)) { + /* this might be a typo and the user has given a password + instead of a username. Careful with this. */ + _log_err(LOG_ALERT, pamh, + "check pass; user (%s) unknown", name); + } else { + name = NULL; + _log_err(LOG_ALERT, pamh, + "check pass; user unknown"); + } + p = NULL; + retval = PAM_AUTHINFO_UNAVAIL; + } + } else { + if (!strlen(salt)) { + /* the stored password is NULL */ + if (off(UNIX__NONULL, ctrl)) { /* this means we've succeeded */ + D(("user has empty password - access granted")); + retval = PAM_SUCCESS; + } else { + D(("user has empty password - access denied")); + retval = PAM_AUTH_ERR; + } + } else if (!p) { + retval = PAM_AUTH_ERR; + } else { + if (!strncmp(salt, "$1$", 3)) { + pp = Goodcrypt_md5(p, salt); + if (strcmp(pp, salt) != 0) { + pp = Brokencrypt_md5(p, salt); + } + } else { + pp = bigcrypt(p, salt); + } + p = NULL; /* no longer needed here */ + + /* the moment of truth -- do we agree with the password? */ + D(("comparing state of pp[%s] and salt[%s]", pp, salt)); + + if (strcmp(pp, salt) == 0) { + retval = PAM_SUCCESS; + } else { + retval = PAM_AUTH_ERR; + } + } + } + + if (retval == PAM_SUCCESS) { + if (data_name) /* reset failures */ + pam_set_data(pamh, data_name, NULL, _cleanup_failures); + } else { + if (data_name != NULL) { + struct _pam_failed_auth *new = NULL; + const struct _pam_failed_auth *old = NULL; + + /* get a failure recorder */ + + new = (struct _pam_failed_auth *) + malloc(sizeof(struct _pam_failed_auth)); + + if (new != NULL) { + + new->user = x_strdup(name ? name : ""); + new->uid = getuid(); + new->euid = geteuid(); + new->name = x_strdup(PAM_getlogin()? PAM_getlogin() : ""); + + /* any previous failures for this user ? */ + pam_get_data(pamh, data_name, (const void **) &old); + + if (old != NULL) { + new->count = old->count + 1; + if (new->count >= UNIX_MAX_RETRIES) { + retval = PAM_MAXTRIES; + } + } else { + const char *service=NULL; + const char *ruser=NULL; + const char *rhost=NULL; + const char *tty=NULL; + + (void) pam_get_item(pamh, PAM_SERVICE, + (const void **)&service); + (void) pam_get_item(pamh, PAM_RUSER, + (const void **)&ruser); + (void) pam_get_item(pamh, PAM_RHOST, + (const void **)&rhost); + (void) pam_get_item(pamh, PAM_TTY, + (const void **)&tty); + + _log_err(LOG_NOTICE, pamh, + "authentication failure; " + "logname=%s uid=%d euid=%d " + "tty=%s ruser=%s rhost=%s " + "%s%s", + new->name, new->uid, new->euid, + tty ? tty : "", + ruser ? ruser : "", + rhost ? rhost : "", + (new->user && new->user[0] != '\0') + ? " user=" : "", + new->user + ); + new->count = 1; + } + + pam_set_data(pamh, data_name, new, _cleanup_failures); + + } else { + _log_err(LOG_CRIT, pamh, + "no memory for failure recorder"); + } + } + } + + if (data_name) + _pam_delete(data_name); + if (salt) + _pam_delete(salt); + if (pp) + _pam_overwrite(pp); + + D(("done [%d].", retval)); + return retval; } -/***************************************************************************/ -/* prompt user for a using conversation calls */ -/***************************************************************************/ +/* + * obtain a password from the user + */ -int _set_auth_tok( pam_handle_t *pamh, - int flags, int argc, - const char **argv ) +int _unix_read_password(pam_handle_t * pamh + ,unsigned int ctrl + ,const char *comment + ,const char *prompt1 + ,const char *prompt2 + ,const char *data_name + ,const char **pass) { - int retval; - char *p; - - struct pam_message msg[1],*pmsg[1]; - struct pam_response *resp; + int authtok_flag; + int retval; + const char *item; + char *token; + + D(("called")); + + /* + * make sure nothing inappropriate gets returned + */ + + *pass = token = NULL; + + /* + * which authentication token are we getting? + */ + + authtok_flag = on(UNIX__OLD_PASSWD, ctrl) ? PAM_OLDAUTHTOK : PAM_AUTHTOK; + + /* + * should we obtain the password from a PAM item ? + */ - /* set up conversation call */ + if (on(UNIX_TRY_FIRST_PASS, ctrl) || on(UNIX_USE_FIRST_PASS, ctrl)) { + retval = pam_get_item(pamh, authtok_flag, (const void **) &item); + if (retval != PAM_SUCCESS) { + /* very strange. */ + _log_err(LOG_ALERT, pamh + ,"pam_get_item returned error to unix-read-password" + ); + return retval; + } else if (item != NULL) { /* we have a password! */ + *pass = item; + item = NULL; + return PAM_SUCCESS; + } else if (on(UNIX_USE_FIRST_PASS, ctrl)) { + return PAM_AUTHTOK_RECOVER_ERR; /* didn't work */ + } else if (on(UNIX_USE_AUTHTOK, ctrl) + && off(UNIX__OLD_PASSWD, ctrl)) { + return PAM_AUTHTOK_RECOVER_ERR; + } + } + /* + * getting here implies we will have to get the password from the + * user directly. + */ - pmsg[0] = &msg[0]; - msg[0].msg_style = PAM_PROMPT_ECHO_OFF; - msg[0].msg = "Password: "; - resp = NULL; + { + struct pam_message msg[3], *pmsg[3]; + struct pam_response *resp; + int i, replies; - if ( ( retval = converse( pamh, 1 , pmsg, &resp ) ) != PAM_SUCCESS ) + /* prepare to converse */ + + if (comment != NULL && off(UNIX__QUIET, ctrl)) { + pmsg[0] = &msg[0]; + msg[0].msg_style = PAM_TEXT_INFO; + msg[0].msg = comment; + i = 1; + } else { + i = 0; + } + + pmsg[i] = &msg[i]; + msg[i].msg_style = PAM_PROMPT_ECHO_OFF; + msg[i++].msg = prompt1; + replies = 1; + + if (prompt2 != NULL) { + pmsg[i] = &msg[i]; + msg[i].msg_style = PAM_PROMPT_ECHO_OFF; + msg[i++].msg = prompt2; + ++replies; + } + /* so call the conversation expecting i responses */ + resp = NULL; + retval = converse(pamh, ctrl, i, pmsg, &resp); + + if (resp != NULL) { + + /* interpret the response */ + + if (retval == PAM_SUCCESS) { /* a good conversation */ + + token = x_strdup(resp[i - replies].resp); + if (token != NULL) { + if (replies == 2) { + + /* verify that password entered correctly */ + if (!resp[i - 1].resp + || strcmp(token, resp[i - 1].resp)) { + _pam_delete(token); /* mistyped */ + retval = PAM_AUTHTOK_RECOVER_ERR; + _make_remark(pamh, ctrl + ,PAM_ERROR_MSG, MISTYPED_PASS); + } + } + } else { + _log_err(LOG_NOTICE, pamh + ,"could not recover authentication token"); + } + + } + /* + * tidy up the conversation (resp_retcode) is ignored + * -- what is it for anyway? AGM + */ + + _pam_drop_reply(resp, i); + + } else { + retval = (retval == PAM_SUCCESS) + ? PAM_AUTHTOK_RECOVER_ERR : retval; + } + } + + if (retval != PAM_SUCCESS) { + if (on(UNIX_DEBUG, ctrl)) + _log_err(LOG_DEBUG, pamh, + "unable to obtain a password"); return retval; + } + /* 'token' is the entered password */ + + if (off(UNIX_NOT_SET_PASS, ctrl)) { + + /* we store this password as an item */ + + retval = pam_set_item(pamh, authtok_flag, token); + _pam_delete(token); /* clean it up */ + if (retval != PAM_SUCCESS + || (retval = pam_get_item(pamh, authtok_flag + ,(const void **) &item)) + != PAM_SUCCESS) { + + _log_err(LOG_CRIT, pamh, "error manipulating password"); + return retval; + + } + } else { + /* + * then store it as data specific to this module. pam_end() + * will arrange to clean it up. + */ + + retval = pam_set_data(pamh, data_name, (void *) token, _cleanup); + if (retval != PAM_SUCCESS) { + _log_err(LOG_CRIT, pamh + ,"error manipulating password data [%s]" + ,pam_strerror(pamh, retval)); + _pam_delete(token); + return retval; + } + item = token; + token = NULL; /* break link to password */ + } + + *pass = item; + item = NULL; /* break link to password */ - if ( resp ) - { - if ( ( flags & PAM_DISALLOW_NULL_AUTHTOK ) && - resp[0].resp == NULL ) - { - free( resp ); - return PAM_AUTH_ERR; - } - - p = resp[ 0 ].resp; - - /* This could be a memory leak. If resp[0].resp - is malloc()ed, then it has to be free()ed! - -- alex - */ - - resp[ 0 ].resp = NULL; - - } - else - return PAM_CONV_ERR; - - free( resp ); - pam_set_item( pamh, PAM_AUTHTOK, p ); return PAM_SUCCESS; } + +/* ****************************************************************** * + * Copyright (c) Jan Rêkorajski 1999. + * Copyright (c) Andrew G. Morgan 1996-8. + * Copyright (c) Alex O. Yuriev, 1996. + * Copyright (c) Cristian Gafton 1996. + * + * 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, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + */ diff --git a/contrib/libpam/modules/pam_unix/support.h b/contrib/libpam/modules/pam_unix/support.h new file mode 100644 index 000000000000..80f0b405d8bb --- /dev/null +++ b/contrib/libpam/modules/pam_unix/support.h @@ -0,0 +1,144 @@ +/* + * $Id: support.h,v 1.3 2000/12/20 05:15:05 vorlon Exp $ + */ + +#ifndef _PAM_UNIX_SUPPORT_H +#define _PAM_UNIX_SUPPORT_H + + +/* + * here is the string to inform the user that the new passwords they + * typed were not the same. + */ + +#define MISTYPED_PASS "Sorry, passwords do not match" + +/* type definition for the control options */ + +typedef struct { + const char *token; + unsigned int mask; /* shall assume 32 bits of flags */ + unsigned int flag; +} UNIX_Ctrls; + +/* + * macro to determine if a given flag is on + */ + +#define on(x,ctrl) (unix_args[x].flag & ctrl) + +/* + * macro to determine that a given flag is NOT on + */ + +#define off(x,ctrl) (!on(x,ctrl)) + +/* + * macro to turn on/off a ctrl flag manually + */ + +#define set(x,ctrl) (ctrl = ((ctrl)&unix_args[x].mask)|unix_args[x].flag) +#define unset(x,ctrl) (ctrl &= ~(unix_args[x].flag)) + +/* the generic mask */ + +#define _ALL_ON_ (~0U) + +/* end of macro definitions definitions for the control flags */ + +/* ****************************************************************** * + * ctrl flags proper.. + */ + +/* + * here are the various options recognized by the unix module. They + * are enumerated here and then defined below. Internal arguments are + * given NULL tokens. + */ + +#define UNIX__OLD_PASSWD 0 /* internal */ +#define UNIX__VERIFY_PASSWD 1 /* internal */ +#define UNIX__IAMROOT 2 /* internal */ + +#define UNIX_AUDIT 3 /* print more things than debug.. + some information may be sensitive */ +#define UNIX_USE_FIRST_PASS 4 +#define UNIX_TRY_FIRST_PASS 5 +#define UNIX_NOT_SET_PASS 6 /* don't set the AUTHTOK items */ + +#define UNIX__PRELIM 7 /* internal */ +#define UNIX__UPDATE 8 /* internal */ +#define UNIX__NONULL 9 /* internal */ +#define UNIX__QUIET 10 /* internal */ +#define UNIX_USE_AUTHTOK 11 /* insist on reading PAM_AUTHTOK */ +#define UNIX_SHADOW 12 /* signal shadow on */ +#define UNIX_MD5_PASS 13 /* force the use of MD5 passwords */ +#define UNIX__NULLOK 14 /* Null token ok */ +#define UNIX_DEBUG 15 /* send more info to syslog(3) */ +#define UNIX_NODELAY 16 /* admin does not want a fail-delay */ +#define UNIX_NIS 17 /* wish to use NIS for pwd */ +#define UNIX_BIGCRYPT 18 /* use DEC-C2 crypt()^x function */ +#define UNIX_LIKE_AUTH 19 /* need to auth for setcred to work */ +#define UNIX_REMEMBER_PASSWD 20 /* Remember N previous passwords */ +/* -------------- */ +#define UNIX_CTRLS_ 21 /* number of ctrl arguments defined */ + + +static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = +{ +/* symbol token name ctrl mask ctrl * + * ----------------------- ------------------- --------------------- -------- */ + +/* UNIX__OLD_PASSWD */ {NULL, _ALL_ON_, 01}, +/* UNIX__VERIFY_PASSWD */ {NULL, _ALL_ON_, 02}, +/* UNIX__IAMROOT */ {NULL, _ALL_ON_, 04}, +/* UNIX_AUDIT */ {"audit", _ALL_ON_, 010}, +/* UNIX_USE_FIRST_PASS */ {"use_first_pass", _ALL_ON_^(060), 020}, +/* UNIX_TRY_FIRST_PASS */ {"try_first_pass", _ALL_ON_^(060), 040}, +/* UNIX_NOT_SET_PASS */ {"not_set_pass", _ALL_ON_, 0100}, +/* UNIX__PRELIM */ {NULL, _ALL_ON_^(0600), 0200}, +/* UNIX__UPDATE */ {NULL, _ALL_ON_^(0600), 0400}, +/* UNIX__NONULL */ {NULL, _ALL_ON_, 01000}, +/* UNIX__QUIET */ {NULL, _ALL_ON_, 02000}, +/* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 04000}, +/* UNIX_SHADOW */ {"shadow", _ALL_ON_, 010000}, +/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(0400000), 020000}, +/* UNIX__NULLOK */ {"nullok", _ALL_ON_^(01000), 0}, +/* UNIX_DEBUG */ {"debug", _ALL_ON_, 040000}, +/* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0100000}, +/* UNIX_NIS */ {"nis", _ALL_ON_^(010000), 0200000}, +/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(020000), 0400000}, +/* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000}, +/* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000}, +}; + +#define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag) + + +/* use this to free strings. ESPECIALLY password strings */ + +#define _pam_delete(xx) \ +{ \ + _pam_overwrite(xx); \ + _pam_drop(xx); \ +} + +extern char *PAM_getlogin(void); +extern void _log_err(int err, pam_handle_t *pamh, const char *format,...); +extern int _make_remark(pam_handle_t * pamh, unsigned int ctrl + ,int type, const char *text); +extern int _set_ctrl(pam_handle_t * pamh, int flags, int *remember, int argc, + const char **argv); +extern int _unix_blankpasswd(unsigned int ctrl, const char *name); +extern int _unix_verify_password(pam_handle_t * pamh, const char *name + ,const char *p, unsigned int ctrl); +extern int _unix_read_password(pam_handle_t * pamh + ,unsigned int ctrl + ,const char *comment + ,const char *prompt1 + ,const char *prompt2 + ,const char *data_name + ,const char **pass); + +#endif /* _PAM_UNIX_SUPPORT_H */ + diff --git a/contrib/libpam/modules/pam_unix/unix_chkpwd.c b/contrib/libpam/modules/pam_unix/unix_chkpwd.c new file mode 100644 index 000000000000..e232e759453c --- /dev/null +++ b/contrib/libpam/modules/pam_unix/unix_chkpwd.c @@ -0,0 +1,314 @@ +/* + * $Id: unix_chkpwd.c,v 1.3 2001/02/11 06:33:53 agmorgan Exp $ + * + * This program is designed to run setuid(root) or with sufficient + * privilege to read all of the unix password databases. It is designed + * to provide a mechanism for the current user (defined by this + * process' uid) to verify their own password. + * + * The password is read from the standard input. The exit status of + * this program indicates whether the user is authenticated or not. + * + * Copyright information is located at the end of the file. + * + */ + +#include <security/_pam_aconf.h> + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <unistd.h> +#include <sys/types.h> +#include <pwd.h> +#include <shadow.h> +#include <signal.h> + +#define MAXPASS 200 /* the maximum length of a password */ + +#include <security/_pam_macros.h> + +#include "md5.h" + +extern char *crypt(const char *key, const char *salt); +extern char *bigcrypt(const char *key, const char *salt); + +#define UNIX_PASSED 0 +#define UNIX_FAILED 1 + +/* syslogging function for errors and other information */ + +static void _log_err(int err, const char *format,...) +{ + va_list args; + + va_start(args, format); + openlog("unix_chkpwd", LOG_CONS | LOG_PID, LOG_AUTH); + vsyslog(err, format, args); + va_end(args); + closelog(); +} + +static void su_sighandler(int sig) +{ + if (sig > 0) { + _log_err(LOG_NOTICE, "caught signal %d.", sig); + exit(sig); + } +} + +static void setup_signals(void) +{ + struct sigaction action; /* posix signal structure */ + + /* + * Setup signal handlers + */ + (void) memset((void *) &action, 0, sizeof(action)); + action.sa_handler = su_sighandler; + action.sa_flags = SA_RESETHAND; + (void) sigaction(SIGILL, &action, NULL); + (void) sigaction(SIGTRAP, &action, NULL); + (void) sigaction(SIGBUS, &action, NULL); + (void) sigaction(SIGSEGV, &action, NULL); + action.sa_handler = SIG_IGN; + action.sa_flags = 0; + (void) sigaction(SIGTERM, &action, NULL); + (void) sigaction(SIGHUP, &action, NULL); + (void) sigaction(SIGINT, &action, NULL); + (void) sigaction(SIGQUIT, &action, NULL); +} + +static int _unix_verify_password(const char *name, const char *p, int opt) +{ + struct passwd *pwd = NULL; + struct spwd *spwdent = NULL; + char *salt = NULL; + char *pp = NULL; + int retval = UNIX_FAILED; + + /* UNIX passwords area */ + setpwent(); + pwd = getpwnam(name); /* Get password file entry... */ + endpwent(); + if (pwd != NULL) { + if (strcmp(pwd->pw_passwd, "x") == 0) { + /* + * ...and shadow password file entry for this user, + * if shadowing is enabled + */ + setspent(); + spwdent = getspnam(name); + endspent(); + if (spwdent != NULL) + salt = x_strdup(spwdent->sp_pwdp); + else + pwd = NULL; + } else { + if (strcmp(pwd->pw_passwd, "*NP*") == 0) { /* NIS+ */ + uid_t save_uid; + + save_uid = geteuid(); + seteuid(pwd->pw_uid); + spwdent = getspnam(name); + seteuid(save_uid); + + salt = x_strdup(spwdent->sp_pwdp); + } else { + salt = x_strdup(pwd->pw_passwd); + } + } + } + if (pwd == NULL || salt == NULL) { + _log_err(LOG_ALERT, "check pass; user unknown"); + p = NULL; + return retval; + } + + if (strlen(salt) == 0) + return (opt == 0) ? UNIX_FAILED : UNIX_PASSED; + + /* the moment of truth -- do we agree with the password? */ + retval = UNIX_FAILED; + if (!strncmp(salt, "$1$", 3)) { + pp = Goodcrypt_md5(p, salt); + if (strcmp(pp, salt) == 0) { + retval = UNIX_PASSED; + } else { + pp = Brokencrypt_md5(p, salt); + if (strcmp(pp, salt) == 0) + retval = UNIX_PASSED; + } + } else { + pp = bigcrypt(p, salt); + if (strcmp(pp, salt) == 0) { + retval = UNIX_PASSED; + } + } + p = NULL; /* no longer needed here */ + + /* clean up */ + { + char *tp = pp; + if (pp != NULL) { + while (tp && *tp) + *tp++ = '\0'; + } + pp = tp = NULL; + } + + return retval; +} + +static char *getuidname(uid_t uid) +{ + struct passwd *pw; + static char username[32]; + + pw = getpwuid(uid); + if (pw == NULL) + return NULL; + + memset(username, 0, 32); + strncpy(username, pw->pw_name, 32); + username[31] = '\0'; + + return username; +} + +int main(int argc, char *argv[]) +{ + char pass[MAXPASS + 1]; + char option[8]; + int npass, opt; + int force_failure = 0; + int retval = UNIX_FAILED; + char *user; + + /* + * Catch or ignore as many signal as possible. + */ + setup_signals(); + + /* + * we establish that this program is running with non-tty stdin. + * this is to discourage casual use. It does *NOT* prevent an + * intruder from repeatadly running this program to determine the + * password of the current user (brute force attack, but one for + * which the attacker must already have gained access to the user's + * account). + */ + + if (isatty(STDIN_FILENO)) { + + _log_err(LOG_NOTICE + ,"inappropriate use of Unix helper binary [UID=%d]" + ,getuid()); + fprintf(stderr + ,"This binary is not designed for running in this way\n" + "-- the system administrator has been informed\n"); + sleep(10); /* this should discourage/annoy the user */ + return UNIX_FAILED; + } + + /* + * determine the current user's name is + */ + user = getuidname(getuid()); + if (argc == 2) { + /* if the caller specifies the username, verify that user + matches it */ + if (strcmp(user, argv[1])) { + force_failure = 1; + } + } + + /* read the nollok/nonull option */ + + npass = read(STDIN_FILENO, option, 8); + + if (npass < 0) { + _log_err(LOG_DEBUG, "no option supplied"); + return UNIX_FAILED; + } else { + option[7] = '\0'; + if (strncmp(option, "nullok", 8) == 0) + opt = 1; + else + opt = 0; + } + + /* read the password from stdin (a pipe from the pam_unix module) */ + + npass = read(STDIN_FILENO, pass, MAXPASS); + + if (npass < 0) { /* is it a valid password? */ + + _log_err(LOG_DEBUG, "no password supplied"); + + } else if (npass >= MAXPASS) { + + _log_err(LOG_DEBUG, "password too long"); + + } else { + if (npass == 0) { + /* the password is NULL */ + + retval = _unix_verify_password(user, NULL, opt); + + } else { + /* does pass agree with the official one? */ + + pass[npass] = '\0'; /* NUL terminate */ + retval = _unix_verify_password(user, pass, opt); + + } + } + + memset(pass, '\0', MAXPASS); /* clear memory of the password */ + + /* return pass or fail */ + + if ((retval != UNIX_PASSED) || force_failure) { + return UNIX_FAILED; + } else { + return UNIX_PASSED; + } +} + +/* + * Copyright (c) Andrew G. Morgan, 1996. 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, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + */ diff --git a/contrib/libpam/modules/pam_unix/yppasswd.h b/contrib/libpam/modules/pam_unix/yppasswd.h new file mode 100644 index 000000000000..6b414be09a57 --- /dev/null +++ b/contrib/libpam/modules/pam_unix/yppasswd.h @@ -0,0 +1,51 @@ +/* + * yppasswdd + * Copyright 1994, 1995, 1996 Olaf Kirch, <okir@monad.swb.de> + * + * This program is covered by the GNU General Public License, version 2. + * It is provided in the hope that it is useful. However, the author + * disclaims ALL WARRANTIES, expressed or implied. See the GPL for details. + * + * This file was generated automatically by rpcgen from yppasswd.x, and + * editied manually. + */ + +#ifndef _YPPASSWD_H_ +#define _YPPASSWD_H_ + +#define YPPASSWDPROG ((u_long)100009) +#define YPPASSWDVERS ((u_long)1) +#define YPPASSWDPROC_UPDATE ((u_long)1) + +/* + * The password struct passed by the update call. I renamed it to + * xpasswd to avoid a type clash with the one defined in <pwd.h>. + */ +#ifndef __sgi +typedef struct xpasswd { + char *pw_name; + char *pw_passwd; + int pw_uid; + int pw_gid; + char *pw_gecos; + char *pw_dir; + char *pw_shell; +} xpasswd; + +#else +#include <pwd.h> +typedef struct xpasswd xpasswd; +#endif + +/* The updated password information, plus the old password. + */ +typedef struct yppasswd { + char *oldpass; + xpasswd newpw; +} yppasswd; + +/* XDR encoding/decoding routines */ +bool_t xdr_xpasswd(XDR * xdrs, xpasswd * objp); +bool_t xdr_yppasswd(XDR * xdrs, yppasswd * objp); + +#endif /* _YPPASSWD_H_ */ diff --git a/contrib/libpam/modules/pam_unix/yppasswd_xdr.c b/contrib/libpam/modules/pam_unix/yppasswd_xdr.c new file mode 100644 index 000000000000..b1a60b4ce11e --- /dev/null +++ b/contrib/libpam/modules/pam_unix/yppasswd_xdr.c @@ -0,0 +1,38 @@ +/* + * yppasswdd + * Copyright 1994, 1995, 1996 Olaf Kirch, <okir@monad.swb.de> + * + * This program is covered by the GNU General Public License, version 2. + * It is provided in the hope that it is useful. However, the author + * disclaims ALL WARRANTIES, expressed or implied. See the GPL for details. + * + * This file was generated automatically by rpcgen from yppasswd.x, and + * editied manually. + */ + +#include <security/_pam_aconf.h> + +#include <rpc/rpc.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> +#include "yppasswd.h" + +bool_t +xdr_xpasswd(XDR * xdrs, xpasswd * objp) +{ + return xdr_string(xdrs, &objp->pw_name, ~0) + && xdr_string(xdrs, &objp->pw_passwd, ~0) + && xdr_int(xdrs, &objp->pw_uid) + && xdr_int(xdrs, &objp->pw_gid) + && xdr_string(xdrs, &objp->pw_gecos, ~0) + && xdr_string(xdrs, &objp->pw_dir, ~0) + && xdr_string(xdrs, &objp->pw_shell, ~0); +} + + +bool_t +xdr_yppasswd(XDR * xdrs, yppasswd * objp) +{ + return xdr_string(xdrs, &objp->oldpass, ~0) + && xdr_xpasswd(xdrs, &objp->newpw); +} diff --git a/contrib/libpam/modules/pam_userdb/Makefile b/contrib/libpam/modules/pam_userdb/Makefile new file mode 100644 index 000000000000..ebdcff9cd335 --- /dev/null +++ b/contrib/libpam/modules/pam_userdb/Makefile @@ -0,0 +1,35 @@ +# +# This Makefile controls a build process of $(TITLE) module for +# Linux-PAM. You should not modify this Makefile (unless you know +# what you are doing!). + +# $Id: Makefile,v 1.4 2001/02/18 03:03:31 agmorgan Exp $ +# Created by Cristian Gafton <gafton@redhat.com> + +include ../../Make.Rules + +TITLE=pam_userdb + +ifeq ($(HAVE_NDBM_H),yes) + WHICH_DB=ndbm + MODULE_SIMPLE_EXTRALIBS = -lndbm +else +ifeq ($(HAVE_LIBDB),yes) + WHICH_DB=db + MODULE_SIMPLE_EXTRALIBS = -ldb +else + WHICH_DB=none +endif +endif + +ifeq ($(WHICH_DB),none) + +include ../dont_makefile + +else + +MODULE_SIMPLE_EXTRAFILES = conv + +include ../Simple.Rules + +endif diff --git a/contrib/libpam/modules/pam_userdb/README b/contrib/libpam/modules/pam_userdb/README new file mode 100644 index 000000000000..af78d47b1309 --- /dev/null +++ b/contrib/libpam/modules/pam_userdb/README @@ -0,0 +1,30 @@ +pam_userdb: + Look up users in a .db database and verify their password against + what is contained in that database. + +RECOGNIZED ARGUMENTS: + debug write a message to syslog indicating success or + failure. + + db=[path] use the [path] database for performing lookup. There + is no default; the module will return PAM_IGNORE if + no database is provided. + + icase make the password verification to be case insensitive + (ie when working with registration numbers and such) + + dump dump all the entries in the database to the log (eek, + don't do this by default!) + +MODULE SERVICES PROVIDED: + auth _authetication and _setcred (blank) + +EXAMPLE USE: + auth sufficient pam_userdb.so icase db=/tmp/dbtest.db + +AUTHOR: + Cristian Gafton <gafton@redhat.com> + + + +$Id: README,v 1.1.1.1 2000/06/20 22:12:09 agmorgan Exp $ diff --git a/contrib/libpam/modules/pam_userdb/conv.c b/contrib/libpam/modules/pam_userdb/conv.c new file mode 100644 index 000000000000..0f13d03a4fc4 --- /dev/null +++ b/contrib/libpam/modules/pam_userdb/conv.c @@ -0,0 +1,125 @@ +/* + * Conversation related functions + */ + +/* $Id */ +/* Copyright at the end of the file */ + +#define _BSD_SOURCE + +#include <stdlib.h> +#include <string.h> + +#include <security/pam_modules.h> +#include <security/_pam_macros.h> + +#include "pam_userdb.h" + +/* + * dummy conversation function sending exactly one prompt + * and expecting exactly one response from the other party + */ +static int converse(pam_handle_t *pamh, + struct pam_message **message, + struct pam_response **response) +{ + int retval; + const struct pam_conv *conv; + + retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv ) ; + if (retval == PAM_SUCCESS) + retval = conv->conv(1, (const struct pam_message **)message, + response, conv->appdata_ptr); + + return retval; /* propagate error status */ +} + + +static char *_pam_delete(register char *xx) +{ + _pam_overwrite(xx); + _pam_drop(xx); + return NULL; +} + +/* + * This is a conversation function to obtain the user's password + */ +int conversation(pam_handle_t *pamh) +{ + struct pam_message msg[2],*pmsg[2]; + struct pam_response *resp; + int retval; + char * token = NULL; + + pmsg[0] = &msg[0]; + msg[0].msg_style = PAM_PROMPT_ECHO_OFF; + msg[0].msg = "Password: "; + + /* so call the conversation expecting i responses */ + resp = NULL; + retval = converse(pamh, pmsg, &resp); + + if (resp != NULL) { + const char * item; + /* interpret the response */ + if (retval == PAM_SUCCESS) { /* a good conversation */ + token = x_strdup(resp[0].resp); + if (token == NULL) { + return PAM_AUTHTOK_RECOVER_ERR; + } + } + + /* set the auth token */ + retval = pam_set_item(pamh, PAM_AUTHTOK, token); + token = _pam_delete(token); /* clean it up */ + if ( (retval != PAM_SUCCESS) || + (retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&item)) + != PAM_SUCCESS ) { + return retval; + } + + _pam_drop_reply(resp, 1); + } else { + retval = (retval == PAM_SUCCESS) + ? PAM_AUTHTOK_RECOVER_ERR:retval ; + } + + return retval; +} + +/* + * Copyright (c) Cristian Gafton <gafton@redhat.com>, 1999 + * 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, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + */ diff --git a/contrib/libpam/modules/pam_userdb/create.pl b/contrib/libpam/modules/pam_userdb/create.pl new file mode 100644 index 000000000000..0e1687dfef65 --- /dev/null +++ b/contrib/libpam/modules/pam_userdb/create.pl @@ -0,0 +1,23 @@ +#!/usr/bin/perl +# this program creates a database in ARGV[1] from pairs given on +# stdandard input +# +# $Id: create.pl,v 1.1.1.1 2000/06/20 22:12:09 agmorgan Exp $ + +use DB_File; + +my $database = $ARGV[0]; +die "Use: check,pl <database>\n" unless ($database); +print "Using database: $database\n"; + +my %lusers = (); + +tie %lusers, 'DB_File', $database, O_RDWR|O_CREAT, 0644, $DB_HASH ; +while (<STDIN>) { + my ($user, $pass) = split; + + $lusers{$user} = $pass; +} +untie %lusers; + + diff --git a/contrib/libpam/modules/pam_userdb/pam_userdb.c b/contrib/libpam/modules/pam_userdb/pam_userdb.c new file mode 100644 index 000000000000..9da93705e514 --- /dev/null +++ b/contrib/libpam/modules/pam_userdb/pam_userdb.c @@ -0,0 +1,304 @@ +/* pam_userdb module */ + +/* + * $Id: pam_userdb.c,v 1.4 2000/12/04 15:02:16 baggins Exp $ + * Written by Cristian Gafton <gafton@redhat.com> 1996/09/10 + * See the end of the file for Copyright Information + */ + +#include <security/_pam_aconf.h> + +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <syslog.h> +#include <stdarg.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + +#include "pam_userdb.h" + +#ifdef HAVE_NDBM_H +# include <ndbm.h> +#else +# ifdef HAVE_DB_H +# define DB_DBM_HSEARCH 1 /* use the dbm interface */ +# include <db.h> +# else +# error "failed to find a libdb or equivalent" +# endif +#endif + +/* + * here, we make a definition for the externally accessible function + * in this file (this definition is required for static a module + * but strongly encouraged generally) it is used to instruct the + * modules include file to define the function prototypes. + */ + +#define PAM_SM_AUTH +#define PAM_SM_ACCOUNT + +#include <security/pam_modules.h> + +/* some syslogging */ + +static void _pam_log(int err, const char *format, ...) +{ + va_list args; + + va_start(args, format); + openlog(MODULE_NAME, LOG_CONS|LOG_PID, LOG_AUTH); + vsyslog(err, format, args); + va_end(args); + closelog(); +} + +char * database = NULL; +static int ctrl = 0; + +static int _pam_parse(int argc, const char **argv) +{ + /* step through arguments */ + for (ctrl = 0; argc-- > 0; ++argv) { + + /* generic options */ + + if (!strcmp(*argv,"debug")) + ctrl |= PAM_DEBUG_ARG; + else if (!strcasecmp(*argv, "icase")) + ctrl |= PAM_ICASE_ARG; + else if (!strcasecmp(*argv, "dump")) + ctrl |= PAM_DUMP_ARG; + else if (!strncasecmp(*argv,"db=", 3)) { + database = strdup((*argv) + 3); + if (database == NULL) + _pam_log(LOG_ERR, "pam_parse: could not parse argument \"%s\"", + *argv); + } else { + _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv); + } + } + + return ctrl; +} + + +/* + * Looks up an user name in a database and checks the password + * + * return values: + * 1 = User not found + * 0 = OK + * -1 = Password incorrect + * -2 = System error + */ +static int user_lookup(const char *user, const char *pass) +{ + DBM *dbm; + datum key, data; + + /* Open the DB file. */ + dbm = dbm_open(database, O_RDONLY, 0644); + if (dbm == NULL) { + _pam_log(LOG_ERR, "user_lookup: could not open database `%s'", + database); + return -2; + } + + if (ctrl &PAM_DUMP_ARG) { + _pam_log(LOG_INFO, "Database dump:"); + for (key = dbm_firstkey(dbm); key.dptr != NULL; + key = dbm_nextkey(dbm)) { + data = dbm_fetch(dbm, key); + _pam_log(LOG_INFO, "key[len=%d] = `%s', data[len=%d] = `%s'", + key.dsize, key.dptr, data.dsize, data.dptr); + } + } + /* do some more init work */ + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + key.dptr = x_strdup(user); + key.dsize = strlen(user); + user = NULL; + + if (key.dptr) { + data = dbm_fetch(dbm, key); + memset(key.dptr, 0, key.dsize); + free(key.dptr); + } + + if (ctrl & PAM_DEBUG_ARG) { + _pam_log(LOG_INFO, "password in database is [%p]`%s', len is %d", + data.dptr, (char *) data.dptr, data.dsize); + } + + if (data.dptr != NULL) { + int compare = 0; + /* bingo, got it */ + if (ctrl & PAM_ICASE_ARG) + compare = strncasecmp(pass, data.dptr, data.dsize); + else + compare = strncmp(pass, data.dptr, data.dsize); + dbm_close(dbm); + if (compare == 0) + return 0; /* match */ + else + return -1; /* wrong */ + } else { + if (ctrl & PAM_DEBUG_ARG) { + _pam_log(LOG_INFO, "error returned by dbm_fetch: %s", + strerror(errno)); + } + dbm_close(dbm); + /* probably we should check dbm_error() here */ + return 1; /* not found */ + } + + /* NOT REACHED */ + return -2; +} + +/* --- authentication management functions (only) --- */ + +PAM_EXTERN +int pam_sm_authenticate(pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + const char *username; + const char *password; + int retval = PAM_AUTH_ERR; + + /* parse arguments */ + ctrl = _pam_parse(argc, argv); + + /* Get the username */ + retval = pam_get_user(pamh, &username, NULL); + if ((retval != PAM_SUCCESS) || (!username)) { + if (ctrl & PAM_DEBUG_ARG) + _pam_log(LOG_DEBUG,"can not get the username"); + return PAM_SERVICE_ERR; + } + + /* Converse just to be sure we have the password */ + retval = conversation(pamh); + if (retval != PAM_SUCCESS) { + _pam_log(LOG_ERR, "could not obtain password for `%s'", + username); + return -2; + } + + /* Get the password */ + retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&password); + if (retval != PAM_SUCCESS) { + _pam_log(LOG_ERR, "Could not retrive user's password"); + return -2; + } + + if (ctrl & PAM_DEBUG_ARG) + _pam_log(LOG_INFO, "Verify user `%s' with password `%s'", + username, password); + + /* Now use the username to look up password in the database file */ + retval = user_lookup(username, password); + switch (retval) { + case -2: + /* some sort of system error. The log was already printed */ + return PAM_SERVICE_ERR; + case -1: + /* incorrect password */ + _pam_log(LOG_WARNING, + "user `%s' denied access (incorrect password)", + username); + return PAM_AUTH_ERR; + case 1: + /* the user does not exist in the database */ + if (ctrl & PAM_DEBUG_ARG) + _pam_log(LOG_NOTICE, "user `%s' not found in the database", + username); + return PAM_USER_UNKNOWN; + case 0: + /* Otherwise, the authentication looked good */ + _pam_log(LOG_NOTICE, "user '%s' granted acces", username); + return PAM_SUCCESS; + default: + /* we don't know anything about this return value */ + _pam_log(LOG_ERR, + "internal module error (retval = %d, user = `%s'", + retval, username); + return PAM_SERVICE_ERR; + } + + /* should not be reached */ + return PAM_IGNORE; +} + +PAM_EXTERN +int pam_sm_setcred(pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + return PAM_SUCCESS; +} + +PAM_EXTERN +int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + return PAM_SUCCESS; +} + + +#ifdef PAM_STATIC + +/* static module data */ + +struct pam_module _pam_userdb_modstruct = { + "pam_userdb", + pam_sm_authenticate, + pam_sm_setcred, + NULL, + NULL, + NULL, + NULL, +}; + +#endif + +/* + * Copyright (c) Cristian Gafton <gafton@redhat.com>, 1999 + * 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, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + */ diff --git a/contrib/libpam/modules/pam_userdb/pam_userdb.h b/contrib/libpam/modules/pam_userdb/pam_userdb.h new file mode 100644 index 000000000000..542cdf57943f --- /dev/null +++ b/contrib/libpam/modules/pam_userdb/pam_userdb.h @@ -0,0 +1,61 @@ + +#ifndef _PAM_USERSDB_H +#define _PAM_USERSDB_H +/* $Id: pam_userdb.h,v 1.1.1.1 2000/06/20 22:12:09 agmorgan Exp $ */ + +/* Header files */ +#include <security/pam_appl.h> + +/* argument parsing */ +#define PAM_DEBUG_ARG 0x0001 +#define PAM_ICASE_ARG 0x0002 +#define PAM_DUMP_ARG 0x0004 + +/* Useful macros */ +#define x_strdup(s) ( (s) ? strdup(s):NULL ) + +/* The name of the module we are compiling */ +#ifndef MODULE_NAME +#define MODULE_NAME "pam_userdb" +#endif /* MODULE_NAME */ + +/* function prototypes */ +int conversation(pam_handle_t *); + +#endif /* _PAM_USERSDB_H */ + +/* + * Copyright (c) Cristian Gafton <gafton@redhat.com>, 1999 + * 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, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + */ diff --git a/contrib/libpam/modules/pam_warn/Makefile b/contrib/libpam/modules/pam_warn/Makefile index 167af5a370ac..b1420538d577 100644 --- a/contrib/libpam/modules/pam_warn/Makefile +++ b/contrib/libpam/modules/pam_warn/Makefile @@ -1,96 +1,15 @@ # -# $Id: Makefile,v 1.2 1997/04/05 06:20:16 morgan Exp $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:06 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.2 1997/04/05 06:20:16 morgan -# fixed fakeroot +# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27 # -# Revision 1.1 1996/12/01 03:12:22 morgan -# Initial revision -# -# -# Created by Andrew Morgan <morgan@parc.power.net> 1996/11/14 -# - -TITLE=pam_warn - -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### -dummy: +include ../../Make.Rules - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< +TITLE=pam_warn +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_warn/README b/contrib/libpam/modules/pam_warn/README index f45b271c0d77..3c4bde8af20d 100644 --- a/contrib/libpam/modules/pam_warn/README +++ b/contrib/libpam/modules/pam_warn/README @@ -1,4 +1,4 @@ -# $Id: README,v 1.1 1996/12/01 03:12:22 morgan Exp $ +# $Id: README,v 1.1.1.1 2000/06/20 22:12:10 agmorgan Exp $ # This module is an authentication module that does not authenticate. @@ -15,7 +15,10 @@ Recognized arguments: module services provided: - auth _autheticate and _setcred (blank) + auth _authenticate and _setcred (blank) + acct _acct_mgmt [mapped to _authenticate] + session _open_session and + _close_session [mapped to _authenticate ] password _chauthtok [mapped to _authenticate] diff --git a/contrib/libpam/modules/pam_warn/pam_warn.c b/contrib/libpam/modules/pam_warn/pam_warn.c index 2a0a23d6e989..a9bcc9e70c5c 100644 --- a/contrib/libpam/modules/pam_warn/pam_warn.c +++ b/contrib/libpam/modules/pam_warn/pam_warn.c @@ -1,20 +1,13 @@ /* pam_warn module */ /* - * $Id: pam_warn.c,v 1.2 1997/02/15 17:19:08 morgan Exp $ - * - * Written by Andrew Morgan <morgan@parc.power.net> 1996/3/11 - * - * $Log: pam_warn.c,v $ - * Revision 1.2 1997/02/15 17:19:08 morgan - * corrected many bugs and removed fixed buffer logging - * - * Revision 1.1 1996/12/01 03:12:22 morgan - * Initial revision - * + * $Id: pam_warn.c,v 1.1.1.1 2000/06/20 22:12:10 agmorgan Exp $ * + * Written by Andrew Morgan <morgan@linux.kernel.org> 1996/3/11 */ +#define _BSD_SOURCE + #include <stdio.h> #include <unistd.h> #include <syslog.h> @@ -93,18 +86,45 @@ int pam_sm_chauthtok(pam_handle_t *pamh,int flags,int argc return pam_sm_authenticate(pamh, flags, argc, argv); } +PAM_EXTERN int +pam_sm_acct_mgmt (pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + /* map to the authentication function... */ + + return pam_sm_authenticate(pamh, flags, argc, argv); +} + +PAM_EXTERN int +pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + /* map to the authentication function... */ + + return pam_sm_authenticate(pamh, flags, argc, argv); +} + +PAM_EXTERN int +pam_sm_close_session (pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + /* map to the authentication function... */ + + return pam_sm_authenticate(pamh, flags, argc, argv); +} + #ifdef PAM_STATIC /* static module data */ struct pam_module _pam_warn_modstruct = { - "pam_warn", - pam_sm_authenticate, - pam_sm_setcred, - NULL, - NULL, - NULL, - pam_sm_chauthtok, + "pam_warn", + pam_sm_authenticate, + pam_sm_setcred, + pam_sm_acct_mgmt, + pam_sm_open_session, + pam_sm_close_session, + pam_sm_chauthtok, }; #endif diff --git a/contrib/libpam/modules/pam_wheel/Makefile b/contrib/libpam/modules/pam_wheel/Makefile index 553e32199668..67947f814101 100644 --- a/contrib/libpam/modules/pam_wheel/Makefile +++ b/contrib/libpam/modules/pam_wheel/Makefile @@ -1,94 +1,15 @@ # +# $Id: Makefile,v 1.2 2000/11/19 23:54:06 agmorgan Exp $ +# # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# Created by Cristian Gafton <gafton@sorosis.ro> 1996/09/10 +# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27 # -ifeq ($(HAVE_PWDBLIB),yes) +include ../../Make.Rules TITLE=pam_wheel -CFLAGS += -DHAVE_PWDBLIB - -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -#LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -EXTRALS = -lpwdb - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -#static/%.o : %.c -# $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -#ifdef STATIC -#LIBSTATIC = lib$(TITLE).o -#endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -#ifdef STATIC -# $(MKDIR) ./static -#endif - -register: -#ifdef STATIC -# ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -#endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) $(EXTRALS) -endif - -#ifdef STATIC -#$(LIBOBJS): $(LIBSRC) -# -#$(LIBSTATIC): $(LIBOBJS) -# $(LD) -r -o $@ $(LIBOBJS) $(EXTRALS) -#endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ *.so - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< -else -include ../dont_makefile -endif +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_wheel/pam_wheel.c b/contrib/libpam/modules/pam_wheel/pam_wheel.c index db262d83d8c9..add72bc43f48 100644 --- a/contrib/libpam/modules/pam_wheel/pam_wheel.c +++ b/contrib/libpam/modules/pam_wheel/pam_wheel.c @@ -21,20 +21,16 @@ * a wheel member. */ +#define _BSD_SOURCE + #include <stdio.h> -#define __USE_BSD #include <unistd.h> #include <string.h> #include <syslog.h> #include <stdarg.h> #include <sys/types.h> -#ifdef HAVE_PWDBLIB -# include <pwdb/pwdb_public.h> -#else -# include <pwd.h> -# include <grp.h> -#endif - +#include <pwd.h> +#include <grp.h> /* * here, we make a definition for the externally accessible function @@ -47,9 +43,6 @@ #include <security/pam_modules.h> -/* variables */ -static char use_group[BUFSIZ]; - /* some syslogging */ static void _pam_log(int err, const char *format, ...) @@ -82,7 +75,7 @@ static int is_on_list(char * const *list, const char *member) #define PAM_TRUST_ARG 0x0004 #define PAM_DENY_ARG 0x0010 -static int _pam_parse(int argc, const char **argv) +static int _pam_parse(int argc, const char **argv, char *use_group) { int ctrl=0; @@ -122,11 +115,12 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc struct passwd *pwd, *tpwd; struct group *grp; int retval = PAM_AUTH_ERR; + char use_group[BUFSIZ]; /* Init the optional group */ - bzero(use_group,sizeof(use_group)); + bzero(use_group,BUFSIZ); - ctrl = _pam_parse(argc, argv); + ctrl = _pam_parse(argc, argv, use_group); retval = pam_get_user(pamh,&username,NULL); if ((retval != PAM_SUCCESS) || (!username)) { if (ctrl & PAM_DEBUG_ARG) @@ -171,10 +165,12 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc } } - if (!use_group[0]) - grp = getgrgid(0); - else - grp = getgrnam(use_group); + if (!use_group[0]) { + if ((grp = getgrnam("wheel")) == NULL) { + grp = getgrgid(0); + } + } else + grp = getgrnam(use_group); if (!grp || !grp->gr_mem) { if (ctrl & PAM_DEBUG_ARG) { |