diff --git a/contrib/libpam/CHANGELOG b/contrib/libpam/CHANGELOG index 99872a4704c..162625b07b2 100644 --- a/contrib/libpam/CHANGELOG +++ b/contrib/libpam/CHANGELOG @@ -1,24 +1,329 @@ -$Id$ +$Id: CHANGELOG,v 1.61 2001/04/08 06:17:04 agmorgan Exp $ ----------------------------- -0.66: whenever +TODO: -TODO - - need to supply a backward compatability path for syslog & friends - - need to make pam_system_log() thread safe. - - need to make logging fix available to non-Linux PAM libraries - - need to change modules to make use of new logging API. + - sanitize use of md5 throughout distribution.. Make a static + library for helping to develop modules that contains it and other + stuff. Also add sha-1 and ripemd-160 digest algorithms. + - once above is done. remove hacks from the secret@here module etc.. + - remove prototype for gethostname in pam_access.c (Derrick) - document PAM_INCOMPLETE changes - - document pam_system_log() changes - verify that the PAM_INCOMPLETE interface is sensible. Can we - catch errors? should we permit item changing etc between + catch errors? should we permit item changing etc., between pam_authenticate re-invocations? - - verify that the PAM_INCOMPLETE interface works - - add PAM_INCOMPLETE support to modules - - verify that + - verify that the PAM_INCOMPLETE interface works (auth seems ok..) + - add PAM_INCOMPLETE support to modules (partially added to pam_pwdb) - work on RFC. + - do we still need to remove openlog/closelog from modules..? + - auth and acct support in pam_cracklib, "yes, I know the password + you just typed was valid, I just don't think it was very strong..." + - add in the pam_cap and pam_netid modules + +==================================================================== +Note, as of release 0.73, all checkins should be accompanied with a +Bug ID. The bug IDs relate to sourceforge IDs.. You can query the +related bug description with the following URL: + + http://sourceforge.net/tracker/index.php?func=detail&aid=XXXXXX&group_id=6663&atid=106663 + +Where you should replace XXXXXX with a bug-id. + +If you have found a bug in Linux-PAM, please consider filing such a +bug report - outstanding bugs are listed here: + + http://sourceforge.net/tracker/?atid=106663&group_id=6663&func=browse + +(to file another bug see the 'submit bug' button on this page). + +==================================================================== + +0.76: please submit patches for this section with actual code/doc + patches! + +* + +0.75: Sat Apr 7 23:10:50 PDT 2001 + + ** WARNING ** + +This release contains backwardly incompatible changes to +libpam. Prior versions were buggy - see bugfix for Bug 129775. + + ** WARNING ** + +* made 0.75 release (Bug 414665 - agmorgan) +* pam_pwdb has been removed from the suggested pam.conf template. I've + replaced it with pam_unix. (Bug 227565 - agmorgan) +* pam_limits - Richard M. Yumul reported that " -" didn't + work, first fix suggested by Werner Puschitz (Bug 404953 - agmorgan) +* Nicolay Pelov suggested a simple fix for freebsd support (Bug 407282 + - agmorgan) +* Michel D'HOOGE submitted documentation fixes (Bug 408961 - agmorgan) +* fix for module linking directions (Bug 133545 - agmorgan) +* fix for glibc-2.2.2 compilation of pam_issue (Bug 133542 - agmorgan) +* fix pam_userdb to make and link both .o files it needs - converse() + wasn't being linked! (Bug 132880 - agmorgan) +* added some sys-admin documentation for the pam_tally module (Bug + 126210 - agmorgan). +* added a link to module examples from the module writers doc (Bug + 131192 - agmorgan). +* fixed a small security hole (more of a user confusion issue) with + the unix and pwdb password helper binaries. The beef is described in + the bug report, but no uid change was possible so no-one should + think they need to issue a security bulletin over this one! (Bug + 112540 - agmorgan) +* pam_lastlog needs to be linked with -lutil, also removed ambiguity + from sysadmin guide regarding this module being a 'session' module + (Bug 131549 - agmorgan). +* pam_cracklib needs to be linked with -lcrypt (old password checking) + (Bug 131601 - agmorgan). +* fixes for static library builds and also the examples when linked + with the debugging build of the libraries. (Bug 131783 - agmorgan) +* fixed URL for original RFC to a cached kernel.org file. (Bug 131503 + - agmorgan) +* quoted the $CRACKLIB_DICTPATH test in configure.in (Bug 130130 - + agmorgan). +* improved handling of the setcred/close_session and update chauthtok + stack. *Warning* This is a backwardly incompatable change, but 'more + sane' than before. (Bug 129775 - agmorgan) +* bumped the version number, and added some code to assist in making + documentation releases (Bug 129644 - agmorgan). + +0.74: Sun Jan 21 22:36:08 PST 2001 + +* made 0.74 release (Bug 129642 - agmorgan) +* libpam - cleaned up a few non-static functions to be static and added + support for libpam to enforce things like pam_[gs]et_data() and + AUTHTOK rules for using the API. Also documented pam_[gs]et_item() + a little better including return codes (Bugs 129027, 128576 - + agmorgan). +* pam_access - fixed the non-default config file option (Bug 127561 - + agmorgan) +* pam.8 manual page clarified with respect to the default location for + finding modules, also added some text describing the [...] control + syntax. (Bug 127625 - agmorgan) +* md5.h ia64 fixes for pam_unix and pam_pwdb (Bug 127700 - agmorgan) +* removed requirement for c++ from the configure{.in,} files (Bug + 128298 - agmorgan) +* removed subdirectories from man page redirections (124396 - baggins) +* per David Lee, fixed non-POSIX shell command in modules/pam_filter/Makefile + (Bug 126440 - vorlon) +* modify format of pam_unix log messages to include service name + (Bug 126423 - vorlon) +* prevent pam_unix from logging unknown usernames (Bug 126431 - vorlon) +* changed format of pam_unix 'authentication failure' log messages to make + them clearer and more consistent (Bug 126036 - vorlon) +* improved portability of pam_unix by eliminating Linux-specific utmp + defines in PAM_getlogin() (Bug 125704 - vorlon) +* removed static variables from pam_tally (Bug 117434 - agmorgan) +* added copyright message to pam_access module from original logdaemon + sources (Bug 125022 - agmorgan) +* configure.in - removed the GCC -Wtraditional flag (Bug 124923 - agmorgan) +* pam_mail - use PAM_PATH_MAILDIR as the location of mail spool + (Bug 124397 - baggins) +* _pam_aconf.h.in, configure.in - added PAM_PATH_MAILDIR set via + --with-mailspool=dir option (default is _PAM_MAILDIR if defined + in paths.h otherwise /var/spool/mail (Bug 124397 - baggins) +* removed unnecessary CVS Log tags from all over the source + (Bug 124391 - baggins) +* pam_tally - check for PAM_TTY if PAM_RHOST is not set when writing + to faillog (Bug 124394 - baggins) +* use O_NOFOLLOW if available when opening debug log (Bug 124385 - baggins) +* pam_cracklib - removed comments about pam_unix not working with + pam_cracklib, added information about use_authtok parameter + (Bug 124388 - baggins) +* pam_userdb - fixed wrong definition of struct pam_module (was pam_wheel) + (Bug 124386 - baggins) +* fixed example/Makefile include path (Bug 124187, 127563(?) - agmorgan) +* pam_userdb compiles on RH5x. Also removed circular dependency on + configure.in. Also bumped revision number to 0.74. (Bug 124136 - + agmorgan) + +0.73: Sat Dec 2 00:04:04 PST 2000 + +* updated documentaion revisions and added 'make release' support + to the top level Makefile (Bug 124132 - agmorgan). +* documented Qmail support in pam_mail (Bug 109219 - baggins) +* add change_uid option to pam_limits, and set real uid only if + this option is present (Bug 124062 - baggins) +* pam_limits - set real uid to the user for who we set limits. + (Bug 123972 - baggins) +* removed static variables from pam_limits (thread safe now). (Bug + 117450 - agmorgan). +* removed static variable from pam_wheel (module should be thread safe + now). (Bug 112906 - agmorgan) +* added support for '/' symbols in pam_time and pam_group config files + (support for modern terminal devices). Fixed infinite loop problem + with '\\[^\n]' in these files. (Bug 116076 - agmorgan) +* avoid potential SIGPIPE when writing to helper binaries with (Bug + 123399 - agmorgan) +* replaced bogus logic in the pam_cracklib module for determining if + the replacement is too similar to the old password (Bug 115055 - + agmorgan) +* added accessconf= feature to pam_access - request from + Aldrin Martoq and Meelis Roos (Bugs 111927,117240 - agmorgan) +* fix for pam_limit module not dealing with all limits Adam J. Richter + (Bug 119554 - agmorgan) +* comment fix describing fail_delay callback in _pam_types.h (Bug + 112646 - agmorgan) +* "likeauth" fix for pam_unix and pam_pwdb which (Bug 113596 - agmorgan) +* fix for pam_unix (support.c) to avoid segfault with NULL password + (Bug 113238 - vorlon) +* fix to pam_unix_passwd: try repeatedly to get a lock on the password + file, instead of failing immediately (Bug 108845 - fix vorlon) +* fix to pam_shells: logged information was not formatted correctly + (extra comma) (Bug 111491 - fix vorlon) +* fix for C++ application support (Bug 111645 - fix agmorgan) +* fix for typo in pam_client.h (Bug 111648 - fix agmorgan) +* removal of -lpam from pam_mkhomedir Makefile (Bug 116380 - fix agmorgan) +* autoconf support [Task ID 15788, Bug ID 108297 - agmorgan with help!] + - bugfix for libpamc.h include file [Bug ID 117476 - agmorgan] + - bugfix for pam_filter.h inclusion [Bug ID 117474 - agmorgan] + +0.72: Mon Dec 13 22:41:11 PST 1999 + +* patches from Debian (Ben Collins): pam_ftp supports event driven + conversations now; pwdb_chkpwd cleanup; pam_warn static compile fix; + user_db compiler warnings removed; debian defs file; pam_mail can + now be used as a session module +* ndbm compilation option for user_db module (fix explained by Richard Khoo) +* pam_cracklib bug fix +* packaging fixes & build from scratch stuff (Konst Bulatnikov & Frodo + Looijaard) +* -ldl appended to the libpam.so compilation make rule. (Charles Seeger) +* Red Hat security patch for pam_pwdb forwarded by Debian! (Ben + Collins. Fix provided by Andrey as it caught the problem earlier in the + code.) +* heuristic to prevent leaking filedescriptors to an agent. [This needs + to be better supported perhaps by an additional libpamc API function?] +* pam_userdb segfault fix from (Ben Collins) +* PAM draft spec extras added at request of 'sen_ml' + +0.71: Sun Nov 7 20:21:19 PST 1999 + +* added -lc to linker pass for pam_nologin module (glibc is weird). +* various header changes to lower the number of warnings on glibc + systems (Dan Yefimov) +* merged a bunch of Debian fixes/patches/documentation (Ben Collins) + things touched: libpam (minor); doc/modules/pam_unix.sgml; pam_env + (plus docs); pam_mkhomedir (new module for new home directories on + the fly...); pam_motd (new module); pam_limits (adjust to match + docs); pam_issue (new module + doc) [Some of these were also + submitted by Thorsten Kukuk] +* small hack to lower the number of warnings that pam_client.h was + generating. +* debian and SuSE apparently can use the pam_ftp module, so + removed the obsolete comment about this from the docs. (Thorsten + Kukuk) + +0.70: Fri Oct 8 22:05:30 PDT 1999 + +* bug fix for parsing of value=action tokens in libpam/pam_misc.c was + segfaulting (Jan Rekorajski and independently Matthew Melvin) +* numerous fixes from Thorsten Kukuk (icluding much needed fixes for + bitrot in modules and some documentation) that got included in SuSE 6.2. +* reentrancy issues in pam_unix and pam_cracklib resolved (Jan Rekorajski) +* added hosts_equiv_rootok module option to pam_rhosts module (Tim Berger) +* added comment about 'expose_account' module argument to admin and + module writers' docs (request from Michael K Johnson). +* myriad of bug fixes for libpamc - library now built by default and + works with the biomouse fingerprint scanner agent/module + (distributed separately). + +0.69: Sun Aug 1 20:25:37 PDT 1999 + +* c++ header #ifdef'ing for pam_appl.h (Tuomo Pyhala) +* added pam_userdb module (Cristian Gafton) +* minor documentation changes +* added in revised pam_client library (libpamc). Not installed by + default yet, since the example agent/module combo is not very secure. +* glibc fixes (Thorsten Kukuk, Adam J. Richter) + +0.68: Sun Jul 4 23:04:13 PDT 1999 + +* completely new pam_unix module from Jan Rekorajski and Stephen Langasek +* Jan Rekorajski pam_mail - support for Maildir format mailboxes +* Jan Rekorajski pam_cracklib - support for old password comparison +* Jan Rekorajski bug fix for pam_pwdb setcred reusing auth retval +* Andrey's pam_tally patch (lstat -> fstat) +* Robert Milkowski's additional pam_tally patches to **change format of + /var/log/faillog** to one from shadow-utils, add new option "per_user" + for pam_tally module, failure time logging, support for fail_line + field, and support for fail_locktime field with new option + no_lock_time. +* pam_tally: clean up the tally application too. +* Marcin Korzonek added process priority settings to pam_limits (bonus + points for adding to documentation!) +* Andrey's pam_pwdb patch (cleanup + md5 endian fubar fix) +* more binary prompt preparations (make misc conv more compatible with spec) +* modified callback hook for fail delay to be more useful with event + driven applications (changed function prototype - suspect no one + will notice). Documented this in app developer guide. +* documentation for pam_access from Tim Berger +* syntax fixes for the documentation - a long time since I've built it :*( + added some more names to the CREDITS file. + +0.67: Sat Jun 19 14:01:24 PDT 1999 + +* [dropped libpam_client - libpamc will be in the next release and + conforms to the developing spec in doc/specs/draft-morgan-pam.raw. + Sorry if you are keeping a PAM tree in CVS. CVS is a pain for + directories, but this directory was actually not referenced by + anything so the disruption should be light.] +* updates to pam_tally from Tim +* multiple updates from Stephen Langasek to pam_unix +* pam_filter had some trouble compiling (bug report from Sridhar) +* pam_wheel now attempts to identify the wheel group for the local + system instead of blindly assuming it is gid=0. In the case that + there is no "wheel" group, we default to assuming gid=0 is what was + meant - former behavior. (courtesy of Sridhar) +* NIS+ changes to pam_unix module from Dmitry O Panov +* hopefully, a fix for redefinition of LOG_AUTHPRIV (bug report Luke + Kenneth Casson Leighton) +* fix for minor typo in pam_wheel documentation (Jacek Kopecky) +* slightly more explanation of the [x=y] pam.conf syntax in the sys + admin guide. + +0.66: Mon Dec 28 20:22:23 PST 1998 + +* Started using cvs to keep track of changes to Linux-PAM. This will + likely break some of the automated building stuff (RPMs etc..). +* security bug fix to pam_unix and pam_tally from Andrey. +* modules make file is now more automatic. It should be possible to + unpack an external module in the modules directory and have it automatically + added to the build process. Also added a modules/download-all script + that will make such downloading easier. I'm happy to receive patches to + this file, informing the distribution of places from which to enrich itself. +* removed pam_system_log stuff. Thought about it long and hard: a + bad idea. If libc cannot guarantee a thread safe syslog, it needs + to be fixed and compatibility with other PAM libraries was + unnecessarily strained. +* SAG documentation changes: Seth Chaiklin +* rhosts: problems with NIS lookup failures with the root-uid check. + As a work-around, I've partially eliminated the need for the lookup + by supplying two new arguments: no_uid_check, superuser=. + As a general rule this is more pluggable, since this module might be + used as an authentication scheme for a network service that does not + need root privilege... +* authenticate retval -> setcred for pam_pwdb (likeauth arg). +* pam_pwdb event driven support +* non openlog pam_listfile logging +* BUGFIX: close filedescriptor in pam_group and pam_time (Emmanuel Galanos) +* Chris Adams' mailhash change for pam_mail module +* fixed malloc failure check in pam_handlers.c (follow up to comment + by Brad M. Garcia). +* update to _pam_compat.h (Brad M. Garcia) +* support static modules in libpam again (Brad M. Garcia) +* libpam/pam_misc.c for egcs to grok the code (Brad M. Garcia) +* added a solaris-2.5.1 defs file (revived by Derrick J Brashear) +* pam_listfile logs failed attempts +* added a comment (Michael K Johnson pointed it out) about sgml2latex + having a new syntax. I'll make it the change real when I upgrade... +* a little more text to the RFC, spelling fix from William J Buffam. +* minor changes to pam_securetty to accommodate event driven support. 0.65: Sun Apr 5 22:29:09 PDT 1998 diff --git a/contrib/libpam/Make.Rules.in b/contrib/libpam/Make.Rules.in new file mode 100644 index 00000000000..2818c1c97db --- /dev/null +++ b/contrib/libpam/Make.Rules.in @@ -0,0 +1,94 @@ +## +## $Id: Make.Rules.in,v 1.6 2001/02/10 22:33:09 agmorgan Exp $ +## +## @configure_input@ +## + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ + +absolute_srcdir = @LOCALSRCDIR@ + +# major and minor numbers of this release +MAJOR_REL=@LIBPAM_VERSION_MAJOR@ +MINOR_REL=@LIBPAM_VERSION_MINOR@ + +# The following is the generic set of compiler options for compiling +# Linux-PAM. True, they are a little anal. Pay attention to the comments +# they generate. + +HEADER_DIRS=-I./include -I$(absolute_srcdir)/libpam/include \ + -I$(absolute_srcdir) -I$(absolute_srcdir)/libpamc/include +WARNINGS=@WARNINGS@ +OS_CFLAGS=@OS_CFLAGS@ +PIC=@PIC@ + +# Mode to install shared libraries with +SHLIBMODE=@SHLIBMODE@ + +NEED_LINK_LIB_C=@PAM_NEEDS_LIBC@ +HAVE_LCKPWDF=@HAVE_LCKPWDF@ +HAVE_LIBCRACK=@HAVE_LIBCRACK@ +HAVE_LIBCRYPT=@HAVE_LIBCRYPT@ +HAVE_LIBUTIL=@HAVE_LIBUTIL@ +HAVE_NDBM_H=@HAVE_NDBM_H@ +HAVE_LIBNDBM=@HAVE_LIBNDBM@ +HAVE_LIBDB=@HAVE_LIBDB@ +HAVE_LIBFL=@HAVE_LIBFL@ +HAVE_LIBNSL=@HAVE_LIBNSL@ +HAVE_LIBPWDB=@HAVE_LIBPWDB@ + +# documentation support +HAVE_SGML2TXT=@HAVE_SGML2TXT@ +HAVE_SGML2HTML=@HAVE_SGML2HTML@ +PSER=@PSER@ + +# configuration settings +WITH_DEBUG=@WITH_DEBUG@ +WITH_LIBDEBUG=@WITH_LIBDEBUG@ +WITH_PAMLOCKING=@WITH_PAMLOCKING@ +WITH_LCKPWDF=@WITH_LCKPWDF@ +STATIC_LIBPAM=@STATIC_LIBPAM@ +DYNAMIC_LIBPAM=@DYNAMIC_LIBPAM@ +STATIC=@STATIC@ +DYNAMIC=@DYNAMIC@ + +# Location of libraries when installed on the system +FAKEROOT=@FAKEROOT@ +SECUREDIR=@SECUREDIR@ +SCONFIGD=@SCONFIGDIR@ +SUPLEMENTED=@SUPLEMENTED@ +INCLUDED=@INCLUDEDIR@/security +CRACKLIB_DICTPATH=@CRACKLIB_DICTPATH@ + +# generic build setup +OS=@OS@ +CC=@CC@ +CFLAGS=$(WARNINGS) -D$(OS) $(OS_CFLAGS) $(HEADER_DIRS) @CONF_CFLAGS@ +LD=@LD@ +LD_D=@LD_D@ +LD_L=@LD_L@ +DYNTYPE=@DYNTYPE@ +LIBDL=@LIBDL@ +MKDIR=@MKDIR@ +INSTALL=@INSTALL@ +RANLIB=@RANLIB@ +STRIP=@STRIP@ +CC_STATIC=@CC_STATIC@ + +LINKLIBS = $(NEED_LINK_LIB_C) $(LIBDL) diff --git a/contrib/libpam/Makefile b/contrib/libpam/Makefile index d25f58bb570..ad2eea2edc2 100644 --- a/contrib/libpam/Makefile +++ b/contrib/libpam/Makefile @@ -1,282 +1,78 @@ ## -## $Id: Makefile,v 1.31 1997/04/05 07:04:25 morgan Exp morgan $ -## -## $Log: Makefile,v $ -## +## $Id: Makefile,v 1.5 2001/01/20 22:29:47 agmorgan Exp $ ## -# major and minor numbers of this release -MAJOR_REL=0 -MINOR_REL=65 -DEBUG_REL=no -#DEBUG_REL=yes +## Note, ideally I would prefer it if this top level makefile did +## not get created by autoconf. As I find typing 'make' and relying +## on it to take care of all dependencies much more friendly than +## the multi-stage autoconf+make and also worry about updates to +## configure.in not getting propagated down the tree. (AGM) [I realise +## that this may not prove possible, but at least I tried.. Sigh.] -# this should be the name of this directory -RELNAME = Linux-PAM-$(MAJOR_REL).$(MINOR_REL) +DISTNAME=Linux-PAM -# this is the name of the archive file -DISTFILE = $(RELNAME).tar.gz - -# define this to indicate to subdirectories that they are part of the -# full source tree. -FULL_LINUX_PAM_SOURCE_TREE=yes -export FULL_LINUX_PAM_SOURCE_TREE - -DYNLOAD="dl" -DYNTYPE="so" - -# Comment out either line to disable that type of linking for *modules only* -# Both at once is a legal configuration! -DYNAMIC=-DPAM_DYNAMIC -#STATIC=-DPAM_STATIC - -# Comment out these lines to disable building dynamic/static libpam.* -DYNAMIC_LIBPAM=yes -#STATIC_LIBPAM=yes - -# All combinations of the above four variable definitions are legal, -# however, not defining either dynamic or static modules and yet -# creating a some flavor of LIBPAM will make an authentication library -# that always fails! - -# Here we indicate which libraries are present on the local system -# they control the building of some modules in this distribution -# Note, these definitions are all "export"ed below... - -HAVE_PWDBLIB=no -HAVE_CRACKLIB=no -HAVE_AFSLIBS=no -HAVE_KRBLIBS=no - -# NB. The following is the generic defines for compilation. -# They can be overridden in the default.defs file below -# -WARNINGS = -ansi -D_POSIX_SOURCE -Wall -Wwrite-strings \ - -Wpointer-arith -Wcast-qual -Wcast-align \ - -Wtraditional -Wstrict-prototypes -Wmissing-prototypes \ - -Wnested-externs -Winline -Wshadow -pedantic -PIC=-fPIC - -# Mode to install shared libraries with -SHLIBMODE=644 - -# -# Conditional defines.. -# - -ifdef DYNAMIC -# need the dynamic library functions -LIBDL=-l$(DYNLOAD) -ifdef STATIC_LIBPAM -# needed because pam_xxx() fn's are now in statically linked library -RDYNAMIC = -rdynamic -endif +ifeq ($(shell test \! -f Make.Rules || echo yes),yes) + include Make.Rules endif -# Here we include the defines for the preferred operating system -# these include things like CC, CFLAGS and destination directories -# etc.. By default, this is a symbolic link to one of the .defs files -# the .../defs/ directory. Please take a moment to check that you are -# using the correct one. +THINGSTOMAKE = modules libpam libpamc libpam_misc doc examples -include default.defs +all: $(THINGSTOMAKE) -# to turn on the fprintf(stderr, ..) debugging lines throughout the -# distribution uncomment this line -#EXTRAS += -DDEBUG - -# For serious memory allocation tracing uncomment the following -#MEMORY_DEBUG=-DMEMORY_DEBUG - -####################################################################### -# The pam_unix module in this file will not work on NIS based systems.# -####################################################################### - -# //////////////////////////////////////////////////// -# // You should not modify anything below this line // -# //////////////////////////////////////////////////// - -# the sub-directories to make things in - -DIRS = modules libpam conf libpam_misc examples - -# -# basic defines -# - -INCLUDEDIR=-I$(shell pwd)/include -PAMLIB=-L$(shell pwd)/libpam -PAMMISCLIB=-L$(shell pwd)/libpam_misc -ifeq ($(DEBUG_REL),yes) - PAMLIB += -lpamd - PAMMISCLIB += -lpamd_misc -else - PAMLIB += -lpam - PAMMISCLIB += -lpam_misc -endif - - -# This is Linux-PAM and not a version from Sun etc.. -# [Note, this does not describe the operating system you are using -# only that you are compiling the "Linux" (read FREE) implementation -# of Pluggable Authentication Modules. -EXTRAS += -DLINUX_PAM - -# -# build composite defines -# - -LOADLIBES = $(PAMLIB) $(RDYNAMIC) $(PAMMISCLIB) $(LIBDL) $(ULIBS) - -CFLAGS += $(EXTRAS) $(MEMORY_DEBUG) $(WARNINGS) $(INCLUDEDIR) $(PIC) -ifneq ($(strip $(OS)),) -CFLAGS += -D$(OS) -endif -ifneq ($(strip $(ARCH)),) -CFLAGS += -D$(ARCH) -endif - -# -# export the libraries-available info; the modules should know how -# to deal with this... -# -export HAVE_PWDBLIB -export HAVE_CRACKLIB -export HAVE_AFSLIBS -export HAVE_KRBLIBS - -# -# generic exports -# -export MAJOR_REL # the major release of this distribution -export MINOR_REL # the minor release of this distribution -export DEBUG_REL # for installing a debugging version of PAM -export OS # operating system -export ARCH # architecture -export CC # the C compiler -export INSTALL # to do instalations with -export MKDIR # to ensure directories exist -export CFLAGS # CC flags used to compile everything -export LD_D # build a shared object file (module) -export LD_L # build a shared library (e.g. libpam) -export USESONAME # does shlib link command require soname option -export SOSWITCH # shlib lib soname switch name -export NEEDSONAME # does shared library link need versioned lib -export LD # build a generic library -export LDCONFIG # rebuild the shared libraries -export AR # build a static library -export RANLIB # reorder a static library -export LOADLIBES # libraries needed for application linking -export PAMLIB # where to find the local libpam.xx file -export DYNTYPE # which suffix is used for libraries -export SHLIBMODE # file mode for shared objects -# -# where to install things -# -export FAKEROOT # for package maintainers -# -export PREFIX # basic prefix for all other directories -export SUPLEMENTED # where to store module helper binaries -export LIBDIR # where libpam and libpam_misc go -export SECUREDIR # where the modules will be placed -export INCLUDED # where to store pam---.h files -export CONFIGED # where pam.conf and pam.d/ go -export SCONFIGED # where modules' config files go - -# -# Conditional exporting ( ... these go on for a while... ) -# -ifdef DYNAMIC -export DYNAMIC -endif -ifdef STATIC -export STATIC -endif -ifdef DYNAMIC_LIBPAM -export DYNAMIC_LIBPAM -endif -ifdef STATIC_LIBPAM -export STATIC_LIBPAM -endif -ifdef MEMORY_DEBUG -export MEMORY_DEBUG -endif - -## -## the rules -## - -all: .freezemake - @for i in $(DIRS) ; do \ - $(MAKE) -C $$i all ; \ - if [ $$? -ne 0 ]; then break ; fi ; \ - done - -.freezemake: -# Do nothing - -.old_freezemake: Makefile - @touch .freezemake - @echo "*WARNING*: If you are running a system that is dependent" - @echo " on PAM to work. DO NOT make sterile NOR make remove." - @echo " These options will delete the PAM files on your system" - @echo " and make it unusable!" - @echo "" - @echo "If you are in any doubt, just do 'make all' (or just" - @echo "'make'). It is likely that this is the SAFEST thing to do...." - @exit 1 - -install: - @for i in $(DIRS) ; do \ - $(MAKE) -C $$i install ; \ - if [ $$? -ne 0 ]; then break ; fi ; \ - done - install ./doc/man/*.3 $(PREFIX)/man/man3/ - install ./doc/man/*.8 $(PREFIX)/man/man8/ - -sterile: .freezemake - @$(MAKE) remove - @$(MAKE) extraclean - -remove: .freezemake - @for i in $(DIRS) ; do \ - $(MAKE) -C $$i remove ; \ - done +prep: + rm -f security + ln -sf . security clean: - @rm -f *~ core - @for i in $(DIRS) ; do \ - $(MAKE) -C $$i clean ; \ - done + if [ ! -f Make.Rules ]; then touch Make.Rules ; fi + for i in $(THINGSTOMAKE) ; do $(MAKE) -C $$i clean ; done + rm -f security *~ *.orig *.rej Make.Rules #*# -extraclean: - @for i in $(DIRS) doc; do \ - $(MAKE) -C $$i extraclean ; \ - done +distclean: clean + rm -f Make.Rules _pam_aconf.h + rm -f config.status config.cache config.log core -check: - @$(MAKE) -C conf check +maintainer-clean: distclean + @echo files should be ok for packaging now. -RCScheck: - @$(MAKE) -C conf RCScheck +# NB _pam_aconf.h.in changes will remake this too +Make.Rules: configure Make.Rules.in _pam_aconf.h.in + @echo XXX - not sure how to preserve past configure options.. + @echo XXX - so not attempting to. Feel free to run ./configure + @echo XXX - by hand, with the options you want. + ./configure -# this can be used to see what hasn't been check'd into RCS +_pam_aconf.h: Make.Rules -open: - @find . \( -type f -a -perm 644 \) -print +configure: configure.in + @echo + @echo You do not appear to have an up-to-date ./configure file. + @echo Please run autoconf, and then ./configure [..options..] + @echo + @rm -f configure + @exit 1 + +$(THINGSTOMAKE): _pam_aconf.h prep + $(MAKE) -C $@ all + +install: _pam_aconf.h prep + $(MKDIR) $(FAKEROOT)$(INCLUDED) + $(INSTALL) -m 444 security/_pam_aconf.h $(FAKEROOT)$(INCLUDED) + for x in $(THINGSTOMAKE) ; do make -C $$x install ; done + +remove: + rm -f $(FAKEROOT)$(INCLUDED)/_pam_aconf.h + for x in $(THINGSTOMAKE) ; do make -C $$x remove ; done release: - @egrep '^DEBUG\_REL\=yes' Makefile|grep -v grep > /dev/null ;\ - if [ $$? -eq 0 ]; then \ - echo "You should first set DEBUG_REL to no" ; exit 1 ; fi - $(MAKE) extraclean - rm -f .freezemake - touch .filelist .RCSlist - chmod 600 .filelist .RCSlist - cd .. ; find $(RELNAME) \! -type d -print | fgrep -v RCS | fgrep -v 'conf/.md5sum' > $(RELNAME)/.filelist - cd .. ; find $(RELNAME) -type f -print | fgrep RCS | fgrep -v 'conf/.RCSsum' > $(RELNAME)/.RCSlist - chmod 400 .filelist .RCSlist - $(MAKE) check - $(MAKE) RCScheck - (cat .filelist ; echo $(RELNAME)/conf/.md5sum) | (cd .. ; tar -cz -f$(DISTFILE) -T-) - (cat .RCSlist ; echo $(RELNAME)/conf/.RCSsum) | (cd .. ; tar -cz -fRCS+$(DISTFILE) -T-) + @if [ ! -f Make.Rules ]; then echo make Make.Rules first ; exit 1; fi + @if [ ! -L ../$(DISTNAME)-$(MAJOR_REL).$(MINOR_REL) ]; then \ + echo generating ../$(DISTNAME)-$(MAJOR_REL).$(MINOR_REL) link ; \ + ln -sf $(DISTNAME) ../$(DISTNAME)-$(MAJOR_REL).$(MINOR_REL) ; \ + echo to ../$(DISTNAME) . ; fi + @diff ../$(DISTNAME)-$(MAJOR_REL).$(MINOR_REL)/Make.Rules Make.Rules + make distclean + cd .. ; tar zvfc $(DISTNAME)-$(MAJOR_REL).$(MINOR_REL).tar.gz \ + --exclude CVS --exclude .cvsignore --exclude '.#*' \ + $(DISTNAME)-$(MAJOR_REL).$(MINOR_REL)/* + diff --git a/contrib/libpam/README b/contrib/libpam/README index 78a428ef46d..1e769a5dba4 100644 --- a/contrib/libpam/README +++ b/contrib/libpam/README @@ -1,167 +1,28 @@ # -# $Id: README,v 1.14 1997/04/05 07:04:46 morgan Exp $ +# $Id: README,v 1.3 2000/11/20 00:01:49 agmorgan Exp $ # Hello! -Thanks for downloading Linux-PAM-0.65. - --------------------------------------------------------------------- -Before you begin: - - * This distribution requires GNU's Make - * It requires GNU's C-compiler: gcc (and 'ld') - * it also requires the GNU shell: bash - * some of the modules require the presence of libpwdb see redhat - * two modules have some need for libcrack too.. - --------------------------------------------------------------------- -[ -Zeroth (optional) thing to do: check the detatched "pgp" signature for -this distribution file, it should be signed by - -Type Bits/KeyID Date User ID -pub 1024/2A398175 1996/11/17 Andrew G. Morgan -] - -First thing to do (I assume you have successfully unpacked it!) is to -run: - - make check [ requires md5sum to be present ] - -This will also check that the distribution has arrived intact. [ -Later, If you change some things, running this command from this -directory will show you what files you have altered. ] - -If you choose to get and install the RCS files that accompany this -release, you may also run - - make RCScheck - -from this directory. - -Next, you should check the symbolic link - - .../Linux-PAM-X.YY/default.defs - -points to the file that best describes your system. The various *.defs -files that are included in this distribution are to be found in the -directory: - - .../Linux-PAM-X.YY/defs/ - -This should configure the distribution to compile on your system. The -default is the version I use for maintaining the distribution. [If you -don't find one that suits your needs, please try to create one, email -it to me and I will include it in a future release.] - -If you are running an ELF based Linux system you should be able to -compile the distribution straight from the box. If you are running an -a.out based system, then some of the functionality of Linux-PAM will -be unavailable to you. Instead, you must switch the DYNAMIC variables -*off* in your "defs" file: comment out the DYNAMIC and DYNAMIC_LIBPAM -defines and uncomment the STATIC and STATIC_LIBPAM defines. NOTE, for -ELF based systems, almost any combination of these four definitions is -legal... If you have ELF, I recommend the default however. - -Second, try to compile it. Use the following command in *this* -directory: - - make - -[ or 'make all' if you prefer ]. The first time you type make, it is -likely to complain. This is to remind you to remove any libraries from -previous versions of the distribution that are likely to confuse this -make... Type 'make' again. - -Before you do the third thing. You should think about whether you want -the default configuration scripts to be installed or not. If you have -a working PAM based system you probably do *not* want this.. Whatever, -before Linux-PAM installs the default scripts you will be prompted as -to whether it is a good idea. Be sure to say NO if you are worried! -** You have been warned. ** - -Third, to install the stuff you need to be root. Do the following: - - su -c "make install" - -If everything has worked as intended there should now be - - some executables in ./bin/ - some filters for pam_filter in /usr/sbin/pam_filter/ - some configuration files: - /etc/pam.conf - /etc/security/*.conf - libpam_misc.a (static library) in /usr/lib/ - -In addition: - - if dynamically linked: - - libpam.so.XXX (shared library) in /usr/lib/ - libpam_misc.so.XXX (shared library) in /usr/lib/ - pam_*.so (modules) in /usr/lib/security/ - - if statically linked: - - libpam.a (static library) in /usr/lib/ - -[These are the default directories that I use. Your own system may -differ as specified in your XXX.defs file.] +Thanks for downloading Linux-PAM. NOTES: -* The documentation, what there is of it, is in ./doc. I am only -including the sgml format source-files. But try to make .ps files -available from the above http address. To locally use these sgml files -you should have linuxdoc-sgml installed. Sorry, but I'm conserving net -bandwidth by only including sources! +How to use it is as follows: -* The source for each module is to be found in ./modules/XXX. If you -want to add a new one, make a directory like XXX for it. Add the name -(XXX) to MODDIRS in ./modules/Makefile and hopefully it will become -part of the overall make. Note, the Makefile in ./modules/ is now -smart enough to check if the directory is there before it changes into -it; If you want to start working on a module, send me its name and I -will add it to the "official" Makefile.. This way, you should be able -to insert your developing module into any new release, and not have to -worry at first about letting it out to the public. This may also give -other people some idea about whether a module is currently being -worked on or not. + ./configure --help | less + ./configure + make -* Currently, you have to 'make' binaries from this directory. 'make -clean', however, works in any directory that has a Makefile. +Note, if you are worried - don't even think about doing the next line +(most Linux distributions already support PAM out of the box, so if +something goes wrong with installing the code from this version your +box may stop working..) -* Also, you can 'make remove' (as root) from *this* directory and it -will delete the various installed files dotted around the system. THIS -IS A VERY BAD IDEA IF YOUR SYSTEM DEPENDS ON PAM TO WORK!!! + make install -* 'make sterile' does 'make remove' and then 'make extraclean', this -might be required if you are alternating your choice of -STATIC(_LIBPAM) and DYNAMIC(_LIBPAM) compilation. SEE COMMENT IN -UPPERCASE IN PARAGRAPH ABOVE!!!! - -Best wishes +That said, please report problems to me. Andrew Morgan - -Email bugs/comments to: the Linux-PAM list -or me - -To see about joining the mailing list, send the following email: --------------------------------- -To: pam-list-request@redhat.com -Subject: help - --------------------------------- - -Additionally, some Linux-PAM files have been known to be found at one -or more of the following places (they are not always the most up to -date...): - -http://www.redhat.com/linux-info/pam/ - -ftp://bach.cis.temple.edu/pub/People/Alex/private/PAM -ftp://ftp.redhat.com/pub/misc/ -ftp://linux.nrao.edu/pub/linux/ALPHA/PAM/ -ftp://tsx-11.mit.edu/pub/linux/ALPHA/PAM/ + + diff --git a/contrib/libpam/_pam_aconf.h.in b/contrib/libpam/_pam_aconf.h.in new file mode 100644 index 00000000000..0da92b79e43 --- /dev/null +++ b/contrib/libpam/_pam_aconf.h.in @@ -0,0 +1,64 @@ +/* + * $Id: _pam_aconf.h.in,v 1.4 2000/12/04 20:56:10 baggins Exp $ + * + * + */ + +#ifndef PAM_ACONF_H +#define PAM_ACONF_H + +/* lots of stuff gets written to /tmp/pam-debug.log */ +#undef DEBUG + +/* build libraries with different names (suffixed with 'd') */ +#undef WITH_LIBDEBUG + +/* provide a global locking facility within libpam */ +#undef PAM_LOCKING + +/* GNU systems as a class, all have the feature.h file */ +#undef HAVE_FEATURES_H +#ifdef HAVE_FEATURES_H +# define _SVID_SOURCE +# define _BSD_SOURCE +# define __USE_BSD +# define __USE_SVID +# define __USE_MISC +# define _GNU_SOURCE +# include +#endif /* HAVE_FEATURES_H */ + +/* we have libcrack available */ +#undef HAVE_LIBCRACK + +/* we have libcrypt - its not part of libc (do we need both definitions?) */ +#undef HAVE_LIBCRYPT +#undef HAVE_CRYPT_H + +/* we have libndbm and/or libdb */ +#undef HAVE_DB_H +#undef HAVE_NDBM_H + +/* have libfl (Flex) */ +#undef HAVE_LIBFL + +/* have libnsl - instead of libc support */ +#undef HAVE_LIBNSL + +/* have libpwdb - don't expect this to be important for much longer */ +#undef HAVE_LIBPWDB + +/* ugly hack to partially support old pam_strerror syntax */ +#undef UGLY_HACK_FOR_PRIOR_BEHAVIOR_SUPPORT + +/* read both confs - read /etc/pam.d and /etc/pam.conf in serial */ +#undef PAM_READ_BOTH_CONFS + +#undef HAVE_PATHS_H +#ifdef HAVE_PATHS_H +#include +#endif +/* location of the mail spool directory */ +#undef PAM_PATH_MAILDIR + +#endif /* PAM_ACONF_H */ diff --git a/contrib/libpam/configure b/contrib/libpam/configure new file mode 100755 index 00000000000..d63a2fba576 --- /dev/null +++ b/contrib/libpam/configure @@ -0,0 +1,3548 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_default_prefix= +ac_help="$ac_help + --enable-debug qspecify you are building with debugging on" +ac_help="$ac_help + --enable-libdebug specify you are building debugging libraries" +ac_help="$ac_help + --enable-fakeroot=" +ac_help="$ac_help + --enable-securedir= [default \$libdir/security]" +ac_help="$ac_help + --enable-sconfigdir= [default \$sysconfdir/security]" +ac_help="$ac_help + --enable-suplementedir= [default \$sbindir]" +ac_help="$ac_help + --enable-includedir= - where to put " +ac_help="$ac_help + --enable-pamlocking configure libpam to observe a global authentication lock" +ac_help="$ac_help + --enable-uglyhack configure libpam to try to honor old pam_strerror syntax" +ac_help="$ac_help + --enable-read-both-confs read both /etc/pam.d and /etc/pam.conf files" +ac_help="$ac_help + --enable-static-libpam build a libpam.a library" +ac_help="$ac_help + --disable-dynamic-libpam do not build a shared libpam library" +ac_help="$ac_help + --enable-static-modules do not make the modules dynamically loadable" +ac_help="$ac_help + --disable-lckpwdf do not use the lckpwdf function" +ac_help="$ac_help + --with-mailspool path to mail spool directory + [default _PATH_MAILDIR if defined in paths.h, otherwise /var/spool/mail]" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=conf/pam_conv1/pam_conv.y + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + + + + +LIBPAM_VERSION_MAJOR=0 +LIBPAM_VERSION_MINOR=75 + + + +cat >> confdefs.h <<\EOF +#define LIBPAM_VERSION_MAJOR 1 +EOF + +cat >> confdefs.h <<\EOF +#define LIBPAM_VERSION_MINOR 1 +EOF + + + + + + +CC=gcc ; +CONF_CFLAGS= ; +MKDIR="mkdir -p" ; +LOCALSRCDIR=`/bin/pwd` ; +OS=`uname|sed -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` + + +DYNTYPE=so ; +USESONAME=yes ; +NEEDSONAME=yes ; +SHLIBMODE=755 ; + +INSTALL=/usr/bin/install ; + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:596: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:626: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:677: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:709: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 720 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:725: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:751: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:756: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:784: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +for ac_prog in 'bison -y' byacc +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:820: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$YACC"; then + ac_cv_prog_YACC="$YACC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_YACC="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +YACC="$ac_cv_prog_YACC" +if test -n "$YACC"; then + echo "$ac_t""$YACC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$YACC" && break +done +test -n "$YACC" || YACC="yacc" + +# Extract the first word of "flex", so it can be a program name with args. +set dummy flex; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:853: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$LEX"; then + ac_cv_prog_LEX="$LEX" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_LEX="flex" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_LEX" && ac_cv_prog_LEX="lex" +fi +fi +LEX="$ac_cv_prog_LEX" +if test -n "$LEX"; then + echo "$ac_t""$LEX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$LEXLIB" +then + case "$LEX" in + flex*) ac_lib=fl ;; + *) ac_lib=l ;; + esac + echo $ac_n "checking for yywrap in -l$ac_lib""... $ac_c" 1>&6 +echo "configure:887: checking for yywrap in -l$ac_lib" >&5 +ac_lib_var=`echo $ac_lib'_'yywrap | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-l$ac_lib $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LEXLIB="-l$ac_lib" +else + echo "$ac_t""no" 1>&6 +fi + +fi + +echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 +echo "configure:929: checking whether ln -s works" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + rm -f conftestdata +if ln -s X conftestdata 2>/dev/null +then + rm -f conftestdata + ac_cv_prog_LN_S="ln -s" +else + ac_cv_prog_LN_S=ln +fi +fi +LN_S="$ac_cv_prog_LN_S" +if test "$ac_cv_prog_LN_S" = "ln -s"; then + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:950: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + + +# Check whether --enable-debug or --disable-debug was given. +if test "${enable_debug+set}" = set; then + enableval="$enable_debug" + WITH_DEBUG=yes ; cat >> confdefs.h <<\EOF +#define DEBUG 1 +EOF + +else + WITH_DEBUG=no +fi + + + +# Check whether --enable-libdebug or --disable-libdebug was given. +if test "${enable_libdebug+set}" = set; then + enableval="$enable_libdebug" + WITH_LIBDEBUG=yes ; cat >> confdefs.h <<\EOF +#define WITH_LIBDEBUG 1 +EOF + +else + WITH_LIBDEBUG=no +fi + + + +# Check whether --enable-fakeroot or --disable-fakeroot was given. +if test "${enable_fakeroot+set}" = set; then + enableval="$enable_fakeroot" + FAKEROOT=$enableval +fi + + + +# Check whether --enable-securedir or --disable-securedir was given. +if test "${enable_securedir+set}" = set; then + enableval="$enable_securedir" + SECUREDIR=$enableval +else + SECUREDIR=$libdir/security +fi + + + +# Check whether --enable-sconfigdir or --disable-sconfigdir was given. +if test "${enable_sconfigdir+set}" = set; then + enableval="$enable_sconfigdir" + SCONFIGDIR=$enableval +else + SCONFIGDIR=$sysconfdir/security +fi + + + +# Check whether --enable-suplementedir or --disable-suplementedir was given. +if test "${enable_suplementedir+set}" = set; then + enableval="$enable_suplementedir" + SUPLEMENTED=$enableval +else + SUPLEMENTED=$sbindir +fi + + + +# Check whether --enable-includedir or --disable-includedir was given. +if test "${enable_includedir+set}" = set; then + enableval="$enable_includedir" + INCLUDEDIR=$enableval +else + INCLUDEDIR=/usr/include +fi + + + +# Check whether --enable-pamlocking or --disable-pamlocking was given. +if test "${enable_pamlocking+set}" = set; then + enableval="$enable_pamlocking" + WITH_PAMLOCKING=yes ; cat >> confdefs.h <<\EOF +#define PAM_LOCKING 1 +EOF + +else + WITH_PAMLOCKING=no +fi + + + +# Check whether --enable-uglyhack or --disable-uglyhack was given. +if test "${enable_uglyhack+set}" = set; then + enableval="$enable_uglyhack" + cat >> confdefs.h <<\EOF +#define UGLY_HACK_FOR_PRIOR_BEHAVIOR_SUPPORT 1 +EOF + +fi + + +# Check whether --enable-read-both-confs or --disable-read-both-confs was given. +if test "${enable_read_both_confs+set}" = set; then + enableval="$enable_read_both_confs" + cat >> confdefs.h <<\EOF +#define PAM_READ_BOTH_CONFS 1 +EOF + +fi + + + +# Check whether --enable-static-libpam or --disable-static-libpam was given. +if test "${enable_static_libpam+set}" = set; then + enableval="$enable_static_libpam" + STATIC_LIBPAM=yes +else + STATIC_LIBPAM=no +fi + + + +# Check whether --enable-dynamic-libpam or --disable-dynamic-libpam was given. +if test "${enable_dynamic_libpam+set}" = set; then + enableval="$enable_dynamic_libpam" + DYNAMIC_LIBPAM=no +else + DYNAMIC_LIBPAM=yes +fi + + + +DYNAMIC=-DPAM_DYNAMIC + + +# Check whether --enable-static-modules or --disable-static-modules was given. +if test "${enable_static_modules+set}" = set; then + enableval="$enable_static_modules" + STATIC=-DPAM_STATIC +fi + + + +# Check whether --enable-lckpwdf or --disable-lckpwdf was given. +if test "${enable_lckpwdf+set}" = set; then + enableval="$enable_lckpwdf" + WITH_LCKPWDF=no +else + WITH_LCKPWDF=yes +fi + + + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:1128: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1149: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1166: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1183: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +for ac_hdr in paths.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1211: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1221: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +# Check whether --with-mailspool or --without-mailspool was given. +if test "${with_mailspool+set}" = set; then + withval="$with_mailspool" + with_mailspool=${withval} +fi + +if test x$with_mailspool != x ; then + pam_mail_spool="\"$with_mailspool\"" +else + if test "$cross_compiling" = yes; then + pam_mail_spool="\"/var/spool/mail\"" +else + cat > conftest.$ac_ext < +int main() { +#ifdef _PATH_MAILDIR +exit(0); +#else +exit(1); +#endif +} +EOF +if { (eval echo configure:1272: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + pam_mail_spool="_PATH_MAILDIR" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + pam_mail_spool="\"/var/spool/mail\"" +fi +rm -fr conftest* +fi + +fi +cat >> confdefs.h <&6 +echo "configure:1291: checking for __libc_sched_setscheduler in -lc" >&5 +ac_lib_var=`echo c'_'__libc_sched_setscheduler | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lc $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + PAM_NEEDS_LIBC= +else + echo "$ac_t""no" 1>&6 +PAM_NEEDS_LIBC=-lc +fi + + + +echo $ac_n "checking for lckpwdf in -lc""... $ac_c" 1>&6 +echo "configure:1334: checking for lckpwdf in -lc" >&5 +ac_lib_var=`echo c'_'lckpwdf | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lc $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + HAVE_LCKPWDF=yes +else + echo "$ac_t""no" 1>&6 +HAVE_LCKPWDF=no +fi + + + +echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 +echo "configure:1377: checking for dlopen in -ldl" >&5 +ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LIBDL=-ldl +else + echo "$ac_t""no" 1>&6 +fi + + + +echo $ac_n "checking for FascistCheck in -lcrack""... $ac_c" 1>&6 +echo "configure:1419: checking for FascistCheck in -lcrack" >&5 +ac_lib_var=`echo crack'_'FascistCheck | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lcrack $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + HAVE_LIBCRACK=yes ; cat >> confdefs.h <<\EOF +#define HAVE_LIBCRACK 1 +EOF + +else + echo "$ac_t""no" 1>&6 +HAVE_LIBCRACK=no +fi + + + +echo $ac_n "checking for fcrypt in -lcrypt""... $ac_c" 1>&6 +echo "configure:1465: checking for fcrypt in -lcrypt" >&5 +ac_lib_var=`echo crypt'_'fcrypt | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lcrypt $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + HAVE_LIBCRYPT=yes ; cat >> confdefs.h <<\EOF +#define HAVE_LIBCRYPT 1 +EOF + +else + echo "$ac_t""no" 1>&6 +HAVE_LIBCRYPT=no +fi + + +echo $ac_n "checking for logwtmp in -lutil""... $ac_c" 1>&6 +echo "configure:1510: checking for logwtmp in -lutil" >&5 +ac_lib_var=`echo util'_'logwtmp | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lutil $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + HAVE_LIBUTIL=yes ; cat >> confdefs.h <<\EOF +#define HAVE_LIBUTIL 1 +EOF + +else + echo "$ac_t""no" 1>&6 +HAVE_LIBUTIL=no +fi + + +echo $ac_n "checking for dbm_store in -lndbm""... $ac_c" 1>&6 +echo "configure:1555: checking for dbm_store in -lndbm" >&5 +ac_lib_var=`echo ndbm'_'dbm_store | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lndbm $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + HAVE_LIBNDBM=yes ; cat >> confdefs.h <<\EOF +#define HAVE_LIBNDBM 1 +EOF + +else + echo "$ac_t""no" 1>&6 +HAVE_LIBNDBM=no +fi + + +echo $ac_n "checking for dbm_store in -ldb""... $ac_c" 1>&6 +echo "configure:1600: checking for dbm_store in -ldb" >&5 +ac_lib_var=`echo db'_'dbm_store | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldb $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + HAVE_LIBDB=yes ; cat >> confdefs.h <<\EOF +#define HAVE_LIBDB 1 +EOF + +else + echo "$ac_t""no" 1>&6 +HAVE_LIBDB=no +fi + + +echo $ac_n "checking for yylex in -lfl""... $ac_c" 1>&6 +echo "configure:1645: checking for yylex in -lfl" >&5 +ac_lib_var=`echo fl'_'yylex | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lfl HAVE_LIBFL=no $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + yyterminate +else + echo "$ac_t""no" 1>&6 +HAVE_LIBFL=yes ; cat >> confdefs.h <<\EOF +#define HAVE_LIBFL 1 +EOF + +fi + + +echo $ac_n "checking for yp_maplist in -lnsl""... $ac_c" 1>&6 +echo "configure:1690: checking for yp_maplist in -lnsl" >&5 +ac_lib_var=`echo nsl'_'yp_maplist | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lnsl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + HAVE_LIBNSL=yes ; cat >> confdefs.h <<\EOF +#define HAVE_LIBNSL 1 +EOF + +else + echo "$ac_t""no" 1>&6 +HAVE_LIBNSL=no +fi + + +echo $ac_n "checking for pwdb_db_name in -lpwdb""... $ac_c" 1>&6 +echo "configure:1735: checking for pwdb_db_name in -lpwdb" >&5 +ac_lib_var=`echo pwdb'_'pwdb_db_name | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lpwdb $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + HAVE_LIBPWDB=yes ; cat >> confdefs.h <<\EOF +#define HAVE_LIBPWDB 1 +EOF + +else + echo "$ac_t""no" 1>&6 +HAVE_LIBPWDB=no +fi + + + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6 +echo "configure:1785: checking for $ac_hdr that defines DIR" >&5 +if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include <$ac_hdr> +int main() { +DIR *dirp = 0; +; return 0; } +EOF +if { (eval echo configure:1798: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_header_dirent_$ac_safe=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_dirent_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then +echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6 +echo "configure:1823: checking for opendir in -ldir" >&5 +ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldir $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LIBS="$LIBS -ldir" +else + echo "$ac_t""no" 1>&6 +fi + +else +echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6 +echo "configure:1864: checking for opendir in -lx" >&5 +ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lx $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LIBS="$LIBS -lx" +else + echo "$ac_t""no" 1>&6 +fi + +fi + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:1906: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +#include +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1919: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext < +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:1986: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6 +echo "configure:2010: checking for sys/wait.h that is POSIX.1 compatible" >&5 +if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#ifndef WEXITSTATUS +#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif +#ifndef WIFEXITED +#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif +int main() { +int s; +wait (&s); +s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; +; return 0; } +EOF +if { (eval echo configure:2031: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_header_sys_wait_h=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_sys_wait_h=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6 +if test $ac_cv_header_sys_wait_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_SYS_WAIT_H 1 +EOF + +fi + +for ac_hdr in fcntl.h limits.h malloc.h sys/file.h sys/ioctl.h sys/time.h syslog.h termio.h unistd.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2055: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2065: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + +for ac_hdr in features.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2096: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2106: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + +for ac_hdr in crypt.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2137: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2147: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + +for ac_hdr in ndbm.h db.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2178: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2188: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +HAVE_NDBM_H=$ac_cv_header_ndbm_h + + +for ac_hdr in lastlog.h utmp.h utmpx.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2221: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2231: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + + +echo $ac_n "checking path to cracklib dictionary""... $ac_c" 1>&6 +echo "configure:2260: checking path to cracklib dictionary" >&5 +DICT_DIR_CANDIDATES="/usr/lib /usr/share/dict /usr/share/lib \ + /usr/local/lib /usr/local/share/lib" +DICT_FILE_CANDIDATES="pw_dict cracklib_dict" +CRACKLIB_DICTPATH="" +for d in $DICT_DIR_CANDIDATES ; do + for f in $DICT_FILE_CANDIDATES ; do + if test -r $d/$f.hwm ; then + CRACKLIB_DICTPATH=$d/$f + break 2 + elif test -r $d/dict/$f.hwm ; then + CRACKLIB_DICTPATH=$d/dict/$f + break 2 + fi + done +done +if test -z "$CRACKLIB_DICTPATH" ; then + echo "$ac_t""none found" 1>&6 +else + echo "$ac_t""$CRACKLIB_DICTPATH" 1>&6 +fi + + + +GCC_WARNINGS="-Wall -Wwrite-strings \ + -Wpointer-arith -Wcast-qual -Wcast-align \ + -Wstrict-prototypes -Wmissing-prototypes \ + -Wnested-externs -Winline -Wshadow" + +if test "$GCC" = yes; then +### +### Non-Linux needs attention on per-OS basis + OS_CFLAGS="-ansi -D_POSIX_SOURCE -pedantic" + WARNINGS="$GCC_WARNINGS" + PIC="-fPIC" +#can/should we use LD=gcc ??? + LD=ld + LD_D="gcc -shared -Xlinker -x" + LD_L="$LD -x -shared" + RANLIB=ranlib + STRIP=strip + CC_STATIC="-Xlinker -export-dynamic" +else +### +### Non-gcc needs attention on per-OS basis +### +### [These are Solaris-C specific...] + OS_CFLAGS="" + WARNINGS="" + PIC="-K pic" + LD=ld + LD_D="cc -z text -G -R." + LD_L="$LD_D" + RANLIB=ranlib + STRIP=strip + CC_STATIC= +fi + + + + + + + + + + + +echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 +echo "configure:2329: checking whether byte ordering is bigendian" >&5 +if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_bigendian=unknown +# See if sys/param.h defines the BYTE_ORDER macro. +cat > conftest.$ac_ext < +#include +int main() { + +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif +; return 0; } +EOF +if { (eval echo configure:2347: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + # It does; now see whether it defined to BIG_ENDIAN or not. +cat > conftest.$ac_ext < +#include +int main() { + +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif +; return 0; } +EOF +if { (eval echo configure:2362: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_bigendian=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_bigendian=no +fi +rm -f conftest* +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +if test $ac_cv_c_bigendian = unknown; then +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_c_bigendian=no +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_c_bigendian=yes +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_c_bigendian" 1>&6 +if test $ac_cv_c_bigendian = yes; then + cat >> confdefs.h <<\EOF +#define WORDS_BIGENDIAN 1 +EOF + +fi + +echo $ac_n "checking for working const""... $ac_c" 1>&6 +echo "configure:2419: checking for working const" >&5 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if { (eval echo configure:2473: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_const=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_c_const" 1>&6 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + +echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 +echo "configure:2494: checking for uid_t in sys/types.h" >&5 +if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "uid_t" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_uid_t=yes +else + rm -rf conftest* + ac_cv_type_uid_t=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_type_uid_t" 1>&6 +if test $ac_cv_type_uid_t = no; then + cat >> confdefs.h <<\EOF +#define uid_t int +EOF + + cat >> confdefs.h <<\EOF +#define gid_t int +EOF + +fi + +echo $ac_n "checking for off_t""... $ac_c" 1>&6 +echo "configure:2528: checking for off_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#include +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z_0-9])off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_off_t=yes +else + rm -rf conftest* + ac_cv_type_off_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_off_t" 1>&6 +if test $ac_cv_type_off_t = no; then + cat >> confdefs.h <<\EOF +#define off_t long +EOF + +fi + +echo $ac_n "checking for pid_t""... $ac_c" 1>&6 +echo "configure:2561: checking for pid_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#include +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z_0-9])pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_pid_t=yes +else + rm -rf conftest* + ac_cv_type_pid_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_pid_t" 1>&6 +if test $ac_cv_type_pid_t = no; then + cat >> confdefs.h <<\EOF +#define pid_t int +EOF + +fi + +echo $ac_n "checking for size_t""... $ac_c" 1>&6 +echo "configure:2594: checking for size_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#include +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_size_t=yes +else + rm -rf conftest* + ac_cv_type_size_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_size_t" 1>&6 +if test $ac_cv_type_size_t = no; then + cat >> confdefs.h <<\EOF +#define size_t unsigned +EOF + +fi + +echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 +echo "configure:2627: checking whether time.h and sys/time.h may both be included" >&5 +if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +int main() { +struct tm *tp; +; return 0; } +EOF +if { (eval echo configure:2641: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_header_time=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_time=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_time" 1>&6 +if test $ac_cv_header_time = yes; then + cat >> confdefs.h <<\EOF +#define TIME_WITH_SYS_TIME 1 +EOF + +fi + +echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6 +echo "configure:2662: checking whether struct tm is in sys/time.h or time.h" >&5 +if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +int main() { +struct tm *tp; tp->tm_sec; +; return 0; } +EOF +if { (eval echo configure:2675: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_struct_tm=time.h +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_struct_tm=sys/time.h +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_struct_tm" 1>&6 +if test $ac_cv_struct_tm = sys/time.h; then + cat >> confdefs.h <<\EOF +#define TM_IN_SYS_TIME 1 +EOF + +fi + + +echo $ac_n "checking type of array argument to getgroups""... $ac_c" 1>&6 +echo "configure:2697: checking type of array argument to getgroups" >&5 +if eval "test \"`echo '$''{'ac_cv_type_getgroups'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_type_getgroups=cross +else + cat > conftest.$ac_ext < +#define NGID 256 +#undef MAX +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +main() +{ + gid_t gidset[NGID]; + int i, n; + union { gid_t gval; long lval; } val; + + val.lval = -1; + for (i = 0; i < NGID; i++) + gidset[i] = val.gval; + n = getgroups (sizeof (gidset) / MAX (sizeof (int), sizeof (gid_t)) - 1, + gidset); + /* Exit non-zero if getgroups seems to require an array of ints. This + happens when gid_t is short but getgroups modifies an array of ints. */ + exit ((n > 0 && gidset[n] != val.gval) ? 1 : 0); +} + +EOF +if { (eval echo configure:2730: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_type_getgroups=gid_t +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_type_getgroups=int +fi +rm -fr conftest* +fi + +if test $ac_cv_type_getgroups = cross; then + cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "getgroups.*int.*gid_t" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_getgroups=gid_t +else + rm -rf conftest* + ac_cv_type_getgroups=int +fi +rm -f conftest* + +fi +fi + +echo "$ac_t""$ac_cv_type_getgroups" 1>&6 +cat >> confdefs.h <&6 +echo "configure:2769: checking whether ${CC-cc} needs -traditional" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_pattern="Autoconf.*'x'" + cat > conftest.$ac_ext < +Autoconf TIOCGETP +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "$ac_pattern" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_prog_gcc_traditional=yes +else + rm -rf conftest* + ac_cv_prog_gcc_traditional=no +fi +rm -f conftest* + + + if test $ac_cv_prog_gcc_traditional = no; then + cat > conftest.$ac_ext < +Autoconf TCGETA +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "$ac_pattern" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_prog_gcc_traditional=yes +fi +rm -f conftest* + + fi +fi + +echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6 + if test $ac_cv_prog_gcc_traditional = yes; then + CC="$CC -traditional" + fi +fi + +echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6 +echo "configure:2815: checking for 8-bit clean memcmp" >&5 +if eval "test \"`echo '$''{'ac_cv_func_memcmp_clean'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_memcmp_clean=no +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_func_memcmp_clean=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_func_memcmp_clean=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_func_memcmp_clean" 1>&6 +test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}" + +echo $ac_n "checking for vprintf""... $ac_c" 1>&6 +echo "configure:2851: checking for vprintf" >&5 +if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char vprintf(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_vprintf) || defined (__stub___vprintf) +choke me +#else +vprintf(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2879: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_vprintf=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_vprintf=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'vprintf`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_VPRINTF 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi + +if test "$ac_cv_func_vprintf" != yes; then +echo $ac_n "checking for _doprnt""... $ac_c" 1>&6 +echo "configure:2903: checking for _doprnt" >&5 +if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char _doprnt(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub__doprnt) || defined (__stub____doprnt) +choke me +#else +_doprnt(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2931: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func__doprnt=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func__doprnt=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'_doprnt`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_DOPRNT 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi + +fi + +for ac_func in gethostname gettimeofday mkdir select strcspn strdup strerror strspn strstr strtol uname +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2958: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2986: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + +# Extract the first word of "sgml2txt", so it can be a program name with args. +set dummy sgml2txt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:3014: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_HAVE_SGML2TXT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$HAVE_SGML2TXT"; then + ac_cv_prog_HAVE_SGML2TXT="$HAVE_SGML2TXT" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_HAVE_SGML2TXT="yes" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_HAVE_SGML2TXT" && ac_cv_prog_HAVE_SGML2TXT="no" +fi +fi +HAVE_SGML2TXT="$ac_cv_prog_HAVE_SGML2TXT" +if test -n "$HAVE_SGML2TXT"; then + echo "$ac_t""$HAVE_SGML2TXT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Extract the first word of "sgml2html", so it can be a program name with args. +set dummy sgml2html; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:3044: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_HAVE_SGML2HTML'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$HAVE_SGML2HTML"; then + ac_cv_prog_HAVE_SGML2HTML="$HAVE_SGML2HTML" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_HAVE_SGML2HTML="yes" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_HAVE_SGML2HTML" && ac_cv_prog_HAVE_SGML2HTML="no" +fi +fi +HAVE_SGML2HTML="$ac_cv_prog_HAVE_SGML2HTML" +if test -n "$HAVE_SGML2HTML"; then + echo "$ac_t""$HAVE_SGML2HTML" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Extract the first word of "sgml2latex", so it can be a program name with args. +set dummy sgml2latex; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:3074: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_HAVE_SGML2LATEX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$HAVE_SGML2LATEX"; then + ac_cv_prog_HAVE_SGML2LATEX="$HAVE_SGML2LATEX" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_HAVE_SGML2LATEX="yes" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_HAVE_SGML2LATEX" && ac_cv_prog_HAVE_SGML2LATEX="no" +fi +fi +HAVE_SGML2LATEX="$ac_cv_prog_HAVE_SGML2LATEX" +if test -n "$HAVE_SGML2LATEX"; then + echo "$ac_t""$HAVE_SGML2LATEX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test $HAVE_SGML2LATEX = "yes" ; then + if sgml2latex -h | grep -e --paper | grep ' -p ' > /dev/null ; then + PSER="sgml2latex -o ps" + else + PSER="sgml2latex -p" + fi +else + # Extract the first word of "sgml2ps", so it can be a program name with args. +set dummy sgml2ps; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:3111: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_HAVE_SGML2PS'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$HAVE_SGML2PS"; then + ac_cv_prog_HAVE_SGML2PS="$HAVE_SGML2PS" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_HAVE_SGML2PS="yes" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_HAVE_SGML2PS" && ac_cv_prog_HAVE_SGML2PS="no" +fi +fi +HAVE_SGML2PS="$ac_cv_prog_HAVE_SGML2PS" +if test -n "$HAVE_SGML2PS"; then + echo "$ac_t""$HAVE_SGML2PS" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test $HAVE_SGML2PS = yes ; then + PSER="sgml2ps" + fi +fi + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir + +trap 'rm -fr `echo "Make.Rules _pam_aconf.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@LIBPAM_VERSION_MAJOR@%$LIBPAM_VERSION_MAJOR%g +s%@LIBPAM_VERSION_MINOR@%$LIBPAM_VERSION_MINOR%g +s%@CC@%$CC%g +s%@CONF_CFLAGS@%$CONF_CFLAGS%g +s%@MKDIR@%$MKDIR%g +s%@LOCALSRCDIR@%$LOCALSRCDIR%g +s%@OS@%$OS%g +s%@DYNTYPE@%$DYNTYPE%g +s%@USESONAME@%$USESONAME%g +s%@NEEDSONAME@%$NEEDSONAME%g +s%@SHLIBMODE@%$SHLIBMODE%g +s%@INSTALL@%$INSTALL%g +s%@YACC@%$YACC%g +s%@LEX@%$LEX%g +s%@LEXLIB@%$LEXLIB%g +s%@LN_S@%$LN_S%g +s%@SET_MAKE@%$SET_MAKE%g +s%@WITH_DEBUG@%$WITH_DEBUG%g +s%@WITH_LIBDEBUG@%$WITH_LIBDEBUG%g +s%@FAKEROOT@%$FAKEROOT%g +s%@SECUREDIR@%$SECUREDIR%g +s%@SCONFIGDIR@%$SCONFIGDIR%g +s%@SUPLEMENTED@%$SUPLEMENTED%g +s%@INCLUDEDIR@%$INCLUDEDIR%g +s%@WITH_PAMLOCKING@%$WITH_PAMLOCKING%g +s%@PAM_READ_BOTH_CONFS@%$PAM_READ_BOTH_CONFS%g +s%@STATIC_LIBPAM@%$STATIC_LIBPAM%g +s%@DYNAMIC_LIBPAM@%$DYNAMIC_LIBPAM%g +s%@DYNAMIC@%$DYNAMIC%g +s%@STATIC@%$STATIC%g +s%@WITH_LCKPWDF@%$WITH_LCKPWDF%g +s%@CPP@%$CPP%g +s%@PAM_NEEDS_LIBC@%$PAM_NEEDS_LIBC%g +s%@HAVE_LCKPWDF@%$HAVE_LCKPWDF%g +s%@LIBDL@%$LIBDL%g +s%@HAVE_LIBCRACK@%$HAVE_LIBCRACK%g +s%@HAVE_LIBCRYPT@%$HAVE_LIBCRYPT%g +s%@HAVE_LIBUTIL@%$HAVE_LIBUTIL%g +s%@HAVE_LIBNDBM@%$HAVE_LIBNDBM%g +s%@HAVE_LIBDB@%$HAVE_LIBDB%g +s%@HAVE_LIBFL@%$HAVE_LIBFL%g +s%@HAVE_LIBNSL@%$HAVE_LIBNSL%g +s%@HAVE_LIBPWDB@%$HAVE_LIBPWDB%g +s%@HAVE_NDBM_H@%$HAVE_NDBM_H%g +s%@CRACKLIB_DICTPATH@%$CRACKLIB_DICTPATH%g +s%@OS_CFLAGS@%$OS_CFLAGS%g +s%@WARNINGS@%$WARNINGS%g +s%@PIC@%$PIC%g +s%@LD@%$LD%g +s%@LD_D@%$LD_D%g +s%@LD_L@%$LD_L%g +s%@RANLIB@%$RANLIB%g +s%@STRIP@%$STRIP%g +s%@CC_STATIC@%$CC_STATIC%g +s%@LIBOBJS@%$LIBOBJS%g +s%@HAVE_SGML2TXT@%$HAVE_SGML2TXT%g +s%@HAVE_SGML2HTML@%$HAVE_SGML2HTML%g +s%@HAVE_SGML2LATEX@%$HAVE_SGML2LATEX%g +s%@HAVE_SGML2PS@%$HAVE_SGML2PS%g +s%@PSER@%$PSER%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/contrib/libpam/configure.in b/contrib/libpam/configure.in new file mode 100644 index 00000000000..fb3752db8dc --- /dev/null +++ b/contrib/libpam/configure.in @@ -0,0 +1,339 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(conf/pam_conv1/pam_conv.y) + +dnl The configuration header file +AC_CONFIG_HEADER(_pam_aconf.h) + +dnl +dnl Release specific +dnl + +LIBPAM_VERSION_MAJOR=0 +LIBPAM_VERSION_MINOR=75 + +AC_SUBST(LIBPAM_VERSION_MAJOR) +AC_SUBST(LIBPAM_VERSION_MINOR) +AC_DEFINE(LIBPAM_VERSION_MAJOR) +AC_DEFINE(LIBPAM_VERSION_MINOR) + +dnl +dnl By default, everything under PAM is installed under the root fs. +dnl + +AC_PREFIX_DEFAULT() + +dnl +dnl Rules needed for the following (hardcoded Linux defaults for now) +dnl + +CC=gcc ; AC_SUBST(CC) +CONF_CFLAGS= ; AC_SUBST(CONF_CFLAGS) +MKDIR="mkdir -p" ; AC_SUBST(MKDIR) +LOCALSRCDIR=`/bin/pwd` ; AC_SUBST(LOCALSRCDIR) +OS=`uname|sed -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` +AC_SUBST(OS) + +dnl These are most likely platform specific - I think HPUX differs +DYNTYPE=so ; AC_SUBST(DYNTYPE) +USESONAME=yes ; AC_SUBST(USESONAME) +NEEDSONAME=yes ; AC_SUBST(NEEDSONAME) +SHLIBMODE=755 ; AC_SUBST(SHLIBMODE) + +dnl ### Should enable this INSTALL detection. +dnl ### Would need to distribute GNU's config.guess and config.sub +dnl AC_PROG_INSTALL +INSTALL=/usr/bin/install ; AC_SUBST(INSTALL) + +dnl Checks for programs. +AC_PROG_CC +dnl ### AC_PROG_CXX +AC_PROG_YACC +AC_PROG_LEX +dnl AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET + +dnl +dnl options and defaults +dnl + +dnl lots of debugging information goes to /tmp/pam-debug.log +AC_ARG_ENABLE(debug, +[ --enable-debug qspecify you are building with debugging on], + WITH_DEBUG=yes ; AC_DEFINE(DEBUG) , WITH_DEBUG=no) +AC_SUBST(WITH_DEBUG) + +dnl build specially named libraries (for debugging purposes) +AC_ARG_ENABLE(libdebug, +[ --enable-libdebug specify you are building debugging libraries], + WITH_LIBDEBUG=yes ; AC_DEFINE(WITH_LIBDEBUG) , WITH_LIBDEBUG=no) +AC_SUBST(WITH_LIBDEBUG) + +dnl packaging convenience +AC_ARG_ENABLE(fakeroot, +[ --enable-fakeroot=], FAKEROOT=$enableval) +AC_SUBST(FAKEROOT) + +AC_ARG_ENABLE(securedir, +[ --enable-securedir= [default \$libdir/security]], + SECUREDIR=$enableval, SECUREDIR=$libdir/security) +AC_SUBST(SECUREDIR) + +AC_ARG_ENABLE(sconfigdir, +[ --enable-sconfigdir= [default \$sysconfdir/security]], + SCONFIGDIR=$enableval, SCONFIGDIR=$sysconfdir/security) +AC_SUBST(SCONFIGDIR) + +AC_ARG_ENABLE(suplementedir, +[ --enable-suplementedir= [default \$sbindir]], + SUPLEMENTED=$enableval, SUPLEMENTED=$sbindir) +AC_SUBST(SUPLEMENTED) + +AC_ARG_ENABLE(includedir, +[ --enable-includedir= - where to put ], + INCLUDEDIR=$enableval, INCLUDEDIR=/usr/include) +AC_SUBST(INCLUDEDIR) + +AC_ARG_ENABLE(pamlocking, +[ --enable-pamlocking configure libpam to observe a global authentication lock], + WITH_PAMLOCKING=yes ; AC_DEFINE(PAM_LOCKING) , WITH_PAMLOCKING=no) +AC_SUBST(WITH_PAMLOCKING) + +AC_ARG_ENABLE(uglyhack, +[ --enable-uglyhack configure libpam to try to honor old pam_strerror syntax], + AC_DEFINE(UGLY_HACK_FOR_PRIOR_BEHAVIOR_SUPPORT)) + +AC_ARG_ENABLE(read-both-confs, +[ --enable-read-both-confs read both /etc/pam.d and /etc/pam.conf files], + AC_DEFINE(PAM_READ_BOTH_CONFS)) +AC_SUBST(PAM_READ_BOTH_CONFS) + +AC_ARG_ENABLE(static-libpam, [ --enable-static-libpam build a libpam.a library], + STATIC_LIBPAM=yes , STATIC_LIBPAM=no) +AC_SUBST(STATIC_LIBPAM) + +AC_ARG_ENABLE(dynamic-libpam, +[ --disable-dynamic-libpam do not build a shared libpam library], + DYNAMIC_LIBPAM=no, DYNAMIC_LIBPAM=yes) +AC_SUBST(DYNAMIC_LIBPAM) + +DYNAMIC=-DPAM_DYNAMIC +AC_SUBST(DYNAMIC) + +AC_ARG_ENABLE(static-modules, +[ --enable-static-modules do not make the modules dynamically loadable], + STATIC=-DPAM_STATIC) +AC_SUBST(STATIC) + +AC_ARG_ENABLE(lckpwdf, +[ --disable-lckpwdf do not use the lckpwdf function], + WITH_LCKPWDF=no, WITH_LCKPWDF=yes) +AC_SUBST(WITH_LCKPWDF) + +AC_CHECK_HEADERS(paths.h) +AC_ARG_WITH(mailspool, +[ --with-mailspool path to mail spool directory + [default _PATH_MAILDIR if defined in paths.h, otherwise /var/spool/mail]], +with_mailspool=${withval}) +if test x$with_mailspool != x ; then + pam_mail_spool="\"$with_mailspool\"" +else + AC_TRY_RUN([ +#include +int main() { +#ifdef _PATH_MAILDIR +exit(0); +#else +exit(1); +#endif +}], pam_mail_spool="_PATH_MAILDIR", +pam_mail_spool="\"/var/spool/mail\"", +pam_mail_spool="\"/var/spool/mail\"") +fi +AC_DEFINE_UNQUOTED(PAM_PATH_MAILDIR, $pam_mail_spool) + +dnl Checks for libraries. +AC_CHECK_LIB(c, __libc_sched_setscheduler, PAM_NEEDS_LIBC=, PAM_NEEDS_LIBC=-lc) +AC_SUBST(PAM_NEEDS_LIBC) + +dnl Checks for the existence of lckpwdf in libc +AC_CHECK_LIB(c, lckpwdf, HAVE_LCKPWDF=yes, HAVE_LCKPWDF=no) +AC_SUBST(HAVE_LCKPWDF) + +dnl Checks for the existence of libdl - on BSD its part of libc +AC_CHECK_LIB(dl, dlopen, LIBDL=-ldl) +AC_SUBST(LIBDL) + +dnl +dnl At least on Solaris, the existing libcrack must be dynamic. +dnl Ought to introduce a check for this. +dnl +AC_CHECK_LIB(crack, FascistCheck, HAVE_LIBCRACK=yes ; AC_DEFINE(HAVE_LIBCRACK), + HAVE_LIBCRACK=no) +AC_SUBST(HAVE_LIBCRACK) + +AC_CHECK_LIB(crypt, fcrypt, HAVE_LIBCRYPT=yes ; AC_DEFINE(HAVE_LIBCRYPT), + HAVE_LIBCRYPT=no) +AC_SUBST(HAVE_LIBCRYPT) +AC_CHECK_LIB(util, logwtmp, HAVE_LIBUTIL=yes ; AC_DEFINE(HAVE_LIBUTIL), + HAVE_LIBUTIL=no) +AC_SUBST(HAVE_LIBUTIL) +AC_CHECK_LIB(ndbm, dbm_store, HAVE_LIBNDBM=yes ; AC_DEFINE(HAVE_LIBNDBM), + HAVE_LIBNDBM=no) +AC_SUBST(HAVE_LIBNDBM) +AC_CHECK_LIB(db, dbm_store, HAVE_LIBDB=yes ; AC_DEFINE(HAVE_LIBDB), + HAVE_LIBDB=no) +AC_SUBST(HAVE_LIBDB) +AC_CHECK_LIB(fl, yylex, yyterminate, HAVE_LIBFL=yes ; AC_DEFINE(HAVE_LIBFL), + HAVE_LIBFL=no) +AC_SUBST(HAVE_LIBFL) +AC_CHECK_LIB(nsl, yp_maplist, HAVE_LIBNSL=yes ; AC_DEFINE(HAVE_LIBNSL), + HAVE_LIBNSL=no) +AC_SUBST(HAVE_LIBNSL) +AC_CHECK_LIB(pwdb, pwdb_db_name, HAVE_LIBPWDB=yes ; AC_DEFINE(HAVE_LIBPWDB), + HAVE_LIBPWDB=no) +AC_SUBST(HAVE_LIBPWDB) + +dnl Checks for header files. +AC_HEADER_DIRENT +AC_HEADER_STDC +AC_HEADER_SYS_WAIT +AC_CHECK_HEADERS(fcntl.h limits.h malloc.h sys/file.h sys/ioctl.h sys/time.h syslog.h termio.h unistd.h) + +dnl Linux wants features.h in some of the source files. +AC_CHECK_HEADERS(features.h) + +dnl For module/pam_cracklib +AC_CHECK_HEADERS(crypt.h) + +dnl For module/pam_userdb +AC_CHECK_HEADERS(ndbm.h db.h) +dnl I suspect the following two lines are a hack. +HAVE_NDBM_H=$ac_cv_header_ndbm_h +AC_SUBST(HAVE_NDBM_H) + +dnl For module/pam_lastlog +AC_CHECK_HEADERS(lastlog.h utmp.h utmpx.h) + +dnl This following rule should be made conditional upon HAVE_LIBCRYPT +dnl being found. + +dnl Look for cracklib dictionary +AC_MSG_CHECKING(path to cracklib dictionary) +DICT_DIR_CANDIDATES="/usr/lib /usr/share/dict /usr/share/lib \ + /usr/local/lib /usr/local/share/lib" +DICT_FILE_CANDIDATES="pw_dict cracklib_dict" +CRACKLIB_DICTPATH="" +for d in $DICT_DIR_CANDIDATES ; do + for f in $DICT_FILE_CANDIDATES ; do + if test -r $d/$f.hwm ; then + CRACKLIB_DICTPATH=$d/$f + break 2 + elif test -r $d/dict/$f.hwm ; then + CRACKLIB_DICTPATH=$d/dict/$f + break 2 + fi + done +done +if test -z "$CRACKLIB_DICTPATH" ; then + AC_MSG_RESULT(none found) +else + AC_MSG_RESULT($CRACKLIB_DICTPATH) +fi +AC_SUBST(CRACKLIB_DICTPATH) + +dnl Set FLAGS, linker options etc. depending on C compiler. +dnl gcc is tested and much preferred; others less so, if at all +dnl +dnl If compiling with gcc, linking is also supposed to be done with gcc; +dnl since we use linker-specific arguments, we may not gain anything by +dnl switching LD_L over, but I think we can use LD_D as-is. +dnl +dnl For the moment, gcc is enforced above at "CC=gcc". +dnl +dnl There is an issue over _POSIX_SOURCE _BSD_SOURCE and _GNU_SOURCE . +dnl The original "Linux-PAM" had blanket inclusion. But portability +dnl requires their default absence: if particular OSes require them, +dnl this should be done selectively. + +GCC_WARNINGS="-Wall -Wwrite-strings \ + -Wpointer-arith -Wcast-qual -Wcast-align \ + -Wstrict-prototypes -Wmissing-prototypes \ + -Wnested-externs -Winline -Wshadow" + +if test "$GCC" = yes; then +### +### Non-Linux needs attention on per-OS basis + OS_CFLAGS="-ansi -D_POSIX_SOURCE -pedantic" + WARNINGS="$GCC_WARNINGS" + PIC="-fPIC" +#can/should we use LD=gcc ??? + LD=ld + LD_D="gcc -shared -Xlinker -x" + LD_L="$LD -x -shared" + RANLIB=ranlib + STRIP=strip + CC_STATIC="-Xlinker -export-dynamic" +else +### +### Non-gcc needs attention on per-OS basis +### +### [These are Solaris-C specific...] + OS_CFLAGS="" + WARNINGS="" + PIC="-K pic" + LD=ld + LD_D="cc -z text -G -R." + LD_L="$LD_D" + RANLIB=ranlib + STRIP=strip + CC_STATIC= +fi + +AC_SUBST(OS_CFLAGS) +AC_SUBST(WARNINGS) +AC_SUBST(PIC) +AC_SUBST(LD) +AC_SUBST(LD_D) +AC_SUBST(LD_L) +AC_SUBST(RANLIB) +AC_SUBST(STRIP) +AC_SUBST(CC_STATIC) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_BIGENDIAN +AC_C_CONST +AC_TYPE_UID_T +AC_TYPE_OFF_T +AC_TYPE_PID_T +AC_TYPE_SIZE_T +AC_HEADER_TIME +AC_STRUCT_TM + +dnl Checks for library functions. +AC_TYPE_GETGROUPS +AC_PROG_GCC_TRADITIONAL +AC_FUNC_MEMCMP +AC_FUNC_VPRINTF +AC_CHECK_FUNCS(gethostname gettimeofday mkdir select strcspn strdup strerror strspn strstr strtol uname) + +dnl Checks for programs/utilities +AC_CHECK_PROG(HAVE_SGML2TXT, sgml2txt, yes, no) +AC_CHECK_PROG(HAVE_SGML2HTML, sgml2html, yes, no) +AC_CHECK_PROG(HAVE_SGML2LATEX, sgml2latex, yes, no) +if test $HAVE_SGML2LATEX = "yes" ; then + if sgml2latex -h | grep -e --paper | grep ' -p ' > /dev/null ; then + PSER="sgml2latex -o ps" + else + PSER="sgml2latex -p" + fi +else + AC_CHECK_PROG(HAVE_SGML2PS, sgml2ps, yes, no) + if test $HAVE_SGML2PS = yes ; then + PSER="sgml2ps" + fi +fi +AC_SUBST(PSER) + +dnl Files to be created from when we run configure +AC_OUTPUT(Make.Rules) diff --git a/contrib/libpam/defs/debian.defs b/contrib/libpam/defs/debian.defs new file mode 100644 index 00000000000..19ba46635ad --- /dev/null +++ b/contrib/libpam/defs/debian.defs @@ -0,0 +1,40 @@ +## +# defs for Debian +# Ben Collins +## +# this file indicates the compiler and the various hardware/OS dependent +# flags for installation. It also defines the various destinations of +# installed files on the system. +## + +CFLAGS := -O2 -I${shell pwd}/include # -D__NO_STRING_INLINES +ifneq (,$(findstring $(DEB_BUILD_OPTIONS),debug DEBUG Debug)) + CFLAGS += -g +endif + +OS := $(shell dpkg-architecture -qDEB_BUILD_GNU_SYSTEM) +ARCH := $(shell dpkg-architecture -qDEB_BUILD_GNU_CPU) +CC := gcc +INSTALL := install +MKDIR := mkdir -p +ULIBS := +LD := ld +LD_D := gcc -shared -Xlinker -x +LD_L := $(LD) -x -shared +AR := ar -cr +RANLIB := ranlib +PREFIX := +LIBDIR := $(PREFIX)/lib +USESONAME := yes +SOSWITCH := -soname +LINKLIBS := -lc -L${shell pwd}/libpam -L${shell pwd}/libpam_misc +NEEDSONAME := no +LDCONFIG := /sbin/ldconfig +FAKEROOT := +SUPLEMENTED := $(PREFIX)/sbin +SECUREDIR := $(LIBDIR)/security +INCLUDED := /usr/include/security +CONFIGED := /etc +SCONFIGED := /etc/security +EXTRALS := -lnsl -lcrypt +WARNINGS := -Wall diff --git a/contrib/libpam/defs/redhat4.defs b/contrib/libpam/defs/redhat4.defs new file mode 100644 index 00000000000..219abeb6fd1 --- /dev/null +++ b/contrib/libpam/defs/redhat4.defs @@ -0,0 +1,35 @@ +## +# defs for Red Hat Linux +# Michael K. Johnson +## +# this file indicates the compiler and the various hardware/OS dependent +# flags for installation. It also defines the various destinations of +# installed files on the system. +# +# This file is the version used for Red Hat Linux. + +OS=linux +ARCH=$(shell rpm --showrc | grep '^build arch' | sed 's/^.*: //g') +CC=gcc +INSTALL=install +MKDIR=mkdir -p +CFLAGS=$(RPM_OPT_FLAGS) -pipe -g +ULIBS=#-lefence +LD=ld +LD_D=gcc -shared -Xlinker -x +LD_L=$(LD) -x -shared +USESONAME=yes +SOSWITCH=-soname +LINKLIBS=-lc +NEEDSONAME=no +LDCONFIG=/sbin/ldconfig +AR=ar -cr +RANLIB=ranlib +FAKEROOT=$(RPM_BUILD_ROOT) +PREFIX= +SUPLEMENTED=$(PREFIX)/sbin +LIBDIR=$(PREFIX)/lib +SECUREDIR=$(LIBDIR)/security +INCLUDED=/usr/include/security +CONFIGED=/etc +SCONFIGED=/etc/security diff --git a/contrib/libpam/defs/solaris-2.1.5.defs b/contrib/libpam/defs/solaris-2.1.5.defs new file mode 100644 index 00000000000..4624b604b7f --- /dev/null +++ b/contrib/libpam/defs/solaris-2.1.5.defs @@ -0,0 +1,45 @@ +## +# Solaris defs contributed by Josh Wilmes +## +# this file indicates the compiler and the various hardware/OS dependent +# flags for installation. It also defines the various destinations of +# installed files on the system. +# +# This file is the default version. Please look in .../defs/ for your +# preferred OS/vendor. + +# Please note that the linker used must be the GNU ld, not the native Sun +# linker. It is fairly common for the gnu linker (/usr/ccs/bin/ld) to be +# configured as the default linker for gcc. To tell gcc to use the +# gnu linker, you need to set the GCC_EXEC_PREFIX environment variable +# to point at the directory where the gnu linker is installed. Here's +# what I do: +# $ mkdir /tmp/foo +# $ ln -s /path/to/gnu/ld /tmp/foo/ld +# $ export GCC_EXEC_PREFIX=/tmp/foo/ +# $ export PATH=/tmp/foo:$PATH + +OS=solaris +ARCH=sun +CC=gcc +INSTALL=install +MKDIR=mkdir -p +CFLAGS=-O7 -pipe -g -D__EXTENSIONS__ -Dsolaris +ULIBS= +LD_D=gcc -shared -Xlinker -x +LD=ld +LD_L=$(LD) -G +USESONAME=yes +SOSWITCH=-h +NEEDSONAME=no +LDCONFIG=/sbin/echo +AR=ar -cr +RANLIB=ranlib +FAKEROOT= +PREFIX=/usr +SUPLEMENTED=$(PREFIX)/sbin +LIBDIR=$(PREFIX)/lib +SECUREDIR=$(LIBDIR)/security +INCLUDED=/usr/include/security +CONFIGED=/etc +SCONFIGED=/etc/security diff --git a/contrib/libpam/defs/suse.defs b/contrib/libpam/defs/suse.defs new file mode 100644 index 00000000000..1fc6b741942 --- /dev/null +++ b/contrib/libpam/defs/suse.defs @@ -0,0 +1,36 @@ +## +# defs for SuSE Linux +# Thorsten Kukuk +## +# this file indicates the compiler and the various hardware/OS dependent +# flags for installation. It also defines the various destinations of +# installed files on the system. +# +# This file is the version used for SuSE Linux. + +OS=linux +ARCH=$(shell rpm --showrc | grep 'build arch' | grep -v "compatible" | sed 's/^.*: //g') +CC=gcc +INSTALL=install +MKDIR=mkdir -p +CFLAGS=$(RPM_OPT_FLAGS) -pipe -D_REENTRANT +ULIBS=#-lefence +LD=ld +LD_D=gcc -shared -Xlinker -x +LD_L=$(LD) -x -shared +USESONAME=yes +SOSWITCH=-soname +LINKLIBS=-lc +NEEDSONAME=yes +LDCONFIG=/sbin/ldconfig +AR=ar -cr +RANLIB=ranlib +FAKEROOT=$(RPM_BUILD_ROOT) +PREFIX= +SUPLEMENTED=$(PREFIX)/sbin +LIBDIR=$(PREFIX)/lib +SECUREDIR=$(LIBDIR)/security +INCLUDED=/usr/include/security +CONFIGED=/etc +SCONFIGED=/etc/security +EXTRALS=-lcrypt diff --git a/contrib/libpam/doc/CREDITS b/contrib/libpam/doc/CREDITS index 95ca2ab36e0..528032bbb8a 100644 --- a/contrib/libpam/doc/CREDITS +++ b/contrib/libpam/doc/CREDITS @@ -1,29 +1,41 @@ +Chris Adams, Peter Allgeyer, Tim Baverstock, +Tim Berger, Craig S. Bell, Derrick J. Brashear, Ben Buxton, +Seth Chaiklin, Oliver Crow, Chris Dent, Marc Ewing, Cristian Gafton, +Emmanuel Galanos, +Brad M. Garcia, Eric Hester, +Michel D'Hooge, Roger Hu, Eric Jacksch, Michael K. Johnson, David Kinchlea, +Olaf Kirch, +Marcin Korzonek, +Stephen Langasek, Nicolai Langfeldt, Elliot Lee, +Luke Kenneth Casson Leighton, Al Longyear, Ingo Luetkebohle, Marek Michalkiewicz, +Robert Milkowski, Aleph One, Martin Pool, Sean Reifschneider, +Jan Rekorajski, Erik Troan, Theodore Ts'o, Jeff Uphoff, diff --git a/contrib/libpam/doc/Makefile b/contrib/libpam/doc/Makefile index 866b408512d..8ff16077a82 100644 --- a/contrib/libpam/doc/Makefile +++ b/contrib/libpam/doc/Makefile @@ -1,10 +1,13 @@ -### $Id: Makefile,v 1.9 1997/01/04 21:55:52 morgan Exp $ +### $Id: Makefile,v 1.3 2001/01/22 08:03:01 agmorgan Exp $ -TXTER=sgml2txt -HTMLER=sgml2html -# older distributions use, sgml2ps -PSER=sgml2latex -p +include ../Make.Rules + +# These two should probably be moved into autoconf... +DOCDIR=/usr/doc/Linux-PAM +MANDIR=/usr/man + +####################################################### FILES=pam pam_appl pam_modules FSRCS=pam.sgml pam_appl.sgml pam_modules.sgml @@ -26,36 +29,48 @@ all: htmls texts postscript htmls: $(HTMLS) $(HTMLS) : $(FSRCS) +ifeq ($(HAVE_SGML2HTML),yes) @for i in $(FILES) ; do \ if [ ! -f "html/$$i.html" ] || [ "$$i.sgml" -nt "html/$$i.html" ]; \ then \ - cd html ; $(HTMLER) ../$$i ; \ + cd html ; sgml2html ../$$i ; \ if [ $$? -ne 0 ]; then exit 1 ; fi ; \ cd .. ; \ fi ; \ done +else + @echo XXX - you do not have the sgml2html binary installed +endif texts: $(TEXTS) $(TEXTS) : $(FSRCS) +ifeq ($(HAVE_SGML2TXT),yes) @for i in $(FILES) ; do \ if [ ! -f "txts/$$i.txt" ] \ || [ "$$i.sgml" -nt "txts/$$i.txt" ]; then \ - cd txts ; $(TXTER) ../$$i ; cd .. ; \ + cd txts ; sgml2txt ../$$i ; cd .. ; \ fi ; \ done +else + @echo XXX - you do not have the sgml2txt binary installed +endif postscript: $(PSFILES) $(PSFILES): $(FSRCS) +ifneq ($(PSER),) @for i in $(FILES) ; do \ if [ ! -f "ps/$$i.ps" ] || [ "$$i.sgml" -nt "ps/$$i.ps" ]; then \ cd ps ; $(PSER) ../$$i ; cd .. ; \ fi ; \ done +else + @echo XXX - neither sgml2ps nor sgml2latex binaries are installed +endif -pam.sgml: pam_source.sgml MODULES-SGML - @sed -e '/^/r MODULES-SGML' pam_source.sgml > pam.sgml +pam.sgml: pam_source.sgml MODULES-SGML CREDITS + @sed -e '/^/r MODULES-SGML' pam_source.sgml | sed -e '/^/r CREDITS' > pam.sgml MODULES-SGML: $(MODULES) @echo 'Building module text from files in modules/*.sgml' @@ -67,11 +82,64 @@ MODULES-SGML: $(MODULES) extraclean: clean +remove: + cd man && for file in *.3 ; do \ + rm -f $(FAKEROOT)$(MANDIR)/man3/$$file ; \ + done + cd man && for file in *.8 ; do \ + rm -f $(FAKEROOT)$(MANDIR)/man8/$$file ; \ + done + cd txts && for file in *.txt; do \ + rm -f $(FAKEROOT)$(DOCDIR)/text/$$file ; \ + done + cd ps && for file in *.ps; do \ + rm -f $(FAKEROOT)$(DOCDIR)/ps/$$file ; \ + done + cd html && for file in *.html; do \ + rm -f $(FAKEROOT)$(DOCDIR)/html/$$file ; \ + done + +install: all +ifeq ($(HAVE_SGML2TXT),yes) + mkdir -p $(FAKEROOT)$(DOCDIR)/text + for file in txts/*.txt; do \ + install -m 644 $$file $(FAKEROOT)$(DOCDIR)/text ; \ + done +endif +ifneq ($(PSER),) + mkdir -p $(FAKEROOT)$(DOCDIR)/ps + for file in ps/*.ps; do \ + install -m 644 $$file $(FAKEROOT)$(DOCDIR)/ps ; \ + done +endif +ifeq ($(HAVE_SGML2HTML),yes) + mkdir -p $(FAKEROOT)$(DOCDIR)/html + for file in html/*.html; do \ + install -m 644 $$file $(FAKEROOT)$(DOCDIR)/html ; \ + done +endif + mkdir -p $(FAKEROOT)$(MANDIR)/man{3,8} + for file in man/*.3 ; do \ + install -m 644 $$file $(FAKEROOT)$(MANDIR)/man3 ; \ + done + for file in man/*.8 ; do \ + install -m 644 $$file $(FAKEROOT)$(MANDIR)/man8 ; \ + done + +spec: + cd specs/formatter && make + specs/formatter/padout < specs/draft-morgan-pam.raw > specs/draft-morgan-pam-current.txt + +releasedocs: all spec + tar zvfc Linux-PAM-$(MAJOR_REL).$(MINOR_REL)-docs.tar.gz --exclude CVS html ps txts specs/draft-morgan-pam-current.txt + clean: rm -f *~ *.bak rm -f html/pam*.html rm -f man/*~ rm -f $(TEXTS) - rm -f $(PSFILES) + rm -f $(PSFILES) ps/missfont.log rm -f MODULES-SGML pam.sgml + rm -f specs/draft-morgan-pam-current.txt + make -C specs/formatter clean diff --git a/contrib/libpam/doc/html/index.html b/contrib/libpam/doc/html/index.html index 91f990fc01e..5cb1e0f0ebb 100644 --- a/contrib/libpam/doc/html/index.html +++ b/contrib/libpam/doc/html/index.html @@ -17,5 +17,5 @@ currently not complete. However, in order of decreasing length:

-REVISION: $Id: index.html,v 1.4 1996/11/21 06:51:01 morgan Exp $ +REVISION: $Id: index.html,v 1.1.1.1 2000/06/20 22:10:56 agmorgan Exp $ diff --git a/contrib/libpam/doc/man/pam.conf.8 b/contrib/libpam/doc/man/pam.conf.8 index ea2dd98bfc9..d067b5596ea 100644 --- a/contrib/libpam/doc/man/pam.conf.8 +++ b/contrib/libpam/doc/man/pam.conf.8 @@ -1 +1 @@ -.so man8/pam.8 +.so pam.8 diff --git a/contrib/libpam/doc/man/pam.d.8 b/contrib/libpam/doc/man/pam.d.8 index ea2dd98bfc9..d067b5596ea 100644 --- a/contrib/libpam/doc/man/pam.d.8 +++ b/contrib/libpam/doc/man/pam.d.8 @@ -1 +1 @@ -.so man8/pam.8 +.so pam.8 diff --git a/contrib/libpam/doc/man/pam_close_session.3 b/contrib/libpam/doc/man/pam_close_session.3 index c809a0e4f0d..d851700cda0 100644 --- a/contrib/libpam/doc/man/pam_close_session.3 +++ b/contrib/libpam/doc/man/pam_close_session.3 @@ -1 +1 @@ -.so man3/pam_open_session.3 +.so pam_open_session.3 diff --git a/contrib/libpam/doc/man/pam_end.3 b/contrib/libpam/doc/man/pam_end.3 index 06fdabb9c46..de999f240cf 100644 --- a/contrib/libpam/doc/man/pam_end.3 +++ b/contrib/libpam/doc/man/pam_end.3 @@ -1 +1 @@ -.so man3/pam_start.3 +.so pam_start.3 diff --git a/contrib/libpam/doc/man/template-man b/contrib/libpam/doc/man/template-man index a635c8bd802..11e7a061504 100644 --- a/contrib/libpam/doc/man/template-man +++ b/contrib/libpam/doc/man/template-man @@ -1,5 +1,5 @@ .\" Hey Emacs! This file is -*- nroff -*- source. -.\" $Id: template-man,v 1.1 1997/01/04 18:25:13 morgan Exp $ +.\" $Id: template-man,v 1.1.1.1 2000/06/20 22:10:58 agmorgan Exp $ .\" Copyright (c) Andrew G. Morgan 1997 .TH PAM_???? 2 "1997 Jan 4" "Linux-PAM 0.55" "Application Programmers' Manual" .SH NAME diff --git a/contrib/libpam/doc/modules/pam_access.sgml b/contrib/libpam/doc/modules/pam_access.sgml new file mode 100644 index 00000000000..00c7ea169d0 --- /dev/null +++ b/contrib/libpam/doc/modules/pam_access.sgml @@ -0,0 +1,108 @@ + + + The access module + +Synopsis + +

+ + +Module Name: + +pam_access + + +Author[s]: + +Alexei Nogin <alexei@nogin.dnttm.ru> + +Maintainer: + +Author + +Management groups provided: + +account + +Cryptographically sensitive: + +Security rating: + +Clean code base: + +System dependencies: +Requires a configuration file. By default +/etc/security/access.conf is used but this can be overridden. + +Network aware: + +Through + +Overview of module + +

+Provides logdaemon style login access control. + + Account component + +

+ + +Recognized arguments: + +accessfile=/path/to/file.conf + +Description: + +This module provides logdaemon style login access control based on +login names and on host (or domain) names, internet addresses (or +network numbers), or on terminal line names in case of non-networked +logins. Diagnostics are reported through +The behavior of this module can be modified with the following +arguments: + + +accessfile=/path/to/file.conf - +indicate an alternative + +Examples/suggested usage: + +Use of module is recommended, for example, on administrative machines +such as /etc/pam.d style configurations where your modules live +in /lib/security, start by adding the following line to +/etc/pam.d/login, /etc/pam.d/rlogin, +/etc/pam.d/rsh and /etc/pam.d/ftp: + + + +account required /lib/security/pam_access.so + + + +Note that use of this module is not effective unless your system ignores +.rhosts files. See the the pam_rhosts_auth documentation. + +A sample access.conf configuration file is included with the +distribution. + + diff --git a/contrib/libpam/doc/modules/pam_issue.sgml b/contrib/libpam/doc/modules/pam_issue.sgml new file mode 100644 index 00000000000..1f617e3b870 --- /dev/null +++ b/contrib/libpam/doc/modules/pam_issue.sgml @@ -0,0 +1,120 @@ + + +Add issue file to user prompt + +Synopsis + +

+ + +Module Name: +Author: +Ben Collins <bcollins@debian.org> + +Maintainer: +Author + +Management groups provided: +Authentication (pam_sm_authenticate) + +Cryptographically sensitive: + +Security rating: + +Clean code base: + +System dependencies: + +Network aware: + + + +Overview of module + +

+This module prepends the issue file (/etc/issue by default) when +prompting for a username. + +Authentication component + +

+ + +Recognized arguments: +Description: +This module allows you to prepend an issue file to the username prompt. It +also by default parses escape codes in the issue file similar to some +common getty's (using \x format). +

+Recognized escapes: + + + + +

+The behavior of this module can be modified with one of the following +flags: + +

+ + + + +Examples/suggested usage: + +login auth pam_issue.so issue=/etc/issue + + + + diff --git a/contrib/libpam/doc/modules/pam_mkhomedir.sgml b/contrib/libpam/doc/modules/pam_mkhomedir.sgml new file mode 100644 index 00000000000..075e16f9fc0 --- /dev/null +++ b/contrib/libpam/doc/modules/pam_mkhomedir.sgml @@ -0,0 +1,83 @@ + + +Create home directories on initial login + +Synopsis + +

+ + +Module Name: +Author: +Jason Gunthorpe <jgg@ualberta.ca> + +Maintainer: +Ben Collins <bcollins@debian.org> + +Management groups provided: +Session + +Cryptographically sensitive: + +Security rating: + +Clean code base: + +System dependencies: + +Network aware: + + + +Overview of module + +

+Creates home directories on the fly for authenticated users. + +Session component + +

+ + +Recognized arguments: +Description: +This module is useful for distributed systems where the user account is +managed in a central database (such as NIS, NIS+, or LDAP) and accessed +through miltiple systems. It frees the administrator from having to create +a default home directory on each of the systems by creating it upon the +first succesfully authenticated login of that user. The skeleton directory +(usually /etc/skel/) is used to copy default files and also set's a umask +for the creation. + +

+The behavior of this module can be modified with one of the following +flags: + +

+ + + + +Examples/suggested usage: + +session required pam_mkhomedir.so skel=/etc/skel/ umask=0022 + + + + diff --git a/contrib/libpam/doc/modules/pam_motd.sgml b/contrib/libpam/doc/modules/pam_motd.sgml new file mode 100644 index 00000000000..8ddc63924e7 --- /dev/null +++ b/contrib/libpam/doc/modules/pam_motd.sgml @@ -0,0 +1,77 @@ + + +Output the motd file + +Synopsis + +

+ + +Module Name: +Author: +Ben Collins <bcollins@debian.org> + +Maintainer: +Author + +Management groups provided: +Session (open) + +Cryptographically sensitive: + +Security rating: + +Clean code base: + +System dependencies: + +Network aware: + + + +Overview of module + +

+This module outputs the motd file (/etc/motd by default) upon +successful login. + +Session component + +

+ + +Recognized arguments: +Description: +This module allows you to have arbitrary motd's (message of the day) +output after a succesful login. By default this file is /etc/motd, +but is configurable to any file. + +

+The behavior of this module can be modified with one of the following +flags: + +

+ + + + +Examples/suggested usage: + +login session pam_motd.so motd=/etc/motd + + + + diff --git a/contrib/libpam/doc/modules/pam_tally.sgml b/contrib/libpam/doc/modules/pam_tally.sgml new file mode 100644 index 00000000000..aca41bbde0f --- /dev/null +++ b/contrib/libpam/doc/modules/pam_tally.sgml @@ -0,0 +1,191 @@ + + +The login counter (tallying) module + +Synopsis + +

+ + +Module Name: +pam_tally + +Author[s]: +Tim Baverstock + +Maintainer: + +Management groups provided: +auth; account + +Cryptographically sensitive: + +Security rating: + +Clean code base: + +System dependencies: +A faillog file (default location /var/log/faillog) + +Network aware: + + + +Overview of module + +

+This module maintains a count of attempted accesses, can reset count +on success, can deny access if too many attempts fail. + +

+pam_tally comes in two parts: pam_tally.so and +pam_tally. The former is the PAM module and the latter, a +stand-alone program. 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. For example, one might find it +useful to clear all counts every midnight from a cron job. + +

+The counts file is organized 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. + +

+Note, there are some outstanding issues with this module: +pam_tally is very dependant on getpw*() - a database +of usernames would be much more flexible; the `keep a count of current +logins' bit has been #ifdef'd out and you can only reset the +counter on successful authentication, for now. + +Generic options accepted by both components +

+ + onerr=(succeed|fail): + if something weird happens, such as unable to open the file, how + should the module react? + file=/where/to/keep/counts: + specify the file location for the counts. + The default location is /var/log/faillog. + + +Authentication component + +

+ + +Recognized arguments: +onerr=(succeed|fail); +file=/where/to/keep/counts; +no_magic_root + +Description: + +

+The authentication component of this module increments the attempted +login counter. + +

+Examples/suggested usage: + +

+The module argument no_magic_root is used to indicate that if +the module is invoked by a user with uid=0, then the counter is +incremented. The sys-admin should use this for daemon-launched +services, like telnet/rsh/login. For user +launched services, like su, this argument should be omitted. + +

+By way of more explanation, when a process already running as root +tries to access some service, the access is magic, and +bypasses pam_tally's checks: this is handy for suing +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. + + + +Account component + +

+ + +Recognized arguments: +onerr=(succeed|fail); +file=/where/to/keep/counts; +deny=n; +no_magic_root; +even_deny_root_account; +reset; +no_reset; +per_user; +no_lock_time + +Description: + +

+The account component can deny access and/or reset the attempts +counter. It also checks to make sure that the counts file is a plain +file and not world writable. + +Examples/suggested usage: + +

+The deny=n option is used to 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 gain access is root and the no_magic_root option +has NOT been specified. + +

+The no_magic_root option ensures that access attempts by root +DON'T ignore deny. Use this for daemon-based stuff, like +telnet/rsh/login. + +

+The even_deny_root_account option is used to ensure that the +root account can become unavailable. Note that magic root +trying to gain root bypasses this, but normal users can be locked out. + +

+The reset option instructs the module to reset count to 0 on +successful entry, even for magic root. The no_reset option is +used to instruct the module to not reset the count on successful +entry. This is the default unless deny exists and the user +attempting access is NOT magic root. + +

+If /var/log/faillog contains a non-zero .fail_max +field for this user then the per_user module argument will +ensure that the module uses this value and not the global +deny=n parameter. + +

+The no_lock_time option is for ensuring that the module does +not use the .fail_locktime field in /var/log/faillog for this +user. + +

+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. + + + + diff --git a/contrib/libpam/doc/modules/pam_unix.sgml b/contrib/libpam/doc/modules/pam_unix.sgml new file mode 100644 index 00000000000..71cb07e3286 --- /dev/null +++ b/contrib/libpam/doc/modules/pam_unix.sgml @@ -0,0 +1,288 @@ + + +The Unix Password module + +Synopsis + +

+ + +Module Name: +pam_unix + +Author: + +Maintainer: + +Management groups provided: +account; authentication; password; session + +Cryptographically sensitive: + +Security rating: + +Clean code base: + +System dependencies: + +Network aware: + + + +Overview of module + +

+This is the standard Unix authentication module. It uses standard calls +from the system's libraries to retrieve and set account information as +well as authentication. Usually this is obtained from the /etc/passwd +and the /etc/shadow file as well if shadow is enabled. + +Account component + +

+ + +Recognized arguments: +Description: + +The Examples/suggested usage: + +In its accounting mode, this module can be inserted as follows: + + +# +# Ensure users account and password are still active +# +login account required pam_unix.so + + + + + +Authentication component + +

+ + +Recognized arguments: +Description: + +The +The default action of this module is to not permit the user access to +a service if their +When given the argument +The argument, nodelay, can be used to discourage the +authentication component from requesting a delay should the +authentication as a whole fail. The default action is for the module +to request a delay-on-failure of the order of one second. + +

+Remaining arguments, supported by the other functions of this module, +are silently ignored. Other arguments are logged as errors through + +A helper binary, unix_chkpwd, is provided to check the user's +password when it is stored in a read protected database. This binary +is very simple and will only check the password of the user invoking +it. It is called transparently on behalf of the user by the +authenticating component of this module. In this way it is possible +for applications like xlock to work without being setuid-root. + +Examples/suggested usage: + +The correct functionality of this module is dictated by having an +appropriate /etc/nsswitch.conf file, the user +databases specified there dictate the source of the authenticated +user's record. +

+In its authentication mode, this module can be inserted as follows: + + +# +# Authenticate the user +# +login auth required pam_unix.so + + + + + +Password component + +

+ + +Recognized arguments: +Description: + +This part of the +In the case of conventional unix databases (which store the password +encrypted) the +The +The argument +The +The +With the +The /etc/security/opasswd in order to force password change history +and keep the user from alternating between the same password too frequently. + +Examples/suggested usage: + +Standard usage: + + +# +# Change the users password +# +passwd password required pam_unix.so + + + +

+An example of the stacking of this module with respect to the +pluggable password checking module, + +# +# Change the users password +# +passwd password required pam_cracklib.so retry=3 minlen=6 difok=3 +passwd password required pam_unix.so use_authtok nullok md5 + + + + + +Session component + +

+ + +Recognized arguments: + +Description: + +No arguments are recognized by this module component. Its action is +simply to log the username and the service-type to +Examples/suggested usage: + +The use of the session modules is straightforward: + + +# +# session opening and closing +# +login session required pam_unix.so + + + + + + diff --git a/contrib/libpam/doc/modules/pam_userdb.sgml b/contrib/libpam/doc/modules/pam_userdb.sgml new file mode 100644 index 00000000000..bdbf80b821d --- /dev/null +++ b/contrib/libpam/doc/modules/pam_userdb.sgml @@ -0,0 +1,112 @@ + + +The userdb module + +Synopsis + +

+ + +Module Name: +Author: +Cristian Gafton <gafton@redhat.com> + +Maintainer: +Author. + +Management groups provided: +authentication + +Cryptographically sensitive: + +Security rating: + +Clean code base: + +System dependencies: +Requires Berkeley DB. + +Network aware: + + + +Overview of module + +

+Look up users in a .db database and verify their password against +what is contained in that database. + +Authentication component + +

+ + +Recognized arguments: +Description: + +This module is used to verify a username/password pair against values stored in +a Berkeley DB database. The database is indexed by the username, and the data +fields corresponding to the username keys are the passwords, in unencrypted form, +so caution must be exercised over the access rights to the DB database itself.. + +The module will read the password from the user using the conversation mechanism. If +you are using this module on top of another authetication module (like +The action of the module may be modified from this default by one or +more of the following flags in the /etc/pam.d/<service> file. + + + + + +/etc/foodata +instead of /etc/foodata.db. + + + +Examples/suggested usage: + +This is a normal ftp configuration file (usually placed as /etc/pam.d/ftp +on most systems) that will accept for login users whose username/password pairs are +provided in the /tmp/dbtest.db file: + + + +#%PAM-1.0 +auth required pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed +auth sufficient pam_userdb.so icase db=/tmp/dbtest +auth required pam_pwdb.so shadow nullok try_first_pass +auth required pam_shells.so +account required pam_pwdb.so +session required pam_pwdb.so + + + + + + diff --git a/contrib/libpam/doc/pam_appl.sgml b/contrib/libpam/doc/pam_appl.sgml index 7c4170ae47b..c32ee136b43 100644 --- a/contrib/libpam/doc/pam_appl.sgml +++ b/contrib/libpam/doc/pam_appl.sgml @@ -2,9 +2,9 @@ +Chris Adams, Peter Allgeyer, Tim Baverstock, +Tim Berger, Craig S. Bell, Derrick J. Brashear, Ben Buxton, +Seth Chaiklin, Oliver Crow, Chris Dent, Marc Ewing, Cristian Gafton, +Emmanuel Galanos, +Brad M. Garcia, Eric Hester, Roger Hu, Eric Jacksch, Michael K. Johnson, David Kinchlea, +Olaf Kirch, +Marcin Korzonek, +Stephen Langasek, Nicolai Langfeldt, Elliot Lee, +Luke Kenneth Casson Leighton, Al Longyear, Ingo Luetkebohle, Marek Michalkiewicz, +Robert Milkowski, Aleph One, Martin Pool, Sean Reifschneider, +Jan Rekorajski, Erik Troan, Theodore Ts'o, Jeff Uphoff, @@ -1495,7 +1604,6 @@ Joseph S. D. Yao and Alex O. Yuriev. -

Thanks are also due to Sun Microsystems, especially to Vipin Samar and Charlie Lai for their advice. At an early stage in the development of @@ -1512,7 +1620,7 @@ credited for all the good work they have done. Copyright information for this document

-Copyright (c) Andrew G. Morgan 1996, 1997. All rights reserved. +Copyright (c) Andrew G. Morgan 1996-9. All rights reserved. Email: <morgan@transmeta.com> @@ -1562,6 +1670,6 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

-$Id: pam_appl.sgml,v 1.16 1997/04/05 06:49:14 morgan Exp morgan $ +$Id: pam_appl.sgml,v 1.5 2001/03/19 01:46:41 agmorgan Exp $ diff --git a/contrib/libpam/doc/pam_modules.sgml b/contrib/libpam/doc/pam_modules.sgml index 418b09beafd..609916c4470 100644 --- a/contrib/libpam/doc/pam_modules.sgml +++ b/contrib/libpam/doc/pam_modules.sgml @@ -2,9 +2,9 @@ - +Chris Adams, Peter Allgeyer, Tim Baverstock, +Tim Berger, Craig S. Bell, Derrick J. Brashear, Ben Buxton, +Seth Chaiklin, Oliver Crow, Chris Dent, Marc Ewing, Cristian Gafton, +Emmanuel Galanos, +Brad M. Garcia, Eric Hester, Roger Hu, Eric Jacksch, Michael K. Johnson, David Kinchlea, +Olaf Kirch, +Marcin Korzonek, +Stephen Langasek, Nicolai Langfeldt, Elliot Lee, +Luke Kenneth Casson Leighton, Al Longyear, Ingo Luetkebohle, Marek Michalkiewicz, +Robert Milkowski, Aleph One, Martin Pool, Sean Reifschneider, +Jan Rekorajski, Erik Troan, Theodore Ts'o, Jeff Uphoff, @@ -1420,6 +1493,6 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

-$Id: pam_modules.sgml,v 1.19 1997/04/05 06:49:14 morgan Exp morgan $ +$Id: pam_modules.sgml,v 1.6 2001/02/22 04:58:51 agmorgan Exp $ diff --git a/contrib/libpam/doc/pam_source.sgml b/contrib/libpam/doc/pam_source.sgml index 093998a0aad..5e4be447bb3 100644 --- a/contrib/libpam/doc/pam_source.sgml +++ b/contrib/libpam/doc/pam_source.sgml @@ -2,9 +2,9 @@ - -Craig S. Bell, -Derrick J. Brashear, -Ben Buxton, -Oliver Crow, -Marc Ewing, -Cristian Gafton, -Eric Hester, -Eric Jacksch, -Michael K. Johnson, -David Kinchlea, -Elliot Lee, -Al Longyear, -Marek Michalkiewicz, -Aleph One, -Sean Reifschneider, -Eric Troan, -Theodore Ts'o, -Jeff Uphoff, -Ronald Wahl, -John Wilmes, -Joseph S. D. Yao -and -Alex O. Yuriev. - +

Thanks are also due to Sun Microsystems, especially to Vipin Samar and @@ -920,9 +1063,6 @@ development of -Currently there is no documentation for PAM-aware applications. -

This manual is unfinished. Only a partial list of people is credited for all the good work they have done. @@ -930,9 +1070,9 @@ for all the good work they have done. Copyright information for this document

-Copyright (c) Andrew G. Morgan 1996. All rights reserved. +Copyright (c) Andrew G. Morgan 1996-9. All rights reserved. -Email: <morgan@parc.power.net> +Email: <morgan@linux.kernel.org>

Redistribution and use in source and binary forms, with or without @@ -980,6 +1120,6 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

-$Id: pam_source.sgml,v 1.5 1997/04/05 06:49:14 morgan Exp morgan $ +$Id: pam_source.sgml,v 1.5 2001/03/19 01:46:41 agmorgan Exp $ diff --git a/contrib/libpam/doc/specs/draft-morgan-pam.raw b/contrib/libpam/doc/specs/draft-morgan-pam.raw new file mode 100644 index 00000000000..dec3e566721 --- /dev/null +++ b/contrib/libpam/doc/specs/draft-morgan-pam.raw @@ -0,0 +1,702 @@ +PAM working group ## A.G. Morgan +Internet Draft: ## October 6, 1999 +Document: draft-morgan-pam-07.txt ## +Expires: June 13, 2000 ## +Obsoletes: draft-morgan-pam-06.txt## + +## Pluggable Authentication Modules ## + +#$ Status of this memo + +This document is an draft specification. The latest version of this +draft may be obtained from here: + + http://linux.kernel.org/pub/linux/libs/pam/pre/doc/ + +As + + Linux-PAM-'version'-docs.tar.gz + +It is also contained in the Linux-PAM tar ball. + +#$ Abstract + +This document is concerned with the definition of a general +infrastructure for module based authentication. The infrastructure is +named Pluggable Authentication Modules (PAM for short). + +#$ Introduction + +Computers are tools. They provide services to people and other +computers (collectively we shall call these _users_ entities). In +order to provide convenient, reliable and individual service to +different entities, it is common for entities to be labelled. Having +defined a label as referring to a some specific entity, the label is +used for the purpose of protecting and allocating data resources. + +All modern operating systems have a notion of labelled entities and +all modern operating systems face a common problem: how to +authenticate the association of a predefined label with applicant +entities. + +There are as many authentication methods as one might care to count. +None of them are perfect and none of them are invulnerable. In +general, any given authentication method becomes weaker over time. It +is common then for new authentication methods to be developed in +response to newly discovered weaknesses in the old authentication +methods. + +The problem with inventing new authentication methods is the fact that +old applications do not support them. This contributes to an inertia +that discourages the overhaul of weakly protected systems. Another +problem is that individuals (people) are frequently powerless to layer +the protective authentication around their systems. They are forced +to rely on single (lowest common denominator) authentication schemes +even in situations where this is far from appropriate. + +PAM, as discussed in this document, is a generalization of the +approach first introduced in [#$R#{OSF_RFC_PAM}]. In short, it is a +general framework of interfaces that abstract the process of +authentication. With PAM, a service provider can custom protect +individual services to the level that they deem is appropriate. + +PAM has nothing explicit to say about transport layer encryption. +Within the context of this document encryption and/or compression of +data exchanges are application specific (strictly between client and +server) and orthogonal to the process of authentication. + +#$ Definitions + +Here we pose the authentication problem as one of configuring defined +interfaces between two entities. + +#$$#{players} Players in the authentication process + +PAM reserves the following words to specify unique entities in the +authentication process: + + applicant + the entity (user) initiating an application for service + [PAM associates the PAM_RUSER _item_ with this requesting user]. + + arbitrator + the entity (user) under whose identity the service application + is negotiated and with whose authority service is granted. + + user + the entity (user) whose identity is being authenticated + [PAM associates the PAM_USER _item_ with this identity]. + + server + the application that provides service, or acts as an + authenticated gateway to the requested service. This + application is completely responsible for the server end of + the transport layer connecting the server to the client. + PAM makes no assumptions about how data is encapsulated for + exchanges between the server and the client, only that full + octet sequences can be freely exchanged without corruption. + + client + application providing the direct/primary interface to + applicant. This application is completely responsible + for the client end of the transport layer connecting the + server to the client. PAM makes no assumptions about how data + is encapsulated for exchanges between the server and the + client, only that full octet sequences can be freely + exchanged without corruption. + + module + authentication binary that provides server-side support for + some (arbitrary) authentication method. + + agent + authentication binary that provides client-side support for + some (arbitrary) authentication method. + +Here is a diagram to help orient the reader: + +## +-------+ +--------+ ## +## . . . . .| agent | .| module | ## +## . +-------+ .+--------+ ## +## V | . | ## +## . | V | ## +## +---------+ +-------+ . +------+ ## +## | | |libpamc| . |libpam| ## +## | | +-------+ . +------+ ## +## |applicant| | . | ## +## | | +--------+ +----------+ ## +## | |---| client |-----------| server | ## +## +---------+ +--------+ +----------+ ## + +Solid lines connecting the boxes represent two-way interaction. The +dotted-directed lines indicate an optional connection beteween the +plugin module (agent) and the server (applicant). In the case of the +module, this represents the module invoking the 'conversation' +callback function provided to libpam by the server application when it +inititializes the libpam library. In the case of the agent, this may +be some out-of-PAM API interaction (for example directly displaying a +dialog box under X). + +#$$ Defined Data Types + +In this draft, we define two composite data types, the text string and +the binary prompt. They are the data types used to communicate +authentication requests and responses. + +#$$$#{text_string} text string + +The text string is a simple sequence of non-NUL (NUL = 0x00) +octets. Terminated with a single NUL (0x00) octet. The character set +employed in the octet sequence may be negotiated out of band, but +defaults to utf-8. + +## --------------------------- ## +## [ character data | NUL ] ## +## [ octet sequence | 0x00 ] ## +## --------------------------- ## + +Within the rest of this text, PAM text strings are delimited with a +pair of double quotes. Example, "this" = {'t';'h';'i';'s';0x00}. + +#$$$#{binary_prompt} binary prompt + +A binary prompt consists of a stream of octets arranged as follows: + +## ---------------------------------------- ## +## [ u32 | u8 | (length-5 octets) ] ## +## [ length | control | data ] ## +## ---------------------------------------- ## + +That is, a 32-bit unsigned integer in network byte order, a single +unsigned byte of control information and a sequence of octets of +length (length-5). The composition of the _data_ is context dependent +but is generally not a concern for either the server or the client. It +is very much the concern of modules and agents. + +For purposes of interoperability, we define the following control +characters as legal. + +## value symbol description ## +## ------------------------------------------------- ## +## 0x01 PAM_BPC_OK - continuation packet ## +## 0x02 PAM_BPC_SELECT - initialization packet ## +## 0x03 PAM_BPC_DONE - termination packet ## +## 0x04 PAM_BPC_FAIL - unable to execute ## + +The following control characters are only legal for exchanges between +an agent and a client (it is the responsibility of the client to +enforce this rule in the face of a rogue server): + +## 0x41 PAM_BPC_GETENV - obtain client env.var ## +## 0x42 PAM_BPC_PUTENV - set client env.var ## +## 0x43 PAM_BPC_TEXT - display message ## +## 0x44 PAM_BPC_ERROR - display error message ## +## 0x45 PAM_BPC_PROMPT - echo'd text prompt ## +## 0x46 PAM_BPC_PASS - non-echo'd text prompt## + +Note, length is always equal to the total length of the binary +prompt and represented by a network ordered unsigned 32 bit integer. + +#$$$$#{agent_ids} PAM_BPC_SELECT binary prompts + +Binary prompts of control type PAM_BPC_SELECT have a defined +data part. It is composed of three elements: + + {agent_id;'/';data} + +The agent_id is a sequence of characters satisfying the following +regexp: + + /^[a-z0-9\_]+(@[a-z0-9\_.]+)?$/ + +and has a specific form for each independent agent. + +o Agent_ids that do not contain an at-sign (@) are reserved to be + assigned by IANA (Internet Assigned Numbers Authority). Names of + this format MUST NOT be used without first registering with IANA. + Registered names MUST NOT contain an at-sign (@). + +o Anyone can define additional agents by using names in the format + name@domainname, e.g. "ouragent@example.com". The part following + the at-sign MUST be a valid fully qualified internet domain name + [RFC-1034] controlled by the person or organization defining the + name. (Said another way, if you control the email address that + your agent has as an identifier, they you are entitled to use + this identifier.) It is up to each domain how it manages its local + namespace. + +The '/' character is a mandatory delimiter, indicating the end of the +agent_id. The trailing data is of a format specific to the agent with +the given agent_id. + + +#$$ Special cases + +In a previous section (#{players}) we identified the most general +selection of authentication participants. In the case of network +authentication, it is straightforward to ascribe identities to the +defined participants. However, there are also special (less general) +cases that we recognize here. + +The primary authentication step, when a user is directly introduced +into a computer system (log's on to a workstation) is a special case. +In this situation, the client and the server are generally one +application. Before authenticating such a user, the applicant is +formally unknown: PAM_RUSER is NULL. + +Some client-server implementations (telnet for example) provide +effective full tty connections. In these cases, the four simple text +string prompting cases (see below) can be handled as in the primary +login step. In other words, the server absorbs most of the overhead of +propagating authentication messages. In these cases, there is special +client/server support for handling binary prompts. + +#$ Defined interfaces for information flow + +Here, we discuss the information exchange interfaces between the +players in the authentication process. It should be understood that +the server side is responsible for driving the authentication of the +applicant. Notably, every request received by the client from the +server must be matched with a single response from the client to the +server. + +#$$#{applicant_client} Applicant <-> client + +Once the client is invoked, requests to the applicant entity are +initiated by the client application. General clients are able to make +the following requests directly to an applicant: + + echo text string + echo error text string + prompt with text string for echo'd text string input + prompt with text string for concealed text string input + +the nature of the interface provided by the client for the benefit of +the applicant entity is client specific and not defined by PAM. + +#$$#{client_agent} Client <-> agent + +In general, authentication schemes require more modes of exchange than +the four defined in the previous section (#{applicant_client}). This +provides a role for client-loadable agents. The client and agent +exchange binary-messages that can have one of the following forms: + + client -> agent + binary prompt agent expecting binary prompt reply to client + + agent -> client + binary prompt reply from agent to clients binary prompt + +Following the acceptance of a binary prompt by the agent, the agent +may attempt to exchange information with the client before returning +its binary prompt reply. Permitted exchanges are binary prompts of the +following types: + + agent -> client + set environment variable (A) + get environment variable (B) + echo text string (C) + echo error text string (D) + prompt for echo'd text string input (E) + prompt for concealed text string input (F) + +In response to these prompts, the client must legitimately respond +with a corresponding binary prompt reply. We list a complete set of +example exchanges, including each type of legitimate response (passes +and a single fail): + +## Type | Agent request | Client response ## +## --------------------------------------------------------------- ## +## (A) | {13;PAM_BPC_PUTENV;"FOO=BAR"} | {5;PAM_BPC_OK;} ## +## | {10;PAM_BPC_PUTENV;"FOO="} | {5;PAM_BPC_OK;} ## +## | {9;PAM_BPC_PUTENV;"FOO"} (*) | {5;PAM_BPC_OK;} ## +## | {9;PAM_BPC_PUTENV;"BAR"} (*) | {5;PAM_BPC_FAIL;} ## +## --------------------------------------------------------------- ## +## (B) | {10;PAM_BPC_GETENV;"TERM"} | {11;PAM_BPC_OK;"vt100"} ## +## | {9;PAM_BPC_GETENV;"FOO"} | {5;PAM_BPC_FAIL;} ## +## --------------------------------------------------------------- ## +## (C) | {12;PAM_BPC_TEXT;"hello!"} | {5;PAM_BPC_OK;} ## +## | {12;PAM_BPC_TEXT;"hello!"} | {5;PAM_BPC_FAIL;} ## +## --------------------------------------------------------------- ## +## (D) | {11;PAM_BPC_TEXT;"ouch!"} | {5;PAM_BPC_OK;} ## +## | {11;PAM_BPC_TEXT;"ouch!"} | {5;PAM_BPC_FAIL;} ## +## --------------------------------------------------------------- ## +## (E) | {13;PAM_BPC_PROMPT;"login: "} | {9;PAM_BPC_OK;"joe"} ## +## | {13;PAM_BPC_PROMPT;"login: "} | {6;PAM_BPC_OK;""} ## +## | {13;PAM_BPC_PROMPT;"login: "} | {5;PAM_BPC_FAIL;} ## +## --------------------------------------------------------------- ## +## (F) | {16;PAM_BPC_PASS;"password: "} | {9;PAM_BPC_OK;"XYZ"} ## +## | {16;PAM_BPC_PASS;"password: "} | {6;PAM_BPC_OK;""} ## +## | {16;PAM_BPC_PASS;"password: "} | {5;PAM_BPC_FAIL;} ## + +(*) Used to attempt the removal of a pre-existing environment +variable. + +#$$ Client <-> server + +Once the client has established a connection with the server (the +nature of the transport protocol is not specified by PAM), the server +is responsible for driving the authentication process. + +General servers can request the following from the client: + + (to be forwarded by the client to the applicant) + echo text string + echo error text string + prompt for echo'd text string response + prompt for concealed text string response + + (to be forwarded by the client to the appropriate agent) + binary prompt for a binary prompt response + +Client side agents are required to process binary prompts. The +agents' binary prompt responses are returned to the server. + +#$$ Server <-> module + +Modules drive the authentication process. The server provides a +conversation function with which it encapsulates module-generated +requests and exchanges them with the client. Every message sent by a +module should be acknowledged. + +General conversation functions can support the following five +conversation requests: + + echo text string + echo error string + prompt for echo'd text string response + prompt for concealed text string response + binary prompt for binary prompt response + +The server is responsible for redirecting these requests to the +client. + +#$ C API for application interfaces (client and server) + +#$$ Applicant <-> client + +No API is defined for this interface. The interface is considered to +be specific to the client application. Example applications include +terminal login, (X)windows login, machine file transfer applications. + +All that is important is that the client application is able to +present the applicant with textual output and to receive textual +input from the applicant. The forms of textual exchange are listed +in an earlier section (#{applicant_client}). Other methods of +data input/output are better suited to being handled via an +authentication agent. + +#$$ Client <-> agent + +The client makes use of a general API for communicating with +agents. The client is not required to communicate directly with +available agents, instead a layer of abstraction (in the form of a +library: libpamc) takes care of loading and maintaining communication +with all requested agents. This layer of abstraction will choose which +agents to interact with based on the content of binary prompts it +receives that have the control type PAM_BPC_SELECT. + +#$$$ Client <-> libpamc + +#$$$$ Compilation information + +The C-header file provided for client-agent abstraction is included +with the following source line: + + \#include + +The library providing the corresponding client-agent abstraction +functions is, libpamc. + + cc .... -lpamc + +#$$$$ Initializing libpamc + +The libpamc library is initialized with a call to the following +function: + + pamc_handle_t pamc_start(void); + +This function is responsible for configuring the library and +registering the location of available agents. The location of the +available agents on the system is implementation specific. + +pamc_start() function returns NULL on failure. Otherwise, the return +value is a pointer to an opaque data type which provides a handle to +the libpamc library. On systems where threading is available, the +libpamc libraray is thread safe provided a single (pamc_handler_t *) +is used by each thread. + +#$$$$ Client (Applicant) selection of agents + +For the purpose of applicant and client review of available agents, +the following function is provided. + + char **pamc_list_agents(pamc_handle_t pch); + +This returns a list of pointers to the agent_id's of the agents which +are available on the system. The list is terminated by a NULL pointer. +It is the clients responsibility to free this memory area by calling +free() on each agent id and the block of agent_id pointers in the +result. + +PAM represents a server-driven authentication model, so by default +any available agent may be invoked in the authentication process. + +#$$$$$ Client demands agent + +If the client requires that a specific authentication agent is +satisfied during the authentication process, then the client should +call the following function, immediately after obtaining a +pamc_handle_t from pamc_start(). + + int pamc_load(pamc_handle_t pch, const char *agent_id); + +agent_id is a PAM text string (see section #{agent_ids}) and is not +suffixed with a '/' delimiter. The return value for this function is: + + PAM_BPC_TRUE - agent located and loaded. + PAM_BPC_FALSE - agent is not available. + +Note, although the agent is loaded, no data is fed to it. The agent's +opportunity to inform the client that it does not trust the server is +when the agent is shutdown. + +#$$$$$ Client marks agent as unusable + +The applicant might prefer that a named agent is marked as not +available. To do this, the client would invoke the following function +immediately after obtaining a pamc_handle_t from pam_start(). + + int pamc_disable(pamc_handle_t pch, const char *agent_id); + +here agent_id is a PAM text string containing an agent_id (section +#{agent_ids}). + +The return value for this function is: + + PAM_BPC_TRUE - agent is disabled. This is the response + independent of whether the agent is locally + available. + + PAM_BPC_FALSE - agent cannot be disabled (this may be because + it has already been invoked). + +#$$$$ Allocating and manipulating binary prompts + +All conversation between an client and an agent takes place with +respect to binary prompts. A binary prompt (see section #{binary_prompt}), is +obtained, resized and deleted via the following C-macro: + + CREATION of a binary prompt with control X1 and data length Y1: + + pamc_bp_t prompt = NULL; + PAM_BP_RENEW(&prompt, X1, Y1); + + REPLACEMENT of a binary prompt with a control X2 and data length Y2: + + PAM_BP_RENEW(&prompt, X2, Y2); + + DELETION of a binary prompt (the referenced prompt is scrubbed): + + PAM_BP_RENEW(&prompt, 0, 0); + +Note, the PAM_BP_RENEW macro always overwrites any prompt that you +call it with, deleting and liberating the old contents in a secure +fashion. Also note that PAM_BP_RENEW, when returning a prompt of data +size Y1>0, will always append a '\0' byte to the end of the prompt (at +data offset Y1). It is thus, by definition, acceptable to treat the +data contents of a binary packet as a text string (see #{text_string}). + + FILLING a binary prompt from a memory pointer U1 from offset O1 of + length L1: + + PAM_BP_FILL(prompt, O1, L1, U1); + + the CONTROL type for the packet can be obtained as follows: + + control = PAM_PB_CONTROL(prompt); + + the LENGTH of a data within the prompt (_excluding_ its header + information) can be obtained as follows: + + length = PAM_BP_LENGTH(prompt); + + the total SIZE of the prompt (_including_ its header information) + can be obtained as follows: + + size = PAM_BP_SIZE(prompt); + + EXTRACTING data from a binary prompt from offset O2 of length L2 to + a memory pointer U2: + + PAM_BP_EXTRACT(prompt, O2, L2, U2); + + If you require direct access to the raw prompt DATA, you should use + the following macro: + + __u8 *raw_data = PAM_BP_DATA(prompt); + +#$$$$ Client<->agent conversations + +All exchanges of binary prompts with agents are handled with the +single function: + + int pamc_converse(pamc_handle_t *pch, pamc_bp_t *prompt_p); + +The return value for pamc_converse(...) is PAM_BPC_TRUE when there is +a response packet and PAM_BPC_FALSE when the client is unable to +handle the request represented by the original prompt. In this latter +case, *prompt_p is set to NULL. + +This function takes a binary prompt and returns a replacement binary +prompt that is either a request from an agent to be acted upon by the +client or the 'result' which should be forwarded to the server. In the +former case, the following macro will return 1 (PAM_BPC_TRUE) and in +all other cases, 0 (PAM_BPC_FALSE): + + PAM_BPC_FOR_CLIENT(/* pamc_bp_t */ prompt) + +Note, all non-NULL binary prompts returned by pamc_converse(...), are +terminated with a '\0', even when the full length of the prompt (as +returned by the agent) does not contain this delimiter. This is a +defined property of the PAM_BP_RENEW macro, and can be relied upon. + +Important security note: in certain implementations, agents are +implemented by executable binaries, which are transparently loaded and +managed by the PAM client library. To ensure there is never a leakage +of elevated privilege to an unprivileged agent, the client application +should go to some effort to lower its level of privilege. It remains +the responsibility of the applicant and the client to ensure that it +is not compromised by a rogue agent. + +#$$$$ Termination of agents + +When closing the authentication session and severing the connection +between a client and a selection of agents, the following function is +used: + + int pamc_end(pamc_handle_t *pch); + +Following a call to pamc_end, the pamc_handle_t will be invalid. + +The return value for this function is one of the following: + + PAM_BPC_TRUE - all invoked agents are content with + authentication (the server is _not_ judged + _un_trustworthy by any agent) + + PAM_BPC_FALSE - one or more agents were unsatisfied at + being terminated. In general, the client + should terminate its connection to the + server and indicate to the applicant that + the server is untrusted. + +#$$$ libpamc <-> agents + +The agents are manipulated from within libpamc. Each agent is an +executable in its own right. This permits the agent to have access to +sensitive data not accessible directly from the client. The mode of +communication between libpamc and an agent is through a pair of +pipes. The agent reads binary prompts (section #{binary_prompt}) +through its standard input file descriptor and writes response (to the +server) binary prompts and instruction binary prompts (instructions +for the client) through its standard output file descriptor. + +#$$ Client <-> server + +This interface is concerned with the exchange of text and binary +prompts between the client application and the server application. No +API is provided for this as it is considered specific to the transport +protocol shared by the client and the server. + +#$$ Server <-> modules + +The server makes use of a general API for communicating with +modules. The client is not required to communicate directly with +available modules. By abstracting the authentication interface, it +becomes possible for the local administrator to make a run time +decision about the authentication method adopted by the server. + +#$$$ Functions and definitions available to servers and modules + +[This section will document the following functions + + pam_set_item() + pam_get_item() + pam_fail_delay(pam_handle_t *pamh, unsigned int micro_sec) + pam_get_env(pam_handle_t *pamh, const char *varname) + pam_strerror(pam_handle_t *pamh, int pam_errno) +] + +#$$$ Server <-> libpam + +[This section will document the following pam_ calls: + + pam_start + pam_end + pam_authenticate (*) + pam_setcred + pam_acct_mgmt + pam_open_session + pam_close_session + pam_chauthtok (*) + +The asterisked functions may return PAM_INCOMPLETE. In such cases, the +application should be aware that the conversation function was called +and that it returned PAM_CONV_AGAIN to a module. The correct action +for the application to take in response to receiving PAM_INCOMPLETE, +is to acquire the replies so that the next time the conversation +function is called it will be able to provide the desired +responses. And then recall pam_authenticate (pam_chauthtok) with the +same arguments. Libpam will arrange that the module stack is resumed +from the module that returned before. This functionality is required +for programs whose user interface is maintained by an event loop. ] + +#$$$ libpam <-> modules + +[This section will document the following pam_ and pam_sm_ calls: + +functions provided by libpam + + pam_set_data + pam_get_data + +functions provided to libpam by each module + + groups: + AUTHENTICATION + pam_sm_authenticate + pam_sm_setcred + ACCOUNT + pam_sm_acct_mgmt + SESSION + pam_sm_open_session + pam_sm_close_session + AUTHENTICATION TOKEN MANAGEMENT + pam_sm_chauthtok +] + +#$ Security considerations + +This document is devoted to standardizing authentication +infrastructure: everything in this document has implications for +security. + +#$ Contact + +The email list for discussing issues related to this document is +. + +#$ References + +[#{OSF_RFC_PAM}] OSF RFC 86.0, "Unified Login with Pluggable Authentication + Modules (PAM)", October 1995 + +#$ Author's Address + +Andrew G. Morgan +Email: morgan@ftp.kernel.org + +## $Id: draft-morgan-pam.raw,v 1.1.1.1 2000/06/20 22:11:07 agmorgan Exp $ ## + diff --git a/contrib/libpam/libpam/Makefile b/contrib/libpam/libpam/Makefile index f3914a478b9..9d3e6d7391e 100644 --- a/contrib/libpam/libpam/Makefile +++ b/contrib/libpam/libpam/Makefile @@ -1,45 +1,14 @@ # -# $Id: Makefile,v 1.19 1997/04/05 06:58:43 morgan Exp morgan $ +# $Id: Makefile,v 1.4 2001/02/10 07:17:53 agmorgan Exp $ # -# $Log: Makefile,v $ -# Revision 1.19 1997/04/05 06:58:43 morgan -# fakeroot -# -# Revision 1.18 1997/02/15 15:56:09 morgan -# inherit major and minor numbers -# -# Revision 1.17 1997/01/04 20:03:09 morgan -# update for .55 -# -# Revision 1.16 1996/12/01 03:14:13 morgan -# update for .54 -# -# Revision 1.15 1996/11/10 20:07:51 morgan -# updated for .53 -# -# Revision 1.14 1996/09/05 06:06:53 morgan -# added local flag for locking, slight reorganization too. # +include ../Make.Rules + # need to tell libpam about the default directory for PAMs MOREFLAGS=-D"DEFAULT_MODULE_PATH=\"$(SECUREDIR)/\"" -# you may uncomment the following to build libpam in modified ways - -# lots of debugging information goes to /tmp/pam-debug.log -#MOREFLAGS += -D"DEBUG" - -# pay attention to locked /etc/pam.conf or /etc/pam.d/* files -#MOREFLAGS += -D"PAM_LOCKING" - -# read both the /etc/pam.d/ and pam.conf files specific to the deisred service -#MOREFLAGS += -D"PAM_READ_BOTH_CONFS" - -# make a kludge attempt to be compatible with the old pam_strerror -# calling convention -#MOREFLAGS += -D"UGLY_HACK_FOR_PRIOR_BEHAVIOR_SUPPORT" - -ifeq ($(DEBUG_REL),yes) +ifeq ($(WITH_LIBDEBUG),yes) LIBNAME=libpamd else LIBNAME=libpam @@ -49,12 +18,13 @@ MODIFICATION=.$(MINOR_REL) # --------------------------------------------- -dummy: - @echo "*** This is not a top-level Makefile!" +dummy: ../Make.Rules all # --------------------------------------------- -CFLAGS += $(DYNAMIC) $(STATIC) $(MOREFLAGS) +CFLAGS += $(DYNAMIC) $(STATIC) $(MOREFLAGS) \ + -DLIBPAM_VERSION_MAJOR=$(MAJOR_REL) \ + -DLIBPAM_VERSION_MINOR=$(MINOR_REL) # dynamic library names @@ -67,8 +37,11 @@ LIBPAMFULL = $(LIBPAMNAME)$(MODIFICATION) LIBPAMSTATIC = $(LIBNAME).a ifdef STATIC +@echo Did you mean to set STATIC\? MODULES = $(shell cat ../modules/_static_module_objects) STATICOBJ = pam_static.o +else +MODULES = endif ifdef MEMORY_DEBUG @@ -80,15 +53,16 @@ LIBOBJECTS = pam_item.o pam_strerror.o pam_end.o pam_start.o pam_data.o \ pam_account.o pam_auth.o pam_session.o pam_password.o \ pam_env.o pam_log.o $(EXTRAS) -ifdef DYNAMIC_LIBPAM +ifeq ($(DYNAMIC_LIBPAM),yes) +# libpam.so needs -ldl, too. DLIBOBJECTS = $(addprefix dynamic/,$(LIBOBJECTS) $(STATICOBJ)) -ifdef STATICOBJ +ifeq ($(STATICOBJ),yes) dynamic/pam_static.o: pam_static.c ../modules/_static_module_objects $(CC) $(CFLAGS) -c pam_static.c -o $@ endif endif -ifdef STATIC_LIBPAM +ifeq ($(STATIC_LIBPAM),yes) SLIBOBJECTS = $(addprefix static/,$(LIBOBJECTS) $(STATICOBJ)) ifdef STATICOBJ static/pam_static.o: pam_static.c ../modules/_static_module_objects @@ -99,45 +73,46 @@ endif # --------------------------------------------- ## rules -all: dirs $(LIBPAM) $(LIBPAMSTATIC) +all: dirs $(LIBPAM) $(LIBPAMSTATIC) ../Make.Rules dirs: -ifdef DYNAMIC_LIBPAM - mkdir -p dynamic +ifeq ($(DYNAMIC_LIBPAM),yes) + $(MKDIR) dynamic endif -ifdef STATIC_LIBPAM - mkdir -p static +ifeq ($(STATIC_LIBPAM),yes) + $(MKDIR) static endif dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ $(LIBPAM): $(DLIBOBJECTS) -ifdef DYNAMIC_LIBPAM +ifeq ($(DYNAMIC_LIBPAM),yes) ifeq ($(USESONAME),yes) - $(LD_L) $(SOSWITCH) $(LIBPAMNAME) -o $@ $(DLIBOBJECTS) $(MODULES) + $(LD_L) $(SOSWITCH) $(LIBPAMNAME) -o $@ $(DLIBOBJECTS) \ + $(MODULES) $(LINKLIBS) else - $(LD_L) -o $@ $(DLIBOBJECTS) $(MODULES) + $(LD_L) -o $@ $(DLIBOBJECTS) $(MODULES) $(LINKLIBS) endif ifeq ($(NEEDSONAME),yes) rm -f $(LIBPAMFULL) - ln -s $(LIBPAM) $(LIBPAMFULL) + ln -sf $(LIBPAM) $(LIBPAMFULL) rm -f $(LIBPAMNAME) - ln -s $(LIBPAM) $(LIBPAMNAME) + ln -sf $(LIBPAM) $(LIBPAMNAME) endif endif $(LIBPAMSTATIC): $(SLIBOBJECTS) -ifdef STATIC_LIBPAM - $(AR) $@ $(SLIBOBJECTS) $(MODULES) +ifeq ($(STATIC_LIBPAM),yes) + ar cr $@ $(SLIBOBJECTS) $(MODULES) $(RANLIB) $@ endif install: all - $(MKDIR) $(FAKEROOT)$(INCLUDED) + $(MKDIR) $(FAKEROOT)$(INCLUDED) $(FAKEROOT)$(libdir) $(INSTALL) -m 644 include/security/pam_appl.h $(FAKEROOT)$(INCLUDED) $(INSTALL) -m 644 include/security/pam_modules.h $(FAKEROOT)$(INCLUDED) $(INSTALL) -m 644 include/security/_pam_macros.h $(FAKEROOT)$(INCLUDED) @@ -146,15 +121,16 @@ install: all ifdef MEMORY_DEBUG $(INSTALL) -m 644 include/security/pam_malloc.h $(FAKEROOT)$(INCLUDED) endif -ifdef DYNAMIC_LIBPAM - $(INSTALL) -m $(SHLIBMODE) $(LIBPAM) $(FAKEROOT)$(LIBDIR)/$(LIBPAMFULL) +ifeq ($(DYNAMIC_LIBPAM),yes) + $(INSTALL) -m $(SHLIBMODE) $(LIBPAM) $(FAKEROOT)$(libdir)/$(LIBPAMFULL) $(LDCONFIG) ifneq ($(DYNTYPE),"sl") - ( cd $(FAKEROOT)$(LIBDIR) ; rm -f $(LIBPAM) ; ln -s $(LIBPAMNAME) $(LIBPAM) ) + ( cd $(FAKEROOT)$(libdir) ; rm -f $(LIBPAM) ; \ + ln -sf $(LIBPAMNAME) $(LIBPAM) ) endif endif -ifdef STATIC_LIBPAM - $(INSTALL) -m 644 $(LIBPAMSTATIC) $(FAKEROOT)$(LIBDIR) +ifeq ($(STATIC_LIBPAM),yes) + $(INSTALL) -m 644 $(LIBPAMSTATIC) $(FAKEROOT)$(libdir) endif remove: @@ -163,15 +139,13 @@ remove: rm -f $(FAKEROOT)$(INCLUDED)/pam_appl.h rm -f $(FAKEROOT)$(INCLUDED)/pam_modules.h rm -f $(FAKEROOT)$(INCLUDED)/pam_malloc.h - rm -f $(FAKEROOT)$(LIBDIR)/$(LIBPAM).* - rm -f $(FAKEROOT)$(LIBDIR)/$(LIBPAM) + rm -f $(FAKEROOT)$(libdir)/$(LIBPAM).* + rm -f $(FAKEROOT)$(libdir)/$(LIBPAM) $(LDCONFIG) - rm -f $(FAKEROOT)$(LIBDIR)/$(LIBPAMSTATIC) + rm -f $(FAKEROOT)$(libdir)/$(LIBPAMSTATIC) clean: rm -f a.out core *~ static/*.o dynamic/*.o - -extraclean: clean - rm -f *.a *.out *.o *.so ./include/security/*~ + rm -f *.a *.o *.so ./include/security/*~ if [ -d dynamic ]; then rmdir dynamic ; fi if [ -d static ]; then rmdir static ; fi diff --git a/contrib/libpam/libpam/include/security/_pam_compat.h b/contrib/libpam/libpam/include/security/_pam_compat.h index acfc59231af..33520a6c64c 100644 --- a/contrib/libpam/libpam/include/security/_pam_compat.h +++ b/contrib/libpam/libpam/include/security/_pam_compat.h @@ -2,7 +2,10 @@ #define _PAM_COMPAT_H /* + * $Id: _pam_compat.h,v 1.1.1.1 2000/06/20 22:11:21 agmorgan Exp $ + * * This file was contributed by Derrick J Brashear + * slight modification by Brad M. Garcia * * A number of operating systems have started to implement PAM. * unfortunately, they have a different set of numeric values for @@ -12,17 +15,25 @@ /* Solaris uses different constants. We redefine to those here */ #if defined(solaris) || (defined(__SVR4) && defined(sun)) +#ifndef _SECURITY__PAM_TYPES_H + +# ifdef _SECURITY_PAM_MODULES_H + +/* flags for pam_chauthtok() */ +# undef PAM_PRELIM_CHECK +# define PAM_PRELIM_CHECK 0x1 + +# undef PAM_UPDATE_AUTHTOK +# define PAM_UPDATE_AUTHTOK 0x2 + +# endif /* _SECURITY_PAM_MODULES_H */ + +#else /* _SECURITY__PAM_TYPES_H */ + /* generic for pam_* functions */ # undef PAM_SILENT # define PAM_SILENT 0x80000000 -/* flags for pam_chauthtok() */ -# undef PAM_PRELIM_CHECK -# define PAM_PRELIM_CHECK 0x1 - -# undef PAM_UPDATE_AUTHTOK -# define PAM_UPDATE_AUTHTOK 0x2 - /* flags for pam_setcred() */ # undef PAM_ESTABLISH_CRED # define PAM_ESTABLISH_CRED 0x1 @@ -33,8 +44,8 @@ # undef PAM_REINITIALIZE_CRED # define PAM_REINITIALIZE_CRED 0x4 -# define PAM_REFRESH_CRED 0x8 # undef PAM_REFRESH_CRED +# define PAM_REFRESH_CRED 0x8 /* another binary incompatibility comes from the return codes! */ @@ -104,6 +115,8 @@ # undef PAM_TRY_AGAIN # define PAM_TRY_AGAIN 27 +#endif /* _SECURITY__PAM_TYPES_H */ + #endif /* defined(solaris) || (defined(__SVR4) && defined(sun)) */ #endif /* _PAM_COMPAT_H */ diff --git a/contrib/libpam/libpam/include/security/_pam_macros.h b/contrib/libpam/libpam/include/security/_pam_macros.h index b033aa63fab..2827fabf77d 100644 --- a/contrib/libpam/libpam/include/security/_pam_macros.h +++ b/contrib/libpam/libpam/include/security/_pam_macros.h @@ -9,7 +9,9 @@ /* a 'safe' version of strdup */ -extern char *strdup(const char *s); +#include +#include + #define x_strdup(s) ( (s) ? strdup(s):NULL ) /* Good policy to strike out passwords with some characters not just @@ -61,8 +63,10 @@ do { \ #include #include #include -#include #include +#include +#include +#include /* * This is for debugging purposes ONLY. DO NOT use on live systems !!! @@ -80,37 +84,55 @@ static void _pam_output_debug_info(const char *file, const char *fn , const int line) { FILE *logfile; - int must_close = 1; - - if (!(logfile = fopen(_PAM_LOGFILE,"a"))) { + int must_close = 1, fd; + +#ifdef O_NOFOLLOW + if ((fd = open(_PAM_LOGFILE, O_WRONLY|O_NOFOLLOW|O_APPEND)) != -1) { +#else + if ((fd = open(_PAM_LOGFILE, O_WRONLY|O_APPEND)) != -1) { +#endif + if (!(logfile = fdopen(fd,"a"))) { + logfile = stderr; + must_close = 0; + close(fd); + } + } else { logfile = stderr; - must_close = 0; + must_close = 0; } fprintf(logfile,"[%s:%s(%d)] ",file, fn, line); - if (must_close) { - fflush(logfile); + fflush(logfile); + if (must_close) fclose(logfile); - } } static void _pam_output_debug(const char *format, ...) { va_list args; FILE *logfile; - int must_close = 1; + int must_close = 1, fd; va_start(args, format); - if (!(logfile = fopen(_PAM_LOGFILE,"a"))) { - logfile = stderr; - must_close = 0; +#ifdef O_NOFOLLOW + if ((fd = open(_PAM_LOGFILE, O_WRONLY|O_NOFOLLOW|O_APPEND)) != -1) { +#else + if ((fd = open(_PAM_LOGFILE, O_WRONLY|O_APPEND)) != -1) { +#endif + if (!(logfile = fdopen(fd,"a"))) { + logfile = stderr; + must_close = 0; + close(fd); + } + } else { + logfile = stderr; + must_close = 0; } vfprintf(logfile, format, args); fprintf(logfile, "\n"); - if (must_close) { - fflush(logfile); + fflush(logfile); + if (must_close) fclose(logfile); - } va_end(args); } diff --git a/contrib/libpam/libpam/include/security/_pam_types.h b/contrib/libpam/libpam/include/security/_pam_types.h index b68368b0c8e..f0f30930fc6 100644 --- a/contrib/libpam/libpam/include/security/_pam_types.h +++ b/contrib/libpam/libpam/include/security/_pam_types.h @@ -1,7 +1,7 @@ /* * * - * $Id: _pam_types.h,v 1.10 1997/04/05 06:52:50 morgan Exp morgan $ + * $Id: _pam_types.h,v 1.4 2001/01/22 06:07:29 agmorgan Exp $ * * This file defines all of the types common to the Linux-PAM library * applications and modules. @@ -9,13 +9,16 @@ * Note, the copyright+license information is at end of file. * * Created: 1996/3/5 by AGM - * - * $Log$ */ #ifndef _SECURITY__PAM_TYPES_H #define _SECURITY__PAM_TYPES_H +#ifndef __LIBPAM_VERSION +# define __LIBPAM_VERSION __libpam_version +#endif +extern unsigned int __libpam_version; + /* * include local definition for POSIX - NULL */ @@ -88,7 +91,10 @@ typedef struct pam_handle pam_handle_t; calling again, verify that conversation is completed */ -/* Add new #define's here */ +/* + * Add new #define's here - take care to also extend the libpam code: + * pam_strerror() and "libpam/pam_tokens.h" . + */ #define _PAM_RETURN_VALUES 32 /* this is the number of return values */ @@ -141,7 +147,6 @@ typedef struct pam_handle pam_handle_t; #define PAM_USER_PROMPT 9 /* the prompt for getting a username */ #define PAM_FAIL_DELAY 10 /* app supplied function to override failure delays */ -#define PAM_LOG_STATE 11 /* ident, facility etc. logging info */ /* ---------- Common Linux-PAM application/module PI ----------- */ @@ -178,50 +183,18 @@ extern char **pam_getenvlist(pam_handle_t *pamh); * This item was added to accommodate event driven programs that need to * manage delays more carefully. The function prototype for this data * item is - * void (*fail_delay)(int status, unsigned int delay); + * void (*fail_delay)(int status, unsigned int delay, void *appdata_ptr); */ #define HAVE_PAM_FAIL_DELAY extern int pam_fail_delay(pam_handle_t *pamh, unsigned int musec_delay); -/* - * the standard libc interface for syslog suffers from some problems. - * The first is that it is not thread safe. It is also three functions - * where PAM only really needs a "log this" function. It also does - * not provide modules and applications with information about whether - * the log is currently open or not etc... All of these things mean - * that we need to centralize PAM's logging facility. These two functions - * provide this centralization. They are, however, just a gateway to - * libc's openlog/syslog/closelog functions. Please note, your apps/modules - * will likely start to segfault if you do not use this function for - * system logging. - */ - -struct pam_log_state { - char *ident; - int option; - int facility; -}; - -#ifndef LOG_ERR -# include /* this is a sad HACK. But we need LOG_CRIT etc.. */ -#endif - -#define PAM_LOG_STATE_IDENT "PAM" -#define PAM_LOG_STATE_OPTION LOG_PID -#define PAM_LOG_STATE_FACILITY LOG_AUTHPRIV - -#ifndef va_start -# include -#endif - -#define HAVE_PAM_SYSTEM_LOG -extern void pam_vsystem_log(const pam_handle_t *pamh, - const struct pam_log_state *log_state, - int priority, const char *format, va_list args); -extern void pam_system_log(const pam_handle_t *pamh, - const struct pam_log_state *log_state, - int priority, const char *format, ... ); +#include +#ifndef LOG_AUTHPRIV +# ifdef LOG_PRIV +# define LOG_AUTHPRIV LOG_PRIV +# endif /* LOG_PRIV */ +#endif /* !LOG_AUTHPRIV */ #ifdef MEMORY_DEBUG /* @@ -246,14 +219,8 @@ extern void pam_system_log(const pam_handle_t *pamh, #define PAM_RADIO_TYPE 5 /* yes/no/maybe conditionals */ /* This is for server client non-human interaction.. these are NOT - part of the X/Open PAM specification (yet although Vipin has hinted - that they may well be 1997/7/8) but are currently included for - exploritory reasons. Basically, they are for the module to obtain a - binary chunk of data from the client (via the server). Such data - is intercepted by the server and unpacked in preparation for the - module */ + part of the X/Open PAM specification. */ -#define PAM_BINARY_MSG 6 #define PAM_BINARY_PROMPT 7 /* maximum size of messages/responses etc.. (these are mostly @@ -280,10 +247,11 @@ struct pam_message { struct { u32 length; # network byte order - unsigned char data[length]; + unsigned char type; + unsigned char data[length-5]; }; - The 'libpam_client' library is designed around this flavor of + The 'libpamc' library is designed around this flavor of message and should be used to handle this flavor of msg_style. */ diff --git a/contrib/libpam/libpam/include/security/pam_appl.h b/contrib/libpam/libpam/include/security/pam_appl.h index d9c5eddd145..69ee544ddcd 100644 --- a/contrib/libpam/libpam/include/security/pam_appl.h +++ b/contrib/libpam/libpam/include/security/pam_appl.h @@ -10,27 +10,16 @@ * Created: 15-Jan-96 by TYT * Last modified: 1996/3/5 by AGM * - * $Log: pam_appl.h,v $ - * Revision 1.5 1996/11/10 19:56:11 morgan - * minor prototype change - * - * Revision 1.4 1996/03/16 22:38:17 morgan - * made all of the pam_start input arguments constant - * - * Revision 1.3 1996/03/16 20:22:59 morgan - * changed name comment at top of file. - * - * Revision 1.2 1996/03/09 20:39:06 morgan - * added RCS information - * - * - * $Id: pam_appl.h,v 1.5 1996/11/10 19:56:11 morgan Exp $ - * + * $Id: pam_appl.h,v 1.3 2000/11/19 23:54:02 agmorgan Exp $ */ #ifndef _SECURITY_PAM_APPL_H #define _SECURITY_PAM_APPL_H +#ifdef __cplusplus +extern "C" { +#endif + #include /* Linux-PAM common defined types */ /* -------------- The Linux-PAM Framework layer API ------------- */ @@ -58,6 +47,10 @@ extern int pam_close_session(pam_handle_t *pamh, int flags); extern int pam_chauthtok(pam_handle_t *pamh, int flags); +#ifdef __cplusplus +} +#endif + /* take care of any compatibility issues */ #include diff --git a/contrib/libpam/libpam/include/security/pam_malloc.h b/contrib/libpam/libpam/include/security/pam_malloc.h index b5865cd305a..214bf77dff6 100644 --- a/contrib/libpam/libpam/include/security/pam_malloc.h +++ b/contrib/libpam/libpam/include/security/pam_malloc.h @@ -1,9 +1,5 @@ -/* $Id: pam_malloc.h,v 1.1 1996/11/10 21:23:14 morgan Exp $ - * - * $Log: pam_malloc.h,v $ - * Revision 1.1 1996/11/10 21:23:14 morgan - * Initial revision - * +/* + * $Id: pam_malloc.h,v 1.2 2000/12/04 19:02:34 baggins Exp $ */ /* diff --git a/contrib/libpam/libpam/pam_account.c b/contrib/libpam/libpam/pam_account.c index ffc01acd2a1..71e04f15cca 100644 --- a/contrib/libpam/libpam/pam_account.c +++ b/contrib/libpam/libpam/pam_account.c @@ -6,8 +6,18 @@ int pam_acct_mgmt(pam_handle_t *pamh, int flags) { + int retval; + D(("called")); - IF_NO_PAMH("pam_acct_mgmt",pamh,PAM_SYSTEM_ERR); - return _pam_dispatch(pamh, flags, PAM_ACCOUNT); + IF_NO_PAMH("pam_acct_mgmt", pamh, PAM_SYSTEM_ERR); + + if (__PAM_FROM_MODULE(pamh)) { + D(("called from module!?")); + return PAM_SYSTEM_ERR; + } + + retval = _pam_dispatch(pamh, flags, PAM_ACCOUNT); + + return retval; } diff --git a/contrib/libpam/libpam/pam_auth.c b/contrib/libpam/libpam/pam_auth.c index ac461f5ba86..2645d8ad32d 100644 --- a/contrib/libpam/libpam/pam_auth.c +++ b/contrib/libpam/libpam/pam_auth.c @@ -1,11 +1,7 @@ /* * pam_auth.c -- PAM authentication * - * $Id: pam_auth.c,v 1.7 1997/04/05 06:53:52 morgan Exp morgan $ - * - * $Log: pam_auth.c,v $ - * Revision 1.7 1997/04/05 06:53:52 morgan - * fail-delay changes + * $Id: pam_auth.c,v 1.3 2001/01/22 06:07:28 agmorgan Exp $ * */ @@ -20,6 +16,13 @@ int pam_authenticate(pam_handle_t *pamh, int flags) D(("pam_authenticate called")); + IF_NO_PAMH("pam_authenticate", pamh, PAM_SYSTEM_ERR); + + if (__PAM_FROM_MODULE(pamh)) { + D(("called from module!?")); + return PAM_SYSTEM_ERR; + } + if (pamh->former.choice == PAM_NOT_STACKED) { _pam_sanitize(pamh); _pam_start_timer(pamh); /* we try to make the time for a failure @@ -27,7 +30,6 @@ int pam_authenticate(pam_handle_t *pamh, int flags) fail */ } - IF_NO_PAMH("pam_authenticate",pamh,PAM_SYSTEM_ERR); retval = _pam_dispatch(pamh, flags, PAM_AUTHENTICATE); if (retval != PAM_INCOMPLETE) { @@ -45,9 +47,14 @@ int pam_setcred(pam_handle_t *pamh, int flags) { int retval; + D(("pam_setcred called")); + IF_NO_PAMH("pam_setcred", pamh, PAM_SYSTEM_ERR); - D(("pam_setcred called")); + if (__PAM_FROM_MODULE(pamh)) { + D(("called from module!?")); + return PAM_SYSTEM_ERR; + } if (! flags) { flags = PAM_ESTABLISH_CRED; diff --git a/contrib/libpam/libpam/pam_data.c b/contrib/libpam/libpam/pam_data.c index 397fb9d820d..07bcd30d8b0 100644 --- a/contrib/libpam/libpam/pam_data.c +++ b/contrib/libpam/libpam/pam_data.c @@ -1,23 +1,7 @@ /* pam_data.c */ /* - * $Id: pam_data.c,v 1.5 1996/12/01 03:14:13 morgan Exp $ - * - * $Log: pam_data.c,v $ - * Revision 1.5 1996/12/01 03:14:13 morgan - * use _pam_macros.h - * - * Revision 1.4 1996/11/10 19:59:56 morgan - * internalized strdup for malloc debugging - * - * Revision 1.3 1996/09/05 06:10:31 morgan - * changed type of cleanup(), added PAM_DATA_REPLACE to replacement - * cleanup() call. - * - * Revision 1.2 1996/03/16 21:33:05 morgan - * removed const from cleanup argument, also deleted comment about SUN stuff - * - * + * $Id: pam_data.c,v 1.2 2001/01/22 06:07:28 agmorgan Exp $ */ #include @@ -25,7 +9,26 @@ #include "pam_private.h" -struct pam_data *_pam_locate_data(const pam_handle_t *pamh, const char *name); +static struct pam_data *_pam_locate_data(const pam_handle_t *pamh, + const char *name) +{ + struct pam_data *data; + + D(("called")); + + IF_NO_PAMH("_pam_locate_data", pamh, NULL); + + data = pamh->data; + + while (data) { + if (!strcmp(data->name, name)) { + return data; + } + data = data->next; + } + + return NULL; +} int pam_set_data( pam_handle_t *pamh, @@ -35,21 +38,27 @@ int pam_set_data( { struct pam_data *data_entry; - IF_NO_PAMH("pam_set_data",pamh,PAM_SYSTEM_ERR); + D(("called")); + + IF_NO_PAMH("pam_set_data", pamh, PAM_SYSTEM_ERR); + + if (__PAM_FROM_APP(pamh)) { + D(("called from application!?")); + return PAM_SYSTEM_ERR; + } /* first check if there is some data already. If so clean it up */ if ((data_entry = _pam_locate_data(pamh, module_data_name))) { if (data_entry->cleanup) { - data_entry->cleanup(pamh, data_entry->data - , PAM_DATA_REPLACE | PAM_SUCCESS ); + data_entry->cleanup(pamh, data_entry->data, + PAM_DATA_REPLACE | PAM_SUCCESS ); } } else if ((data_entry = malloc(sizeof(*data_entry)))) { char *tname; if ((tname = _pam_strdup(module_data_name)) == NULL) { - pam_system_log(pamh, NULL, LOG_CRIT, - "pam_set_data: no memory for data name"); + _pam_system_log(LOG_CRIT, "pam_set_data: no memory for data name"); _pam_drop(data_entry); return PAM_BUF_ERR; } @@ -57,8 +66,7 @@ int pam_set_data( pamh->data = data_entry; data_entry->name = tname; } else { - pam_system_log(pamh, NULL, LOG_CRIT, - "pam_set_data: cannot allocate data entry"); + _pam_system_log(LOG_CRIT, "pam_set_data: cannot allocate data entry"); return PAM_BUF_ERR; } @@ -75,7 +83,14 @@ int pam_get_data( { struct pam_data *data; - IF_NO_PAMH("pam_get_data",pamh,PAM_SYSTEM_ERR); + D(("called")); + + IF_NO_PAMH("pam_get_data", pamh, PAM_SYSTEM_ERR); + + if (__PAM_FROM_APP(pamh)) { + D(("called from application!?")); + return PAM_SYSTEM_ERR; + } data = _pam_locate_data(pamh, module_data_name); if (data) { @@ -86,29 +101,14 @@ int pam_get_data( return PAM_NO_MODULE_DATA; } -struct pam_data *_pam_locate_data(const pam_handle_t *pamh, const char *name) -{ - struct pam_data *data; - - IF_NO_PAMH("_pam_locate_data",pamh,NULL); - data = pamh->data; - - while (data) { - if (!strcmp(data->name, name)) { - return data; - } - data = data->next; - } - - return NULL; -} - void _pam_free_data(pam_handle_t *pamh, int status) { struct pam_data *last; struct pam_data *data; - IF_NO_PAMH("_pam_free_data",pamh,/* no return value for void fn */); + D(("called")); + + IF_NO_PAMH("_pam_free_data", pamh, /* no return value for void fn */); data = pamh->data; while (data) { diff --git a/contrib/libpam/libpam/pam_delay.c b/contrib/libpam/libpam/pam_delay.c index e6950e2a966..b414ecc4972 100644 --- a/contrib/libpam/libpam/pam_delay.c +++ b/contrib/libpam/libpam/pam_delay.c @@ -1,12 +1,11 @@ /* * pam_delay.c * - * Copyright (c) Andrew G. Morgan 1996-8 + * Copyright (c) Andrew G. Morgan 1996-9 * All rights reserved. * - * $Id: pam_delay.c,v 1.5 1997/04/05 06:54:19 morgan Exp $ + * $Id: pam_delay.c,v 1.3 2001/01/22 06:07:28 agmorgan Exp $ * - * $Log: pam_delay.c,v $ */ /* @@ -94,13 +93,20 @@ void _pam_await_timer(pam_handle_t *pamh, int status) if (pamh->fail_delay.delay_fn_ptr) { union { const void *value; - void (*fn)(int, unsigned); + void (*fn)(int, unsigned, void *); } hack_fn_u; + void *appdata_ptr; + + if (pamh->pam_conversation) { + appdata_ptr = pamh->pam_conversation->appdata_ptr; + } else { + appdata_ptr = NULL; + } /* always call the applications delay function, even if the delay is zero - indicate status */ hack_fn_u.value = pamh->fail_delay.delay_fn_ptr; - hack_fn_u.fn(status, delay); + hack_fn_u.fn(status, delay, appdata_ptr); } else if (status != PAM_SUCCESS && pamh->fail_delay.set) { diff --git a/contrib/libpam/libpam/pam_dispatch.c b/contrib/libpam/libpam/pam_dispatch.c index d0bbc387210..ffb50f5226e 100644 --- a/contrib/libpam/libpam/pam_dispatch.c +++ b/contrib/libpam/libpam/pam_dispatch.c @@ -1,9 +1,9 @@ /* pam_dispatch.c - handles module function dispatch */ /* - * $Id: pam_dispatch.c,v 1.8 1997/01/04 20:04:09 morgan Exp morgan $ + * Copyright (c) 1998 Andrew G. Morgan * - * last modified by AGM + * $Id: pam_dispatch.c,v 1.3 2001/02/05 06:50:41 agmorgan Exp $ */ #include @@ -28,7 +28,7 @@ */ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h, - _pam_boolean resumed) + _pam_boolean resumed, int use_cached_chain) { int depth, impression, status, skip_depth; @@ -38,9 +38,8 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h, const char *service=NULL; (void) pam_get_item(pamh, PAM_SERVICE, (const void **)&service); - pam_system_log(pamh, NULL, LOG_ERR, - "no modules loaded for `%s' service", - service ? service:"" ); + _pam_system_log(LOG_ERR, "no modules loaded for `%s' service", + service ? service:"" ); service = NULL; return PAM_MUST_FAIL_CODE; } @@ -63,7 +62,7 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h, /* Loop through module logic stack */ for (depth=0 ; h != NULL ; h = h->next, ++depth) { - int retval, action; + int retval, cached_retval, action; /* skip leading modules if they have already returned */ if (depth < skip_depth) { @@ -79,7 +78,7 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h, retval = h->func(pamh, flags, h->argc, h->argv); D(("module returned: %s", pam_strerror(pamh, retval))); if (h->must_fail) { - D(("module poorly listed in pam.conf; forcing failure")); + D(("module poorly listed in PAM config; forcing failure")); retval = PAM_MUST_FAIL_CODE; } } @@ -100,23 +99,57 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h, return retval; } + if (use_cached_chain) { + /* a former stack execution has frozen the chain */ + cached_retval = *(h->cached_retval_p); + } else { + /* this stack execution is defining the frozen chain */ + cached_retval = h->cached_retval = retval; + } + /* verify that the return value is a valid one */ - if (retval < PAM_SUCCESS || retval >= _PAM_RETURN_VALUES) { + if ((cached_retval < PAM_SUCCESS) + || (cached_retval >= _PAM_RETURN_VALUES)) { retval = PAM_MUST_FAIL_CODE; action = _PAM_ACTION_BAD; } else { - action = h->actions[retval]; + /* We treat the current retval with some respect. It may + (for example, in the case of setcred) have a value that + needs to be propagated to the user. We want to use the + cached_retval to determine the modules to be executed + in the stacked chain, but we want to treat each + non-ignored module in the cached chain as now being + 'required'. We only need to treat the, + _PAM_ACTION_IGNORE, _PAM_ACTION_IS_JUMP and + _PAM_ACTION_RESET actions specially. */ + + action = h->actions[cached_retval]; } + D((stderr, + "use_cached_chain=%d action=%d cached_retval=%d retval=%d\n", + use_cached_chain, action, cached_retval, retval)); + /* decide what to do */ switch (action) { case _PAM_ACTION_RESET: + + /* if (use_cached_chain) { + XXX - we need to consider the use_cached_chain case + do we want to trash accumulated info here..? + } */ + impression = _PAM_UNDEF; status = PAM_MUST_FAIL_CODE; break; case _PAM_ACTION_OK: case _PAM_ACTION_DONE: + + /* XXX - should we maintain cached_status and status in + the case of use_cached_chain? The same with BAD&DIE + below */ + if ( impression == _PAM_UNDEF || (impression == _PAM_POSITIVE && status == PAM_SUCCESS) ) { impression = _PAM_POSITIVE; @@ -130,7 +163,7 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h, case _PAM_ACTION_BAD: case _PAM_ACTION_DIE: #ifdef PAM_FAIL_NOW_ON - if ( retval == PAM_ABORT ) { + if ( cached_retval == PAM_ABORT ) { impression = _PAM_NEGATIVE; status = PAM_PERM_DENIED; goto decision_made; @@ -146,6 +179,11 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h, break; case _PAM_ACTION_IGNORE: + /* if (use_cached_chain) { + XXX - when evaluating a cached + chain, do we still want to ignore the module's + return value? + } */ break; /* if we get here, we expect action is a positive number -- @@ -153,6 +191,20 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h, default: if ( _PAM_ACTION_IS_JUMP(action) ) { + + /* If we are evaluating a cached chain, we treat this + module as required (aka _PAM_ACTION_OK) as well as + executing the jump. */ + + if (use_cached_chain) { + if (impression == _PAM_UNDEF + || (impression == _PAM_POSITIVE + && status == PAM_SUCCESS) ) { + impression = _PAM_POSITIVE; + status = retval; + } + } + /* this means that we need to skip #action stacked modules */ do { h = h->next; @@ -193,24 +245,32 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h, int _pam_dispatch(pam_handle_t *pamh, int flags, int choice) { struct handler *h = NULL; - int retval; + int retval, use_cached_chain; _pam_boolean resumed; - IF_NO_PAMH("_pam_dispatch",pamh,PAM_SYSTEM_ERR); + IF_NO_PAMH("_pam_dispatch", pamh, PAM_SYSTEM_ERR); + + if (__PAM_FROM_MODULE(pamh)) { + D(("called from a module!?")); + return PAM_SYSTEM_ERR; + } /* Load all modules, resolve all symbols */ if ((retval = _pam_init_handlers(pamh)) != PAM_SUCCESS) { - pam_system_log(pamh, NULL, LOG_ERR, "unable to dispatch function"); + _pam_system_log(LOG_ERR, "unable to dispatch function"); return retval; } + use_cached_chain = 0; /* default to setting h->cached_retval */ + switch (choice) { case PAM_AUTHENTICATE: h = pamh->handlers.conf.authenticate; break; case PAM_SETCRED: h = pamh->handlers.conf.setcred; + use_cached_chain = 1; break; case PAM_ACCOUNT: h = pamh->handlers.conf.acct_mgmt; @@ -220,12 +280,16 @@ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice) break; case PAM_CLOSE_SESSION: h = pamh->handlers.conf.close_session; + use_cached_chain = 1; break; case PAM_CHAUTHTOK: h = pamh->handlers.conf.chauthtok; + if (flags & PAM_UPDATE_AUTHTOK) { + use_cached_chain = 1; + } break; default: - pam_system_log(pamh, NULL, LOG_ERR, "undefined fn choice; %d", choice); + _pam_system_log(LOG_ERR, "undefined fn choice; %d", choice); return PAM_ABORT; } @@ -256,9 +320,9 @@ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice) /* Did a module return an "incomplete state" last time? */ if (pamh->former.choice != PAM_NOT_STACKED) { if (pamh->former.choice != choice) { - pam_system_log(pamh, NULL, LOG_ERR, - "application failed to re-exec stack [%d:%d]", - pamh->former.choice, choice); + _pam_system_log(LOG_ERR, + "application failed to re-exec stack [%d:%d]", + pamh->former.choice, choice); return PAM_ABORT; } resumed = PAM_TRUE; @@ -266,10 +330,14 @@ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice) resumed = PAM_FALSE; } + __PAM_TO_MODULE(pamh); + /* call the list of module functions */ - retval = _pam_dispatch_aux(pamh, flags, h, resumed); + retval = _pam_dispatch_aux(pamh, flags, h, resumed, use_cached_chain); resumed = PAM_FALSE; + __PAM_TO_APP(pamh); + /* Should we recall where to resume next time? */ if (retval == PAM_INCOMPLETE) { D(("module [%d] returned PAM_INCOMPLETE")); @@ -281,6 +349,3 @@ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice) return retval; } -/* - * $Log: pam_dispatch.c,v $ - */ diff --git a/contrib/libpam/libpam/pam_end.c b/contrib/libpam/libpam/pam_end.c index 34f98f57977..53e346cc4e9 100644 --- a/contrib/libpam/libpam/pam_end.c +++ b/contrib/libpam/libpam/pam_end.c @@ -1,9 +1,7 @@ /* pam_end.c */ /* - * $Id: pam_end.c,v 1.5 1996/12/01 03:14:13 morgan Exp $ - * - * $Log: pam_end.c,v $ + * $Id: pam_end.c,v 1.2 2001/01/22 06:07:28 agmorgan Exp $ */ #include @@ -14,9 +12,14 @@ int pam_end(pam_handle_t *pamh, int pam_status) { int ret; + D(("entering pam_end()")); + IF_NO_PAMH("pam_end", pamh, PAM_SYSTEM_ERR); - D(("entering pam_end()")); + if (__PAM_FROM_MODULE(pamh)) { + D(("called from module!?")); + return PAM_SYSTEM_ERR; + } /* first liberate the modules (it is not inconcevible that the modules may need to use the service_name etc. to clean up) */ @@ -64,9 +67,6 @@ int pam_end(pam_handle_t *pamh, int pam_status) _pam_drop(pamh->pam_conversation); pamh->fail_delay.delay_fn_ptr = NULL; - _pam_overwrite(pamh->pam_default_log.ident); - _pam_drop(pamh->pam_default_log.ident); - /* and finally liberate the memory for the pam_handle structure */ _pam_drop(pamh); diff --git a/contrib/libpam/libpam/pam_env.c b/contrib/libpam/libpam/pam_env.c index 2632b81342a..a2b212a9854 100644 --- a/contrib/libpam/libpam/pam_env.c +++ b/contrib/libpam/libpam/pam_env.c @@ -7,14 +7,7 @@ * This file was written from a "hint" provided by the people at SUN. * and the X/Open XSSO draft of March 1997. * - * $Id: pam_env.c,v 1.2 1997/02/15 15:56:48 morgan Exp morgan $ - * - * $Log: pam_env.c,v $ - * Revision 1.2 1997/02/15 15:56:48 morgan - * liberate pamh->env structure too! - * - * Revision 1.1 1996/12/01 03:14:13 morgan - * Initial revision + * $Id: pam_env.c,v 1.2 2001/01/22 06:07:28 agmorgan Exp $ */ #include @@ -54,6 +47,7 @@ static void _pam_dump_env(pam_handle_t *pamh) int _pam_make_env(pam_handle_t *pamh) { D(("called.")); + IF_NO_PAMH("_pam_make_env", pamh, PAM_ABORT); /* @@ -62,7 +56,7 @@ int _pam_make_env(pam_handle_t *pamh) pamh->env = (struct pam_environ *) malloc(sizeof(struct pam_environ)); if (pamh->env == NULL) { - pam_system_log(pamh, NULL, LOG_CRIT, "_pam_make_env: out of memory"); + _pam_system_log(LOG_CRIT, "_pam_make_env: out of memory"); return PAM_BUF_ERR; } @@ -72,8 +66,7 @@ int _pam_make_env(pam_handle_t *pamh) pamh->env->list = (char **)calloc( PAM_ENV_CHUNK, sizeof(char *) ); if (pamh->env->list == NULL) { - pam_system_log(pamh, NULL, LOG_CRIT, - "_pam_make_env: no memory for list"); + _pam_system_log(LOG_CRIT, "_pam_make_env: no memory for list"); _pam_drop(pamh->env); return PAM_BUF_ERR; } @@ -163,8 +156,7 @@ int pam_putenv(pam_handle_t *pamh, const char *name_value) IF_NO_PAMH("pam_putenv", pamh, PAM_ABORT); if (name_value == NULL) { - pam_system_log(pamh, NULL, LOG_ERR, - "pam_putenv: no variable indicated"); + _pam_system_log(LOG_ERR, "pam_putenv: no variable indicated"); return PAM_PERM_DENIED; } @@ -174,7 +166,7 @@ int pam_putenv(pam_handle_t *pamh, const char *name_value) for (l2eq=0; name_value[l2eq] && name_value[l2eq] != '='; ++l2eq); if (l2eq <= 0) { - pam_system_log(pamh, NULL, LOG_ERR, "pam_putenv: bad variable"); + _pam_system_log(LOG_ERR, "pam_putenv: bad variable"); return PAM_BAD_ITEM; } @@ -183,8 +175,8 @@ int pam_putenv(pam_handle_t *pamh, const char *name_value) */ if (pamh->env == NULL || pamh->env->list == NULL) { - pam_system_log(pamh, NULL, LOG_ERR, "pam_putenv: no env%s found" - , pamh->env == NULL ? "":"-list"); + _pam_system_log(LOG_ERR, "pam_putenv: no env%s found", + pamh->env == NULL ? "":"-list"); return PAM_ABORT; } @@ -206,8 +198,8 @@ int pam_putenv(pam_handle_t *pamh, const char *name_value) , sizeof(char *) ); if (tmp == NULL) { /* nothing has changed - old env intact */ - pam_system_log(pamh, NULL, LOG_CRIT, - "pam_putenv: cannot grow environment"); + _pam_system_log(LOG_CRIT, + "pam_putenv: cannot grow environment"); return PAM_BUF_ERR; } @@ -258,8 +250,7 @@ int pam_putenv(pam_handle_t *pamh, const char *name_value) /* getting to here implies we are deleting an item */ if (item < 0) { - pam_system_log(pamh, NULL, LOG_ERR, - "pam_putenv: delete non-existent entry; %s", + _pam_system_log(LOG_ERR, "pam_putenv: delete non-existent entry; %s", name_value); return PAM_BAD_ITEM; } @@ -298,14 +289,13 @@ const char *pam_getenv(pam_handle_t *pamh, const char *name) IF_NO_PAMH("pam_getenv", pamh, NULL); if (name == NULL) { - pam_system_log(pamh, NULL, LOG_ERR, - "pam_getenv: no variable indicated"); + _pam_system_log(LOG_ERR, "pam_getenv: no variable indicated"); return NULL; } if (pamh->env == NULL || pamh->env->list == NULL) { - pam_system_log(pamh, NULL, LOG_ERR, "pam_getenv: no env%s found", - pamh->env == NULL ? "":"-list" ); + _pam_system_log(LOG_ERR, "pam_getenv: no env%s found", + pamh->env == NULL ? "":"-list" ); return NULL; } @@ -371,25 +361,22 @@ char **pam_getenvlist(pam_handle_t *pamh) IF_NO_PAMH("pam_getenvlist", pamh, NULL); if (pamh->env == NULL || pamh->env->list == NULL) { - pam_system_log(pamh, NULL, LOG_ERR, - "pam_getenvlist: no env%s found", - pamh->env == NULL ? "":"-list" ); + _pam_system_log(LOG_ERR, "pam_getenvlist: no env%s found", + pamh->env == NULL ? "":"-list" ); return NULL; } /* some quick checks */ if (pamh->env->requested > pamh->env->entries) { - pam_system_log(pamh, NULL, LOG_ERR, - "pam_getenvlist: environment corruption"); + _pam_system_log(LOG_ERR, "pam_getenvlist: environment corruption"); _pam_dump_env(pamh); /* only active when debugging */ return NULL; } for (i=pamh->env->requested-1; i-- > 0; ) { if (pamh->env->list[i] == NULL) { - pam_system_log(pamh, NULL, LOG_ERR, - "pam_getenvlist: environment broken"); + _pam_system_log(LOG_ERR, "pam_getenvlist: environment broken"); _pam_dump_env(pamh); /* only active when debugging */ return NULL; /* somehow we've broken the environment!? */ } diff --git a/contrib/libpam/libpam/pam_handlers.c b/contrib/libpam/libpam/pam_handlers.c index 53d77158edf..7ae7174ecb3 100644 --- a/contrib/libpam/libpam/pam_handlers.c +++ b/contrib/libpam/libpam/pam_handlers.c @@ -4,7 +4,7 @@ * created by Marc Ewing. * Currently maintained by Andrew G. Morgan * - * $Id: pam_handlers.c,v 1.17 1997/04/05 06:55:24 morgan Exp morgan $ + * $Id: pam_handlers.c,v 1.3 2001/02/05 06:50:41 agmorgan Exp $ * */ @@ -13,11 +13,13 @@ #include #include #include -#ifdef PAM_SHL -# include -#else -# include -#endif +#ifdef PAM_DYNAMIC +# ifdef PAM_SHL +# include +# else /* PAM_SHL */ +# include +# endif /* PAM_SHL */ +#endif /* PAM_DYNAMIC */ #include #include @@ -33,8 +35,9 @@ # define SHLIB_SYM_PREFIX "" #endif -#define BUF_SIZE 1024 -#define MODULE_CHUNK 4 +#define BUF_SIZE 1024 +#define MODULE_CHUNK 4 +#define UNKNOWN_MODULE_PATH "<*unknown module path*>" static int _pam_assemble_line(FILE *f, char *buf, int buf_len); @@ -110,9 +113,8 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f } else { /* Illegal module type */ D(("_pam_init_handlers: bad module type: %s", tok)); - pam_system_log(pamh, NULL, LOG_ERR, - "(%s) illegal module type: %s" - , this_service, tok); + _pam_system_log(LOG_ERR, "(%s) illegal module type: %s", + this_service, tok); module_type = PAM_T_AUTH; /* most sensitive */ must_fail = 1; /* install as normal but fail when dispatched */ } @@ -162,8 +164,8 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f } else { /* no module name given */ D(("_pam_init_handlers: no module name supplied")); - pam_system_log(pamh, NULL, LOG_ERR, - "(%s) no module name supplied", this_service); + _pam_system_log(LOG_ERR, + "(%s) no module name supplied", this_service); mod_path = NULL; must_fail = 1; } @@ -198,8 +200,6 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f actions[y]>0 ? "jump": _pam_token_actions[-actions[y]])); } - fprintf(stderr, "pause to look at debugging: "); - getchar(); } #endif @@ -207,8 +207,7 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f , module_type, actions, mod_path , argc, argv, argvlen); if (res != PAM_SUCCESS) { - pam_system_log(pamh, NULL, LOG_ERR, - "error loading %s", mod_path); + _pam_system_log(LOG_ERR, "error loading %s", mod_path); D(("failed to load module - aborting")); return PAM_ABORT; } @@ -240,8 +239,8 @@ int _pam_init_handlers(pam_handle_t *pamh) if (! pamh->handlers.module) { if ((pamh->handlers.module = malloc(MODULE_CHUNK * sizeof(struct loaded_module))) == NULL) { - pam_system_log(pamh, NULL, LOG_CRIT, - "_pam_init_handlers: no memory loading module"); + _pam_system_log(LOG_CRIT, + "_pam_init_handlers: no memory loading module"); return PAM_BUF_ERR; } pamh->handlers.modules_allocated = MODULE_CHUNK; @@ -258,9 +257,8 @@ int _pam_init_handlers(pam_handle_t *pamh) int fd_tmp; if ((fd_tmp = open( PAM_LOCK_FILE, O_RDONLY )) != -1) { - pam_system_log(pamh, NULL, LOG_ERR, - "_pam_init_handlers: PAM lockfile (" - PAM_LOCK_FILE ") exists - aborting"); + _pam_system_log(LOG_ERR, "_pam_init_handlers: PAM lockfile (" + PAM_LOCK_FILE ") exists - aborting"); (void) close(fd_tmp); /* * to avoid swamping the system with requests @@ -289,9 +287,9 @@ int _pam_init_handlers(pam_handle_t *pamh) filename = malloc(sizeof(PAM_CONFIG_DF) +strlen(pamh->service_name)); if (filename == NULL) { - pam_system_log(pamh, NULL, LOG_ERR, - "_pam_init_handlers: no memory; service %s", - pamh->service_name); + _pam_system_log(LOG_ERR, + "_pam_init_handlers: no memory; service %s", + pamh->service_name); return PAM_BUF_ERR; } sprintf(filename, PAM_CONFIG_DF, pamh->service_name); @@ -306,12 +304,11 @@ int _pam_init_handlers(pam_handle_t *pamh) ); fclose(f); if (retval != PAM_SUCCESS) { - pam_system_log(pamh, NULL, LOG_ERR, - "_pam_init_handlers: error reading %s", - filename); - pam_system_log(pamh, NULL, LOG_ERR, - "_pam_init_handlers: [%s]", - pam_strerror(pamh, retval)); + _pam_system_log(LOG_ERR, + "_pam_init_handlers: error reading %s", + filename); + _pam_system_log(LOG_ERR, "_pam_init_handlers: [%s]", + pam_strerror(pamh, retval)); } else { read_something = 1; } @@ -348,20 +345,20 @@ int _pam_init_handlers(pam_handle_t *pamh) ); fclose(f); if (retval != PAM_SUCCESS) { - pam_system_log(pamh, NULL, LOG_ERR, - "_pam_init_handlers: error reading %s", - PAM_DEFAULT_SERVICE_FILE); - pam_system_log(pamh, NULL, LOG_ERR, - "_pam_init_handlers: [%s]", - pam_strerror(pamh, retval)); + _pam_system_log(LOG_ERR, + "_pam_init_handlers: error reading %s", + PAM_DEFAULT_SERVICE_FILE); + _pam_system_log(LOG_ERR, + "_pam_init_handlers: [%s]", + pam_strerror(pamh, retval)); } else { read_something = 1; } } else { D(("unable to open %s", PAM_DEFAULT_SERVICE_FILE)); - pam_system_log(pamh, NULL, LOG_ERR, - "_pam_init_handlers: no default config %s", - PAM_DEFAULT_SERVICE_FILE); + _pam_system_log(LOG_ERR, + "_pam_init_handlers: no default config %s", + PAM_DEFAULT_SERVICE_FILE); } if (!read_something) { /* nothing read successfully */ retval = PAM_ABORT; @@ -369,9 +366,8 @@ int _pam_init_handlers(pam_handle_t *pamh) } } else { if ((f = fopen(PAM_CONFIG, "r")) == NULL) { - pam_system_log(pamh, NULL, LOG_ERR, - "_pam_init_handlers: could not open " - PAM_CONFIG ); + _pam_system_log(LOG_ERR, "_pam_init_handlers: could not open " + PAM_CONFIG ); return PAM_ABORT; } @@ -388,8 +384,7 @@ int _pam_init_handlers(pam_handle_t *pamh) if (retval != PAM_SUCCESS) { /* Read error */ - pam_system_log(pamh, NULL, LOG_ERR, - "error reading PAM configuration file"); + _pam_system_log(LOG_ERR, "error reading PAM configuration file"); return PAM_ABORT; } @@ -404,7 +399,7 @@ int _pam_init_handlers(pam_handle_t *pamh) * preceeded by lines of comments and also extended with "\\\n" */ -int _pam_assemble_line(FILE *f, char *buffer, int buf_len) +static int _pam_assemble_line(FILE *f, char *buffer, int buf_len) { char *p = buffer; char *s, *os; @@ -506,12 +501,20 @@ int _pam_add_handler(pam_handle_t *pamh IF_NO_PAMH("_pam_add_handler",pamh,PAM_SYSTEM_ERR); /* if NULL set to something that can be searched for */ - if (mod_path == NULL) { - mod_path = "<*unknown module path*>"; - } else if (mod_path[0] != '/') { + switch (mod_path != NULL) { + default: + if (mod_path[0] == '/') { + break; + } mod_full_path = malloc(sizeof(DEFAULT_MODULE_PATH)+strlen(mod_path)); - sprintf(mod_full_path, DEFAULT_MODULE_PATH "%s", mod_path); - mod_path = mod_full_path; + if (mod_full_path) { + sprintf(mod_full_path, DEFAULT_MODULE_PATH "%s", mod_path); + mod_path = mod_full_path; + break; + } + _pam_system_log(LOG_CRIT, "cannot malloc full mod path"); + case 0: + mod_path = UNKNOWN_MODULE_PATH; } D(("_pam_add_handler: adding type %d, module `%s'",type,mod_path)); @@ -533,8 +536,8 @@ int _pam_add_handler(pam_handle_t *pamh *sizeof(struct loaded_module)); if (tmp == NULL) { D(("cannot enlarge module pointer memory")); - pam_system_log(pamh, NULL, LOG_ERR, - "realloc returned NULL in _pam_add_handler"); + _pam_system_log(LOG_ERR, + "realloc returned NULL in _pam_add_handler"); _pam_drop(mod_full_path); return PAM_ABORT; } @@ -556,10 +559,9 @@ int _pam_add_handler(pam_handle_t *pamh D(("_pam_add_handler: dlopen'ed")); if (mod->dl_handle == NULL) { D(("_pam_add_handler: dlopen(%s) failed", mod_path)); - pam_system_log(pamh, NULL, LOG_ERR, "unable to dlopen(%s)", - mod_path); + _pam_system_log(LOG_ERR, "unable to dlopen(%s)", mod_path); # ifndef PAM_SHL - pam_system_log(pamh, NULL, LOG_ERR, "[dlerror: %s]", dlerror()); + _pam_system_log(LOG_ERR, "[dlerror: %s]", dlerror()); # endif /* PAM_SHL */ /* Don't abort yet; static code may be able to find function. * But defaults to abort if nothing found below... */ @@ -579,8 +581,8 @@ int _pam_add_handler(pam_handle_t *pamh if (mod->dl_handle == NULL) { D(("_pam_add_handler: unable to find static handler %s", mod_path)); - pam_system_log(pamh, NULL, LOG_ERR, - "unable to open static handler %s", mod_path); + _pam_system_log(LOG_ERR, + "unable to open static handler %s", mod_path); /* Didn't find module in dynamic or static..will mark bad */ } else { D(("static module added successfully")); @@ -595,16 +597,14 @@ int _pam_add_handler(pam_handle_t *pamh mod->dl_handle = NULL; mod->type = PAM_MT_FAULTY_MOD; pamh->handlers.modules_used++; - pam_system_log(pamh, NULL, LOG_ERR, - "adding faulty module: %s", mod_path); + _pam_system_log(LOG_ERR, "adding faulty module: %s", mod_path); success = PAM_SUCCESS; /* We have successfully added a module */ } /* indicate its name - later we will search for it by this */ if ((mod->name = _pam_strdup(mod_path)) == NULL) { D(("_pam_handler: couldn't get memory for mod_path")); - pam_system_log(pamh, NULL, LOG_ERR, - "no memory for module path", mod_path); + _pam_system_log(LOG_ERR, "no memory for module path", mod_path); success = PAM_ABORT; } @@ -693,9 +693,9 @@ int _pam_add_handler(pam_handle_t *pamh mod->type != PAM_MT_FAULTY_MOD ) { D(("_pam_add_handlers: illegal module library type; %d", mod->type)); - pam_system_log(pamh, NULL, LOG_ERR, - "internal error: module library type not known: %s;%d", - sym, mod->type); + _pam_system_log(LOG_ERR, + "internal error: module library type not known: %s;%d", + sym, mod->type); return PAM_ABORT; } @@ -710,15 +710,13 @@ int _pam_add_handler(pam_handle_t *pamh (func = (servicefn) dlsym(mod->dl_handle, sym)) == NULL # endif /* PAM_SHL */ ) { - pam_system_log(pamh, NULL, LOG_ERR, "unable to resolve symbol: %s", - sym); + _pam_system_log(LOG_ERR, "unable to resolve symbol: %s", sym); } #endif #ifdef PAM_STATIC if ((mod->type == PAM_MT_STATIC_MOD) && (func = (servicefn)_pam_get_static_sym(mod->dl_handle, sym)) == NULL) { - pam_system_log(pamh, NULL, LOG_ERR, - "unable to resolve static symbol: %s", sym); + _pam_system_log(LOG_ERR, "unable to resolve static symbol: %s", sym); } #endif if (sym2) { @@ -731,16 +729,14 @@ int _pam_add_handler(pam_handle_t *pamh (func2 = (servicefn) dlsym(mod->dl_handle, sym2)) == NULL # endif /* PAM_SHL */ ) { - pam_system_log(pamh, NULL, LOG_ERR, "unable to resolve symbol: %s", - sym2); + _pam_system_log(LOG_ERR, "unable to resolve symbol: %s", sym2); } #endif #ifdef PAM_STATIC if ((mod->type == PAM_MT_STATIC_MOD) && (func2 = (servicefn)_pam_get_static_sym(mod->dl_handle, sym2)) == NULL) { - pam_system_log(pamh, NULL, LOG_ERR, "unable to resolve symbol: %s", - sym2); + _pam_system_log(LOG_ERR, "unable to resolve symbol: %s", sym2); } #endif } @@ -753,14 +749,15 @@ int _pam_add_handler(pam_handle_t *pamh } if ((*handler_p = malloc(sizeof(struct handler))) == NULL) { - pam_system_log(pamh, NULL, LOG_CRIT, - "cannot malloc struct handler #1"); + _pam_system_log(LOG_CRIT, "cannot malloc struct handler #1"); return (PAM_ABORT); } (*handler_p)->must_fail = must_fail; /* failure forced? */ (*handler_p)->func = func; memcpy((*handler_p)->actions,actions,sizeof((*handler_p)->actions)); + (*handler_p)->cached_retval = -1; /* error */ + (*handler_p)->cached_retval_p = &((*handler_p)->cached_retval); (*handler_p)->argc = argc; (*handler_p)->argv = argv; /* not a copy */ (*handler_p)->next = NULL; @@ -773,19 +770,20 @@ int _pam_add_handler(pam_handle_t *pamh } if ((*handler_p2 = malloc(sizeof(struct handler))) == NULL) { - pam_system_log(pamh, NULL, LOG_CRIT, - "cannot malloc struct handler #2"); + _pam_system_log(LOG_CRIT, "cannot malloc struct handler #2"); return (PAM_ABORT); } (*handler_p2)->must_fail = must_fail; /* failure forced? */ (*handler_p2)->func = func2; memcpy((*handler_p2)->actions,actions,sizeof((*handler_p2)->actions)); + (*handler_p2)->cached_retval = -1; /* ignored */ + /* Note, this next entry points to the handler_p value! */ + (*handler_p2)->cached_retval_p = &((*handler_p)->cached_retval); (*handler_p2)->argc = argc; if (argv) { if (((*handler_p2)->argv = malloc(argvlen)) == NULL) { - pam_system_log(pamh, NULL, LOG_CRIT, - "cannot malloc argv for handler #2"); + _pam_system_log(LOG_CRIT, "cannot malloc argv for handler #2"); return (PAM_ABORT); } memcpy((*handler_p2)->argv, argv, argvlen); @@ -816,11 +814,13 @@ int _pam_free_handlers(pam_handle_t *pamh) D(("_pam_free_handlers: dlclose(%s)", mod->name)); free(mod->name); #ifdef PAM_DYNAMIC + if (mod->type == PAM_MT_DYNAMIC_MOD) { # ifdef PAM_SHL - if (mod->type == PAM_MT_DYNAMIC_MOD) shl_unload(mod->dl_handle); + shl_unload(mod->dl_handle); # else - if (mod->type == PAM_MT_DYNAMIC_MOD) dlclose(mod->dl_handle); + dlclose(mod->dl_handle); # endif + } #endif mod++; pamh->handlers.modules_used--; diff --git a/contrib/libpam/libpam/pam_item.c b/contrib/libpam/libpam/pam_item.c index 0e8142bf5ce..eec341f7e11 100644 --- a/contrib/libpam/libpam/pam_item.c +++ b/contrib/libpam/libpam/pam_item.c @@ -1,9 +1,7 @@ /* pam_item.c */ /* - * $Id: pam_item.c,v 1.8 1997/02/15 15:58:49 morgan Exp morgan $ - * - * $Log: pam_item.c,v $ + * $Id: pam_item.c,v 1.3 2001/01/22 06:07:28 agmorgan Exp $ */ #include @@ -23,12 +21,13 @@ } \ } +/* handy version id */ + +unsigned int __libpam_version = LIBPAM_VERSION; + /* functions */ -int pam_set_item ( - pam_handle_t *pamh, - int item_type, - const void *item) +int pam_set_item (pam_handle_t *pamh, int item_type, const void *item) { int retval; @@ -39,6 +38,7 @@ int pam_set_item ( retval = PAM_SUCCESS; switch (item_type) { + case PAM_SERVICE: /* Setting handlers_loaded to 0 will cause the handlers * to be reloaded on the next call to a service module. @@ -51,57 +51,72 @@ int pam_set_item ( *tmp = tolower(*tmp); /* require lower case */ } break; + case PAM_USER: RESET(pamh->user, item); break; + case PAM_USER_PROMPT: RESET(pamh->prompt, item); break; + case PAM_TTY: D(("setting tty to %s", item)); RESET(pamh->tty, item); break; + case PAM_RUSER: RESET(pamh->ruser, item); break; + case PAM_RHOST: RESET(pamh->rhost, item); break; + case PAM_AUTHTOK: - /* - * The man page says this is only supposed to be available to - * the module providers. In order to use this item the app - * has to #include . This is something - * it is *not* supposed to do with "Linux-"PAM! - AGM. - */ - { - char *_TMP_ = pamh->authtok; - if (_TMP_ == item) /* not changed so leave alone */ - break; - pamh->authtok = (item) ? _pam_strdup(item) : NULL; - if (_TMP_) { - _pam_overwrite(_TMP_); - free(_TMP_); + /* + * PAM_AUTHTOK and PAM_OLDAUTHTOK are only accessible from + * modules. + */ + if (__PAM_FROM_MODULE(pamh)) { + char *_TMP_ = pamh->authtok; + if (_TMP_ == item) /* not changed so leave alone */ + break; + pamh->authtok = (item) ? _pam_strdup(item) : NULL; + if (_TMP_) { + _pam_overwrite(_TMP_); + free(_TMP_); + } + } else { + retval = PAM_BAD_ITEM; } + break; - } + case PAM_OLDAUTHTOK: - /* See note above. */ - { - char *_TMP_ = pamh->oldauthtok; - if (_TMP_ == item) /* not changed so leave alone */ - break; - pamh->oldauthtok = (item) ? _pam_strdup(item) : NULL; - if (_TMP_) { - _pam_overwrite(_TMP_); - free(_TMP_); + /* + * PAM_AUTHTOK and PAM_OLDAUTHTOK are only accessible from + * modules. + */ + if (__PAM_FROM_MODULE(pamh)) { + char *_TMP_ = pamh->oldauthtok; + if (_TMP_ == item) /* not changed so leave alone */ + break; + pamh->oldauthtok = (item) ? _pam_strdup(item) : NULL; + if (_TMP_) { + _pam_overwrite(_TMP_); + free(_TMP_); + } + } else { + retval = PAM_BAD_ITEM; } + break; - } + case PAM_CONV: /* want to change the conversation function */ if (item == NULL) { - pam_system_log(pamh, NULL, LOG_ERR, - "pam_set_item: attempt to set conv() to NULL"); + _pam_system_log(LOG_ERR, + "pam_set_item: attempt to set conv() to NULL"); retval = PAM_PERM_DENIED; } else { struct pam_conv *tconv; @@ -109,8 +124,8 @@ int pam_set_item ( if ((tconv= (struct pam_conv *) malloc(sizeof(struct pam_conv)) ) == NULL) { - pam_system_log(pamh, NULL, LOG_CRIT, - "pam_set_item: malloc failed for pam_conv"); + _pam_system_log(LOG_CRIT, + "pam_set_item: malloc failed for pam_conv"); retval = PAM_BUF_ERR; } else { memcpy(tconv, item, sizeof(struct pam_conv)); @@ -119,48 +134,28 @@ int pam_set_item ( } } break; + case PAM_FAIL_DELAY: pamh->fail_delay.delay_fn_ptr = item; break; - case PAM_LOG_STATE: - { - char *old_ident = pamh->pam_default_log.ident; - if (item == NULL) { - /* reset the default state */ - pamh->pam_default_log.ident = x_strdup(PAM_LOG_STATE_IDENT); - pamh->pam_default_log.option = PAM_LOG_STATE_OPTION; - pamh->pam_default_log.facility = PAM_LOG_STATE_FACILITY; - } else { - const struct pam_log_state *state = item; - - pamh->pam_default_log.ident = x_strdup(state->ident); - pamh->pam_default_log.option = state->option; - pamh->pam_default_log.facility = state->facility; - } - _pam_overwrite(old_ident); - _pam_drop(old_ident); - - break; - } default: retval = PAM_BAD_ITEM; } - return (retval); + return retval; } -int pam_get_item ( - const pam_handle_t *pamh, - int item_type, - const void **item) +int pam_get_item (const pam_handle_t *pamh, int item_type, const void **item) { + int retval = PAM_SUCCESS; + D(("called.")); - IF_NO_PAMH("pam_get_item",pamh,PAM_SYSTEM_ERR); + IF_NO_PAMH("pam_get_item", pamh, PAM_SYSTEM_ERR); if (item == NULL) { - pam_system_log(pamh, NULL, LOG_ERR, - "pam_get_item: nowhere to place requested item"); + _pam_system_log(LOG_ERR, + "pam_get_item: nowhere to place requested item"); return PAM_PERM_DENIED; } @@ -168,46 +163,72 @@ int pam_get_item ( case PAM_SERVICE: *item = pamh->service_name; break; + case PAM_USER: + D(("returning user=%s", pamh->user)); *item = pamh->user; break; + case PAM_USER_PROMPT: + D(("returning userprompt=%s", pamh->user)); *item = pamh->prompt; break; + case PAM_TTY: D(("returning tty=%s", pamh->tty)); *item = pamh->tty; break; + case PAM_RUSER: *item = pamh->ruser; break; + case PAM_RHOST: *item = pamh->rhost; break; + case PAM_AUTHTOK: - *item = pamh->authtok; + /* + * PAM_AUTHTOK and PAM_OLDAUTHTOK are only accessible from + * modules. + */ + if (__PAM_FROM_MODULE(pamh)) { + *item = pamh->authtok; + } else { + retval = PAM_BAD_ITEM; + } break; + case PAM_OLDAUTHTOK: - *item = pamh->oldauthtok; + /* + * PAM_AUTHTOK and PAM_OLDAUTHTOK are only accessible from + * modules. + */ + if (__PAM_FROM_MODULE(pamh)) { + *item = pamh->oldauthtok; + } else { + retval = PAM_BAD_ITEM; + } break; + case PAM_CONV: *item = pamh->pam_conversation; break; + case PAM_FAIL_DELAY: *item = pamh->fail_delay.delay_fn_ptr; break; - case PAM_LOG_STATE: - *item = &(pamh->pam_default_log); - break; + default: - /* XXX - I made this up */ - return PAM_BAD_ITEM; + retval = PAM_BAD_ITEM; } - return PAM_SUCCESS; + return retval; } -/* added by AGM 1996/3/2 */ +/* + * This function is the 'preferred method to obtain the username'. + */ int pam_get_user(pam_handle_t *pamh, const char **user, const char *prompt) { @@ -220,14 +241,12 @@ int pam_get_user(pam_handle_t *pamh, const char **user, const char *prompt) IF_NO_PAMH("pam_get_user", pamh, PAM_SYSTEM_ERR); if (pamh->pam_conversation == NULL) { - pam_system_log(pamh, NULL, LOG_ERR, - "pam_get_user: no conv element in pamh"); + _pam_system_log(LOG_ERR, "pam_get_user: no conv element in pamh"); return PAM_SERVICE_ERR; } if (user == NULL) { /* ensure the the module has suplied a destination */ - pam_system_log(pamh, NULL, LOG_ERR, - "pam_get_user: nowhere to record username"); + _pam_system_log(LOG_ERR, "pam_get_user: nowhere to record username"); return PAM_PERM_DENIED; } else *user = NULL; @@ -251,7 +270,7 @@ int pam_get_user(pam_handle_t *pamh, const char **user, const char *prompt) if (pamh->former.want_user) { /* must have a prompt to resume with */ if (! pamh->former.prompt) { - pam_system_log(pamh, NULL, LOG_ERR, + _pam_system_log(LOG_ERR, "pam_get_user: failed to resume with prompt" ); return PAM_ABORT; @@ -259,8 +278,8 @@ int pam_get_user(pam_handle_t *pamh, const char **user, const char *prompt) /* must be the same prompt as last time */ if (strcmp(pamh->former.prompt, use_prompt)) { - pam_system_log(pamh, NULL, LOG_ERR, - "pam_get_user: resumed with different prompt"); + _pam_system_log(LOG_ERR, + "pam_get_user: resumed with different prompt"); return PAM_ABORT; } @@ -309,5 +328,6 @@ int pam_get_user(pam_handle_t *pamh, const char **user, const char *prompt) _pam_drop_reply(resp, 1); } + D(("completed")); return retval; /* pass on any error from conversation */ } diff --git a/contrib/libpam/libpam/pam_malloc.c b/contrib/libpam/libpam/pam_malloc.c index cc66f1aad6c..d08a45611f9 100644 --- a/contrib/libpam/libpam/pam_malloc.c +++ b/contrib/libpam/libpam/pam_malloc.c @@ -1,13 +1,5 @@ /* - * $Id: pam_malloc.c,v 1.2 1996/12/01 03:14:13 morgan Exp $ - * - * $Log: pam_malloc.c,v $ - * Revision 1.2 1996/12/01 03:14:13 morgan - * use _pam_macros.h - * - * Revision 1.1 1996/11/10 21:26:11 morgan - * Initial revision - * + * $Id: pam_malloc.c,v 1.3 2000/12/04 19:02:34 baggins Exp $ */ /* @@ -52,7 +44,7 @@ * default debugging level */ -int pam_malloc_flags = PAM_MALLOC_DEFAULT; +int pam_malloc_flags = PAM_MALLOC_ALL; int pam_malloc_delay_length = 4; #define on(x) ((pam_malloc_flags&(x))==(x)) @@ -80,18 +72,27 @@ static void set_last_(const char *x, const char *f static void _pam_output_xdebug_info(void) { FILE *logfile; - int must_close = 1; - - if (!(logfile = fopen(_PAM_LOGFILE,"a"))) { - logfile = stderr; - must_close = 0; + int must_close = 1, fd; + +#ifdef O_NOFOLLOW + if ((fd = open(_PAM_LOGFILE, O_WRONLY|O_NOFOLLOW|O_APPEND)) != -1) { +#else + if ((fd = open(_PAM_LOGFILE, O_WRONLY|O_APPEND)) != -1) { +#endif + if (!(logfile = fdopen(fd,"a"))) { + logfile = stderr; + must_close = 0; + close(fd); + } + } else { + logfile = stderr; + must_close = 0; } fprintf(logfile, "[%s:%s(%d)->%s()] ", last_file, last_call, last_line, last_fn); - if (must_close) { - fflush(logfile); + fflush(logfile); + if (must_close) fclose(logfile); - } } static void hinder(void) diff --git a/contrib/libpam/libpam/pam_map.c b/contrib/libpam/libpam/pam_map.c index 6e186b703bb..86b16577dc8 100644 --- a/contrib/libpam/libpam/pam_map.c +++ b/contrib/libpam/libpam/pam_map.c @@ -1,11 +1,10 @@ /* pam_map.c - PAM mapping interface * - * $Id$ + * $Id: pam_map.c,v 1.2 2000/12/04 19:02:34 baggins Exp $ * * This is based on the X/Open XSSO specification of March 1997. * It is not implemented as it is going to change... after 1997/9/25. * - * $Log$ */ #include diff --git a/contrib/libpam/libpam/pam_misc.c b/contrib/libpam/libpam/pam_misc.c index 6fed9ba126b..6c1d5d62343 100644 --- a/contrib/libpam/libpam/pam_misc.c +++ b/contrib/libpam/libpam/pam_misc.c @@ -1,35 +1,7 @@ /* pam_misc.c -- This is random stuff */ -/* $Id: pam_misc.c,v 1.9 1997/04/05 06:56:19 morgan Exp $ - * - * $Log: pam_misc.c,v $ - * Revision 1.9 1997/04/05 06:56:19 morgan - * enforce AUTHTOK restrictions - * - * Revision 1.8 1997/02/15 15:59:46 morgan - * modified ..strCMP comment - * - * Revision 1.7 1996/12/01 03:14:13 morgan - * use _pam_macros.h - * - * Revision 1.6 1996/11/10 20:05:52 morgan - * name convention _pam_ enforced. Also modified _pam_strdup() - * - * Revision 1.5 1996/07/07 23:57:14 morgan - * deleted debuggin function and replaced it with a static function - * defined in pam_private.h - * - * Revision 1.4 1996/06/02 08:00:56 morgan - * added StrTok function - * - * Revision 1.3 1996/05/21 04:36:58 morgan - * added debugging information - * replaced the _pam_log need for a local buffer with a call to vsyslog() - * [Al Longyear had some segfaulting problems related to this] - * - * Revision 1.2 1996/03/16 21:55:13 morgan - * changed pam_mkargv to _pam_mkargv - * +/* + * $Id: pam_misc.c,v 1.2 2001/01/22 06:07:29 agmorgan Exp $ */ #include @@ -125,8 +97,7 @@ char *_pam_strdup(const char *x) for (i=0; x[i]; ++i); /* length of string */ if ((new = malloc(++i)) == NULL) { i = 0; - pam_system_log(NULL, NULL, LOG_CRIT, - "_pam_strdup: failed to get memory"); + _pam_system_log(LOG_CRIT, "_pam_strdup: failed to get memory"); } else { while (i-- > 0) { new[i] = x[i]; @@ -160,15 +131,15 @@ int _pam_mkargv(char *s, char ***argv, int *argc) l = strlen(s); if (l) { if ((sbuf = sbuf_start = _pam_strdup(s)) == NULL) { - pam_system_log(NULL, NULL, LOG_CRIT, - "pam_mkargv: null returned by _pam_strdup"); + _pam_system_log(LOG_CRIT, + "pam_mkargv: null returned by _pam_strdup"); D(("arg NULL")); } else { /* Overkill on the malloc, but not large */ argvlen = (l + 1) * ((sizeof(char)) + sizeof(char *)); if ((our_argv = argvbuf = malloc(argvlen)) == NULL) { - pam_system_log(NULL, NULL, LOG_CRIT, - "pam_mkargv: null returned by malloc"); + _pam_system_log(LOG_CRIT, + "pam_mkargv: null returned by malloc"); } else { char *tmp=NULL; @@ -206,11 +177,15 @@ int _pam_mkargv(char *s, char ***argv, int *argc) void _pam_sanitize(pam_handle_t *pamh) { + int old_caller_is = pamh->caller_is; + /* * this is for security. We reset the auth-tokens here. */ - pam_set_item(pamh,PAM_AUTHTOK,NULL); - pam_set_item(pamh,PAM_OLDAUTHTOK,NULL); + __PAM_TO_MODULE(pamh); + pam_set_item(pamh, PAM_AUTHTOK, NULL); + pam_set_item(pamh, PAM_OLDAUTHTOK, NULL); + pamh->caller_is = old_caller_is; } /* @@ -247,7 +222,7 @@ void _pam_parse_control(int *control_array, char *tok) int act, len; /* skip leading space */ - while (isspace(*tok) && *++tok); + while (isspace((int)*tok) && *++tok); if (!*tok) break; @@ -264,21 +239,21 @@ void _pam_parse_control(int *control_array, char *tok) } /* observe '=' */ - while (isspace(*tok) && *++tok); + while (isspace((int)*tok) && *++tok); if (!*tok || *tok++ != '=') { error = "expecting '='"; goto parse_error; } /* skip leading space */ - while (isspace(*tok) && *++tok); + while (isspace((int)*tok) && *++tok); if (!*tok) { error = "expecting action"; goto parse_error; } /* observe action type */ - for (act=0; act<=-_PAM_ACTION_UNDEF; ++act) { + for (act=0; act < (-(_PAM_ACTION_UNDEF)); ++act) { len = strlen(_pam_token_actions[act]); if (!strncmp(_pam_token_actions[act], tok, len)) { act *= -1; @@ -296,7 +271,7 @@ void _pam_parse_control(int *control_array, char *tok) * cause looping problems. So, for now, we will just * allow forward jumps. (AGM 1998/1/7) */ - if (!isdigit(*tok)) { + if (!isdigit((int)*tok)) { error = "expecting jump number"; goto parse_error; } @@ -305,7 +280,7 @@ void _pam_parse_control(int *control_array, char *tok) do { act *= 10; act += *tok - '0'; /* XXX - this assumes ascii behavior */ - } while (*++tok && isdigit(*tok)); + } while (*++tok && isdigit((int)*tok)); if (! act) { /* we do not allow 0 jumps. There is a token ('ignore') for that */ @@ -328,7 +303,7 @@ void _pam_parse_control(int *control_array, char *tok) parse_error: /* treat everything as bad */ - pam_system_log(NULL, NULL, LOG_ERR, "pam_parse: %s; [...%s]", error, tok); + _pam_system_log(LOG_ERR, "pam_parse: %s; [...%s]", error, tok); for (ret=0; ret<_PAM_RETURN_VALUES; control_array[ret++]=_PAM_ACTION_BAD); } diff --git a/contrib/libpam/libpam/pam_password.c b/contrib/libpam/libpam/pam_password.c index 303425ab625..c247b1269f7 100644 --- a/contrib/libpam/libpam/pam_password.c +++ b/contrib/libpam/libpam/pam_password.c @@ -1,14 +1,14 @@ /* pam_password.c - PAM Password Management */ /* - * $Id: pam_password.c,v 1.7 1997/04/05 06:56:45 morgan Exp $ - * - * $Log: pam_password.c,v $ + * $Id: pam_password.c,v 1.2 2001/01/22 06:07:29 agmorgan Exp $ */ #include #include +/* #define DEBUG */ + #include "pam_private.h" int pam_chauthtok(pam_handle_t *pamh, int flags) @@ -19,6 +19,11 @@ int pam_chauthtok(pam_handle_t *pamh, int flags) IF_NO_PAMH("pam_chauthtok", pamh, PAM_SYSTEM_ERR); + if (__PAM_FROM_MODULE(pamh)) { + D(("called from module!?")); + return PAM_SYSTEM_ERR; + } + if (pamh->former.choice == PAM_NOT_STACKED) { _pam_start_timer(pamh); /* we try to make the time for a failure independent of the time it takes to @@ -27,10 +32,11 @@ int pam_chauthtok(pam_handle_t *pamh, int flags) pamh->former.update = PAM_FALSE; } - /* first loop through to check if there will be a problem */ + /* first call to check if there will be a problem */ if (pamh->former.update || (retval = _pam_dispatch(pamh, flags|PAM_PRELIM_CHECK, PAM_CHAUTHTOK)) == PAM_SUCCESS) { + D(("completed check ok: former=%d", pamh->former.update)); pamh->former.update = PAM_TRUE; retval = _pam_dispatch(pamh, flags|PAM_UPDATE_AUTHTOK, PAM_CHAUTHTOK); @@ -41,9 +47,9 @@ int pam_chauthtok(pam_handle_t *pamh, int flags) _pam_sanitize(pamh); pamh->former.update = PAM_FALSE; _pam_await_timer(pamh, retval); /* if unsuccessful then wait now */ - D(("pam_authenticate exit")); + D(("pam_chauthtok exit %d - %d", retval, pamh->former.choice)); } else { - D(("will resume when ready")); + D(("will resume when ready", retval)); } return retval; diff --git a/contrib/libpam/libpam/pam_private.h b/contrib/libpam/libpam/pam_private.h index f8a0da54fc9..cd7843f92dc 100644 --- a/contrib/libpam/libpam/pam_private.h +++ b/contrib/libpam/libpam/pam_private.h @@ -1,7 +1,7 @@ /* * pam_private.h * - * $Id: pam_private.h,v 1.12 1997/04/05 06:57:37 morgan Exp morgan $ + * $Id: pam_private.h,v 1.4 2001/02/05 06:50:41 agmorgan Exp $ * * This is the Linux-PAM Library Private Header. It contains things * internal to the Linux-PAM library. Things not needed by either an @@ -10,16 +10,16 @@ * Please see end of file for copyright. * * Creator: Marc Ewing. - * Maintained: AGM - * - * $Log: pam_private.h,v $ + * Maintained: CVS */ #ifndef _PAM_PRIVATE_H #define _PAM_PRIVATE_H +#include + /* this is not used at the moment --- AGM */ -#define LIBPAM_VERSION 65 +#define LIBPAM_VERSION (LIBPAM_VERSION_MAJOR*0x100 + LIBPAM_VERSION_MINOR) #include #include @@ -47,6 +47,9 @@ struct handler { int must_fail; int (*func)(pam_handle_t *pamh, int flags, int argc, char **argv); int actions[_PAM_RETURN_VALUES]; + /* set by authenticate, open_session, chauthtok(1st) + consumed by setcred, close_session, chauthtok(2nd) */ + int cached_retval; int *cached_retval_p; int argc; char **argv; struct handler *next; @@ -126,6 +129,7 @@ struct _pam_former_state { struct pam_handle { char *authtok; + unsigned caller_is; struct pam_conv *pam_conversation; char *oldauthtok; char *prompt; /* for use by pam_get_user() */ @@ -134,7 +138,6 @@ struct pam_handle { char *rhost; char *ruser; char *tty; - struct pam_log_state pam_default_log; /* for ident etc., log state */ struct pam_data *data; struct pam_environ *env; /* structure to maintain environment list */ struct _pam_fail_delay fail_delay; /* helper function for easy delays */ @@ -191,8 +194,6 @@ int _pam_make_env(pam_handle_t *pamh); /* delete the environment structure */ void _pam_drop_env(pam_handle_t *pamh); -#ifdef LINUX_PAM - /* these functions deal with failure delays as required by the authentication modules and application. Their *interface* is likely to remain the same although their function is hopefully going to @@ -207,16 +208,13 @@ void _pam_start_timer(pam_handle_t *pamh); /* this waits for the clock to stop ticking if status != PAM_SUCCESS */ void _pam_await_timer(pam_handle_t *pamh, int status); - -#endif /* LINUX_PAM */ - typedef void (*voidfunc(void))(void); #ifdef PAM_STATIC /* The next two in ../modules/_pam_static/pam_static.c */ /* Return pointer to data structure used to define a static module */ -struct pam_module * _pam_open_static_handler(char *path); +struct pam_module * _pam_open_static_handler(const char *path); /* Return pointer to function requested from static module */ @@ -250,6 +248,9 @@ void _pam_set_default_control(int *control_array, int default_action); void _pam_parse_control(int *control_array, char *tok); +void _pam_system_log(int priority, const char *format, ... ); +#define _PAM_SYSTEM_LOG_PREFIX "PAM " + /* * XXX - Take care with this. It could confuse the logic of a trailing * else @@ -257,7 +258,7 @@ void _pam_parse_control(int *control_array, char *tok); #define IF_NO_PAMH(X,pamh,ERR) \ if ((pamh) == NULL) { \ - pam_system_log(NULL, NULL, LOG_ERR, X ": NULL pam handle passed"); \ + _pam_system_log(LOG_ERR, X ": NULL pam handle passed"); \ return ERR; \ } @@ -265,25 +266,28 @@ if ((pamh) == NULL) { \ #define PAM_DEFAULT_PROMPT "Please enter username: " -/* - * pam_system_log default ident/facility.. - */ - -#define PAM_LOG_STATE_DEFAULT { \ - PAM_LOG_STATE_IDENT, \ - PAM_LOG_STATE_OPTION, \ - PAM_LOG_STATE_FACILITY \ -} - /* * include some helpful macros */ #include +/* used to work out where control currently resides (in an application + or in a module) */ + +#define _PAM_CALLED_FROM_MODULE 1 +#define _PAM_CALLED_FROM_APP 2 + +#define __PAM_FROM_MODULE(pamh) ((pamh)->caller_is == _PAM_CALLED_FROM_MODULE) +#define __PAM_FROM_APP(pamh) ((pamh)->caller_is == _PAM_CALLED_FROM_APP) +#define __PAM_TO_MODULE(pamh) \ + do { (pamh)->caller_is = _PAM_CALLED_FROM_MODULE; } while (0) +#define __PAM_TO_APP(pamh) \ + do { (pamh)->caller_is = _PAM_CALLED_FROM_APP; } while (0) + /* * Copyright (C) 1995 by Red Hat Software, Marc Ewing - * Copyright (c) 1996-8, Andrew G. Morgan + * Copyright (c) 1996-8,2001 by Andrew G. Morgan * * All rights reserved * diff --git a/contrib/libpam/libpam/pam_second.c b/contrib/libpam/libpam/pam_second.c index b720774e7e6..72bd7ea5ddc 100644 --- a/contrib/libpam/libpam/pam_second.c +++ b/contrib/libpam/libpam/pam_second.c @@ -2,9 +2,8 @@ * pam_second.c -- PAM secondary authentication * (based on XSSO draft spec of March 1997) * - * $Id$ + * $Id: pam_second.c,v 1.2 2000/12/04 19:02:34 baggins Exp $ * - * $Log$ */ #include diff --git a/contrib/libpam/libpam/pam_session.c b/contrib/libpam/libpam/pam_session.c index 38b93fe7054..3709f62d77a 100644 --- a/contrib/libpam/libpam/pam_session.c +++ b/contrib/libpam/libpam/pam_session.c @@ -1,17 +1,7 @@ /* pam_session.c - PAM Session Management */ /* - * $Id: pam_session.c,v 1.3 1996/12/01 03:14:13 morgan Exp $ - * - * $Log: pam_session.c,v $ - * Revision 1.3 1996/12/01 03:14:13 morgan - * use _pam_macros.h - * - * Revision 1.2 1996/03/10 02:19:12 morgan - * some oversight meant that this wasn't being compiled. It needed a - * couple of changes. - * - * + * $Id: pam_session.c,v 1.3 2001/01/22 06:07:29 agmorgan Exp $ */ #include @@ -22,7 +12,13 @@ int pam_open_session(pam_handle_t *pamh, int flags) { D(("called")); - IF_NO_PAMH("pam_open_session",pamh,PAM_SYSTEM_ERR); + IF_NO_PAMH("pam_open_session", pamh, PAM_SYSTEM_ERR); + + if (__PAM_FROM_MODULE(pamh)) { + D(("called from module!?")); + return PAM_SYSTEM_ERR; + } + return _pam_dispatch(pamh, flags, PAM_OPEN_SESSION); } @@ -30,6 +26,12 @@ int pam_close_session(pam_handle_t *pamh, int flags) { D(("called")); - IF_NO_PAMH("pam_close_session",pamh,PAM_SYSTEM_ERR); + IF_NO_PAMH("pam_close_session", pamh, PAM_SYSTEM_ERR); + + if (__PAM_FROM_MODULE(pamh)) { + D(("called from module!?")); + return PAM_SYSTEM_ERR; + } + return _pam_dispatch(pamh, flags, PAM_CLOSE_SESSION); } diff --git a/contrib/libpam/libpam/pam_start.c b/contrib/libpam/libpam/pam_start.c index 53700a09102..2296c9a9500 100644 --- a/contrib/libpam/libpam/pam_start.c +++ b/contrib/libpam/libpam/pam_start.c @@ -3,9 +3,8 @@ /* Creator Marc Ewing * Maintained by AGM * - * $Id: pam_start.c,v 1.10 1997/04/05 06:58:11 morgan Exp $ + * $Id: pam_start.c,v 1.2 2001/01/22 06:07:29 agmorgan Exp $ * - * $Log: pam_start.c,v $ */ #include @@ -26,17 +25,21 @@ int pam_start ( ,service_name, user, pam_conversation, pamh)); if ((*pamh = calloc(1, sizeof(**pamh))) == NULL) { - pam_system_log(NULL, NULL, LOG_CRIT, - "pam_start: calloc failed for *pamh"); + _pam_system_log(LOG_CRIT, "pam_start: calloc failed for *pamh"); return (PAM_BUF_ERR); } + /* Mark the caller as the application - permission to do certain + things is limited to a module or an application */ + + __PAM_TO_APP(*pamh); + if (service_name) { char *tmp; if (((*pamh)->service_name = _pam_strdup(service_name)) == NULL) { - pam_system_log(NULL, NULL, LOG_CRIT, - "pam_start: _pam_strdup failed for service name"); + _pam_system_log(LOG_CRIT, + "pam_start: _pam_strdup failed for service name"); _pam_drop(*pamh); return (PAM_BUF_ERR); } @@ -47,8 +50,8 @@ int pam_start ( if (user) { if (((*pamh)->user = _pam_strdup(user)) == NULL) { - pam_system_log(NULL, NULL, LOG_CRIT, - "pam_start: _pam_strdup failed for user"); + _pam_system_log(LOG_CRIT, + "pam_start: _pam_strdup failed for user"); _pam_drop((*pamh)->service_name); _pam_drop(*pamh); return (PAM_BUF_ERR); @@ -68,8 +71,7 @@ int pam_start ( if (pam_conversation == NULL || ((*pamh)->pam_conversation = (struct pam_conv *) malloc(sizeof(struct pam_conv))) == NULL) { - pam_system_log(NULL, NULL, LOG_CRIT, - "pam_start: malloc failed for pam_conv"); + _pam_system_log(LOG_CRIT, "pam_start: malloc failed for pam_conv"); _pam_drop((*pamh)->service_name); _pam_drop((*pamh)->user); _pam_drop(*pamh); @@ -81,8 +83,7 @@ int pam_start ( (*pamh)->data = NULL; if ( _pam_make_env(*pamh) != PAM_SUCCESS ) { - pam_system_log(NULL, NULL, LOG_ERR, - "pam_start: failed to initialize environment"); + _pam_system_log(LOG_ERR,"pam_start: failed to initialize environment"); _pam_drop((*pamh)->service_name); _pam_drop((*pamh)->user); _pam_drop(*pamh); @@ -96,21 +97,15 @@ int pam_start ( /* According to the SunOS man pages, loading modules and resolving * symbols happens on the first call from the application. */ - /* - * XXX - should we call _pam_init_handlers() here ? The following - * is new as of Linux-PAM 0.55 - */ - if ( _pam_init_handlers(*pamh) != PAM_SUCCESS ) { - pam_system_log(NULL, NULL, LOG_ERR, - "pam_start: failed to initialize handlers"); + _pam_system_log(LOG_ERR, "pam_start: failed to initialize handlers"); _pam_drop_env(*pamh); /* purge the environment */ _pam_drop((*pamh)->service_name); _pam_drop((*pamh)->user); _pam_drop(*pamh); return PAM_ABORT; } - + D(("exiting pam_start successfully")); return PAM_SUCCESS; diff --git a/contrib/libpam/libpam/pam_strerror.c b/contrib/libpam/libpam/pam_strerror.c index 607c6d5dbfe..4f2249db75d 100644 --- a/contrib/libpam/libpam/pam_strerror.c +++ b/contrib/libpam/libpam/pam_strerror.c @@ -1,20 +1,7 @@ /* pam_strerror.c */ -/* $Id: pam_strerror.c,v 1.6 1997/01/04 20:12:02 morgan Exp morgan $ - * - * $Log: pam_strerror.c,v $ - * Revision 1.6 1997/01/04 20:12:02 morgan - * replaced conditional FAIL_NOW with ABORT - * - * Revision 1.5 1996/07/07 23:58:56 morgan - * corrected "... " to "..." - * - * Revision 1.4 1996/06/02 08:03:29 morgan - * spelling correction - * - * Revision 1.3 1996/03/16 23:08:54 morgan - * PAM --> Linux-PAM ;) - * +/* + * $Id: pam_strerror.c,v 1.2 2000/12/04 19:02:34 baggins Exp $ */ #include "pam_private.h" diff --git a/contrib/libpam/libpam/pam_tokens.h b/contrib/libpam/libpam/pam_tokens.h index 9380f8837b9..69e794895ec 100644 --- a/contrib/libpam/libpam/pam_tokens.h +++ b/contrib/libpam/libpam/pam_tokens.h @@ -1,7 +1,7 @@ /* * pam_tokens.h * - * $Id$ + * $Id: pam_tokens.h,v 1.3 2001/01/22 06:07:29 agmorgan Exp $ * * This is a Linux-PAM Library Private Header file. It contains tokens * that are used when we parse the configuration file(s). @@ -9,8 +9,7 @@ * Please see end of file for copyright. * * Creator: Andrew Morgan. - * - * $Log$ + * */ #ifndef _PAM_TOKENS_H @@ -60,13 +59,15 @@ const char * const _pam_token_returns[_PAM_RETURN_VALUES+1] = { "authtok_expired", /* 27 */ "module_unknown", /* 28 */ "bad_item", /* 29 */ + "conv_again", /* 30 */ + "incomplete", /* 31 */ /* add new return codes here */ "default" /* this is _PAM_RETURN_VALUES and indicates the default return action */ }; /* - * Copyright (C) 1998, Andrew G. Morgan + * Copyright (C) 1998,2001 Andrew G. Morgan * * All rights reserved * diff --git a/contrib/libpam/libpam_misc/Makefile b/contrib/libpam/libpam_misc/Makefile index 1cfc86577b1..b7ff178cbe7 100644 --- a/contrib/libpam/libpam_misc/Makefile +++ b/contrib/libpam/libpam_misc/Makefile @@ -1,109 +1,106 @@ -# $Header: /home/morgan/pam/Linux-PAM-0.57/libpam_misc/RCS/Makefile,v 1.10 1997/04/05 07:00:18 morgan Exp $ # -# $Log: Makefile,v $ -# Revision 1.10 1997/04/05 07:00:18 morgan -# fakeroot -# -# Revision 1.9 1997/02/15 15:46:56 morgan -# inherit major and minor numbers from top level -# -# Revision 1.8 1997/01/04 20:20:11 morgan -# update for .55 and make -> $(MAKE) -# -# Revision 1.7 1996/12/01 03:28:11 morgan -# update for 0.54 +# $Id: Makefile,v 1.3 2001/02/10 07:17:53 agmorgan Exp $ # -dummy: - @echo "*** This is not a top-level Makefile!" +# lots of debugging information goes to /tmp/pam-debug.log +#MOREFLAGS += -D"DEBUG" -# /////////////////////////////////////////////////////////////////// +include ../Make.Rules -# uncomment if you wnat libpam_misc to be made as a dynamic library -# AGM has had some segfaulting from libdl when I did this. I have not -# investigated the cause... - -MAKE_DYNAMIC=yes - -ifeq ($(DEBUG_REL),yes) - LIBNAME=pamd_misc +ifeq ($(WITH_LIBDEBUG),yes) + LIBNAME=libpam_miscd else - LIBNAME=pam_misc + LIBNAME=libpam_misc endif -LIBMAJOR=$(MAJOR_REL) -LIBMINOR=$(MINOR_REL) +VERSION=.$(MAJOR_REL) +MODIFICATION=.$(MINOR_REL) -FILES=misc_conv help_env +CFLAGS += $(MOREFLAGS) $(DYNAMIC) $(STATIC) -# -# Probably no need to alter anything below here. -# +# dynamic library names -# build dynamic library names - -LIBDYNAMIC=lib$(LIBNAME).$(DYNTYPE) -LIBDYNMAJ=$(LIBDYNAMIC).$(LIBMAJOR) -LIBDYNMIN=$(LIBDYNMAJ).$(LIBMINOR) +LIBNAMED = $(LIBNAME).$(DYNTYPE) +LIBNAMEDNAME = $(LIBNAMED)$(VERSION) +LIBNAMEDFULL = $(LIBNAMEDNAME)$(MODIFICATION) # static library name -LIBSTATIC = lib$(LIBNAME).a +LIBNAMEDSTATIC = $(LIBNAME).a -# sources and object files +LIBOBJECTS = help_env.o misc_conv.o -LIBSRC = $(addsuffix .c,$(FILES)) -LIBOBJ = $(addsuffix .o,$(FILES)) +ifeq ($(DYNAMIC_LIBPAM),yes) +DLIBOBJECTS = $(addprefix dynamic/,$(LIBOBJECTS)) +endif -# rules +ifeq ($(STATIC_LIBPAM),yes) +SLIBOBJECTS = $(addprefix static/,$(LIBOBJECTS)) +endif -all: $(LIBSTATIC) $(LIBDYNAMIC) +# --------------------------------------------- +## rules -$(LIBDYNAMIC): $(LIBOBJ) -ifdef MAKE_DYNAMIC +all: dirs $(LIBNAMED) $(LIBNAMEDSTATIC) + +dirs: +ifeq ($(DYNAMIC_LIBPAM),yes) + $(MKDIR) dynamic +endif +ifeq ($(STATIC_LIBPAM),yes) + $(MKDIR) static +endif + +dynamic/%.o : %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +static/%.o : %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +$(LIBNAMED): $(DLIBOBJECTS) +ifeq ($(DYNAMIC_LIBPAM),yes) ifeq ($(USESONAME),yes) - $(LD_L) $(SOSWITCH) $(LIBDYNMAJ) -o $@ $(LIBOBJ) + $(LD_L) $(SOSWITCH) $(LIBNAMEDNAME) -o $@ $(DLIBOBJECTS) $(MODULES) $(LINKLIBS) else - $(LD_L) -o $@ $(LIBOBJ) + $(LD_L) -o $@ $(DLIBOBJECTS) $(MODULES) endif ifeq ($(NEEDSONAME),yes) - rm -f $(LIBDYNMIN) - ln -s $(LIBDYNAMIC) $(LIBDYNMAJ) - rm -f $(LIBDYNMAJ) - ln -s $(LIBDYNAMIC) $(LIBDYNMIN) + rm -f $(LIBNAMEDFULL) + ln -s $(LIBNAMED) $(LIBNAMEDFULL) + rm -f $(LIBNAMEDNAME) + ln -s $(LIBNAMED) $(LIBNAMEDNAME) endif endif -$(LIBSTATIC): $(LIBOBJ) - $(AR) $@ $(LIBOBJ) +$(LIBNAMEDSTATIC): $(SLIBOBJECTS) +ifeq ($(STATIC_LIBPAM),yes) + $(AR) rc $@ $(SLIBOBJECTS) $(MODULES) $(RANLIB) $@ +endif install: all $(MKDIR) $(FAKEROOT)$(INCLUDED) - $(INSTALL) -m 644 ./pam_misc.h $(FAKEROOT)$(INCLUDED) -ifdef MAKE_DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBDYNAMIC) $(FAKEROOT)$(LIBDIR)/$(LIBDYNMIN) + $(INSTALL) -m 644 include/security/pam_misc.h $(FAKEROOT)$(INCLUDED) +ifeq ($(DYNAMIC_LIBPAM),yes) + $(MKDIR) $(FAKEROOT)$(libdir) + $(INSTALL) -m $(SHLIBMODE) $(LIBNAMED) $(FAKEROOT)$(libdir)/$(LIBNAMEDFULL) $(LDCONFIG) ifneq ($(DYNTYPE),"sl") - ( cd $(FAKEROOT)$(LIBDIR) ; ln -sf $(LIBDYNMAJ) $(LIBDYNAMIC) ) + ( cd $(FAKEROOT)$(libdir) ; rm -f $(LIBNAMED) ; ln -s $(LIBNAMEDNAME) $(LIBNAMED) ) endif endif - $(INSTALL) -m 644 $(LIBSTATIC) $(FAKEROOT)$(LIBDIR) - -clean: - rm -f *.so *.a core a.out *~ +ifeq ($(STATIC_LIBPAM),yes) + $(INSTALL) -m 644 $(LIBNAMEDSTATIC) $(FAKEROOT)$(libdir) +endif remove: rm -f $(FAKEROOT)$(INCLUDED)/pam_misc.h - rm -f $(FAKEROOT)$(LIBDIR)/$(LIBDYNAMIC).* - rm -f $(FAKEROOT)$(LIBDIR)/$(LIBDYNAMIC) + rm -f $(FAKEROOT)$(libdir)/$(LIBNAMEDFULL) + rm -f $(FAKEROOT)$(libdir)/$(LIBNAMED) $(LDCONFIG) - rm -f $(FAKEROOT)$(LIBDIR)/$(LIBSTATIC) - rm -f $(FAKEROOT)$(INCLUDED)/chk_malloc.h - -.c.o: - $(CC) -c $(DEFS) $(CFLAGS) $< - -extraclean: - @$(MAKE) clean - rm -f *.o *.bak + rm -f $(FAKEROOT)$(libdir)/$(LIBNAMEDSTATIC) +clean: + rm -f a.out core *~ static/*.o dynamic/*.o + rm -f *.a *.out *.o *.so ./include/security/*~ + if [ -d dynamic ]; then rmdir dynamic ; fi + if [ -d static ]; then rmdir static ; fi diff --git a/contrib/libpam/libpam_misc/help_env.c b/contrib/libpam/libpam_misc/help_env.c index d35b66b948c..e1390984273 100644 --- a/contrib/libpam/libpam_misc/help_env.c +++ b/contrib/libpam/libpam_misc/help_env.c @@ -1,15 +1,8 @@ /* - * $Id: help_env.c,v 1.2 1997/01/04 20:19:20 morgan Exp morgan $ + * $Id: help_env.c,v 1.2 2000/12/04 19:02:34 baggins Exp $ * * This file was written by Andrew G. Morgan * - * $Log: help_env.c,v $ - * Revision 1.2 1997/01/04 20:19:20 morgan - * added a prototype (no warning) and fixed paste function - * - * Revision 1.1 1996/12/01 03:25:37 morgan - * Initial revision - * */ #include diff --git a/contrib/libpam/libpam_misc/include/security/pam_misc.h b/contrib/libpam/libpam_misc/include/security/pam_misc.h new file mode 100644 index 00000000000..1e8c4784c53 --- /dev/null +++ b/contrib/libpam/libpam_misc/include/security/pam_misc.h @@ -0,0 +1,57 @@ +/* $Id: pam_misc.h,v 1.3 2001/01/20 22:29:47 agmorgan Exp $ */ + +#ifndef __PAMMISC_H +#define __PAMMISC_H + +#include +#include + +/* include some useful macros */ + +#include + +/* functions defined in pam_misc.* libraries */ + +extern int misc_conv(int num_msg, const struct pam_message **msgm, + struct pam_response **response, void *appdata_ptr); + +#include + +extern time_t pam_misc_conv_warn_time; /* time that we should warn user */ +extern time_t pam_misc_conv_die_time; /* cut-off time for input */ +extern const char *pam_misc_conv_warn_line; /* warning notice */ +extern const char *pam_misc_conv_die_line; /* cut-off remark */ +extern int pam_misc_conv_died; /* 1 = cut-off time reached (0 not) */ +extern int (*pam_binary_handler_fn)(void *appdata, pamc_bp_t *prompt_p); +extern void (*pam_binary_handler_free)(void *appdata, pamc_bp_t *prompt_p); +/* + * Environment helper functions + */ + +/* transcribe given environment (to pam) */ +extern int pam_misc_paste_env(pam_handle_t *pamh + , const char * const * user_env); + +/* char **pam_misc_copy_env(pam_handle_t *pamh); + + This is no longer defined as a prototype because the X/Open XSSO + spec makes it clear that PAM's pam_getenvlist() does exactly + what this was needed for. + + A wrapper is still provided in the pam_misc library - so that + legacy applications will still work. But _BE_WARNED_ it will + disappear by the release of libpam 1.0 . */ + +/* delete environment as obtained from (pam_getenvlist) */ +extern char **pam_misc_drop_env(char **env); + +/* provide something like the POSIX setenv function for the (Linux-)PAM + * environment. */ + +extern int pam_misc_setenv(pam_handle_t *pamh, const char *name + , const char *value, int readonly); + +#endif + + + diff --git a/contrib/libpam/libpam_misc/misc_conv.c b/contrib/libpam/libpam_misc/misc_conv.c index 53cf51b76cc..8e2460dc4c1 100644 --- a/contrib/libpam/libpam_misc/misc_conv.c +++ b/contrib/libpam/libpam_misc/misc_conv.c @@ -1,32 +1,12 @@ /* - * $Id: misc_conv.c,v 1.5 1997/01/04 20:16:48 morgan Exp morgan $ + * $Id: misc_conv.c,v 1.3 2001/01/20 22:29:47 agmorgan Exp $ * * A generic conversation function for text based applications * * Written by Andrew Morgan - * - * $Log: misc_conv.c,v $ - * Revision 1.5 1997/01/04 20:16:48 morgan - * removed getpass. Replaced with POSIX code for same function which - * also observes timeouts specified by the parent application - * - * Revision 1.4 1996/12/01 03:26:51 morgan - * *** empty log message *** - * - * Revision 1.3 1996/11/10 20:10:01 morgan - * sgi definition - * - * Revision 1.2 1996/07/07 23:59:56 morgan - * changed the name of the misc include file - * - * Revision 1.1 1996/05/02 05:17:06 morgan - * Initial revision */ -#ifdef linux -#define _GNU_SOURCE -#include -#endif +#include #include #include @@ -57,39 +37,23 @@ const char *pam_misc_conv_die_line = "..\a.Sorry, your time is up!\n"; int pam_misc_conv_died=0; /* application can probe this for timeout */ -static void pam_misc_conv_delete_binary(void **delete_me) -{ - if (delete_me && *delete_me) { - unsigned char *packet = *(unsigned char **)delete_me; - int length; +/* + * These functions are for binary prompt manipulation. + * The manner in which a binary prompt is processed is application + * specific, so these function pointers are provided and can be + * initialized by the application prior to the conversation function + * being used. + */ - length = 4+(packet[0]<<24)+(packet[1]<<16)+(packet[2]<<8)+packet[3]; - memset(packet, 0, length); - free(packet); - *delete_me = packet = NULL; - } +static void pam_misc_conv_delete_binary(void *appdata, + pamc_bp_t *delete_me) +{ + PAM_BP_RENEW(delete_me, 0, 0); } -/* These function pointers are for application specific binary - conversations. One or both of the arguments to the first function - must be non-NULL. The first function must return PAM_SUCCESS or - PAM_CONV_ERR. If input is non-NULL, a response is expected, this - response should be malloc()'d and will eventually be free()'d by - the calling module. The structure of this malloc()'d response is as - follows: - - { int length, char data[length] } - - For convenience, the pointer used by the two function pointer - prototypes is 'void *'. - - The ...free() fn pointer is used to discard a binary message that - is not of the default form. It should be explicitly overwritten - when using some other convention for the structure of a binary - prompt (not recommended). */ - -int (*pam_binary_handler_fn)(const void *send, void **receive) = NULL; -void (*pam_binary_handler_free)(void **packet_p) = pam_misc_conv_delete_binary; +int (*pam_binary_handler_fn)(void *appdata, pamc_bp_t *prompt_p) = NULL; +void (*pam_binary_handler_free)(void *appdata, pamc_bp_t *prompt_p) + = pam_misc_conv_delete_binary; /* the following code is used to get text input */ @@ -293,26 +257,26 @@ int misc_conv(int num_msg, const struct pam_message **msgm, break; case PAM_BINARY_PROMPT: { - void *pack_out=NULL; - const void *pack_in = msgm[count]->msg; + pamc_bp_t binary_prompt = NULL; - if (!pam_binary_handler_fn - || pam_binary_handler_fn(pack_in, &pack_out) != PAM_SUCCESS - || pack_out == NULL) { + if (!msgm[count]->msg || !pam_binary_handler_fn) { goto failed_conversation; } - string = (char *) pack_out; - pack_out = NULL; - break; - } - case PAM_BINARY_MSG: - { - const void *pack_in = msgm[count]->msg; - if (!pam_binary_handler_fn - || pam_binary_handler_fn(pack_in, NULL) != PAM_SUCCESS) { + PAM_BP_RENEW(&binary_prompt, + PAM_BP_RCONTROL(msgm[count]->msg), + PAM_BP_LENGTH(msgm[count]->msg)); + PAM_BP_FILL(binary_prompt, 0, PAM_BP_LENGTH(msgm[count]->msg), + PAM_BP_RDATA(msgm[count]->msg)); + + if (pam_binary_handler_fn(appdata_ptr, + &binary_prompt) != PAM_SUCCESS + || (binary_prompt == NULL)) { goto failed_conversation; } + string = (char *) binary_prompt; + binary_prompt = NULL; + break; } default: @@ -351,11 +315,11 @@ int misc_conv(int num_msg, const struct pam_message **msgm, free(reply[count].resp); break; case PAM_BINARY_PROMPT: - pam_binary_handler_free((void **) &reply[count].resp); + pam_binary_handler_free(appdata_ptr, + (pamc_bp_t *) &reply[count].resp); break; case PAM_ERROR_MSG: case PAM_TEXT_INFO: - case PAM_BINARY_MSG: /* should not actually be able to get here... */ free(reply[count].resp); } diff --git a/contrib/libpam/libpamc/License b/contrib/libpam/libpamc/License new file mode 100644 index 00000000000..9010695470a --- /dev/null +++ b/contrib/libpam/libpamc/License @@ -0,0 +1,42 @@ +Unless otherwise *explicitly* stated the following text describes the +licensed conditions under which the contents of this libpamc release +may be distributed: + +------------------------------------------------------------------------- +Redistribution and use in source and binary forms of libpamc, +with or without modification, are permitted provided that the +following conditions are met: + +1. Redistributions of source code must retain any existing copyright + notice, and this entire permission notice in its entirety, + including the disclaimer of warranties. + +2. Redistributions in binary form must reproduce all prior and current + copyright notices, this list of conditions, and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + +3. The name of any author may not be used to endorse or promote + products derived from this software without their specific prior + written permission. + +ALTERNATIVELY, this product may be distributed under the terms of the +GNU Library General Public License (LGPL), in which case the +provisions of the GNU LGPL are required INSTEAD OF the above +restrictions. (This clause is necessary due to a potential conflict +between the GNU LGPL 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(S) 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/libpamc/Makefile b/contrib/libpam/libpamc/Makefile new file mode 100644 index 00000000000..1869cfe9dfb --- /dev/null +++ b/contrib/libpam/libpamc/Makefile @@ -0,0 +1,107 @@ +# +# $Id: Makefile,v 1.3 2001/02/10 07:17:53 agmorgan Exp $ +# + +# lots of debugging information goes to /tmp/pam-debug.log +#MOREFLAGS += -D"DEBUG" + +include ../Make.Rules + +ifeq ($(DEBUG_REL),yes) + LIBNAME=libpamcd +else + LIBNAME=libpamc +endif +VERSION=.$(MAJOR_REL) +MODIFICATION=.$(MINOR_REL) + +CFLAGS += $(MOREFLAGS) $(DYNAMIC) $(STATIC) + +# dynamic library names + +LIBNAMED = $(LIBNAME).$(DYNTYPE) +LIBNAMEDNAME = $(LIBNAMED)$(VERSION) +LIBNAMEDFULL = $(LIBNAMEDNAME)$(MODIFICATION) + +# static library name + +LIBNAMEDSTATIC = $(LIBNAME).a + +LIBOBJECTS = pamc_client.o pamc_converse.o pamc_load.o + +ifeq ($(DYNAMIC_LIBPAM),yes) +DLIBOBJECTS = $(addprefix dynamic/,$(LIBOBJECTS)) +endif + +ifeq ($(STATIC_LIBPAM),yes) +SLIBOBJECTS = $(addprefix static/,$(LIBOBJECTS)) +endif + +# --------------------------------------------- +## rules + +all: dirs $(LIBNAMED) $(LIBNAMEDSTATIC) + +dirs: +ifeq ($(DYNAMIC_LIBPAM),yes) + $(MKDIR) dynamic +endif +ifeq ($(STATIC_LIBPAM),yes) + $(MKDIR) static +endif + +dynamic/%.o : %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +static/%.o : %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +$(LIBNAMED): $(DLIBOBJECTS) +ifeq ($(DYNAMIC_LIBPAM),yes) + ifeq ($(USESONAME),yes) + $(LD_L) $(SOSWITCH) $(LIBNAMEDNAME) -o $@ $(DLIBOBJECTS) $(MODULES) $(LINKLIBS) + else + $(LD_L) -o $@ $(DLIBOBJECTS) $(MODULES) + endif + ifeq ($(NEEDSONAME),yes) + rm -f $(LIBNAMEDFULL) + ln -s $(LIBNAMED) $(LIBNAMEDFULL) + rm -f $(LIBNAMEDNAME) + ln -s $(LIBNAMED) $(LIBNAMEDNAME) + endif +endif + +$(LIBNAMEDSTATIC): $(SLIBOBJECTS) +ifeq ($(STATIC_LIBPAM),yes) + $(AR) rc $@ $(SLIBOBJECTS) $(MODULES) + $(RANLIB) $@ +endif + +install: all + $(MKDIR) $(FAKEROOT)$(INCLUDED) + $(INSTALL) -m 644 include/security/pam_client.h $(FAKEROOT)$(INCLUDED) +ifeq ($(DYNAMIC_LIBPAM),yes) + $(MKDIR) $(FAKEROOT)$(libdir) + $(INSTALL) -m $(SHLIBMODE) $(LIBNAMED) $(FAKEROOT)$(libdir)/$(LIBNAMEDFULL) + $(LDCONFIG) + ifneq ($(DYNTYPE),"sl") + ( cd $(FAKEROOT)$(libdir) ; rm -f $(LIBNAMED) ; ln -s $(LIBNAMEDNAME) $(LIBNAMED) ) + endif +endif +ifeq ($(STATIC_LIBPAM),yes) + $(INSTALL) -m 644 $(LIBNAMEDSTATIC) $(FAKEROOT)$(libdir) +endif + +remove: + rm -f $(FAKEROOT)$(INCLUDED)/pam_client.h + rm -f $(FAKEROOT)$(libdir)/$(LIBNAMEDFULL) + rm -f $(FAKEROOT)$(libdir)/$(LIBNAMED) + $(LDCONFIG) + rm -f $(FAKEROOT)$(libdir)/$(LIBNAMEDSTATIC) + +clean: + rm -f a.out core *~ static/*.o dynamic/*.o + rm -f *.a *.out *.o *.so ./include/security/*~ + if [ -d dynamic ]; then rmdir dynamic ; fi + if [ -d static ]; then rmdir static ; fi + diff --git a/contrib/libpam/libpamc/include/security/pam_client.h b/contrib/libpam/libpamc/include/security/pam_client.h new file mode 100644 index 00000000000..08aa817a28d --- /dev/null +++ b/contrib/libpam/libpamc/include/security/pam_client.h @@ -0,0 +1,190 @@ +/* + * $Id: pam_client.h,v 1.4 2001/01/20 22:29:47 agmorgan Exp $ + * + * Copyright (c) 1999 Andrew G. Morgan + * + * This header file provides the prototypes for the PAM client API + */ + +#ifndef PAM_CLIENT_H +#define PAM_CLIENT_H + +#include +#include +#include + +/* opaque agent handling structure */ + +typedef struct pamc_handle_s *pamc_handle_t; + +/* binary prompt structure pointer */ +#ifndef __u32 +# define __u32 unsigned int +#endif +#ifndef __u8 +# define __u8 unsigned char +#endif +typedef struct { __u32 length; __u8 control; } *pamc_bp_t; + +/* + * functions provided by libpamc + */ + +/* + * Initialize the agent abstraction library + */ + +pamc_handle_t pamc_start(void); + +/* + * Terminate the authentication process + */ + +int pamc_end(pamc_handle_t *pch); + +/* + * force the loading of a specified agent + */ + +int pamc_load(pamc_handle_t pch, const char *agent_id); + +/* + * Single conversation interface for binary prompts + */ + +int pamc_converse(pamc_handle_t pch, pamc_bp_t *prompt_p); + +/* + * disable an agent + */ + +int pamc_disable(pamc_handle_t pch, const char *agent_id); + +/* + * obtain a list of available agents + */ + +char **pamc_list_agents(pamc_handle_t pch); + +/* + * PAM_BP_ MACROS for creating, destroying and manipulating binary prompts + */ + +#include +#include +#include + +#ifndef PAM_BP_ASSERT +# define PAM_BP_ASSERT(x) do { printf(__FILE__ "(%d): %s\n", \ + __LINE__, x) ; exit(1); } while (0) +#endif /* PAM_BP_ASSERT */ + +#ifndef PAM_BP_CALLOC +# define PAM_BP_CALLOC calloc +#endif /* PAM_BP_CALLOC */ + +#ifndef PAM_BP_FREE +# define PAM_BP_FREE free +#endif /* PAM_BP_FREE */ + +#define __PAM_BP_WOCTET(x,y) (*((y) + (__u8 *)(x))) +#define __PAM_BP_ROCTET(x,y) (*((y) + (const __u8 *)(x))) + +#define PAM_BP_MIN_SIZE (sizeof(__u32) + sizeof(__u8)) +#define PAM_BP_MAX_LENGTH 0x20000 /* an advisory limit */ +#define PAM_BP_WCONTROL(x) (__PAM_BP_WOCTET(x,4)) +#define PAM_BP_RCONTROL(x) (__PAM_BP_ROCTET(x,4)) +#define PAM_BP_SIZE(x) ((__PAM_BP_ROCTET(x,0)<<24)+ \ + (__PAM_BP_ROCTET(x,1)<<16)+ \ + (__PAM_BP_ROCTET(x,2)<< 8)+ \ + (__PAM_BP_ROCTET(x,3) )) +#define PAM_BP_LENGTH(x) (PAM_BP_SIZE(x) - PAM_BP_MIN_SIZE) +#define PAM_BP_WDATA(x) (PAM_BP_MIN_SIZE + (__u8 *) (x)) +#define PAM_BP_RDATA(x) (PAM_BP_MIN_SIZE + (const __u8 *) (x)) + +/* Note, this macro always '\0' terminates renewed packets */ + +#define PAM_BP_RENEW(old_p, cntrl, data_length) \ +do { \ + if (old_p) { \ + if (*(old_p)) { \ + __u32 __size; \ + __size = PAM_BP_SIZE(*(old_p)); \ + memset(*(old_p), 0, __size); \ + PAM_BP_FREE(*(old_p)); \ + } \ + if (cntrl) { \ + __u32 __size; \ + \ + __size = PAM_BP_MIN_SIZE + data_length; \ + if ((*(old_p) = PAM_BP_CALLOC(1, 1+__size))) { \ + __PAM_BP_WOCTET(*(old_p), 3) = __size & 0xFF; \ + __PAM_BP_WOCTET(*(old_p), 2) = (__size>>=8) & 0xFF; \ + __PAM_BP_WOCTET(*(old_p), 1) = (__size>>=8) & 0xFF; \ + __PAM_BP_WOCTET(*(old_p), 0) = (__size>>=8) & 0xFF; \ + (*(old_p))->control = cntrl; \ + } else { \ + PAM_BP_ASSERT("out of memory for binary prompt"); \ + } \ + } else { \ + *old_p = NULL; \ + } \ + } else { \ + PAM_BP_ASSERT("programming error, invalid binary prompt pointer"); \ + } \ +} while (0) + +#define PAM_BP_FILL(prmpt, offset, length, data) \ +do { \ + int bp_length; \ + __u8 *prompt = (__u8 *) (prmpt); \ + bp_length = PAM_BP_LENGTH(prompt); \ + if (bp_length < ((length)+(offset))) { \ + PAM_BP_ASSERT("attempt to write over end of prompt"); \ + } \ + memcpy((offset) + PAM_BP_WDATA(prompt), (data), (length)); \ +} while (0) + +#define PAM_BP_EXTRACT(prmpt, offset, length, data) \ +do { \ + int __bp_length; \ + const __u8 *__prompt = (const __u8 *) (prmpt); \ + __bp_length = PAM_BP_LENGTH(__prompt); \ + if (((offset) < 0) || (__bp_length < ((length)+(offset))) \ + || ((length) < 0)) { \ + PAM_BP_ASSERT("invalid extraction from prompt"); \ + } \ + memcpy((data), (offset) + PAM_BP_RDATA(__prompt), (length)); \ +} while (0) + + +/* Control types */ + +#define PAM_BPC_FALSE 0 +#define PAM_BPC_TRUE 1 + +#define PAM_BPC_OK 0x01 /* continuation packet */ +#define PAM_BPC_SELECT 0x02 /* initialization packet */ +#define PAM_BPC_DONE 0x03 /* termination packet */ +#define PAM_BPC_FAIL 0x04 /* unable to execute */ + +/* The following control characters are only legal for echanges + between an agent and a client (it is the responsibility of the + client to enforce this rule in the face of a rogue server): */ + +#define PAM_BPC_GETENV 0x41 /* obtain client env.var */ +#define PAM_BPC_PUTENV 0x42 /* set client env.var */ +#define PAM_BPC_TEXT 0x43 /* display message */ +#define PAM_BPC_ERROR 0x44 /* display error message */ +#define PAM_BPC_PROMPT 0x45 /* echo'd text prompt */ +#define PAM_BPC_PASS 0x46 /* non-echo'd text prompt*/ + +/* quick check for prompts that are legal for the client (by + implication the server too) to send to libpamc */ + +#define PAM_BPC_FOR_CLIENT(/* pamc_bp_t */ prompt) \ + (((prompt)->control <= PAM_BPC_FAIL && (prompt)->control >= PAM_BPC_OK) \ + ? PAM_BPC_TRUE:PAM_BPC_FALSE) + + +#endif /* PAM_CLIENT_H */ diff --git a/contrib/libpam/libpamc/libpamc.h b/contrib/libpam/libpamc/libpamc.h new file mode 100644 index 00000000000..1c9397c9071 --- /dev/null +++ b/contrib/libpam/libpamc/libpamc.h @@ -0,0 +1,63 @@ +/* + * $Id: libpamc.h,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ + * + * Copyright (c) Andrew G. Morgan + * + */ + +#ifndef LIBPAMC_H +#define LIBPAMC_H + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define _PAMC_DEFAULT_TOP_FD 10 + +struct pamc_handle_s { + struct pamc_agent_s *current; + struct pamc_agent_s *chain; + struct pamc_blocked_s *blocked_agents; + int max_path; + char **agent_paths; + int combined_status; + int highest_fd_to_close; +}; + +typedef struct pamc_blocked_s { + char *id; /* terminated */ + struct pamc_blocked_s *next; +} pamc_blocked_t; + +typedef struct pamc_agent_s { + char *id; + int id_length; + struct pamc_agent_s *next; + int writer; /* write to agent */ + int reader; /* read from agent */ + pid_t pid; /* agent process id */ +} pamc_agent_t; + +/* used to build a tree of unique, sorted agent ids */ + +typedef struct pamc_id_node { + struct pamc_id_node *left, *right; + int child_count; + char *agent_id; +} pamc_id_node_t; + +/* internal function */ +int __pamc_valid_agent_id(int id_length, const char *id); + +#define PAMC_SYSTEM_AGENT_PATH "/lib/pamc:/usr/lib/pamc" +#define PAMC_SYSTEM_AGENT_SEPARATOR ':' + +#endif /* LIBPAMC_H */ diff --git a/contrib/libpam/libpamc/pamc_client.c b/contrib/libpam/libpamc/pamc_client.c new file mode 100644 index 00000000000..19eff429f89 --- /dev/null +++ b/contrib/libpam/libpamc/pamc_client.c @@ -0,0 +1,189 @@ +/* + * $Id: pamc_client.c,v 1.1.1.1 2000/06/20 22:11:25 agmorgan Exp $ + * + * Copyright (c) Andrew G. Morgan + * + * pamc_start and pamc_end + */ + +#include "libpamc.h" + +/* + * liberate path list + */ + +static void __pamc_delete_path_list(pamc_handle_t pch) +{ + int i; + + for (i=0; pch->agent_paths[i]; ++i) { + free(pch->agent_paths[i]); + pch->agent_paths[i] = NULL; + } + + free(pch->agent_paths); + pch->agent_paths = NULL; +} + +/* + * open the pamc library + */ + +pamc_handle_t pamc_start(void) +{ + int i, count, last, this; + const char *default_path; + pamc_handle_t pch; + + pch = calloc(1, sizeof(struct pamc_handle_s)); + if (pch == NULL) { + D(("no memory for *pch")); + return NULL; + } + + pch->highest_fd_to_close = _PAMC_DEFAULT_TOP_FD; + + default_path = getenv("PAMC_AGENT_PATH"); + if (default_path == NULL) { + default_path = PAMC_SYSTEM_AGENT_PATH; + } + + /* number of individual paths */ + for (count=1, i=0; default_path[i]; ++i) { + if (default_path[i] == PAMC_SYSTEM_AGENT_SEPARATOR) { + ++count; + } + } + + pch->agent_paths = calloc(count+1, sizeof(char *)); + if (pch->agent_paths == NULL) { + D(("no memory for path list")); + goto drop_pch; + } + + this = last = i = 0; + while ( default_path[i] || (i != last) ) { + if ( default_path[i] == PAMC_SYSTEM_AGENT_SEPARATOR + || !default_path[i] ) { + int length; + + pch->agent_paths[this] = malloc(length = 1+i-last); + + if (pch->agent_paths[this] == NULL) { + D(("no memory for next path")); + goto drop_list; + } + + memcpy(pch->agent_paths[this], default_path + last, i-last); + pch->agent_paths[this][i-last] = '\0'; + if (length > pch->max_path) { + pch->max_path = length; + } + + if (++this == count) { + break; + } + + last = ++i; + } else { + ++i; + } + } + + return pch; + +drop_list: + __pamc_delete_path_list(pch); + +drop_pch: + free(pch); + + return NULL; +} + +/* + * shutdown each of the loaded agents and + */ + +static int __pamc_shutdown_agents(pamc_handle_t pch) +{ + int retval = PAM_BPC_TRUE; + + D(("called")); + + while (pch->chain) { + pid_t pid; + int status; + pamc_agent_t *this; + + this = pch->chain; + D(("cleaning up agent %p", this)); + pch->chain = pch->chain->next; + this->next = NULL; + D(("cleaning up agent: %s", this->id)); + + /* close off contact with agent and wait for it to shutdown */ + + close(this->writer); + this->writer = -1; + close(this->reader); + this->reader = -1; + + pid = waitpid(this->pid, &status, 0); + if (pid == this->pid) { + + D(("is exit:%d, exit val:%d", + WIFEXITED(status), WEXITSTATUS(status))); + + if (!(WIFEXITED(status) && (WEXITSTATUS(status) == 0))) { + retval = PAM_BPC_FALSE; + } + } else { + D(("problem shutting down agent (%s): pid(%d) != waitpid(%d)!?", + this->id, this->pid, pid)); + retval = PAM_BPC_FALSE; + } + pid = this->pid = 0; + + memset(this->id, 0, this->id_length); + free(this->id); + this->id = NULL; + this->id_length = 0; + + free(this); + this = NULL; + } + + return retval; +} + +/* + * close the pamc library + */ + +int pamc_end(pamc_handle_t *pch_p) +{ + int retval; + + if (pch_p == NULL) { + D(("called with no pch_p")); + return PAM_BPC_FALSE; + } + + if (*pch_p == NULL) { + D(("called with no *pch_p")); + return PAM_BPC_FALSE; + } + + D(("removing path_list")); + __pamc_delete_path_list(*pch_p); + + D(("shutting down agents")); + retval = __pamc_shutdown_agents(*pch_p); + + D(("freeing *pch_p")); + free(*pch_p); + *pch_p = NULL; + + return retval; +} diff --git a/contrib/libpam/libpamc/pamc_converse.c b/contrib/libpam/libpamc/pamc_converse.c new file mode 100644 index 00000000000..131789fb15a --- /dev/null +++ b/contrib/libpam/libpamc/pamc_converse.c @@ -0,0 +1,211 @@ +/* + * $Id: pamc_converse.c,v 1.2 2001/01/20 22:29:47 agmorgan Exp $ + * + * Copyright (c) Andrew G. Morgan + * + * pamc_converse + */ + +#include "libpamc.h" + +/* + * select agent + */ + +static int __pamc_select_agent(pamc_handle_t pch, char *agent_id) +{ + pamc_agent_t *agent; + + for (agent = pch->chain; agent; agent = agent->next) { + if (!strcmp(agent->id, agent_id)) { + pch->current = agent; + return PAM_BPC_TRUE; + } + } + + D(("failed to locate agent")); + pch->current = NULL; + return PAM_BPC_FALSE; +} + +/* + * pass a binary prompt to the active agent and wait for a reply prompt + */ + +int pamc_converse(pamc_handle_t pch, pamc_bp_t *prompt_p) +{ + __u32 size, offset=0; + __u8 control, raw[PAM_BP_MIN_SIZE]; + + D(("called")); + + if (pch == NULL) { + D(("null pch")); + goto pamc_converse_failure; + } + + if (prompt_p == NULL) { + D(("null prompt_p")); + goto pamc_converse_failure; + } + + if (*prompt_p == NULL) { + D(("null *prompt_p")); + goto pamc_converse_failure; + } + + /* from here on, failures are interoperability problems.. */ + + size = PAM_BP_SIZE(*prompt_p); + if (size < PAM_BP_MIN_SIZE) { + D(("problem with size being too short (%u)", size)); + goto pamc_unknown_prompt; + } + + if (PAM_BPC_FOR_CLIENT(*prompt_p) != PAM_BPC_TRUE) { + D(("*prompt_p is not legal for the client to use")); + goto pamc_unknown_prompt; + } + + /* do we need to select the agent? */ + if ((*prompt_p)->control == PAM_BPC_SELECT) { + char *rawh; + int i, retval; + + D(("selecting a specified agent")); + + rawh = (char *) *prompt_p; + for (i = PAM_BP_MIN_SIZE; i= size) + || !__pamc_valid_agent_id(i-PAM_BP_MIN_SIZE, + rawh + PAM_BP_MIN_SIZE) ) { + goto pamc_unknown_prompt; + } + + rawh[i] = '\0'; + retval = pamc_load(pch, PAM_BP_MIN_SIZE + rawh); + if (retval == PAM_BPC_TRUE) { + retval = __pamc_select_agent(pch, PAM_BP_MIN_SIZE + rawh); + } + rawh[i] = '/'; + + if (retval != PAM_BPC_TRUE) { + goto pamc_unknown_prompt; + } + + D(("agent is loaded")); + } + + if (pch->current == NULL) { + D(("unable to address agent")); + goto pamc_unknown_prompt; + } + + /* pump all of the prompt into the agent */ + do { + int rval = write(pch->current->writer, + offset + (const __u8 *) (*prompt_p), + size - offset); + if (rval == -1) { + switch (errno) { + case EINTR: + break; + default: + D(("problem writing to agent: %s", strerror(errno))); + goto pamc_unknown_prompt; + } + } else { + offset += rval; + } + } while (offset < size); + + D(("whole prompt sent to agent")); + + /* read size and control for response prompt */ + + offset = 0; + memset(raw, 0, sizeof(raw)); + do { + int rval; + + rval = read(pch->current->reader, raw + offset, + PAM_BP_MIN_SIZE - offset); + + if (rval == -1) { + switch (errno) { + case EINTR: + break; + default: + D(("problem reading from agent: %s", strerror(errno))); + goto pamc_unknown_prompt; + } + } else if (rval) { + offset += rval; + } else { + D(("agent has closed its output pipe - nothing more to read")); + goto pamc_converse_failure; + } + } while (offset < PAM_BP_MIN_SIZE); + + /* construct the whole reply prompt */ + + size = PAM_BP_SIZE(raw); + control = PAM_BP_RCONTROL(raw); + memset(raw, 0, sizeof(raw)); + + D(("agent replied with prompt of size %d and control %u", + size, control)); + + PAM_BP_RENEW(prompt_p, control, size - PAM_BP_MIN_SIZE); + if (*prompt_p == NULL) { + D(("problem making a new prompt for reply")); + goto pamc_unknown_prompt; + } + + /* read the rest of the reply prompt -- note offset has the correct + value from the previous loop */ + + while (offset < size) { + int rval = read(pch->current->reader, offset + (__u8 *) *prompt_p, + size-offset); + + if (rval == -1) { + switch (errno) { + case EINTR: + break; + default: + D(("problem reading from agent: %s", strerror(errno))); + goto pamc_unknown_prompt; + } + } else if (rval) { + offset += rval; + } else { + D(("problem reading prompt (%d) with %d to go", + size, size-offset)); + goto pamc_converse_failure; + } + } + + D(("returning success")); + + return PAM_BPC_TRUE; + +pamc_converse_failure: + + D(("conversation failure")); + PAM_BP_RENEW(prompt_p, 0, 0); + return PAM_BPC_FALSE; + +pamc_unknown_prompt: + + /* the server is trying something that the client does not support */ + D(("unknown prompt")); + PAM_BP_RENEW(prompt_p, PAM_BPC_FAIL, 0); + return PAM_BPC_TRUE; +} + diff --git a/contrib/libpam/libpamc/pamc_load.c b/contrib/libpam/libpamc/pamc_load.c new file mode 100644 index 00000000000..01304cc1afe --- /dev/null +++ b/contrib/libpam/libpamc/pamc_load.c @@ -0,0 +1,477 @@ +/* + * $Id: pamc_load.c,v 1.1.1.1 2000/06/20 22:11:26 agmorgan Exp $ + * + * Copyright (c) 1999 Andrew G. Morgan + * + * pamc_load + */ + +#include "libpamc.h" + +static int __pamc_exec_agent(pamc_handle_t pch, pamc_agent_t *agent) +{ + char *full_path; + int found_agent, length, reset_length, to_agent[2], from_agent[2]; + int return_code = PAM_BPC_FAIL; + + if (agent->id[agent->id_length] != '\0') { + PAM_BP_ASSERT("libpamc: internal error agent_id not terminated"); + } + + for (length=0; (length < agent->id_length); ++length) { + switch (agent->id[length]) { + case '/': + D(("ill formed agent id")); + return PAM_BPC_FAIL; + } + } + + /* enough memory for any path + this agent */ + reset_length = 3 + pch->max_path + agent->id_length; + D(("reset_length = %d (3+%d+%d)", + reset_length, pch->max_path, agent->id_length)); + full_path = malloc(reset_length); + if (full_path == NULL) { + D(("no memory for agent path")); + return PAM_BPC_FAIL; + } + + found_agent = 0; + for (length=0; pch->agent_paths[length]; ++length) { + struct stat buf; + + D(("path: [%s]", pch->agent_paths[length])); + D(("agent id: [%s]", agent->id)); + + sprintf(full_path, "%s/%s", pch->agent_paths[length], agent->id); + + D(("looking for agent here: [%s]\n", full_path)); + if (stat(full_path, &buf) == 0) { + D(("file existis")); + found_agent = 1; + break; + } + } + + if (! found_agent) { + D(("no agent was found")); + goto free_and_return; + } + + if (pipe(to_agent)) { + D(("failed to open pipe to agent")); + goto free_and_return; + } + + if (pipe(from_agent)) { + D(("failed to open pipe from agent")); + goto close_the_agent; + } + + agent->pid = fork(); + if (agent->pid == -1) { + + D(("failed to fork for agent")); + goto close_both_pipes; + + } else if (agent->pid == 0) { + + int i; + + dup2(from_agent[1], STDOUT_FILENO); + dup2(to_agent[0], STDIN_FILENO); + + /* we close all of the files that have filedescriptors lower + and equal to twice the highest we have seen, The idea is + that we don't want to leak filedescriptors to agents from a + privileged client application. + + XXX - this is a heuristic at this point. There is a growing + need for an extra 'set param' libpamc function, that could + be used to supply info like the highest fd to close etc.. + */ + + if (from_agent[1] > pch->highest_fd_to_close) { + pch->highest_fd_to_close = 2*from_agent[1]; + } + + for (i=0; i <= pch->highest_fd_to_close; ++i) { + switch (i) { + case STDOUT_FILENO: + case STDERR_FILENO: + case STDIN_FILENO: + /* only these three remain open */ + break; + default: + (void) close(i); /* don't care if its not open */ + } + } + + /* we make no attempt to drop other privileges - this library + has no idea how that would be done in the general case. It + is up to the client application (when calling + pamc_converse) to make sure no privilege will leak into an + (untrusted) agent. */ + + /* we propogate no environment - future versions of this + library may have the ability to audit all agent + transactions. */ + + D(("exec'ing agent %s", full_path)); + execle(full_path, "pam-agent", NULL, NULL); + + D(("exec failed")); + exit(1); + + } + + close(to_agent[0]); + close(from_agent[1]); + + agent->writer = to_agent[1]; + agent->reader = from_agent[0]; + + return_code = PAM_BPC_TRUE; + goto free_and_return; + +close_both_pipes: + close(from_agent[0]); + close(from_agent[1]); + +close_the_agent: + close(to_agent[0]); + close(to_agent[1]); + +free_and_return: + memset(full_path, 0, reset_length); + free(full_path); + + D(("returning %d", return_code)); + + return return_code; +} + +/* + * has the named agent been loaded? + */ + +static int __pamc_agent_is_enabled(pamc_handle_t pch, const char *agent_id) +{ + pamc_agent_t *agent; + + for (agent = pch->chain; agent; agent = agent->next) { + if (!strcmp(agent->id, agent_id)) { + D(("agent already loaded")); + return PAM_BPC_TRUE; + } + } + + D(("agent is not loaded")); + return PAM_BPC_FALSE; +} + +/* + * has the named agent been disabled? + */ + +static int __pamc_agent_is_disabled(pamc_handle_t pch, const char *agent_id) +{ + pamc_blocked_t *blocked; + + for (blocked=pch->blocked_agents; blocked; blocked = blocked->next) { + if (!strcmp(agent_id, blocked->id)) { + D(("agent is disabled")); + return PAM_BPC_TRUE; + } + } + + D(("agent is not disabled")); + return PAM_BPC_FALSE; +} + +/* + * disable an agent + */ + +int pamc_disable(pamc_handle_t pch, const char *agent_id) +{ + pamc_blocked_t *block; + + if (pch == NULL) { + D(("pch is NULL")); + return PAM_BPC_FALSE; + } + + if (agent_id == NULL) { + D(("agent_id is NULL")); + return PAM_BPC_FALSE; + } + + if (__pamc_agent_is_enabled(pch, agent_id) != PAM_BPC_FALSE) { + D(("agent is already loaded")); + return PAM_BPC_FALSE; + } + + if (__pamc_agent_is_disabled(pch, agent_id) != PAM_BPC_FALSE) { + D(("agent is already disabled")); + return PAM_BPC_TRUE; + } + + block = calloc(1, sizeof(pamc_blocked_t)); + if (block == NULL) { + D(("no memory for new blocking structure")); + return PAM_BPC_FALSE; + } + + block->id = malloc(1 + strlen(agent_id)); + if (block->id == NULL) { + D(("no memory for agent id")); + free(block); + return PAM_BPC_FALSE; + } + + strcpy(block->id, agent_id); + block->next = pch->blocked_agents; + pch->blocked_agents = block; + + return PAM_BPC_TRUE; +} + +/* + * force the loading of a particular agent + */ + +int pamc_load(pamc_handle_t pch, const char *agent_id) +{ + pamc_agent_t *agent; + int length; + + /* santity checking */ + + if (pch == NULL) { + D(("pch is NULL")); + return PAM_BPC_FALSE; + } + + if (agent_id == NULL) { + D(("agent_id is NULL")); + return PAM_BPC_FALSE; + } + + if (__pamc_agent_is_disabled(pch, agent_id) != PAM_BPC_FALSE) { + D(("sorry agent is disabled")); + return PAM_BPC_FALSE; + } + + length = strlen(agent_id); + + /* scan list to see if agent is loaded */ + + if (__pamc_agent_is_enabled(pch, agent_id) == PAM_BPC_TRUE) { + D(("no need to load an already loaded agent (%s)", agent_id)); + return PAM_BPC_TRUE; + } + + /* not in the list, so we need to load it and add it to the head + of the chain */ + + agent = calloc(1, sizeof(pamc_agent_t)); + if (agent == NULL) { + D(("no memory for new agent")); + return PAM_BPC_FALSE; + } + agent->id = calloc(1, 1+length); + if (agent->id == NULL) { + D(("no memory for new agent's id")); + goto fail_free_agent; + } + memcpy(agent->id, agent_id, length); + agent->id[length] = '\0'; + agent->id_length = length; + + if (__pamc_exec_agent(pch, agent) != PAM_BPC_TRUE) { + D(("unable to exec agent")); + goto fail_free_agent_id; + } + + agent->next = pch->chain; + pch->chain = agent; + + return PAM_BPC_TRUE; + +fail_free_agent_id: + + memset(agent->id, 0, agent->id_length); + free(agent->id); + + memset(agent, 0, sizeof(*agent)); + +fail_free_agent: + + free(agent); + return PAM_BPC_FALSE; +} + +/* + * what's a valid agent name? + */ + +int __pamc_valid_agent_id(int id_length, const char *id) +{ + int post, i; + + for (i=post=0 ; i < id_length; ++i) { + int ch = id[i++]; + + if (isalpha(ch) || isdigit(ch) || (ch == '_')) { + continue; + } else if (post && (ch == '.')) { + continue; + } else if ((i > 1) && (!post) && (ch == '@')) { + post = 1; + } else { + D(("id=%s contains '%c' which is illegal", id, ch)); + return 0; + } + } + + if (!i) { + D(("length of id is 0")); + return 0; + } else { + return 1; /* id is valid */ + } +} + +/* + * building a tree of available agent names + */ + +static pamc_id_node_t *__pamc_add_node(pamc_id_node_t *root, const char *id, + int *counter) +{ + if (root) { + + int cmp; + + if ((cmp = strcmp(id, root->agent_id))) { + if (cmp > 0) { + root->right = __pamc_add_node(root->right, id, + &(root->child_count)); + } else { + root->left = __pamc_add_node(root->left, id, + &(root->child_count)); + } + } + + return root; + + } else { + + pamc_id_node_t *node = calloc(1, sizeof(pamc_id_node_t)); + + if (node) { + node->agent_id = malloc(1+strlen(id)); + if (node->agent_id) { + strcpy(node->agent_id, id); + } else { + free(node); + node = NULL; + } + } + + (*counter)++; + return node; + } +} + +/* + * drop all of the tree and any remaining ids + */ + +static pamc_id_node_t *__pamc_liberate_nodes(pamc_id_node_t *tree) +{ + if (tree) { + if (tree->agent_id) { + free(tree->agent_id); + tree->agent_id = NULL; + } + + tree->left = __pamc_liberate_nodes(tree->left); + tree->right = __pamc_liberate_nodes(tree->right); + + tree->child_count = 0; + free(tree); + } + + return NULL; +} + +/* + * fill a list with the contents of the tree (in ascii order) + */ + +static void __pamc_fill_list_from_tree(pamc_id_node_t *tree, char **agent_list, + int *counter) +{ + if (tree) { + __pamc_fill_list_from_tree(tree->left, agent_list, counter); + agent_list[(*counter)++] = tree->agent_id; + tree->agent_id = NULL; + __pamc_fill_list_from_tree(tree->right, agent_list, counter); + } +} + +/* + * get a list of the available agents + */ + +char **pamc_list_agents(pamc_handle_t pch) +{ + int i, total_agent_count=0; + pamc_id_node_t *tree = NULL; + char **agent_list; + + /* loop over agent paths */ + + for (i=0; pch->agent_paths[i]; ++i) { + DIR *dir; + + dir = opendir(pch->agent_paths[i]); + if (dir) { + struct dirent *item; + + while ((item = readdir(dir))) { + + /* this is a cheat on recognizing agent_ids */ + if (!__pamc_valid_agent_id(strlen(item->d_name), + item->d_name)) { + continue; + } + + tree = __pamc_add_node(tree, item->d_name, &total_agent_count); + } + + closedir(dir); + } + } + + /* now, we build a list of ids */ + D(("total of %d available agents\n", total_agent_count)); + + agent_list = calloc(total_agent_count+1, sizeof(char *)); + if (agent_list) { + int counter=0; + + __pamc_fill_list_from_tree(tree, agent_list, &counter); + if (counter != total_agent_count) { + PAM_BP_ASSERT("libpamc: internal error transcribing tree"); + } + } else { + D(("no memory for agent list")); + } + + __pamc_liberate_nodes(tree); + + return agent_list; +} diff --git a/contrib/libpam/libpamc/test/agents/secret@here b/contrib/libpam/libpamc/test/agents/secret@here new file mode 100755 index 00000000000..afdcbaa801a --- /dev/null +++ b/contrib/libpam/libpamc/test/agents/secret@here @@ -0,0 +1,308 @@ +#!/usr/bin/perl +# +# This is a simple example PAM authentication agent, it implements a +# simple shared secret authentication scheme. The PAM module pam_secret.so +# is its counter part. Both the agent and the remote server are able to +# authenticate one another, but the server is given the opportunity to +# ignore a failed authentication. +# + +$^W = 1; +use strict; +use IPC::Open2; +$| = 1; + +# display extra information to STDERR +my $debug = 0; +if (scalar @ARGV) { + $debug = 1; +} + +# Globals + +my %state; +my $default_key; + +my $next_key = $$; + +# loop over binary prompts +for (;;) { + my ($control, $data) = ReadBinaryPrompt(); + my ($reply_control, $reply_data); + + if ($control == 0) { + if ($debug) { + print STDERR "agent: no packet to read\n"; + } + last; + } elsif ($control == 0x02) { + ($reply_control, $reply_data) = HandleAgentSelection($data); + } elsif ($control == 0x01) { + ($reply_control, $reply_data) = HandleContinuation($data); + } else { + if ($debug) { + print STDERR + "agent: unrecognized packet $control {$data} to read\n"; + } + ($reply_control, $reply_data) = (0x04, ""); + } + + WriteBinaryPrompt($reply_control, $reply_data); +} + +# Only willing to exit well if we've completed our authentication exchange + +if (scalar keys %state) { + if ($debug) { + print STDERR "The following sessions are still active:\n "; + print STDERR join ', ', keys %state; + print STDERR "\n"; + } + exit 1; +} else { + exit 0; +} + +sub HandleAgentSelection ($) { + my ($data) = @_; + + unless ( $data =~ /^([a-zA-Z0-9_]+\@?[a-zA-Z0-9_.]*)\/(.*)$/ ) { + return (0x04, ""); + } + + my ($agent_name, $payload) = ($1, $2); + if ($debug) { + print STDERR "agent: ". "agent=$agent_name, payload=$payload\n"; + } + + # this agent has a defined name + if ($agent_name ne "secret\@here") { + if ($debug) { + print STDERR "bad agent name: [$agent_name]\n"; + } + return (0x04, ""); + } + + # the selection request is acompanied with a hexadecimal cookie + my @tokens = split '\|', $payload; + + unless ((scalar @tokens) == 2) { + if ($debug) { + print STDERR "bad payload\n"; + } + return (0x04, ""); + } + + unless ($tokens[1] =~ /^[a-z0-9]+$/) { + if ($debug) { + print STDERR "bad server cookie\n"; + } + return (0x04, ""); + } + + my $shared_secret = IdentifyLocalSecret($tokens[0]); + + unless (defined $shared_secret) { + # make a secret up + if ($debug) { + print STDERR "agent: cannot authenticate user\n"; + } + $shared_secret = GetRandom(); + } + + my $local_cookie = GetRandom(); + $default_key = $next_key++; + + $state{$default_key} = $local_cookie ."|". $tokens[1] ."|". $shared_secret; + + if ($debug) { + print STDERR "agent: \$state{$default_key} = $state{$default_key}\n"; + } + + return (0x01, $default_key ."|". $local_cookie); +} + +sub HandleContinuation ($) { + my ($data) = @_; + + my ($key, $server_digest) = split '\|', $data; + + unless (defined $state{$key}) { + # retries and out of sequence prompts are not permitted + return (0x04, ""); + } + + my $expected_digest = CreateDigest($state{$key}); + my ($local_cookie, $remote_cookie, $shared_secret) + = split '\|', $state{$key}; + delete $state{$key}; + + unless ($expected_digest eq $server_digest) { + if ($debug) { + print STDERR "agent: don't trust server - faking reply\n"; + print STDERR "agent: got ($server_digest)\n"; + print STDERR "agent: expected ($expected_digest)\n"; + } + + ## FIXME: Agent should exchange a prompt with the client warning + ## that the server is faking us out. + + return (0x03, CreateDigest($expected_digest . $data . GetRandom())); + } + + if ($debug) { + print STDERR "agent: server appears to know the secret\n"; + } + + my $session_authenticated_ticket = + CreateDigest($remote_cookie."|".$shared_secret."|".$local_cookie); + + # FIXME: Agent should set a derived session key environment + # variable (available for the client (and its children) to sign + # future data exchanges. + + if ($debug) { + print STDERR "agent: should putenv(" + ."\"AUTH_SESSION_TICKET=$session_authenticated_ticket\")\n"; + } + + # return agent's authenticating digest + return (0x03, CreateDigest($shared_secret."|".$remote_cookie + ."|".$local_cookie)); +} + +sub ReadBinaryPrompt { + my $buffer = " "; + my $count = read(STDIN, $buffer, 5); + if ($count == 0) { + # no more packets to read + return (0, ""); + } + + if ($count != 5) { + # broken packet header + return (-1, ""); + } + + my ($length, $control) = unpack("N C", $buffer); + if ($length < 5) { + # broken packet length + return (-1, ""); + } + + my $data = ""; + $length -= 5; + while ($count = read(STDIN, $buffer, $length)) { + $data .= $buffer; + if ($count != $length) { + $length -= $count; + next; + } + + if ($debug) { + print STDERR "agent: ". "data is [$data]\n"; + } + + return ($control, $data); + } + + # broken packet data + return (-1, ""); +} + +sub WriteBinaryPrompt ($$) { + my ($control, $data) = @_; + + my $length = 5 + length($data); + if ($debug) { + printf STDERR "agent: ". "{%d|0x%.2x|%s}\n", $length, $control, $data; + } + my $bp = pack("N C a*", $length, $control, $data); + print STDOUT $bp; + if ($debug) { + printf STDERR "agent: ". "agent has replied\n"; + } +} + +## +## Here is where we parse the simple secret file +## The format of this file is a list of lines of the following form: +## +## user@client0.host.name secret_string1 +## user@client1.host.name secret_string2 +## user@client2.host.name secret_string3 +## + +sub IdentifyLocalSecret ($) { + my ($identifier) = @_; + my $secret; + + if (open SECRETS, "< ". (getpwuid($<))[7] ."/.secret\@here") { + my $line; + while (defined ($line = )) { + my ($id, $sec) = split /[\s]+/, $line; + if ((defined $id) && ($id eq $identifier)) { + $secret = $sec; + last; + } + } + close SECRETS; + } + + return $secret; +} + +## Here is where we generate a message digest + +sub CreateDigest ($) { + my ($data) = @_; + + my $pid = open2(\*MD5out, \*MD5in, "/usr/bin/md5sum -") + or die "you'll need /usr/bin/md5sum installed"; + + my $oldfd = select MD5in; $|=1; select $oldfd; + if ($debug) { + print STDERR "agent: ". "telling md5: <$data>\n"; + } + print MD5in "$data"; + close MD5in; + my $reply = ; + ($reply) = split /\s/, $reply; + if ($debug) { + print STDERR "agent: ". "md5 said: <$reply>\n"; + } + close MD5out; + + return $reply; +} + +## get a random number + +sub GetRandom { + + if ( -r "/dev/urandom" ) { + open RANDOM, "< /dev/urandom" or die "crazy"; + + my $i; + my $reply = ""; + + for ($i=0; $i<4; ++$i) { + my $buffer = " "; + while (read(RANDOM, $buffer, 4) != 4) { + ; + } + $reply .= sprintf "%.8x", unpack("N", $buffer); + if ($debug) { + print STDERR "growing reply: [$reply]\n"; + } + } + close RANDOM; + + return $reply; + } else { + print STDERR "agent: ". "[got linux?]\n"; + return "%.8x%.8x%.8x%.8x", time, time, time, time; + } + +} + diff --git a/contrib/libpam/libpamc/test/modules/Makefile b/contrib/libpam/libpamc/test/modules/Makefile new file mode 100644 index 00000000000..48065462976 --- /dev/null +++ b/contrib/libpam/libpamc/test/modules/Makefile @@ -0,0 +1,9 @@ +CFLAGS = -g -fPIC -I"../../include" + +pam_secret.so: pam_secret.o + ld -x --shared -o pam_secret.so pam_secret.o -lc + +.o.c: + +clean: + rm -f *.so *.o diff --git a/contrib/libpam/libpamc/test/modules/pam_secret.c b/contrib/libpam/libpamc/test/modules/pam_secret.c new file mode 100644 index 00000000000..f59e53a5472 --- /dev/null +++ b/contrib/libpam/libpamc/test/modules/pam_secret.c @@ -0,0 +1,670 @@ +/* + * $Id: pam_secret.c,v 1.2 2001/01/20 22:29:47 agmorgan Exp $ + * + * Copyright (c) 1999 Andrew G. Morgan + */ + +/* + * WARNING: AS WRITTEN THIS CODE IS NOT SECURE. THE MD5 IMPLEMENTATION + * NEEDS TO BE INTEGRATED MORE NATIVELY. + */ + +/* #define DEBUG */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * This is a sample module that demonstrates the use of binary prompts + * and how they can be used to implement sophisticated authentication + * schemes. + */ + +struct ps_state_s { + int retval; /* last retval returned by the authentication fn */ + int state; /* what state the module was in when it + returned incomplete */ + + char *username; /* the name of the local user */ + + char server_cookie[33]; /* storage for 32 bytes of server cookie */ + char client_cookie[33]; /* storage for 32 bytes of client cookie */ + + char *secret_data; /* pointer to terminated secret_data */ + int invalid_secret; /* indication of whether the secret is valid */ + + pamc_bp_t current_prompt; /* place to store the current prompt */ + pamc_bp_t current_reply; /* place to receive the reply prompt */ +}; + +#define PS_STATE_ID "PAM_SECRET__STATE" +#define PS_AGENT_ID "secret@here" +#define PS_STATE_DEAD 0 +#define PS_STATE_INIT 1 +#define PS_STATE_PROMPT1 2 +#define PS_STATE_PROMPT2 3 + +#define MAX_LEN_HOSTNAME 512 +#define MAX_FILE_LINE_LEN 1024 + +/* + * Routine for generating 16*8 bits of random data represented in ASCII hex + */ + +static int generate_cookie(unsigned char *buffer_33) +{ + static const char hexarray[] = "0123456789abcdef"; + int i, fd; + + /* fill buffer_33 with 32 hex characters (lower case) + '\0' */ + fd = open("/dev/urandom", O_RDONLY); + if (fd < 0) { + D(("failed to open /dev/urandom")); + return 0; + } + read(fd, buffer_33 + 16, 16); + close(fd); + + /* expand top 16 bytes into 32 nibbles */ + for (i=0; i<16; ++i) { + buffer_33[2*i ] = hexarray[(buffer_33[16+i] & 0xf0)>>4]; + buffer_33[2*i+1] = hexarray[(buffer_33[16+i] & 0x0f)]; + } + + buffer_33[32] = '\0'; + + return 1; +} + +/* + * XXX - This is a hack, and is fundamentally insecure. Its subject to + * all sorts of attacks not to mention the fact that all our secrets + * will be displayed on the command line for someone doing 'ps' to + * see. This is just for programming convenience in this instance, it + * needs to be replaced with the md5 code. Although I am loath to + * add yet another instance of md5 code to the Linux-PAM source code. + * [Need to think of a cleaner way to do this for the distribution as + * a whole...] + */ + +#define COMMAND_FORMAT "/bin/echo -n '%s|%s|%s'|/usr/bin/md5sum -" + +int create_digest(const char *d1, const char *d2, const char *d3, + char *buffer_33) +{ + int length; + char *buffer; + FILE *pipe; + + length = strlen(d1)+strlen(d2)+strlen(d3)+sizeof(COMMAND_FORMAT); + buffer = malloc(length); + if (buffer == NULL) { + D(("out of memory")); + return 0; + } + + sprintf(buffer, COMMAND_FORMAT, d1,d2,d3); + + D(("executing pipe [%s]", buffer)); + pipe = popen(buffer, "r"); + memset(buffer, 0, length); + free(buffer); + + if (pipe == NULL) { + D(("failed to launch pipe")); + return 0; + } + + if (fgets(buffer_33, 33, pipe) == NULL) { + D(("failed to read digest")); + return 0; + } + + if (strlen(buffer_33) != 32) { + D(("digest was not 32 chars")); + return 0; + } + + fclose(pipe); + + D(("done [%s]", buffer_33)); + + return 1; +} + +/* + * method to attempt to instruct the application's conversation function + */ + +static int converse(pam_handle_t *pamh, struct ps_state_s *new) +{ + int retval; + struct pam_conv *conv; + + D(("called")); + + retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv); + if (retval == PAM_SUCCESS) { + struct pam_message msg; + struct pam_response *single_reply; + const struct pam_message *msg_ptr; + + memset(&msg, 0, sizeof(msg)); + msg.msg_style = PAM_BINARY_PROMPT; + msg.msg = (const char *) new->current_prompt; + msg_ptr = &msg; + + single_reply = NULL; + retval = conv->conv(1, &msg_ptr, &single_reply, conv->appdata_ptr); + if (retval == PAM_SUCCESS) { + if ((single_reply == NULL) || (single_reply->resp == NULL)) { + retval == PAM_CONV_ERR; + } else { + new->current_reply = (pamc_bp_t) single_reply->resp; + single_reply->resp = NULL; + } + } + + if (single_reply) { + free(single_reply); + } + } + +#ifdef DEBUG + if (retval == PAM_SUCCESS) { + D(("reply has length=%d and control=%u", + PAM_BP_LENGTH(new->current_reply), + PAM_BP_CONTROL(new->current_reply))); + } + D(("returning %s", pam_strerror(pamh, retval))); +#endif + + return retval; +} + +/* + * identify the secret in question + */ + +#define SECRET_FILE_FORMAT "%s/.secret@here" + +char *identify_secret(char *identity, const char *user) +{ + struct passwd *pwd; + char *temp; + FILE *secrets; + int length_id; + + pwd = getpwnam(user); + if ((pwd == NULL) || (pwd->pw_dir == NULL)) { + D(("user [%s] is not known", user)); + } + + length_id = strlen(pwd->pw_dir) + sizeof(SECRET_FILE_FORMAT); + temp = malloc(length_id); + if (temp == NULL) { + D(("out of memory")); + pwd = NULL; + return NULL; + } + + sprintf(temp, SECRET_FILE_FORMAT, pwd->pw_dir); + pwd = NULL; + + D(("opening key file [%s]", temp)); + secrets = fopen(temp, "r"); + memset(temp, 0, length_id); + + if (secrets == NULL) { + D(("failed to open key file")); + return NULL; + } + + length_id = strlen(identity); + temp = malloc(MAX_FILE_LINE_LEN); + + for (;;) { + char *secret = NULL; + + if (fgets(temp, MAX_FILE_LINE_LEN, secrets) == NULL) { + fclose(secrets); + return NULL; + } + + D(("cf[%s][%s]", identity, temp)); + if (memcmp(temp, identity, length_id)) { + continue; + } + + D(("found entry")); + fclose(secrets); + + for (secret=temp+length_id; *secret; ++secret) { + if (!(*secret == ' ' || *secret == '\n' || *secret == '\t')) { + break; + } + } + + memmove(temp, secret, MAX_FILE_LINE_LEN-(secret-(temp+length_id))); + secret = temp; + + for (; *secret; ++secret) { + if (*secret == ' ' || *secret == '\n' || *secret == '\t') { + break; + } + } + + if (*secret) { + *secret = '\0'; + } + + D(("secret found [%s]", temp)); + + return temp; + } + + /* NOT REACHED */ +} + +/* + * function to perform the two message authentication process + * (with support for event driven conversation functions) + */ + +static int auth_sequence(pam_handle_t *pamh, + const struct ps_state_s *old, struct ps_state_s *new) +{ + const char *rhostname; + const char *rusername; + int retval; + + retval = pam_get_item(pamh, PAM_RUSER, (const void **) &rusername); + if ((retval != PAM_SUCCESS) || (rusername == NULL)) { + D(("failed to obtain an rusername")); + new->state = PS_STATE_DEAD; + return PAM_AUTH_ERR; + } + + retval = pam_get_item(pamh, PAM_RHOST, (const void **) &rhostname); + if ((retval != PAM_SUCCESS) || (rhostname == NULL)) { + D(("failed to identify local hostname: ", pam_strerror(pamh, retval))); + new->state = PS_STATE_DEAD; + return PAM_AUTH_ERR; + } + + D(("switch on new->state=%d [%s@%s]", new->state, rusername, rhostname)); + switch (new->state) { + + case PS_STATE_INIT: + { + const char *user = NULL; + + retval = pam_get_user(pamh, &user, NULL); + + if ((retval == PAM_SUCCESS) && (user == NULL)) { + D(("success but no username?")); + new->state = PS_STATE_DEAD; + retval = PAM_USER_UNKNOWN; + } + + if (retval != PAM_SUCCESS) { + if (retval == PAM_CONV_AGAIN) { + retval = PAM_INCOMPLETE; + } else { + new->state = PS_STATE_DEAD; + } + D(("state init failed: %s", pam_strerror(pamh, retval))); + return retval; + } + + /* nothing else in this 'case' can be retried */ + + new->username = strdup(user); + if (new->username == NULL) { + D(("out of memory")); + new->state = PS_STATE_DEAD; + return PAM_BUF_ERR; + } + + if (! generate_cookie(new->server_cookie)) { + D(("problem generating server cookie")); + new->state = PS_STATE_DEAD; + return PAM_ABORT; + } + + new->current_prompt = NULL; + PAM_BP_RENEW(&new->current_prompt, PAM_BPC_SELECT, + sizeof(PS_AGENT_ID) + strlen(rusername) + 1 + + strlen(rhostname) + 1 + 32); + sprintf(PAM_BP_WDATA(new->current_prompt), + PS_AGENT_ID "/%s@%s|%.32s", rusername, rhostname, + new->server_cookie); + + /* note, the BP is guaranteed by the spec to be terminated */ + D(("initialization packet [%s]", PAM_BP_DATA(new->current_prompt))); + + /* fall through */ + new->state = PS_STATE_PROMPT1; + + D(("fall through to state_prompt1")); + } + + case PS_STATE_PROMPT1: + { + int i, length; + + /* send {secret@here/jdoe@client.host|} */ + retval = converse(pamh, new); + if (retval != PAM_SUCCESS) { + if (retval == PAM_CONV_AGAIN) { + D(("conversation failed to complete")); + return PAM_INCOMPLETE; + } else { + new->state = PS_STATE_DEAD; + return retval; + } + } + + if (retval != PAM_SUCCESS) { + D(("failed to read ruser@rhost")); + new->state = PS_STATE_DEAD; + return PAM_AUTH_ERR; + } + + /* expect to receive the following {|} */ + if (new->current_reply == NULL) { + D(("converstation returned [%s] but gave no reply", + pam_strerror(pamh, retval))); + new->state = PS_STATE_DEAD; + return PAM_CONV_ERR; + } + + /* find | */ + length = PAM_BP_LENGTH(new->current_reply); + for (i=0; icurrent_reply)[i] == '|') { + break; + } + } + if (i >= length) { + D(("malformed response (no |) of length %d", length)); + new->state = PS_STATE_DEAD; + return PAM_CONV_ERR; + } + if ((length - ++i) != 32) { + D(("cookie is incorrect length (%d,%d) %d != 32", + length, i, length-i)); + new->state = PS_STATE_DEAD; + return PAM_CONV_ERR; + } + + /* copy client cookie */ + memcpy(new->client_cookie, PAM_BP_RDATA(new->current_reply)+i, 32); + + /* generate a prompt that is length(seqid) + length(|) + 32 long */ + PAM_BP_RENEW(&new->current_prompt, PAM_BPC_OK, i+32); + /* copy the head of the response prompt */ + memcpy(PAM_BP_WDATA(new->current_prompt), + PAM_BP_RDATA(new->current_reply), i); + PAM_BP_RENEW(&new->current_reply, 0, 0); + + /* look up the secret */ + new->invalid_secret = 0; + + if (new->secret_data == NULL) { + char *ruser_rhost; + + ruser_rhost = malloc(strlen(rusername)+2+strlen(rhostname)); + if (ruser_rhost == NULL) { + D(("out of memory")); + new->state = PS_STATE_DEAD; + return PAM_BUF_ERR; + } + sprintf(ruser_rhost, "%s@%s", rusername, rhostname); + new->secret_data = identify_secret(ruser_rhost, new->username); + + memset(ruser_rhost, 0, strlen(ruser_rhost)); + free(ruser_rhost); + } + + if (new->secret_data == NULL) { + D(("secret not found for user")); + new->invalid_secret = 1; + + /* need to make up a secret */ + new->secret_data = malloc(32 + 1); + if (new->secret_data == NULL) { + D(("out of memory")); + new->state = PS_STATE_DEAD; + return PAM_BUF_ERR; + } + if (! generate_cookie(new->secret_data)) { + D(("what's up - no fake cookie generated?")); + new->state = PS_STATE_DEAD; + return PAM_ABORT; + } + } + + /* construct md5[||] */ + if (! create_digest(new->client_cookie, new->server_cookie, + new->secret_data, + PAM_BP_WDATA(new->current_prompt)+i)) { + D(("md5 digesting failed")); + new->state = PS_STATE_DEAD; + return PAM_ABORT; + } + + /* prompt2 is now constructed - fall through to send it */ + } + + case PS_STATE_PROMPT2: + { + /* send {|md5[||]} */ + retval = converse(pamh, new); + if (retval != PAM_SUCCESS) { + if (retval == PAM_CONV_AGAIN) { + D(("conversation failed to complete")); + return PAM_INCOMPLETE; + } else { + new->state = PS_STATE_DEAD; + return retval; + } + } + + /* After we complete this section, we should not be able to + recall this authentication function. So, we force all + future calls into the weeds. */ + + new->state = PS_STATE_DEAD; + + /* expect reply:{md5[||]} */ + + { + int cf; + char expectation[33]; + + if (!create_digest(new->secret_data, new->server_cookie, + new->client_cookie, expectation)) { + new->state = PS_STATE_DEAD; + return PAM_ABORT; + } + + cf = strcmp(expectation, PAM_BP_RDATA(new->current_reply)); + memset(expectation, 0, sizeof(expectation)); + if (cf || new->invalid_secret) { + D(("failed to authenticate")); + return PAM_AUTH_ERR; + } + } + + D(("correctly authenticated :)")); + return PAM_SUCCESS; + } + + default: + new->state = PS_STATE_DEAD; + + case PS_STATE_DEAD: + + D(("state is currently dead/unknown")); + return PAM_AUTH_ERR; + } + + fprintf(stderr, "pam_secret: this should not be reached\n"); + return PAM_ABORT; +} + +static void clean_data(pam_handle_t *pamh, void *datum, int error_status) +{ + struct ps_state_s *data = datum; + + D(("liberating datum=%p", datum)); + + if (data) { + D(("renew prompt")); + PAM_BP_RENEW(&data->current_prompt, 0, 0); + D(("renew reply")); + PAM_BP_RENEW(&data->current_reply, 0, 0); + D(("overwrite datum")); + memset(data, 0, sizeof(struct ps_state_s)); + D(("liberate datum")); + free(data); + } + + D(("done.")); +} + +/* + * front end for the authentication function + */ + +int pam_sm_authenticate(pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + int retval; + struct ps_state_s *new_data; + const struct ps_state_s *old_data; + + D(("called")); + + new_data = calloc(1, sizeof(struct ps_state_s)); + if (new_data == NULL) { + D(("out of memory")); + return PAM_BUF_ERR; + } + new_data->retval = PAM_SUCCESS; + + retval = pam_get_data(pamh, PS_STATE_ID, (const void **) &old_data); + if (retval == PAM_SUCCESS) { + new_data->state = old_data->state; + memcpy(new_data->server_cookie, old_data->server_cookie, 32); + memcpy(new_data->client_cookie, old_data->client_cookie, 32); + if (old_data->username) { + new_data->username = strdup(old_data->username); + } + if (old_data->secret_data) { + new_data->secret_data = strdup(old_data->secret_data); + } + if (old_data->current_prompt) { + int length; + + length = PAM_BP_LENGTH(old_data->current_prompt); + PAM_BP_RENEW(&new_data->current_prompt, + PAM_BP_CONTROL(old_data->current_prompt), length); + PAM_BP_FILL(new_data->current_prompt, 0, length, + PAM_BP_RDATA(old_data->current_prompt)); + } + /* don't need to duplicate current_reply */ + } else { + old_data = NULL; + new_data->state = PS_STATE_INIT; + } + + D(("call auth_sequence")); + new_data->retval = auth_sequence(pamh, old_data, new_data); + D(("returned from auth_sequence")); + + retval = pam_set_data(pamh, PS_STATE_ID, new_data, clean_data); + if (retval != PAM_SUCCESS) { + D(("unable to store new_data")); + } else { + retval = new_data->retval; + } + + old_data = new_data = NULL; + + D(("done (%d)", retval)); + return retval; +} + +/* + * front end for the credential setting function + */ + +#define AUTH_SESSION_TICKET_ENV_FORMAT "AUTH_SESSION_TICKET=" + +int pam_sm_setcred(pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + int retval; + const struct ps_state_s *old_data; + + D(("called")); + + /* XXX - need to pay attention to the various flavors of call */ + + /* XXX - need provide an option to turn this feature on/off: if + other modules want to supply an AUTH_SESSION_TICKET, we should + leave it up to the admin which module dominiates. */ + + retval = pam_get_data(pamh, PS_STATE_ID, (const void **) &old_data); + if (retval != PAM_SUCCESS) { + D(("no data to base decision on")); + return PAM_AUTH_ERR; + } + + /* + * If ok, export a derived shared secret session ticket to the + * client's PAM environment - the ticket has the form + * + * AUTH_SESSION_TICKET = + * md5[||] + * + * This is a precursor to supporting a spoof resistant trusted + * path mechanism. This shared secret ticket can be used to add + * a hard-to-guess checksum to further authentication data. + */ + + retval = old_data->retval; + if (retval == PAM_SUCCESS) { + char envticket[sizeof(AUTH_SESSION_TICKET_ENV_FORMAT)+32]; + + memcpy(envticket, AUTH_SESSION_TICKET_ENV_FORMAT, + sizeof(AUTH_SESSION_TICKET_ENV_FORMAT)); + + if (! create_digest(old_data->server_cookie, old_data->secret_data, + old_data->client_cookie, + envticket+sizeof(AUTH_SESSION_TICKET_ENV_FORMAT)-1 + )) { + D(("unable to generate a digest for session ticket")); + return PAM_ABORT; + } + + D(("putenv[%s]", envticket)); + retval = pam_putenv(pamh, envticket); + memset(envticket, 0, sizeof(envticket)); + } + + old_data = NULL; + D(("done (%d)", retval)); + + return retval; +} diff --git a/contrib/libpam/libpamc/test/regress/Makefile b/contrib/libpam/libpamc/test/regress/Makefile new file mode 100644 index 00000000000..ff63e5f087a --- /dev/null +++ b/contrib/libpam/libpamc/test/regress/Makefile @@ -0,0 +1,7 @@ +CFLAGS = -g -I ../../include + +test.libpamc: test.libpamc.o + $(CC) -o $@ $< -L ../.. -lpamc + +clean: + rm -f test.libpamc test.libpamc.o diff --git a/contrib/libpam/libpamc/test/regress/run_test.sh b/contrib/libpam/libpamc/test/regress/run_test.sh new file mode 100755 index 00000000000..a1bf010b11c --- /dev/null +++ b/contrib/libpam/libpamc/test/regress/run_test.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +export LD_LIBRARY_PATH=../.. +export PAMC_AGENT_PATH="../agents" + +./test.libpamc diff --git a/contrib/libpam/libpamc/test/regress/test.libpamc.c b/contrib/libpam/libpamc/test/regress/test.libpamc.c new file mode 100644 index 00000000000..b7bc4e4bca7 --- /dev/null +++ b/contrib/libpam/libpamc/test/regress/test.libpamc.c @@ -0,0 +1,342 @@ +/* + * This is a small test program for testing libpamc against the + * secret@here agent. It does the same as the test.secret@here perl + * script in this directory, but via the libpamc API. + */ + +#include +#include +#include +#include + +struct internal_packet { + int length; + int at; + char *buffer; +}; + + +void append_data(struct internal_packet *packet, int extra, const char *data) +{ + if ((extra + packet->at) >= packet->length) { + if (packet->length == 0) { + packet->length = 1000; + } + /* make sure we have at least a char extra space available */ + while (packet->length <= (extra + packet->at)) { + packet->length <<= 1; + } + packet->buffer = realloc(packet->buffer, packet->length); + if (packet->buffer == NULL) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + } + + if (data != NULL) { + memcpy(packet->at + packet->buffer, data, extra); + } + packet->at += extra; + + /* assisting string manipulation */ + packet->buffer[packet->at] = '\0'; +} + +void append_string(struct internal_packet *packet, const char *string, + int with_nul) +{ + append_data(packet, strlen(string) + (with_nul ? 1:0), string); +} + +char *identify_secret(char *identity) +{ + struct internal_packet temp_packet; + FILE *secrets; + int length_id; + + temp_packet.length = temp_packet.at = 0; + temp_packet.buffer = NULL; + + append_string(&temp_packet, "/home/", 0); + append_string(&temp_packet, getlogin(), 0); + append_string(&temp_packet, "/.secret@here", 1); + + secrets = fopen(temp_packet.buffer, "r"); + if (secrets == NULL) { + fprintf(stderr, "server: failed to open\n [%s]\n", + temp_packet.buffer); + exit(1); + } + + length_id = strlen(identity); + for (;;) { + char *secret = NULL; + temp_packet.at = 0; + + if (fgets(temp_packet.buffer, temp_packet.length, secrets) == NULL) { + fclose(secrets); + return NULL; + } + + if (memcmp(temp_packet.buffer, identity, length_id)) { + continue; + } + + fclose(secrets); + for (secret=temp_packet.buffer; *secret; ++secret) { + if (*secret == ' ' || *secret == '\n' || *secret == '\t') { + break; + } + } + for (; *secret; ++secret) { + if (!(*secret == ' ' || *secret == '\n' || *secret == '\t')) { + break; + } + } + + for (temp_packet.buffer=secret; *temp_packet.buffer; + ++temp_packet.buffer) { + if (*temp_packet.buffer == ' ' || *temp_packet.buffer == '\n' + || *temp_packet.buffer == '\t') { + break; + } + } + if (*temp_packet.buffer) { + *temp_packet.buffer = '\0'; + } + + return secret; + } + + /* NOT REACHED */ +} + +/* + * This is a hack, and is fundamentally insecure. All our secrets will be + * displayed on the command line for someone doing 'ps' to see. This + * is just for programming convenience in this instance, since this + * program is simply a regression test. The pam_secret module should + * not do this, but make use of md5 routines directly. + */ + +char *create_digest(int length, const char *raw) +{ + struct internal_packet temp_packet; + FILE *pipe; + + temp_packet.length = temp_packet.at = 0; + temp_packet.buffer = NULL; + + append_string(&temp_packet, "echo -n '", 0); + append_string(&temp_packet, raw, 0); + append_string(&temp_packet, "'|/usr/bin/md5sum -", 1); + + fprintf(stderr, "am attempting to run [%s]\n", temp_packet.buffer); + + pipe = popen(temp_packet.buffer, "r"); + if (pipe == NULL) { + fprintf(stderr, "server: failed to run\n [%s]\n", temp_packet.buffer); + exit(1); + } + + temp_packet.at = 0; + append_data(&temp_packet, 32, NULL); + + if (fgets(temp_packet.buffer, 33, pipe) == NULL) { + fprintf(stderr, "server: failed to read digest\n"); + exit(1); + } + if (strlen(temp_packet.buffer) != 32) { + fprintf(stderr, "server: digest was not 32 chars?? [%s]\n", + temp_packet.buffer); + exit(1); + } + + fclose(pipe); + + return temp_packet.buffer; +} + +void packet_to_prompt(pamc_bp_t *prompt_p, __u8 control, + struct internal_packet *packet) +{ + PAM_BP_RENEW(prompt_p, control, packet->at); + PAM_BP_FILL(*prompt_p, 0, packet->at, packet->buffer); + packet->at = 0; +} + +void prompt_to_packet(pamc_bp_t prompt, struct internal_packet *packet) +{ + int data_length; + + data_length = PAM_BP_LENGTH(prompt); + packet->at = 0; + append_data(packet, data_length, NULL); + + PAM_BP_EXTRACT(prompt, 0, data_length, packet->buffer); + + fprintf(stderr, "server received[%d]: {%d|0x%.2x|%s}\n", + data_length, + PAM_BP_SIZE(prompt), PAM_BP_RCONTROL(prompt), + PAM_BP_RDATA(prompt)); +} + +int main(int argc, char **argv) +{ + pamc_handle_t pch; + pamc_bp_t prompt = NULL; + struct internal_packet packet_data, *packet; + char *temp_string, *secret, *user, *a_cookie, *seqid, *digest; + const char *cookie = "123451234512345"; + int retval; + + packet = &packet_data; + packet->length = 0; + packet->at = 0; + packet->buffer = NULL; + + pch = pamc_start(); + if (pch == NULL) { + fprintf(stderr, "server: unable to get a handle from libpamc\n"); + exit(1); + } + + temp_string = getlogin(); + if (temp_string == NULL) { + fprintf(stderr, "server: who are you?\n"); + exit(1); + } +#define DOMAIN "@local.host" + user = malloc(1+strlen(temp_string)+strlen(DOMAIN)); + if (user == NULL) { + fprintf(stderr, "server: out of memory for user id\n"); + exit(1); + } + sprintf(user, "%s%s", temp_string, DOMAIN); + + append_string(packet, "secret@here/", 0); + append_string(packet, user, 0); + append_string(packet, "|", 0); + append_string(packet, cookie, 0); + packet_to_prompt(&prompt, PAM_BPC_SELECT, packet); + + /* get the library to accept the first packet (which should load + the secret@here agent) */ + + retval = pamc_converse(pch, &prompt); + fprintf(stderr, "server: after conversation\n"); + if (PAM_BP_RCONTROL(prompt) != PAM_BPC_OK) { + fprintf(stderr, "server: prompt had unexpected control type: %u\n", + PAM_BP_RCONTROL(prompt)); + exit(1); + } + + fprintf(stderr, "server: got a prompt back\n"); + + prompt_to_packet(prompt, packet); + + temp_string = strtok(packet->buffer, "|"); + if (temp_string == NULL) { + fprintf(stderr, "server: prompt does not contain anything"); + exit(1); + } + seqid = strdup(temp_string); + if (seqid == NULL) { + fprintf(stderr, "server: unable to store sequence id\n"); + } + + temp_string = strtok(NULL, "|"); + if (temp_string == NULL) { + fprintf(stderr, "server: no cookie from agent\n"); + exit(1); + } + a_cookie = strdup(temp_string); + if (a_cookie == NULL) { + fprintf(stderr, "server: no memory to store agent cookie\n"); + exit(1); + } + + fprintf(stderr, "server: agent responded with {%s|%s}\n", seqid, a_cookie); + secret = identify_secret(user); + fprintf(stderr, "server: secret=%s\n", secret); + + /* now, we construct the response */ + packet->at = 0; + append_string(packet, a_cookie, 0); + append_string(packet, "|", 0); + append_string(packet, cookie, 0); + append_string(packet, "|", 0); + append_string(packet, secret, 0); + + fprintf(stderr, "server: get digest of %s\n", packet->buffer); + + digest = create_digest(packet->at, packet->buffer); + + fprintf(stderr, "server: secret=%s, digest=%s\n", secret, digest); + + packet->at = 0; + append_string(packet, seqid, 0); + append_string(packet, "|", 0); + append_string(packet, digest, 0); + packet_to_prompt(&prompt, PAM_BPC_OK, packet); + + retval = pamc_converse(pch, &prompt); + fprintf(stderr, "server: after 2nd conversation\n"); + if (PAM_BP_RCONTROL(prompt) != PAM_BPC_DONE) { + fprintf(stderr, "server: 2nd prompt had unexpected control type: %u\n", + PAM_BP_RCONTROL(prompt)); + exit(1); + } + + prompt_to_packet(prompt, packet); + PAM_BP_RENEW(&prompt, 0, 0); + + temp_string = strtok(packet->buffer, "|"); + if (temp_string == NULL) { + fprintf(stderr, "no digest from agent\n"); + exit(1); + } + temp_string = strdup(temp_string); + + packet->at = 0; + append_string(packet, secret, 0); + append_string(packet, "|", 0); + append_string(packet, cookie, 0); + append_string(packet, "|", 0); + append_string(packet, a_cookie, 0); + + fprintf(stderr, "server: get digest of %s\n", packet->buffer); + + digest = create_digest(packet->at, packet->buffer); + + fprintf(stderr, "server: digest=%s\n", digest); + + if (strcmp(digest, temp_string)) { + fprintf(stderr, "server: agent doesn't know the secret\n"); + fprintf(stderr, "server: agent says: [%s]\n" + "server: server says: [%s]\n", temp_string, digest); + exit(1); + } else { + fprintf(stderr, "server: agent seems to know the secret\n"); + + packet->at = 0; + append_string(packet, cookie, 0); + append_string(packet, "|", 0); + append_string(packet, secret, 0); + append_string(packet, "|", 0); + append_string(packet, a_cookie, 0); + + digest = create_digest(packet->at, packet->buffer); + + fprintf(stderr, "server: putenv(\"AUTH_SESSION_TICKET=%s\")\n", + digest); + } + + + retval = pamc_end(&pch); + + fprintf(stderr, "server: agent(s) were %shappy to terminate\n", + retval == PAM_BPC_TRUE ? "":"un"); + + exit(!retval); +} diff --git a/contrib/libpam/libpamc/test/regress/test.secret@here b/contrib/libpam/libpamc/test/regress/test.secret@here new file mode 100755 index 00000000000..2e0b9b940cb --- /dev/null +++ b/contrib/libpam/libpamc/test/regress/test.secret@here @@ -0,0 +1,152 @@ +#!/usr/bin/perl + +## +## this is a test script for regressing changes to the secret@here PAM +## agent +## + +$^W = 1; +use strict; +use IPC::Open2; + +$| = 1; + +my $whoami = `/usr/bin/whoami`; chomp $whoami; +my $cookie = "12345"; +my $user_domain = "$whoami\@local.host"; + +my $pid = open2(\*Reader, \*Writer, "../agents/secret\@here blah") + or die "failed to load secret\@here agent"; + +unless (-f (getpwuid($<))[7]."/.secret\@here") { + print STDERR "server: ". "no " .(getpwuid($<))[7]. "/.secret\@here file\n"; + die "no config file"; +} + +WriteBinaryPrompt(\*Writer, 0x02, "secret\@here/$user_domain|$cookie"); + +my ($control, $data) = ReadBinaryPrompt(\*Reader); + +print STDERR "server: ". "reply: control=$control, data=$data\n"; +if ($control != 1) { + die "expected 1 (OK) for the first agent reply; got $control"; +} +my ($seqid, $a_cookie) = split '\|', $data; + +# server needs to convince agent that it knows the secret before +# agent will give a valid response +my $secret = IdentifyLocalSecret($user_domain); +my $digest = CreateDigest($a_cookie."|".$cookie."|".$secret); + +print STDERR "server: ". "digest = $digest\n"; +WriteBinaryPrompt(\*Writer, 0x01, "$seqid|$digest"); + +# The agent will authenticate us and then reply with its +# authenticating digest. we check that before we're done. + +($control, $data) = ReadBinaryPrompt(\*Reader); +if ($control != 0x03) { + die "server: agent did not reply with a 'done' prompt ($control)\n"; +} + +unless ($data eq CreateDigest($secret."|".$cookie."|".$a_cookie)) { + die "server: agent is not authenticated\n"; +} + +print STDERR "server: agent appears to know secret\n"; + +my $session_authenticated_ticket + = CreateDigest($cookie."|".$secret."|".$a_cookie); + +print STDERR "server: should putenv(" + ."\"AUTH_SESSION_TICKET=$session_authenticated_ticket\")\n"; + +exit 0; + +sub CreateDigest ($) { + my ($data) = @_; + + my $pid = open2(\*MD5out, \*MD5in, "/usr/bin/md5sum -") + or die "you'll need /usr/bin/md5sum installed"; + + my $oldfd = select MD5in; $|=1; select $oldfd; + print MD5in "$data"; + close MD5in; + my $reply = ; + ($reply) = split /\s/, $reply; + print STDERR "server: ". "md5 said: <$reply>\n"; + close MD5out; + + return $reply; +} + +sub ReadBinaryPrompt ($) { + my ($fd) = @_; + + my $buffer = " "; + my $count = read($fd, $buffer, 5); + if ($count == 0) { + # no more packets to read + return (0, ""); + } + + if ($count != 5) { + # broken packet header + return (-1, ""); + } + + my ($length, $control) = unpack("N C", $buffer); + if ($length < 5) { + # broken packet length + return (-1, ""); + } + + my $data = ""; + $length -= 5; + while ($count = read($fd, $buffer, $length)) { + $data .= $buffer; + if ($count != $length) { + $length -= $count; + next; + } + + print STDERR "server: ". "data is [$data]\n"; + + return ($control, $data); + } + + # broken packet data + return (-1, ""); +} + +sub WriteBinaryPrompt ($$$) { + my ($fd, $control, $data) = @_; + + my $length = 5 + length($data); + printf STDERR "server: ". "{%d|0x%.2x|%s}\n", $length, $control, $data; + my $bp = pack("N C a*", $length, $control, $data); + print $fd $bp; + + print STDERR "server: ". "control passed to agent\@here\n"; +} + +sub IdentifyLocalSecret ($) { + my ($identifier) = @_; + my $secret; + + my $whoami = `/usr/bin/whoami` ; chomp $whoami; + if (open SECRETS, "< " .(getpwuid($<))[7]. "/.secret\@here") { + my $line; + while (defined ($line = )) { + my ($id, $sec) = split /[\s]/, $line; + if ((defined $id) && ($id eq $identifier)) { + $secret = $sec; + last; + } + } + close SECRETS; + } + + return $secret; +} + diff --git a/contrib/libpam/modules/Simple.Rules b/contrib/libpam/modules/Simple.Rules new file mode 100644 index 00000000000..954641c668a --- /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/download-all b/contrib/libpam/modules/download-all new file mode 100755 index 00000000000..9b6cf655813 --- /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 < 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 00000000000..2cb54bec77d --- /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 + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define PAM_SM_AUTH + +#include + +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_mail/README b/contrib/libpam/modules/pam_mail/README new file mode 100644 index 00000000000..155bd1db66d --- /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/ + "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_mkhomedir/Makefile b/contrib/libpam/modules/pam_mkhomedir/Makefile new file mode 100644 index 00000000000..f017f4a469e --- /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 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 00000000000..ec05993dfa1 --- /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 Feb 1999 + Structure taken from pam_lastlogin by Andrew Morgan + 1996 + */ + +/* I want snprintf dammit */ +#define _GNU_SOURCE 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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 +#include + +/* 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 00000000000..fb83807a36d --- /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 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 00000000000..2434b2986c9 --- /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 + * + * 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 1996/10/24 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +/* + * 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 + +/* --- 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_tally/faillog.h b/contrib/libpam/modules/pam_tally/faillog.h new file mode 100644 index 00000000000..0f16261bbd9 --- /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_app.c b/contrib/libpam/modules/pam_tally/pam_tally_app.c new file mode 100644 index 00000000000..9e6e1fafd06 --- /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_unix/bigcrypt.c b/contrib/libpam/modules/pam_unix/bigcrypt.c new file mode 100644 index 00000000000..b1568d6b340 --- /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 + */ + +#include +#include + +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 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 00000000000..b5ff45850b4 --- /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 , + * public domain. + */ + +#include +#include + +#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 00000000000..7ee9ed00cde --- /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 +#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<>(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 00000000000..103f168a91c --- /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 00000000000..257e4bb6bd0 --- /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): + * 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 +#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/support.h b/contrib/libpam/modules/pam_unix/support.h new file mode 100644 index 00000000000..80f0b405d8b --- /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 00000000000..e232e759453 --- /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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAXPASS 200 /* the maximum length of a password */ + +#include + +#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 00000000000..6b414be09a5 --- /dev/null +++ b/contrib/libpam/modules/pam_unix/yppasswd.h @@ -0,0 +1,51 @@ +/* + * yppasswdd + * Copyright 1994, 1995, 1996 Olaf Kirch, + * + * 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 . + */ +#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 +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 00000000000..b1a60b4ce11 --- /dev/null +++ b/contrib/libpam/modules/pam_unix/yppasswd_xdr.c @@ -0,0 +1,38 @@ +/* + * yppasswdd + * Copyright 1994, 1995, 1996 Olaf Kirch, + * + * 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 + +#include +#include +#include +#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 00000000000..ebdcff9cd33 --- /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 + +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 00000000000..af78d47b130 --- /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 + + + +$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 00000000000..0f13d03a4fc --- /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 +#include + +#include +#include + +#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 , 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 00000000000..0e1687dfef6 --- /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 \n" unless ($database); +print "Using database: $database\n"; + +my %lusers = (); + +tie %lusers, 'DB_File', $database, O_RDWR|O_CREAT, 0644, $DB_HASH ; +while () { + 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 00000000000..9da93705e51 --- /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 1996/09/10 + * See the end of the file for Copyright Information + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pam_userdb.h" + +#ifdef HAVE_NDBM_H +# include +#else +# ifdef HAVE_DB_H +# define DB_DBM_HSEARCH 1 /* use the dbm interface */ +# include +# 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 + +/* 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 , 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 00000000000..542cdf57943 --- /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 + +/* 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 , 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. + */