From 5791a4d4466a137893028f8243622286dae2bb0d Mon Sep 17 00:00:00 2001 From: Mark Murray Date: Thu, 3 May 2001 09:36:08 +0000 Subject: [PATCH] Vendor import Linux PAM 0.75 --- contrib/libpam/CHANGELOG | 329 +- contrib/libpam/Make.Rules.in | 94 + contrib/libpam/Makefile | 324 +- contrib/libpam/README | 167 +- contrib/libpam/_pam_aconf.h.in | 64 + contrib/libpam/bin/README | 11 +- contrib/libpam/conf/Makefile | 28 +- contrib/libpam/conf/md5itall | 4 +- contrib/libpam/conf/pam.conf | 74 +- contrib/libpam/conf/pam_conv1/README | 2 +- contrib/libpam/conf/pam_conv1/pam_conv.lex | 4 +- contrib/libpam/conf/pam_conv1/pam_conv.y | 4 +- contrib/libpam/configure | 3548 +++++++++++++++++ contrib/libpam/configure.in | 339 ++ contrib/libpam/defs/debian.defs | 40 + contrib/libpam/defs/linux.defs | 4 +- contrib/libpam/defs/morgan.defs | 1 + contrib/libpam/defs/redhat.defs | 4 +- contrib/libpam/defs/redhat4.defs | 35 + contrib/libpam/defs/solaris-2.1.5.defs | 45 + contrib/libpam/defs/suse.defs | 36 + contrib/libpam/doc/CREDITS | 14 +- contrib/libpam/doc/Makefile | 88 +- contrib/libpam/doc/html/index.html | 2 +- contrib/libpam/doc/man/pam.8 | 124 +- contrib/libpam/doc/man/pam.conf.8 | 2 +- contrib/libpam/doc/man/pam.d.8 | 2 +- contrib/libpam/doc/man/pam_authenticate.3 | 2 +- contrib/libpam/doc/man/pam_chauthtok.3 | 2 +- contrib/libpam/doc/man/pam_close_session.3 | 2 +- contrib/libpam/doc/man/pam_end.3 | 2 +- contrib/libpam/doc/man/pam_fail_delay.3 | 2 +- contrib/libpam/doc/man/pam_open_session.3 | 2 +- contrib/libpam/doc/man/pam_setcred.3 | 2 +- contrib/libpam/doc/man/pam_start.3 | 2 +- contrib/libpam/doc/man/pam_strerror.3 | 14 +- contrib/libpam/doc/man/template-man | 2 +- contrib/libpam/doc/modules/README | 2 +- .../libpam/doc/modules/module.sgml-template | 4 +- contrib/libpam/doc/modules/pam_access.sgml | 108 + contrib/libpam/doc/modules/pam_chroot.sgml | 2 +- contrib/libpam/doc/modules/pam_cracklib.sgml | 39 +- contrib/libpam/doc/modules/pam_deny.sgml | 2 +- contrib/libpam/doc/modules/pam_env.sgml | 24 +- contrib/libpam/doc/modules/pam_filter.sgml | 6 +- contrib/libpam/doc/modules/pam_ftp.sgml | 8 +- contrib/libpam/doc/modules/pam_group.sgml | 2 +- contrib/libpam/doc/modules/pam_issue.sgml | 120 + contrib/libpam/doc/modules/pam_krb4.sgml | 2 +- contrib/libpam/doc/modules/pam_lastlog.sgml | 24 +- contrib/libpam/doc/modules/pam_limits.sgml | 38 +- contrib/libpam/doc/modules/pam_listfile.sgml | 6 +- contrib/libpam/doc/modules/pam_mail.sgml | 46 +- contrib/libpam/doc/modules/pam_mkhomedir.sgml | 83 + contrib/libpam/doc/modules/pam_motd.sgml | 77 + contrib/libpam/doc/modules/pam_nologin.sgml | 2 +- contrib/libpam/doc/modules/pam_permit.sgml | 2 +- contrib/libpam/doc/modules/pam_pwdb.sgml | 19 +- contrib/libpam/doc/modules/pam_radius.sgml | 6 +- contrib/libpam/doc/modules/pam_rhosts.sgml | 11 +- contrib/libpam/doc/modules/pam_rootok.sgml | 2 +- contrib/libpam/doc/modules/pam_securetty.sgml | 2 +- contrib/libpam/doc/modules/pam_tally.sgml | 191 + contrib/libpam/doc/modules/pam_time.sgml | 4 +- contrib/libpam/doc/modules/pam_unix.sgml | 288 ++ contrib/libpam/doc/modules/pam_userdb.sgml | 112 + contrib/libpam/doc/modules/pam_warn.sgml | 2 +- contrib/libpam/doc/modules/pam_wheel.sgml | 13 +- contrib/libpam/doc/pam_appl.sgml | 288 +- contrib/libpam/doc/pam_modules.sgml | 185 +- contrib/libpam/doc/pam_source.sgml | 280 +- contrib/libpam/doc/ps/README | 2 +- contrib/libpam/doc/specs/draft-morgan-pam.raw | 702 ++++ contrib/libpam/doc/txts/README | 2 +- contrib/libpam/examples/Makefile | 44 +- contrib/libpam/examples/blank.c | 19 +- contrib/libpam/examples/check_user.c | 9 +- contrib/libpam/examples/test.c | 13 +- contrib/libpam/examples/vpass.c | 2 +- contrib/libpam/examples/xsh.c | 54 +- contrib/libpam/libpam/Makefile | 108 +- .../libpam/include/security/_pam_compat.h | 29 +- .../libpam/include/security/_pam_macros.h | 54 +- .../libpam/include/security/_pam_types.h | 74 +- .../libpam/libpam/include/security/pam_appl.h | 25 +- .../libpam/include/security/pam_malloc.h | 8 +- .../libpam/include/security/pam_modules.h | 24 +- contrib/libpam/libpam/pam_account.c | 14 +- contrib/libpam/libpam/pam_auth.c | 21 +- contrib/libpam/libpam/pam_data.c | 88 +- contrib/libpam/libpam/pam_delay.c | 16 +- contrib/libpam/libpam/pam_dispatch.c | 109 +- contrib/libpam/libpam/pam_end.c | 14 +- contrib/libpam/libpam/pam_env.c | 49 +- contrib/libpam/libpam/pam_handlers.c | 162 +- contrib/libpam/libpam/pam_item.c | 180 +- contrib/libpam/libpam/pam_log.c | 94 +- contrib/libpam/libpam/pam_malloc.c | 37 +- contrib/libpam/libpam/pam_map.c | 3 +- contrib/libpam/libpam/pam_misc.c | 65 +- contrib/libpam/libpam/pam_password.c | 18 +- contrib/libpam/libpam/pam_private.h | 52 +- contrib/libpam/libpam/pam_second.c | 3 +- contrib/libpam/libpam/pam_session.c | 28 +- contrib/libpam/libpam/pam_start.c | 35 +- contrib/libpam/libpam/pam_static.c | 32 +- contrib/libpam/libpam/pam_strerror.c | 17 +- contrib/libpam/libpam/pam_tokens.h | 9 +- contrib/libpam/libpam_misc/Makefile | 139 +- contrib/libpam/libpam_misc/help_env.c | 9 +- .../libpam_misc/include/security/pam_misc.h | 57 + contrib/libpam/libpam_misc/misc_conv.c | 100 +- contrib/libpam/libpam_misc/xstrdup.c | 9 +- contrib/libpam/libpamc/License | 42 + contrib/libpam/libpamc/Makefile | 107 + .../libpamc/include/security/pam_client.h | 190 + contrib/libpam/libpamc/libpamc.h | 63 + contrib/libpam/libpamc/pamc_client.c | 189 + contrib/libpam/libpamc/pamc_converse.c | 211 + contrib/libpam/libpamc/pamc_load.c | 477 +++ .../libpam/libpamc/test/agents/secret@here | 308 ++ contrib/libpam/libpamc/test/modules/Makefile | 9 + .../libpam/libpamc/test/modules/pam_secret.c | 670 ++++ contrib/libpam/libpamc/test/regress/Makefile | 7 + .../libpam/libpamc/test/regress/run_test.sh | 6 + .../libpamc/test/regress/test.libpamc.c | 342 ++ .../libpamc/test/regress/test.secret@here | 152 + contrib/libpam/modules/Makefile | 90 +- contrib/libpam/modules/README | 2 +- contrib/libpam/modules/Simple.Rules | 92 + contrib/libpam/modules/dont_makefile | 4 +- contrib/libpam/modules/download-all | 30 + contrib/libpam/modules/install_conf | 49 + contrib/libpam/modules/pam_access/Makefile | 110 +- contrib/libpam/modules/pam_access/README | 6 +- .../libpam/modules/pam_access/pam_access.c | 153 +- contrib/libpam/modules/pam_cracklib/Makefile | 106 +- contrib/libpam/modules/pam_cracklib/README | 18 +- .../modules/pam_cracklib/pam_cracklib.c | 433 +- contrib/libpam/modules/pam_deny/Makefile | 118 +- contrib/libpam/modules/pam_deny/README | 2 +- contrib/libpam/modules/pam_deny/pam_deny.c | 15 +- contrib/libpam/modules/pam_env/Makefile | 107 +- contrib/libpam/modules/pam_env/README | 6 +- contrib/libpam/modules/pam_env/pam_env.c | 186 +- .../modules/pam_env/pam_env.conf-example | 6 +- contrib/libpam/modules/pam_filter/Makefile | 64 +- contrib/libpam/modules/pam_filter/README | 2 +- .../modules/pam_filter/include/pam_filter.h | 4 +- .../libpam/modules/pam_filter/pam_filter.c | 18 +- .../modules/pam_filter/upperLOWER/Makefile | 33 +- .../pam_filter/upperLOWER/upperLOWER.c | 17 +- contrib/libpam/modules/pam_ftp/Makefile | 91 +- contrib/libpam/modules/pam_ftp/README | 26 +- contrib/libpam/modules/pam_ftp/pam_ftp.c | 52 +- contrib/libpam/modules/pam_group/Makefile | 113 +- contrib/libpam/modules/pam_group/group.conf | 2 +- contrib/libpam/modules/pam_group/pam_group.c | 41 +- contrib/libpam/modules/pam_issue/Makefile | 15 + contrib/libpam/modules/pam_issue/pam_issue.c | 266 ++ contrib/libpam/modules/pam_lastlog/Makefile | 101 +- .../libpam/modules/pam_lastlog/pam_lastlog.c | 17 +- contrib/libpam/modules/pam_limits/Makefile | 103 +- contrib/libpam/modules/pam_limits/README | 35 +- contrib/libpam/modules/pam_limits/limits.skel | 1 + .../libpam/modules/pam_limits/pam_limits.c | 246 +- contrib/libpam/modules/pam_listfile/Makefile | 83 +- .../modules/pam_listfile/pam_listfile.c | 103 +- contrib/libpam/modules/pam_mail/Makefile | 102 +- contrib/libpam/modules/pam_mail/README | 17 + contrib/libpam/modules/pam_mail/pam_mail.c | 242 +- contrib/libpam/modules/pam_mkhomedir/Makefile | 15 + .../modules/pam_mkhomedir/pam_mkhomedir.c | 370 ++ contrib/libpam/modules/pam_motd/Makefile | 15 + contrib/libpam/modules/pam_motd/pam_motd.c | 119 + contrib/libpam/modules/pam_nologin/Makefile | 83 +- contrib/libpam/modules/pam_nologin/README | 2 +- .../libpam/modules/pam_nologin/pam_nologin.c | 16 +- contrib/libpam/modules/pam_permit/Makefile | 119 +- contrib/libpam/modules/pam_permit/README | 2 +- .../libpam/modules/pam_permit/pam_permit.c | 12 +- contrib/libpam/modules/pam_pwdb/BUGS | 7 +- contrib/libpam/modules/pam_pwdb/CHANGELOG | 2 +- contrib/libpam/modules/pam_pwdb/Makefile | 91 +- contrib/libpam/modules/pam_pwdb/README | 4 +- contrib/libpam/modules/pam_pwdb/TODO | 2 +- contrib/libpam/modules/pam_pwdb/md5.c | 26 +- contrib/libpam/modules/pam_pwdb/md5.h | 20 +- contrib/libpam/modules/pam_pwdb/md5_crypt.c | 72 +- contrib/libpam/modules/pam_pwdb/pam_pwdb.c | 55 +- .../libpam/modules/pam_pwdb/pam_unix_acct.-c | 24 +- .../libpam/modules/pam_pwdb/pam_unix_auth.-c | 46 +- .../libpam/modules/pam_pwdb/pam_unix_md.-c | 20 +- .../modules/pam_pwdb/pam_unix_passwd.-c | 60 +- .../libpam/modules/pam_pwdb/pam_unix_pwupd.-c | 14 +- .../libpam/modules/pam_pwdb/pam_unix_sess.-c | 18 +- contrib/libpam/modules/pam_pwdb/pwdb_chkpwd.c | 39 +- contrib/libpam/modules/pam_pwdb/support.-c | 136 +- contrib/libpam/modules/pam_radius/Makefile | 12 +- .../libpam/modules/pam_radius/pam_radius.h | 9 +- contrib/libpam/modules/pam_rhosts/Makefile | 103 +- .../modules/pam_rhosts/pam_rhosts_auth.c | 56 +- contrib/libpam/modules/pam_rootok/Makefile | 106 +- contrib/libpam/modules/pam_rootok/README | 2 +- .../libpam/modules/pam_rootok/pam_rootok.c | 17 +- contrib/libpam/modules/pam_securetty/Makefile | 82 +- .../modules/pam_securetty/pam_securetty.c | 67 +- contrib/libpam/modules/pam_shells/Makefile | 83 +- .../libpam/modules/pam_shells/pam_shells.c | 18 +- contrib/libpam/modules/pam_stress/Makefile | 104 +- contrib/libpam/modules/pam_stress/README | 2 +- .../libpam/modules/pam_stress/pam_stress.c | 30 +- contrib/libpam/modules/pam_tally/Makefile | 54 +- contrib/libpam/modules/pam_tally/README | 52 +- contrib/libpam/modules/pam_tally/faillog.h | 55 + contrib/libpam/modules/pam_tally/pam_tally.c | 150 +- .../libpam/modules/pam_tally/pam_tally_app.c | 7 + contrib/libpam/modules/pam_time/Makefile | 120 +- contrib/libpam/modules/pam_time/README | 9 +- contrib/libpam/modules/pam_time/pam_time.c | 29 +- contrib/libpam/modules/pam_unix/CHANGELOG | 57 +- contrib/libpam/modules/pam_unix/Makefile | 170 +- contrib/libpam/modules/pam_unix/README | 56 +- contrib/libpam/modules/pam_unix/bigcrypt.c | 119 + contrib/libpam/modules/pam_unix/lckpwdf.-c | 117 + contrib/libpam/modules/pam_unix/md5.c | 256 ++ contrib/libpam/modules/pam_unix/md5.h | 31 + contrib/libpam/modules/pam_unix/md5_crypt.c | 149 + .../libpam/modules/pam_unix/pam_unix_acct.c | 195 +- .../libpam/modules/pam_unix/pam_unix_auth.c | 357 +- .../libpam/modules/pam_unix/pam_unix_passwd.c | 1609 ++++---- .../libpam/modules/pam_unix/pam_unix_sess.c | 244 +- contrib/libpam/modules/pam_unix/support.c | 964 ++++- contrib/libpam/modules/pam_unix/support.h | 144 + contrib/libpam/modules/pam_unix/unix_chkpwd.c | 314 ++ contrib/libpam/modules/pam_unix/yppasswd.h | 51 + .../libpam/modules/pam_unix/yppasswd_xdr.c | 38 + contrib/libpam/modules/pam_userdb/Makefile | 35 + contrib/libpam/modules/pam_userdb/README | 30 + contrib/libpam/modules/pam_userdb/conv.c | 125 + contrib/libpam/modules/pam_userdb/create.pl | 23 + .../libpam/modules/pam_userdb/pam_userdb.c | 304 ++ .../libpam/modules/pam_userdb/pam_userdb.h | 61 + contrib/libpam/modules/pam_warn/Makefile | 91 +- contrib/libpam/modules/pam_warn/README | 7 +- contrib/libpam/modules/pam_warn/pam_warn.c | 56 +- contrib/libpam/modules/pam_wheel/Makefile | 89 +- contrib/libpam/modules/pam_wheel/pam_wheel.c | 32 +- 248 files changed, 17892 insertions(+), 6438 deletions(-) create mode 100644 contrib/libpam/Make.Rules.in create mode 100644 contrib/libpam/_pam_aconf.h.in create mode 100755 contrib/libpam/configure create mode 100644 contrib/libpam/configure.in create mode 100644 contrib/libpam/defs/debian.defs create mode 100644 contrib/libpam/defs/redhat4.defs create mode 100644 contrib/libpam/defs/solaris-2.1.5.defs create mode 100644 contrib/libpam/defs/suse.defs create mode 100644 contrib/libpam/doc/modules/pam_access.sgml create mode 100644 contrib/libpam/doc/modules/pam_issue.sgml create mode 100644 contrib/libpam/doc/modules/pam_mkhomedir.sgml create mode 100644 contrib/libpam/doc/modules/pam_motd.sgml create mode 100644 contrib/libpam/doc/modules/pam_tally.sgml create mode 100644 contrib/libpam/doc/modules/pam_unix.sgml create mode 100644 contrib/libpam/doc/modules/pam_userdb.sgml create mode 100644 contrib/libpam/doc/specs/draft-morgan-pam.raw create mode 100644 contrib/libpam/libpam_misc/include/security/pam_misc.h create mode 100644 contrib/libpam/libpamc/License create mode 100644 contrib/libpam/libpamc/Makefile create mode 100644 contrib/libpam/libpamc/include/security/pam_client.h create mode 100644 contrib/libpam/libpamc/libpamc.h create mode 100644 contrib/libpam/libpamc/pamc_client.c create mode 100644 contrib/libpam/libpamc/pamc_converse.c create mode 100644 contrib/libpam/libpamc/pamc_load.c create mode 100755 contrib/libpam/libpamc/test/agents/secret@here create mode 100644 contrib/libpam/libpamc/test/modules/Makefile create mode 100644 contrib/libpam/libpamc/test/modules/pam_secret.c create mode 100644 contrib/libpam/libpamc/test/regress/Makefile create mode 100755 contrib/libpam/libpamc/test/regress/run_test.sh create mode 100644 contrib/libpam/libpamc/test/regress/test.libpamc.c create mode 100755 contrib/libpam/libpamc/test/regress/test.secret@here create mode 100644 contrib/libpam/modules/Simple.Rules create mode 100755 contrib/libpam/modules/download-all create mode 100755 contrib/libpam/modules/install_conf create mode 100644 contrib/libpam/modules/pam_issue/Makefile create mode 100644 contrib/libpam/modules/pam_issue/pam_issue.c create mode 100644 contrib/libpam/modules/pam_mail/README create mode 100644 contrib/libpam/modules/pam_mkhomedir/Makefile create mode 100644 contrib/libpam/modules/pam_mkhomedir/pam_mkhomedir.c create mode 100644 contrib/libpam/modules/pam_motd/Makefile create mode 100644 contrib/libpam/modules/pam_motd/pam_motd.c create mode 100644 contrib/libpam/modules/pam_tally/faillog.h create mode 100644 contrib/libpam/modules/pam_tally/pam_tally_app.c create mode 100644 contrib/libpam/modules/pam_unix/bigcrypt.c create mode 100644 contrib/libpam/modules/pam_unix/lckpwdf.-c create mode 100644 contrib/libpam/modules/pam_unix/md5.c create mode 100644 contrib/libpam/modules/pam_unix/md5.h create mode 100644 contrib/libpam/modules/pam_unix/md5_crypt.c create mode 100644 contrib/libpam/modules/pam_unix/support.h create mode 100644 contrib/libpam/modules/pam_unix/unix_chkpwd.c create mode 100644 contrib/libpam/modules/pam_unix/yppasswd.h create mode 100644 contrib/libpam/modules/pam_unix/yppasswd_xdr.c create mode 100644 contrib/libpam/modules/pam_userdb/Makefile create mode 100644 contrib/libpam/modules/pam_userdb/README create mode 100644 contrib/libpam/modules/pam_userdb/conv.c create mode 100644 contrib/libpam/modules/pam_userdb/create.pl create mode 100644 contrib/libpam/modules/pam_userdb/pam_userdb.c create mode 100644 contrib/libpam/modules/pam_userdb/pam_userdb.h diff --git a/contrib/libpam/CHANGELOG b/contrib/libpam/CHANGELOG index 99872a4704c7..162625b07b24 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 000000000000..2818c1c97db1 --- /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 d25f58bb570e..ad2eea2edc29 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 78a428ef46d3..1e769a5dba49 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 000000000000..0da92b79e43a --- /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/bin/README b/contrib/libpam/bin/README index 92ab5253faa9..2d2fba52e4e4 100644 --- a/contrib/libpam/bin/README +++ b/contrib/libpam/bin/README @@ -1,14 +1,5 @@ ## -# $Id: README,v 1.6 1997/02/15 19:21:08 morgan Exp $ -## -# $Log: README,v $ -# Revision 1.6 1997/02/15 19:21:08 morgan -# fixed email -# -# Revision 1.5 1996/08/09 05:29:43 morgan -# trimmed in line with the removal of applications from the distribution -# -# +# $Id: README,v 1.2 2000/12/04 19:02:33 baggins Exp $ ## (now we are getting networked apps, be careful to try and test on a diff --git a/contrib/libpam/conf/Makefile b/contrib/libpam/conf/Makefile index 4fb9f7c40c60..67523c59f182 100644 --- a/contrib/libpam/conf/Makefile +++ b/contrib/libpam/conf/Makefile @@ -1,28 +1,5 @@ # -# $Id: Makefile,v 1.8 1997/04/05 06:59:33 morgan Exp $ -# -# $Log: Makefile,v $ -# Revision 1.8 1997/04/05 06:59:33 morgan -# fakeroot and $(MAKE) -# -# Revision 1.7 1997/02/15 15:53:51 morgan -# added lines to make pam_conv1 -# -# Revision 1.6 1996/11/10 19:48:09 morgan -# fix for systems that have not installed bash in /bin/ -# -# Revision 1.5 1996/03/16 22:21:26 morgan -# added 'make remove' option -# -# Revision 1.4 1996/03/10 21:01:47 morgan -# added .ignore_age flag file -# -# Revision 1.3 1996/03/10 17:41:28 morgan -# make RCScheck check for the presence of the executable before running -# it! -# -# Revision 1.2 1996/03/10 17:16:42 morgan -# added md5RCS/ RCScheck entry +# $Id: Makefile,v 1.1.1.1 2000/06/20 22:10:44 agmorgan Exp $ # # @@ -47,9 +24,6 @@ remove: check: bash -f ./md5itall -RCScheck: - if [ -x ./md5RCS ]; then bash -f ./md5RCS ; fi - lclean: rm -f core *~ .ignore_age diff --git a/contrib/libpam/conf/md5itall b/contrib/libpam/conf/md5itall index 6328a4f6fc5a..0f2656fe746b 100755 --- a/contrib/libpam/conf/md5itall +++ b/contrib/libpam/conf/md5itall @@ -1,8 +1,6 @@ #!/bin/bash # -# $Id$ -# -# $Log$ +# $Id: md5itall,v 1.2 2000/12/04 19:02:33 baggins Exp $ # # Created by Andrew G. Morgan (morgan@parc.power.net) # diff --git a/contrib/libpam/conf/pam.conf b/contrib/libpam/conf/pam.conf index 2e4f0342189a..8e78e547a01b 100644 --- a/contrib/libpam/conf/pam.conf +++ b/contrib/libpam/conf/pam.conf @@ -1,9 +1,9 @@ # ---------------------------------------------------------------------------# # /etc/pam.conf # # # -# Last modified by Andrew G. Morgan # +# Last modified by Andrew G. Morgan # # ---------------------------------------------------------------------------# -# $Id: pam.conf,v 1.18 1997/02/15 20:20:20 morgan Exp morgan $ +# $Id: pam.conf,v 1.2 2001/04/08 06:02:33 agmorgan Exp $ # ---------------------------------------------------------------------------# # serv. module ctrl module [path] ...[args..] # # name type flag # @@ -11,46 +11,46 @@ # # The PAM configuration file for the `chfn' service # -chfn auth required pam_pwdb.so -chfn account required pam_pwdb.so +chfn auth required pam_unix.so +chfn account required pam_unix.so chfn password required pam_cracklib.so retry=3 -chfn password required pam_pwdb.so shadow md5 use_authtok +chfn password required pam_unix.so shadow md5 use_authtok # # The PAM configuration file for the `chsh' service # -chsh auth required pam_pwdb.so -chsh account required pam_pwdb.so +chsh auth required pam_unix.so +chsh account required pam_unix.so chsh password required pam_cracklib.so retry=3 -chsh password required pam_pwdb.so shadow md5 use_authtok +chsh password required pam_unix.so shadow md5 use_authtok # # The PAM configuration file for the `ftp' service # ftp auth requisite pam_listfile.so \ item=user sense=deny file=/etc/ftpusers onerr=succeed ftp auth requisite pam_shells.so -ftp auth required pam_pwdb.so -ftp account required pam_pwdb.so +ftp auth required pam_unix.so +ftp account required pam_unix.so # # The PAM configuration file for the `imap' service # -imap auth required pam_pwdb.so -imap account required pam_pwdb.so +imap auth required pam_unix.so +imap account required pam_unix.so # # The PAM configuration file for the `login' service # login auth requisite pam_securetty.so -login auth required pam_pwdb.so +login auth required pam_unix.so login auth optional pam_group.so login account requisite pam_time.so -login account required pam_pwdb.so +login account required pam_unix.so login password required pam_cracklib.so retry=3 -login password required pam_pwdb.so shadow md5 use_authtok -login session required pam_pwdb.so +login password required pam_unix.so shadow md5 use_authtok +login session required pam_unix.so # # The PAM configuration file for the `netatalk' service # -netatalk auth required pam_pwdb.so -netatalk account required pam_pwdb.so +netatalk auth required pam_unix.so +netatalk account required pam_unix.so # # The PAM configuration file for the `other' service # @@ -64,16 +64,16 @@ other session required pam_deny.so # The PAM configuration file for the `passwd' service # passwd password requisite pam_cracklib.so retry=3 -passwd password required pam_pwdb.so shadow md5 use_authtok +passwd password required pam_unix.so shadow md5 use_authtok # # The PAM configuration file for the `rexec' service # rexec auth requisite pam_securetty.so rexec auth requisite pam_nologin.so rexec auth sufficient pam_rhosts_auth.so -rexec auth required pam_pwdb.so -rexec account required pam_pwdb.so -rexec session required pam_pwdb.so +rexec auth required pam_unix.so +rexec account required pam_unix.so +rexec session required pam_unix.so rexec session required pam_limits.so # # The PAM configuration file for the `rlogin' service @@ -82,10 +82,10 @@ rexec session required pam_limits.so rlogin auth requisite pam_securetty.so rlogin auth requisite pam_nologin.so rlogin auth required pam_rhosts_auth.so -rlogin account required pam_pwdb.so +rlogin account required pam_unix.so rlogin password required pam_cracklib.so retry=3 -rlogin password required pam_pwdb.so shadow md5 use_authtok -rlogin session required pam_pwdb.so +rlogin password required pam_unix.so shadow md5 use_authtok +rlogin session required pam_unix.so rlogin session required pam_limits.so # # The PAM configuration file for the `rsh' service @@ -93,34 +93,34 @@ rlogin session required pam_limits.so rsh auth requisite pam_securetty.so rsh auth requisite pam_nologin.so rsh auth sufficient pam_rhosts_auth.so -rsh auth required pam_pwdb.so -rsh account required pam_pwdb.so -rsh session required pam_pwdb.so +rsh auth required pam_unix.so +rsh account required pam_unix.so +rsh session required pam_unix.so rsh session required pam_limits.so # # The PAM configuration file for the `samba' service # -samba auth required pam_pwdb.so -samba account required pam_pwdb.so +samba auth required pam_unix.so +samba account required pam_unix.so # # The PAM configuration file for the `su' service # su auth required pam_wheel.so su auth sufficient pam_rootok.so -su auth required pam_pwdb.so -su account required pam_pwdb.so -su session required pam_pwdb.so +su auth required pam_unix.so +su account required pam_unix.so +su session required pam_unix.so # # The PAM configuration file for the `vlock' service # -vlock auth required pam_pwdb.so +vlock auth required pam_unix.so # # The PAM configuration file for the `xdm' service # -xdm auth required pam_pwdb.so -xdm account required pam_pwdb.so +xdm auth required pam_unix.so +xdm account required pam_unix.so # # The PAM configuration file for the `xlock' service # -xlock auth required pam_pwdb.so +xlock auth required pam_unix.so diff --git a/contrib/libpam/conf/pam_conv1/README b/contrib/libpam/conf/pam_conv1/README index d3344bb34ff0..7a09df389c00 100644 --- a/contrib/libpam/conf/pam_conv1/README +++ b/contrib/libpam/conf/pam_conv1/README @@ -1,4 +1,4 @@ -$Id: README,v 1.1 1997/02/15 15:50:50 morgan Exp $ +$Id: README,v 1.1.1.1 2000/06/20 22:10:45 agmorgan Exp $ This directory contains a untility to convert pam.conf files to a pam.d/ tree. The conversion program takes pam.conf from the standard input and diff --git a/contrib/libpam/conf/pam_conv1/pam_conv.lex b/contrib/libpam/conf/pam_conv1/pam_conv.lex index d5f618ef4518..ef8cb41a6cbf 100644 --- a/contrib/libpam/conf/pam_conv1/pam_conv.lex +++ b/contrib/libpam/conf/pam_conv1/pam_conv.lex @@ -1,7 +1,7 @@ %{ /* - * $Id: pam_conv.lex,v 1.1 1997/01/23 05:35:50 morgan Exp $ + * $Id: pam_conv.lex,v 1.1.1.1 2000/06/20 22:10:45 agmorgan Exp $ * * Copyright (c) Andrew G. Morgan 1997 * @@ -10,7 +10,7 @@ */ const static char lexid[]= - "$Id: pam_conv.lex,v 1.1 1997/01/23 05:35:50 morgan Exp $\n" + "$Id: pam_conv.lex,v 1.1.1.1 2000/06/20 22:10:45 agmorgan Exp $\n" "Copyright (c) Andrew G. Morgan 1997 \n"; extern int current_line; diff --git a/contrib/libpam/conf/pam_conv1/pam_conv.y b/contrib/libpam/conf/pam_conv1/pam_conv.y index 8ce5ab08f023..a3307b847054 100644 --- a/contrib/libpam/conf/pam_conv1/pam_conv.y +++ b/contrib/libpam/conf/pam_conv1/pam_conv.y @@ -1,7 +1,7 @@ %{ /* - * $Id: pam_conv.y,v 1.3 1997/02/15 15:50:50 morgan Exp morgan $ + * $Id: pam_conv.y,v 1.1.1.1 2000/06/20 22:10:45 agmorgan Exp $ * * Copyright (c) Andrew G. Morgan 1997 * @@ -10,7 +10,7 @@ */ const static char bisonid[]= - "$Id: pam_conv.y,v 1.3 1997/02/15 15:50:50 morgan Exp morgan $\n" + "$Id: pam_conv.y,v 1.1.1.1 2000/06/20 22:10:45 agmorgan Exp $\n" "Copyright (c) Andrew G. Morgan 1997-8 \n"; #include diff --git a/contrib/libpam/configure b/contrib/libpam/configure new file mode 100755 index 000000000000..d63a2fba5760 --- /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 000000000000..fb3752db8dc8 --- /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 000000000000..19ba46635ad1 --- /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/linux.defs b/contrib/libpam/defs/linux.defs index 94e9968c6b25..0e2743203cd5 100644 --- a/contrib/libpam/defs/linux.defs +++ b/contrib/libpam/defs/linux.defs @@ -6,7 +6,7 @@ # preferred OS/vendor. OS=linux -ARCH=`uname -m | sed 's/^i?86/i386/'` +ARCH=i386 # should be changed for alpha CC=gcc INSTALL=install MKDIR=mkdir -p @@ -16,6 +16,7 @@ LD=ld LD_D=gcc -shared -Xlinker -x LD_L=$(LD) -x -shared USESONAME=yes +LINKLIBS=-lc SOSWITCH=-soname NEEDSONAME=no LDCONFIG=/sbin/ldconfig @@ -29,4 +30,3 @@ SECUREDIR=$(LIBDIR)/security INCLUDED=/usr/include/security CONFIGED=/etc SCONFIGED=/etc/security -NSLLIB=-lnsl diff --git a/contrib/libpam/defs/morgan.defs b/contrib/libpam/defs/morgan.defs index 178de28d21a8..2b0cf289e46a 100644 --- a/contrib/libpam/defs/morgan.defs +++ b/contrib/libpam/defs/morgan.defs @@ -21,6 +21,7 @@ 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 diff --git a/contrib/libpam/defs/redhat.defs b/contrib/libpam/defs/redhat.defs index 8c7e1e17f75a..a6ed36da1b20 100644 --- a/contrib/libpam/defs/redhat.defs +++ b/contrib/libpam/defs/redhat.defs @@ -9,7 +9,7 @@ # This file is the version used for Red Hat Linux. OS=linux -ARCH=$(shell rpm --showrc | grep 'build arch' | sed 's/^.*: //g') +ARCH=$(shell rpm --showrc | grep '^build arch' | sed 's/^.*: //g') CC=gcc INSTALL=install MKDIR=mkdir -p @@ -20,6 +20,7 @@ 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 @@ -32,3 +33,4 @@ SECUREDIR=$(LIBDIR)/security INCLUDED=/usr/include/security CONFIGED=/etc SCONFIGED=/etc/security +EXTRALS=-lcrypt diff --git a/contrib/libpam/defs/redhat4.defs b/contrib/libpam/defs/redhat4.defs new file mode 100644 index 000000000000..219abeb6fd1d --- /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 000000000000..4624b604b7fa --- /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 000000000000..1fc6b7419427 --- /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 95ca2ab36e02..528032bbb8ae 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 866b408512df..8ff16077a82a 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 91f990fc01e0..5cb1e0f0ebb4 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.8 b/contrib/libpam/doc/man/pam.8 index 75384416f2cf..b814cebe2ec2 100644 --- a/contrib/libpam/doc/man/pam.8 +++ b/contrib/libpam/doc/man/pam.8 @@ -1,7 +1,7 @@ .\" Hey Emacs! This file is -*- nroff -*- source. -.\" $Id: pam.8,v 1.2 1997/02/15 18:37:27 morgan Exp $ -.\" Copyright (c) Andrew G. Morgan 1996-7 -.TH PAM 8 "1997 Feb 9" "Linux-PAM 0.56" "Linux-PAM Manual" +.\" $Id: pam.8,v 1.2 2001/01/20 23:47:07 agmorgan Exp $ +.\" Copyright (c) Andrew G. Morgan 1996-7,2001 +.TH PAM 8 "2001 Jan 20" "Linux-PAM 0.74" "Linux-PAM Manual" .SH NAME Linux-PAM \- Pluggable Authentication Modules for Linux @@ -197,7 +197,14 @@ The meaning of each of these tokens was explained above. The third field, .BR control ", " indicates the behavior of the PAM-API should the module fail to -succeed in its authentication task. Valid +succeed in its authentication task. There are two types of syntax for +this control field: the simple one has a single simple keyword; the +more complicated one involves a square-bracketed selection of +.B value=action +pairs. + +.sp +For the simple (historical) syntax valid .BR control values are: .BR requisite @@ -223,9 +230,98 @@ module has failed the success of this one is only module in the stack associated with this .BR service "+" type "." +.sp +For the more complicated syntax valid +.B control +values have the following form: +.sp +.RB [value1=action1 value2=action2 ...] +.sp +Where +.B valueN +corresponds to the return code from the function invoked in the module +for which the line is defined. It is selected from one of these: +.BR success ; +.BR open_err ; +.BR symbol_err ; +.BR service_err ; +.BR system_err ; +.BR buf_err ; +.BR perm_denied ; +.BR auth_err ; +.BR cred_insufficient ; +.BR authinfo_unavail ; +.BR user_unknown ; +.BR maxtries ; +.BR new_authtok_reqd ; +.BR acct_expired ; +.BR session_err ; +.BR cred_unavail ; +.BR cred_expired ; +.BR cred_err ; +.BR no_module_data ; +.BR conv_err ; +.BR authtok_err ; +.BR authtok_recover_err ; +.BR authtok_lock_busy ; +.BR authtok_disable_aging ; +.BR try_again ; +.BR ignore ; +.BR abort ; +.BR authtok_expired ; +.BR module_unknown ; +.BR bad_item "; and" +.BR default . +The last of these, +.BR default , +implies 'all +.BR valueN 's +not mentioned explicitly. Note, the full list of PAM errors is +available in /usr/include/security/_pam_types.h . The +.B actionN +can be: an unsigned integer, +.BR J , +signifying an action of 'jump over the next J modules in the stack'; +or take one of the following forms: +.br +.B ignore +- when used with a stack of modules, the module's return status will +not contribute to the return code the application obtains; +.br +.B bad +- this action indicates that the return code should be thought of as +indicative of the module failing. If this module is the first in the +stack to fail, its status value will be used for that of the whole +stack. +.br +.B die +- equivalent to bad with the side effect of terminating the module +stack and PAM immediately returning to the application. +.br +.B ok +- this tells PAM that the administrator thinks this return code +should contribute directly to the return code of the full stack of +modules. In other words, if the former state of the stack would lead +to a return of +.BR PAM_SUCCESS , +the module's return code will override this value. Note, if the former +state of the stack holds some value that is indicative of a modules +failure, this 'ok' value will not be used to override that value. +.br +.B done +- equivalent to ok with the side effect of terminating the module +stack and PAM immediately returning to the application. +.br +.B reset +- clear all memory of the state of the module stack and start again +with the next stacked module. + .sp .BR module-path -- this is the full filename of the PAM to be used by the application +- this is either the full filename of the PAM to be used by the +application (it begins with a '/'), or a relative pathname from the +default module location: +.BR /lib/security/ . .sp .BR module-arguments @@ -238,19 +334,13 @@ documented for each individual module. .br .BR /etc/pam.d/ " - the" .BR Linux-PAM -configuration directory. If this directory is present, the +configuration directory. Generally, if this directory is present, the .B /etc/pam.conf file is ignored. .br -.BR /usr/lib/libpam.so.X " - the dynamic library" +.BR /lib/libpam.so.X " - the dynamic library" .br -.BR /usr/lib/security/*.so " - the PAMs - -.sp -Note, to conform to the Linux File-system standard, the libraries and -modules in your system may be located in -.BR /lib " and " /lib/security -respectively. +.BR /lib/security/*.so " - the PAMs .SH ERRORS Typically errors generated by the @@ -261,8 +351,8 @@ system of libraries, will be written to .SH "CONFORMING TO" DCE-RFC 86.0, October 1995. .br -Contains additional features, currently under consideration by the -DCE-RFC committee. +Contains additional features, but remains backwardly compatible with +this RFC. .SH BUGS .sp 2 @@ -273,7 +363,7 @@ None known. The three .BR Linux-PAM Guides, for -.BR "System administrators" ", " +.BR "system administrators" ", " .BR "module developers" ", " and .BR "application developers" ". " diff --git a/contrib/libpam/doc/man/pam.conf.8 b/contrib/libpam/doc/man/pam.conf.8 index ea2dd98bfc9f..d067b5596eab 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 ea2dd98bfc9f..d067b5596eab 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_authenticate.3 b/contrib/libpam/doc/man/pam_authenticate.3 index f631c47286be..7383f5f06b40 100644 --- a/contrib/libpam/doc/man/pam_authenticate.3 +++ b/contrib/libpam/doc/man/pam_authenticate.3 @@ -1,5 +1,5 @@ .\" Hey Emacs! This file is -*- nroff -*- source. -.\" $Id: pam_authenticate.3,v 1.2 1997/02/15 18:39:59 morgan Exp $ +.\" $Id: pam_authenticate.3,v 1.1.1.1 2000/06/20 22:10:57 agmorgan Exp $ .\" Copyright (c) Andrew G. Morgan 1996-7 .TH PAM_AUTHENTICATE 3 "1996 Dec 9" "Linux-PAM 0.55" "App. Programmers' Manual" .SH NAME diff --git a/contrib/libpam/doc/man/pam_chauthtok.3 b/contrib/libpam/doc/man/pam_chauthtok.3 index b0997d592893..a0466f0fccc6 100644 --- a/contrib/libpam/doc/man/pam_chauthtok.3 +++ b/contrib/libpam/doc/man/pam_chauthtok.3 @@ -1,5 +1,5 @@ .\" Hey Emacs! This file is -*- nroff -*- source. -.\" $Id: pam_chauthtok.3,v 1.2 1997/02/15 18:42:23 morgan Exp $ +.\" $Id: pam_chauthtok.3,v 1.1.1.1 2000/06/20 22:10:57 agmorgan Exp $ .\" Copyright (c) Andrew G. Morgan 1997 .TH PAM_CHAUTHTOK 3 "1997 Jan 4" "Linux-PAM 0.55" "App. Programmers' Manual" .SH NAME diff --git a/contrib/libpam/doc/man/pam_close_session.3 b/contrib/libpam/doc/man/pam_close_session.3 index c809a0e4f0d8..d851700cda02 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 06fdabb9c462..de999f240cfb 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/pam_fail_delay.3 b/contrib/libpam/doc/man/pam_fail_delay.3 index 42bccd6b9258..3b72f3d98b42 100644 --- a/contrib/libpam/doc/man/pam_fail_delay.3 +++ b/contrib/libpam/doc/man/pam_fail_delay.3 @@ -1,5 +1,5 @@ .\" Hey Emacs! This file is -*- nroff -*- source. -.\" $Id: pam_fail_delay.3,v 1.2 1997/02/15 18:47:46 morgan Exp morgan $ +.\" $Id: pam_fail_delay.3,v 1.1.1.1 2000/06/20 22:10:58 agmorgan Exp $ .\" Copyright (c) Andrew G. Morgan 1997 .TH PAM_FAIL_DELAY 3 "1997 Jan 12" "Linux-PAM 0.56" "Programmers' Manual" .SH NAME diff --git a/contrib/libpam/doc/man/pam_open_session.3 b/contrib/libpam/doc/man/pam_open_session.3 index 1b2dcf980bdb..53f6adf12c75 100644 --- a/contrib/libpam/doc/man/pam_open_session.3 +++ b/contrib/libpam/doc/man/pam_open_session.3 @@ -1,5 +1,5 @@ .\" Hey Emacs! This file is -*- nroff -*- source. -.\" $Id: pam_open_session.3,v 1.2 1997/02/15 18:49:02 morgan Exp $ +.\" $Id: pam_open_session.3,v 1.1.1.1 2000/06/20 22:10:58 agmorgan Exp $ .\" Copyright (c) Andrew G. Morgan 1997 .TH PAM_OPEN_SESSION 3 "1997 Jan 4" "Linux-PAM 0.55" "App. Programmers' Manual" .SH NAME diff --git a/contrib/libpam/doc/man/pam_setcred.3 b/contrib/libpam/doc/man/pam_setcred.3 index 388a5d766703..ea251405ac7d 100644 --- a/contrib/libpam/doc/man/pam_setcred.3 +++ b/contrib/libpam/doc/man/pam_setcred.3 @@ -1,5 +1,5 @@ .\" Hey Emacs! This file is -*- nroff -*- source. -.\" $Id: pam_setcred.3,v 1.2 1997/02/15 18:50:49 morgan Exp morgan $ +.\" $Id: pam_setcred.3,v 1.1.1.1 2000/06/20 22:10:58 agmorgan Exp $ .\" Copyright (c) Andrew G. Morgan 1996,1997 .TH PAM_SETCRED 3 "1997 July 6" "Linux-PAM 0.58" "App. Programmers' Manual" .SH NAME diff --git a/contrib/libpam/doc/man/pam_start.3 b/contrib/libpam/doc/man/pam_start.3 index 0299533b4f5e..a912cc754664 100644 --- a/contrib/libpam/doc/man/pam_start.3 +++ b/contrib/libpam/doc/man/pam_start.3 @@ -1,5 +1,5 @@ .\" Hey Emacs! This file is -*- nroff -*- source. -.\" $Id: pam_start.3,v 1.2 1997/02/15 18:51:54 morgan Exp $ +.\" $Id: pam_start.3,v 1.1.1.1 2000/06/20 22:10:58 agmorgan Exp $ .\" Copyright (c) Andrew G. Morgan 1996-7 .TH PAM_START 3 "1997 Feb 15" "Linux-PAM 0.56" "Application Programmers' Manual" .SH NAME diff --git a/contrib/libpam/doc/man/pam_strerror.3 b/contrib/libpam/doc/man/pam_strerror.3 index 33b4fda4c31e..b2318f2884c7 100644 --- a/contrib/libpam/doc/man/pam_strerror.3 +++ b/contrib/libpam/doc/man/pam_strerror.3 @@ -1,8 +1,8 @@ .\" Hey Emacs! This file is -*- nroff -*- source. .\" ripped off from Rick Faith's getgroups man page -.\" $Id: pam_strerror.3,v 1.2 1997/02/15 18:53:04 morgan Exp $ -.\" Copyright (c) Andrew G. Morgan 1996-7 -.TH PAM_STRERROR 3 "1997 Feb 15" "Linux-PAM 0.56" "Programmers' Manual" +.\" $Id: pam_strerror.3,v 1.1.1.1 2000/06/20 22:10:58 agmorgan Exp $ +.\" Copyright (c) Andrew G. Morgan 1996-7 +.TH PAM_STRERROR 3 "1999 Oct 4" "Linux-PAM 0.70" "Programmers' Manual" .SH NAME pam_strerror \- return a textual description of a Linux-PAM error @@ -14,14 +14,16 @@ or, .br .B #include .sp -.BI "const char *pam_strerror(" int " pam_error); +.BI "const char * pam_strerror( pam_handle_t " "*pamh" ", int " pam_error ");" .sp 2 .SH DESCRIPTION .B pam_strerror -This function returns a pointer to a line of text describing the +This function returns some text describing the .BR Linux-PAM -error passed as its sole argument. +error associated with the +.B pam_error +argument. .SH "RETURN VALUE" diff --git a/contrib/libpam/doc/man/template-man b/contrib/libpam/doc/man/template-man index a635c8bd8024..11e7a061504a 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/README b/contrib/libpam/doc/modules/README index b97b2cd501b9..b6587f508c25 100644 --- a/contrib/libpam/doc/modules/README +++ b/contrib/libpam/doc/modules/README @@ -1,4 +1,4 @@ -$Id: README,v 1.2 1996/11/17 17:20:28 morgan Exp $ +$Id: README,v 1.1.1.1 2000/06/20 22:10:58 agmorgan Exp $ This directory contains a number of sgml sub-files. One for each documented module. They contain a description of each module and give diff --git a/contrib/libpam/doc/modules/module.sgml-template b/contrib/libpam/doc/modules/module.sgml-template index 53cd809f338d..3fffc754b047 100644 --- a/contrib/libpam/doc/modules/module.sgml-template +++ b/contrib/libpam/doc/modules/module.sgml-template @@ -1,9 +1,9 @@ + + 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_chroot.sgml b/contrib/libpam/doc/modules/pam_chroot.sgml index 7f8c4a39b642..2366880eabfc 100644 --- a/contrib/libpam/doc/modules/pam_chroot.sgml +++ b/contrib/libpam/doc/modules/pam_chroot.sgml @@ -1,5 +1,5 @@ diff --git a/contrib/libpam/doc/modules/pam_cracklib.sgml b/contrib/libpam/doc/modules/pam_cracklib.sgml index 4700c2a04f03..810b261e83e9 100644 --- a/contrib/libpam/doc/modules/pam_cracklib.sgml +++ b/contrib/libpam/doc/modules/pam_cracklib.sgml @@ -1,5 +1,5 @@ diff --git a/contrib/libpam/doc/modules/pam_env.sgml b/contrib/libpam/doc/modules/pam_env.sgml index a62f4576f132..a6361cacc76a 100644 --- a/contrib/libpam/doc/modules/pam_env.sgml +++ b/contrib/libpam/doc/modules/pam_env.sgml @@ -1,5 +1,5 @@ @@ -100,8 +100,8 @@ the filter might expect.

Permitted values for + This file was written by Andrew G. Morgan --> Anonymous access module @@ -15,7 +15,7 @@ Author: -Andrew G. Morgan <morgan@parc.power.net> +Andrew G. Morgan <morgan@linux.kernel.org> Maintainer: Author. @@ -56,7 +56,7 @@ mode of access. This module intercepts the user's name and password. If the name is `` --> diff --git a/contrib/libpam/doc/modules/pam_issue.sgml b/contrib/libpam/doc/modules/pam_issue.sgml new file mode 100644 index 000000000000..1f617e3b870e --- /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_krb4.sgml b/contrib/libpam/doc/modules/pam_krb4.sgml index edb87d1a0584..51a46522890c 100644 --- a/contrib/libpam/doc/modules/pam_krb4.sgml +++ b/contrib/libpam/doc/modules/pam_krb4.sgml @@ -1,5 +1,5 @@ diff --git a/contrib/libpam/doc/modules/pam_lastlog.sgml b/contrib/libpam/doc/modules/pam_lastlog.sgml index 8c0e662c3cf9..451bfaa2fda6 100644 --- a/contrib/libpam/doc/modules/pam_lastlog.sgml +++ b/contrib/libpam/doc/modules/pam_lastlog.sgml @@ -1,7 +1,7 @@ The last login module @@ -15,7 +15,7 @@ Author: -Andrew G. Morgan <morgan@parc.power.net> +Andrew G. Morgan <morgan@kernel.org> Maintainer: Author @@ -30,7 +30,7 @@ auth Clean code base: System dependencies: -uses information contained in the /var/log/wtmp file. +uses information contained in the /var/log/lastlog file. Network aware: @@ -39,14 +39,14 @@ uses information contained in the /var/log/wtmp file. Overview of module

-This session module maintains the /var/log/wtmp file. Adding +This session module maintains the /var/log/lastlog file. Adding an open entry when called via the pam_open_seesion() function and completing it when pam_close_session() is called. This module can also display a line of information about the last login of the user. If an application already performs these tasks, it is not necessary to use this module. -Authentication component +Session component

@@ -61,7 +61,7 @@ necessary to use this module. This module can be used to provide a ``Last login on ...'' message. when the user logs into the system from what ever application uses the PAM libraries. In addition, the module maintains the -/var/log/wtmp file. +/var/log/lastlog file.

The behavior of this module can be modified with one of the following @@ -85,10 +85,10 @@ attempt. /var/log/wtmp file. +the /var/log/lastlog file. /var/log/wtmp file does not contain any old entries +- if the /var/log/lastlog file does not contain any old entries for the user, indicate that the user has never previously logged in with a ``welcome..." message. @@ -98,13 +98,13 @@ with a ``welcome..." message. This module can be used to indicate that the user has new mail when they /etc/pam.conf file: +/etc/pam.d/XXX file: # -# do we have any mail? +# When were we last here? # -login session optional pam_lastlog.so +session optional pam_lastlog.so diff --git a/contrib/libpam/doc/modules/pam_limits.sgml b/contrib/libpam/doc/modules/pam_limits.sgml index 6b98ea64fcbd..c4bdb4df503e 100644 --- a/contrib/libpam/doc/modules/pam_limits.sgml +++ b/contrib/libpam/doc/modules/pam_limits.sgml @@ -1,5 +1,5 @@ @@ -111,8 +111,8 @@ Note, users listed in /etc/ftpusers file are (counterintuitively) -To allow login access only for certain users, you can use an -pam.conf entry like this: +To allow login access only for certain users, you can use a + # diff --git a/contrib/libpam/doc/modules/pam_mail.sgml b/contrib/libpam/doc/modules/pam_mail.sgml index 9a99f2064c36..65937a9f8dda 100644 --- a/contrib/libpam/doc/modules/pam_mail.sgml +++ b/contrib/libpam/doc/modules/pam_mail.sgml @@ -1,7 +1,7 @@ The mail module @@ -15,13 +15,14 @@ Author: -Andrew G. Morgan <morgan@parc.power.net> +Andrew G. Morgan <morgan@linux.kernel.org> Maintainer: Author Management groups provided: -auth +Authentication (credential) +Session (open) Cryptographically sensitive: @@ -42,14 +43,15 @@ Default mail directory /var/spool/mail/ This module looks at the user's mail directory and indicates whether the user has any mail in it. -Authentication component +Session component

Recognized arguments: -Description: @@ -59,12 +61,6 @@ single message indicating the -Although the module supplies functions for the authentication -management group of functions, it cannot be used to authenticate a -user; its authentication function instructs The behavior of this module can be modified with one of the following flags: @@ -97,6 +93,17 @@ the user's credentials are revoked. - indicate that the user's mail directory is empty if this is found to be the case. +/var/spool/mail/u/s/user. + + Examples/suggested usage: @@ -109,16 +116,27 @@ they +

+Note, if the mail spool file (be it /var/spool/mail/$USER or +a pathname given with the dir= parameter) is a directory then +pam_mail assumes it is in the Qmail Maildir format. +

Note, some applications may perform this function themselves. In such cases, this module is not necessary. +Authentication component + +

+Then authentication companent works the same as the session component, +except that everything is done during the pam_setcred() phase. + diff --git a/contrib/libpam/doc/modules/pam_mkhomedir.sgml b/contrib/libpam/doc/modules/pam_mkhomedir.sgml new file mode 100644 index 000000000000..075e16f9fc05 --- /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 000000000000..8ddc63924e78 --- /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_nologin.sgml b/contrib/libpam/doc/modules/pam_nologin.sgml index de4b32a8efbd..963fa4282b4f 100644 --- a/contrib/libpam/doc/modules/pam_nologin.sgml +++ b/contrib/libpam/doc/modules/pam_nologin.sgml @@ -1,5 +1,5 @@ diff --git a/contrib/libpam/doc/modules/pam_permit.sgml b/contrib/libpam/doc/modules/pam_permit.sgml index 84df9fc1754f..2588110ddcd4 100644 --- a/contrib/libpam/doc/modules/pam_permit.sgml +++ b/contrib/libpam/doc/modules/pam_permit.sgml @@ -1,5 +1,5 @@ diff --git a/contrib/libpam/doc/modules/pam_pwdb.sgml b/contrib/libpam/doc/modules/pam_pwdb.sgml index c9f7bff1124a..625572064bb2 100644 --- a/contrib/libpam/doc/modules/pam_pwdb.sgml +++ b/contrib/libpam/doc/modules/pam_pwdb.sgml @@ -1,7 +1,7 @@ The Password-Database module @@ -16,7 +16,7 @@ pam_pwdb Author: Cristian Gafton <gafton@redhat.com> -and Andrew G. Morgan <morgan@parc.power.net> +and Andrew G. Morgan <morgan@kernel.org> Maintainer: Authors. @@ -44,8 +44,8 @@ This module is a pluggable replacement for the . +url="http://linux.kernel.org/morgan/libpwdb/index.html" +name="http://linux.kernel.org/morgan/libpwdb/index.html">. Account component @@ -101,7 +101,8 @@ login account required pam_pwdb.so Description: @@ -141,6 +142,12 @@ 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. +

+The likeauth argument makes the module return the same value +when called as a credential setting module and an authentication +module. This will help libpam take a sane path through the auth +component of your configuration file. + Examples/suggested usage: The correct functionality of this module is dictated by having an diff --git a/contrib/libpam/doc/modules/pam_radius.sgml b/contrib/libpam/doc/modules/pam_radius.sgml index 4d5f39ab3422..8ebfa0a83592 100644 --- a/contrib/libpam/doc/modules/pam_radius.sgml +++ b/contrib/libpam/doc/modules/pam_radius.sgml @@ -1,5 +1,5 @@ @@ -44,7 +44,7 @@ yes; this is a network module (independent of application).

This module is intended to provide the session service for users -autheticated with a RADIUS server. At the present stage, the only +authenticated with a RADIUS server. At the present stage, the only option supported is the use of the RADIUS server as an accounting server. @@ -60,7 +60,7 @@ server. Description: This module is intended to provide the session service for users -autheticated with a RADIUS server. At the present stage, the only +authenticated with a RADIUS server. At the present stage, the only option supported is the use of the RADIUS server as an --> @@ -81,7 +81,8 @@ of independently probing the network connection for such information.

In the case of /etc/host.equiv file is -hosts_equiv_rootok option +should be used. Instead, the superuser must have a correctly configured personal configuration file.

@@ -102,6 +103,12 @@ fix this!) /etc/hosts.equiv file. + +/etc/hosts.equiv for superuser. Without this +option /etc/hosts.equiv is not consulted for the superuser account. +This option has no effect if the no_hosts_equiv option is used. + --> diff --git a/contrib/libpam/doc/modules/pam_securetty.sgml b/contrib/libpam/doc/modules/pam_securetty.sgml index 276ae90435c2..fc89af23460a 100644 --- a/contrib/libpam/doc/modules/pam_securetty.sgml +++ b/contrib/libpam/doc/modules/pam_securetty.sgml @@ -1,5 +1,5 @@ diff --git a/contrib/libpam/doc/modules/pam_tally.sgml b/contrib/libpam/doc/modules/pam_tally.sgml new file mode 100644 index 000000000000..aca41bbde0f0 --- /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_time.sgml b/contrib/libpam/doc/modules/pam_time.sgml index 0b3cddfcb44a..8889c4501dea 100644 --- a/contrib/libpam/doc/modules/pam_time.sgml +++ b/contrib/libpam/doc/modules/pam_time.sgml @@ -1,5 +1,5 @@ @@ -142,7 +142,7 @@ Some examples of rules that can be placed in the /etc/security/time.conf configuration file are the following: -login ; tty* & ; !ttyp* ; !root ; !Al0000-2400 +login ; tty* & !ttyp* ; !root ; !Al0000-2400 all users except for + + Converted from the pam_pwdb.sgml file for pam_unix by Ben Collins +--> + +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 000000000000..bdbf80b821d0 --- /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/modules/pam_warn.sgml b/contrib/libpam/doc/modules/pam_warn.sgml index 6e81f187f694..af01740c2f98 100644 --- a/contrib/libpam/doc/modules/pam_warn.sgml +++ b/contrib/libpam/doc/modules/pam_warn.sgml @@ -1,5 +1,5 @@ diff --git a/contrib/libpam/doc/modules/pam_wheel.sgml b/contrib/libpam/doc/modules/pam_wheel.sgml index 9139695fec84..bf19a9bab808 100644 --- a/contrib/libpam/doc/modules/pam_wheel.sgml +++ b/contrib/libpam/doc/modules/pam_wheel.sgml @@ -1,5 +1,5 @@ +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 418b09beafd3..609916c4470d 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 093998a0aad1..5e4be447bb32 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/ps/README b/contrib/libpam/doc/ps/README index 6234e14f8f8e..5b24f9b52b3a 100644 --- a/contrib/libpam/doc/ps/README +++ b/contrib/libpam/doc/ps/README @@ -1,3 +1,3 @@ -$Id: README,v 1.1 1996/11/10 19:28:16 morgan Exp $ +$Id: README,v 1.1.1.1 2000/06/20 22:11:05 agmorgan Exp $ this is the directory for the postscipt documentation 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 000000000000..dec3e566721d --- /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/doc/txts/README b/contrib/libpam/doc/txts/README index b62bc2d7448a..f63820cffde0 100644 --- a/contrib/libpam/doc/txts/README +++ b/contrib/libpam/doc/txts/README @@ -1,3 +1,3 @@ -$Id: README,v 1.1 1996/11/10 19:18:06 morgan Exp $ +$Id: README,v 1.1.1.1 2000/06/20 22:11:12 agmorgan Exp $ This is a directory for text versions of the pam documentation diff --git a/contrib/libpam/examples/Makefile b/contrib/libpam/examples/Makefile index 063f24d0df03..2cf67f7007aa 100644 --- a/contrib/libpam/examples/Makefile +++ b/contrib/libpam/examples/Makefile @@ -1,20 +1,31 @@ # -# $Id: Makefile,v 1.10 1996/11/10 19:50:59 morgan Exp $ +# $Id: Makefile,v 1.4 2001/02/10 07:17:53 agmorgan Exp $ # -dummy: - - @echo "*** This is not a top level Makefile!" +include ../Make.Rules PROGS = blank xsh check_user SRCS = blank.c xsh.c check_user.c - -# have removed the following pair since they no longer conform to -# any recognized conventions: vpass test -# ditto: vpass.c test.c - PROGSUID = +ifeq ($(WITH_LIBDEBUG),yes) + LIBSUFFIX=d +else + LIBSUFFIX= +endif + +CFLAGS += -I../libpam_misc/include -I../libpamc/include + +LOADLIBES = -L../libpam -L../libpamc -L../libpam_misc \ + -lpam$(LIBSUFFIX) -lpam_misc$(LIBSUFFIX) + +ifeq ($(STATIC_LIBPAM),yes) + ifneq ($(DYNAMIC),) + CFLAGS += $(CC_STATIC) + LOADLIBES += $(LIBDL) + endif +endif + all: $(PROGS) check_user: check_user.o @@ -26,17 +37,18 @@ blank: blank.o xsh: xsh.o $(CC) $(CFLAGS) -o $@ $< $(LOADLIBES) +clean: + rm -f *.a *.so *.o *~ $(PROGS) $(PROGSUID) + rm -f *.a *.out *.o *.so + +# note, the programs are test programs, they should not be +# installed on your system! + install: all if [ -n "$(PROGS)" ]; then cp $(PROGS) ../bin ; fi if [ -n "$(PROGSUID)" ]; then \ - $(INSTALL) -m 4555 -o root -g bin $(PROGSUID) ../bin ; fi - -clean: - rm -f *.a *.so *.o *~ $(PROGS) $(PROGSUID) + $(INSTALL) -m 4555 $(PROGSUID) ../bin ; fi remove: cd ../bin ; rm -f $(PROGS) $(PROGSUID) - -extraclean: clean - rm -f *.a *.out *.o *.so for x in $(PROGS) $(PROGSUID) ; do rm -f ../bin/$$x ; done diff --git a/contrib/libpam/examples/blank.c b/contrib/libpam/examples/blank.c index 3808e5589f80..20896b5ced75 100644 --- a/contrib/libpam/examples/blank.c +++ b/contrib/libpam/examples/blank.c @@ -1,20 +1,5 @@ /* - * $Id: blank.c,v 1.7 1996/12/01 03:16:53 morgan Exp morgan $ - * - * $Log: blank.c,v $ - * Revision 1.7 1996/12/01 03:16:53 morgan - * added setcred closing function - * - * Revision 1.6 1996/11/10 19:51:40 morgan - * minor change to avoid gcc warning - * - * Revision 1.5 1996/07/07 23:53:05 morgan - * added optional fail delay (non-standard Linux-PAM) - * - * Revision 1.4 1996/05/02 04:44:18 morgan - * moved conversation to a libmisc library routine. - * - * + * $Id: blank.c,v 1.2 2000/12/04 19:02:33 baggins Exp $ */ /* Andrew Morgan (morgan@parc.power.net) -- a self contained `blank' @@ -53,7 +38,7 @@ static struct pam_conv conv = { /* ------- the application itself -------- */ -void main(int argc, char **argv) +int main(int argc, char **argv) { pam_handle_t *pamh=NULL; char *username=NULL; diff --git a/contrib/libpam/examples/check_user.c b/contrib/libpam/examples/check_user.c index 6a64c22d7ad9..cb539c4ee998 100644 --- a/contrib/libpam/examples/check_user.c +++ b/contrib/libpam/examples/check_user.c @@ -1,5 +1,5 @@ /* - $Id: check_user.c,v 1.1 1996/11/10 21:19:30 morgan Exp morgan $ + $Id: check_user.c,v 1.2 2000/12/04 19:02:33 baggins Exp $ This program was contributed by Shane Watts slight modifications by AGM. @@ -8,12 +8,7 @@ # check authorization check auth required pam_unix_auth.so check account required pam_unix_acct.so - - $Log: check_user.c,v $ - Revision 1.1 1996/11/10 21:19:30 morgan - Initial revision - - */ +*/ #include #include diff --git a/contrib/libpam/examples/test.c b/contrib/libpam/examples/test.c index 0a1f5a6168fb..7e166b48ba98 100644 --- a/contrib/libpam/examples/test.c +++ b/contrib/libpam/examples/test.c @@ -1,16 +1,5 @@ /* - * $Log: test.c,v $ - * Revision 1.3 1996/03/10 00:14:20 morgan - * made lines less than 80 chars long. - * - * Revision 1.2 1996/03/09 09:16:26 morgan - * changed the header file that it includes. - * - * Revision 1.1 1996/03/09 09:13:34 morgan - * Initial revision - */ - -/* Marc Ewing (marc@redhat.com) - original test code + * Marc Ewing (marc@redhat.com) - original test code * Alexander O. Yuriev (alex@bach.cis.temple.edu) * Andrew Morgan (morgan@physics.ucla.edu) */ diff --git a/contrib/libpam/examples/vpass.c b/contrib/libpam/examples/vpass.c index 617a5f2e8241..9a07ee380340 100644 --- a/contrib/libpam/examples/vpass.c +++ b/contrib/libpam/examples/vpass.c @@ -36,7 +36,7 @@ int main(void) pam_start("vpass", user, &conv, &pamh); pam_set_item(pamh, PAM_TTY, "/dev/tty"); if ((res = pam_authenticate(pamh, 0)) != PAM_SUCCESS) { - fprintf(stderr, "Oops: %s\n", pam_strerror(res)); + fprintf(stderr, "Oops: %s\n", pam_strerror(pamh, res)); exit(1); } diff --git a/contrib/libpam/examples/xsh.c b/contrib/libpam/examples/xsh.c index ad134f6217ba..ea54886462fe 100644 --- a/contrib/libpam/examples/xsh.c +++ b/contrib/libpam/examples/xsh.c @@ -1,22 +1,8 @@ /* - * $Id: xsh.c,v 1.4 1996/11/10 21:09:45 morgan Exp morgan $ - * - * $Log: xsh.c,v $ - * Revision 1.4 1996/11/10 21:09:45 morgan - * no gcc warnings - * - * Revision 1.3 1996/07/07 23:53:36 morgan - * added support for non standard pam_fail_delay - * - * Revision 1.2 1996/05/02 04:44:48 morgan - * moved conversaation to a libmisc routine. - * - * Revision 1.1 1996/04/07 08:18:55 morgan - * Initial revision - * + * $Id: xsh.c,v 1.3 2001/02/05 06:50:41 agmorgan Exp $ */ -/* Andrew Morgan (morgan@parc.power.net) -- an example application +/* Andrew Morgan (morgan@kernel.org) -- an example application * that invokes a shell, based on blank.c */ #include @@ -44,22 +30,28 @@ static struct pam_conv conv = { /* ------- the application itself -------- */ -void main(int argc, char **argv, char **envp) +int main(int argc, char **argv) { pam_handle_t *pamh=NULL; - char *username=NULL; + const char *username=NULL; + const char *service="xsh"; int retcode; - /* did the user call with a username as an argument ? */ + /* did the user call with a username as an argument ? + * did they also */ - if (argc > 2) { - fprintf(stderr,"usage: %s [username]\n",argv[0]); - } else if (argc == 2) { + if (argc > 3) { + fprintf(stderr,"usage: %s [username [service-name]]\n",argv[0]); + } + if (argc >= 2) { username = argv[1]; - } + } + if (argc == 3) { + service = argv[2]; + } /* initialize the Linux-PAM library */ - retcode = pam_start("xsh", username, &conv, &pamh); + retcode = pam_start(service, username, &conv, &pamh); bail_out(pamh,1,retcode,"pam_start"); /* to avoid using goto we abuse a loop here */ @@ -111,7 +103,10 @@ void main(int argc, char **argv, char **envp) break; } - fprintf(stderr,"The user has been authenticated and `logged in'\n"); + pam_get_item(pamh, PAM_USER, (const void **) &username); + fprintf(stderr, + "The user [%s] has been authenticated and `logged in'\n", + username); /* this is always a really bad thing for security! */ system("/bin/sh"); @@ -127,6 +122,15 @@ void main(int argc, char **argv, char **envp) break; } + /* `0' could be as above */ + retcode = pam_setcred(pamh, PAM_DELETE_CRED); + bail_out(pamh,0,retcode,"pam_setcred"); + if (retcode != PAM_SUCCESS) { + fprintf(stderr,"%s: problem deleting user credentials\n" + ,argv[0]); + break; + } + break; /* don't go on for ever! */ } diff --git a/contrib/libpam/libpam/Makefile b/contrib/libpam/libpam/Makefile index f3914a478b9a..9d3e6d7391e8 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 acfc59231af0..33520a6c64c3 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 b033aa63fab6..2827fabf77d0 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 b68368b0c8e2..f0f30930fc69 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 d9c5eddd145b..69ee544ddcd9 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 b5865cd305ad..214bf77dff6c 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/include/security/pam_modules.h b/contrib/libpam/libpam/include/security/pam_modules.h index 6ba9cc66588a..1f20993fea3b 100644 --- a/contrib/libpam/libpam/include/security/pam_modules.h +++ b/contrib/libpam/libpam/include/security/pam_modules.h @@ -1,27 +1,7 @@ /* * * - * $Id: pam_modules.h,v 1.8 1997/01/04 20:14:42 morgan Exp morgan $ - * - * This header file documents the PAM SPI --- that is, interface - * between the PAM library and a PAM service library which is called - * by the PAM library. - * - * Note, the copyright information is at end of file. - * - * $Log: pam_modules.h,v $ - * Revision 1.8 1997/01/04 20:14:42 morgan - * moved PAM_DATA_SILENT to _pam_types.h so applications can use it too - * - * Revision 1.7 1996/11/10 19:57:08 morgan - * pam_get_user prototype. - * - * Revision 1.6 1996/09/05 06:18:45 morgan - * added some data error_status masks, changed prototype for cleanup() - * - * Revision 1.5 1996/06/02 07:58:37 morgan - * altered the way in which modules obtain static prototypes for - * functions + * $Id: pam_modules.h,v 1.3 2001/02/05 06:50:41 agmorgan Exp $ * */ @@ -132,7 +112,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, #define PAM_PRELIM_CHECK 0x4000 /* The password service should update passwords Note: PAM_PRELIM_CHECK - * and PAM_UPDATE_AUTHTOK can not both be set simultaneously! */ + * and PAM_UPDATE_AUTHTOK cannot both be set simultaneously! */ #define PAM_UPDATE_AUTHTOK 0x2000 diff --git a/contrib/libpam/libpam/pam_account.c b/contrib/libpam/libpam/pam_account.c index ffc01acd2a1b..71e04f15ccaf 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 ac461f5ba863..2645d8ad32d1 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 397fb9d820d1..07bcd30d8b02 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 e6950e2a966b..b414ecc4972d 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 d0bbc3872103..ffb50f5226e8 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 34f98f579779..53e346cc4e98 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 2632b81342a2..a2b212a98545 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 53d77158edf5..7ae7174ecb32 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 0e8142bf5ce4..eec341f7e11b 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_log.c b/contrib/libpam/libpam/pam_log.c index 9eddf29ba0ee..c42fe01559df 100644 --- a/contrib/libpam/libpam/pam_log.c +++ b/contrib/libpam/libpam/pam_log.c @@ -1,17 +1,16 @@ /* * pam_log.c -- PAM system logging * - * $Id$ + * $Id: pam_log.c,v 1.2 2000/11/19 23:54:02 agmorgan Exp $ * - * $Log$ */ +#include "pam_private.h" + #include #include #include -#include "pam_private.h" - #ifdef __hpux # include # include @@ -342,84 +341,35 @@ vsyslog(priority, fmt, va_alist) } #endif /* __hpux */ -void pam_vsystem_log(const pam_handle_t *pamh, - const struct pam_log_state *log_state, - int priority, const char *format, va_list args) +/* internal logging function */ + +void _pam_system_log(int priority, const char *format, ... ) { - const char *ident; - int option, facility; - - D(("pam_vsystem_log called")); - - /* make sure we have a log state to use */ - if (NULL == log_state) { - if (NULL != pamh && NULL != pamh->pam_default_log.ident) { - ident = pamh->pam_default_log.ident; - option = pamh->pam_default_log.option; - facility = pamh->pam_default_log.facility; - } else { - ident = PAM_LOG_STATE_IDENT; - option = PAM_LOG_STATE_OPTION; - facility = PAM_LOG_STATE_FACILITY; - } - openlog(ident, option, facility); - } else { - openlog(log_state->ident, log_state->option, log_state->facility); - } - - vsyslog(priority, format, args); - closelog(); - - D(("done.")); -} - -void pam_system_log(const pam_handle_t *pamh, - const struct pam_log_state *log_state, - int priority, const char *format, ... ) -{ - const char *ident; - int option, facility; va_list args; + char *eformat; D(("pam_system_log called")); - /* make sure we have a log state to use */ - if (NULL == log_state) { - if (NULL != pamh && NULL != pamh->pam_default_log.ident) { - ident = pamh->pam_default_log.ident; - option = pamh->pam_default_log.option; - facility = pamh->pam_default_log.facility; - } else { - ident = PAM_LOG_STATE_IDENT; - option = PAM_LOG_STATE_OPTION; - facility = PAM_LOG_STATE_FACILITY; - } - openlog(ident, option, facility); - } else { - openlog(log_state->ident, log_state->option, log_state->facility); + if (format == NULL) { + D(("NULL format to _pam_system_log() call")); + return; } va_start(args, format); - vsyslog(priority, format, args); + + eformat = malloc(sizeof(_PAM_SYSTEM_LOG_PREFIX)+strlen(format)); + if (eformat != NULL) { + strcpy(eformat, _PAM_SYSTEM_LOG_PREFIX); + strcpy(eformat + sizeof(_PAM_SYSTEM_LOG_PREFIX) - 1, format); + vsyslog(priority, eformat, args); + _pam_overwrite(eformat); + _pam_drop(eformat); + } else { + vsyslog(priority, format, args); + } + va_end(args); - closelog(); D(("done.")); } -/* - * Recommended #defines to make porting legacy apps easier [Ed. at this - * point, the syslog() #define is breoken -- suggestions?] - * - * #ifdef PAM_LOG_STATE - * # define openlog(ident, option, facility) { \ - * struct pam_log_state tmp_state; \ - * tmp_state.ident = ident; \ - * tmp_state.option = option; \ - * tmp_state.facility = facility; \ - * (void) pam_set_item(pamh, PAM_LOG_STATE, &tmp_state); \ - * } - * # define syslog pam_system_log - * # define closelog() - * #endif - */ diff --git a/contrib/libpam/libpam/pam_malloc.c b/contrib/libpam/libpam/pam_malloc.c index cc66f1aad6c7..d08a45611f90 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 6e186b703bb0..86b16577dc86 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 6fed9ba126b9..6c1d5d62343c 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 303425ab6254..c247b1269f79 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 f8a0da54fc94..cd7843f92dcc 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 b720774e7e61..72bd7ea5ddcd 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 38b93fe70549..3709f62d77ae 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 53700a091029..2296c9a95001 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_static.c b/contrib/libpam/libpam/pam_static.c index d840a2dc6d2c..5a2b5a5d265e 100644 --- a/contrib/libpam/libpam/pam_static.c +++ b/contrib/libpam/libpam/pam_static.c @@ -2,21 +2,7 @@ /* created by Michael K. Johnson, johnsonm@redhat.com * - * $Id: pam_static.c,v 1.4 1996/12/01 03:14:13 morgan Exp $ - * - * $Log: pam_static.c,v $ - * Revision 1.4 1996/12/01 03:14:13 morgan - * use _pam_macros.h - * - * Revision 1.3 1996/11/10 20:09:16 morgan - * name convention change _pam_ - * - * Revision 1.2 1996/06/02 08:02:56 morgan - * Michael's minor alterations - * - * Revision 1.1 1996/05/26 04:34:04 morgan - * Initial revision - * + * $Id: pam_static.c,v 1.1.1.1 2000/06/20 22:11:21 agmorgan Exp $ */ /* This whole file is only used for PAM_STATIC */ @@ -53,16 +39,18 @@ static struct pam_module *static_modules[] = { */ /* 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) +{ int i; - char *lpath = path, *end; + const char *clpath = path; + char *lpath, *end; - if (strchr(lpath, '/')) { + if (strchr(clpath, '/')) { /* ignore path and leading "/" */ - lpath = strrchr(lpath, '/') + 1; + clpath = strrchr(lpath, '/') + 1; } /* create copy to muck with (must free before return) */ - lpath = _pam_strdup(lpath); + lpath = _pam_strdup(clpath); /* chop .so off copy if it exists (or other extension on other platform...) */ end = strstr(lpath, ".so"); @@ -80,8 +68,8 @@ struct pam_module * _pam_open_static_handler(char *path) { } if (static_modules[i] == NULL) { - pam_system_log(pamh, NULL, LOG_ERR, "no static module named %s", - lpath); + _pam_system_log(NULL, NULL, LOG_ERR, "no static module named %s", + lpath); } free(lpath); diff --git a/contrib/libpam/libpam/pam_strerror.c b/contrib/libpam/libpam/pam_strerror.c index 607c6d5dbfef..4f2249db75de 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 9380f8837b96..69e794895ecc 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 1cfc86577b1f..b7ff178cbe7d 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 d35b66b948ca..e1390984273c 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 000000000000..1e8c4784c532 --- /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 53cf51b76ccc..8e2460dc4c13 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/libpam_misc/xstrdup.c b/contrib/libpam/libpam_misc/xstrdup.c index e54a87dda7a6..cce476e89f59 100644 --- a/contrib/libpam/libpam_misc/xstrdup.c +++ b/contrib/libpam/libpam_misc/xstrdup.c @@ -1,11 +1,4 @@ -/* $Header: /home/morgan/pam/Linux-PAM-0.53/libpam_misc/RCS/xstrdup.c,v 1.4 1996/11/10 20:10:56 morgan Exp $ */ - -/* - * $Log: xstrdup.c,v $ - * Revision 1.4 1996/11/10 20:10:56 morgan - * modification for stack paranoia - * - */ +/* $Id: xstrdup.c,v 1.1.1.1 2000/06/20 22:11:25 agmorgan Exp $ */ #include #include diff --git a/contrib/libpam/libpamc/License b/contrib/libpam/libpamc/License new file mode 100644 index 000000000000..9010695470a1 --- /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 000000000000..1869cfe9dfbc --- /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 000000000000..08aa817a28d6 --- /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 000000000000..1c9397c9071a --- /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 000000000000..19eff429f892 --- /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 000000000000..131789fb15a3 --- /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 000000000000..01304cc1afe2 --- /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 000000000000..afdcbaa801aa --- /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 000000000000..480654629764 --- /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 000000000000..f59e53a54727 --- /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 000000000000..ff63e5f087ad --- /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 000000000000..a1bf010b11c1 --- /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 000000000000..b7bc4e4bca75 --- /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 000000000000..2e0b9b940cb6 --- /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/Makefile b/contrib/libpam/modules/Makefile index 0066fb473e0c..aece2068904c 100644 --- a/contrib/libpam/modules/Makefile +++ b/contrib/libpam/modules/Makefile @@ -1,89 +1,17 @@ -# $Id: Makefile,v 1.21 1997/04/05 06:44:43 morgan Exp morgan $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ # # Makefile # # This makefile controls the build process of shared and static PAM modules. # -# $Log: Makefile,v $ -# Revision 1.21 1997/04/05 06:44:43 morgan -# pam_env and pam_tally added -# -# Revision 1.20 1997/02/15 18:57:11 morgan -# fixed bash syntax -# -# Revision 1.19 1997/01/04 20:21:32 morgan -# moved responsibility of conditional compilation to modules (more flexible) -# -# Revision 1.18 1996/12/01 03:34:40 morgan -# update for .54 -# -# Revision 1.17 1996/11/10 20:20:15 morgan -# cross platform support and new modules -# -# Revision 1.16 1996/09/05 06:20:45 morgan -# added two modules: listfile and shells -# -# Revision 1.15 1996/08/09 05:38:28 morgan -# added new/proposed modules. -# fixed makefile installation dependencies -# -# Revision 1.14 1996/07/08 00:00:33 morgan -# added wheel and group modules # -MODDIRS=\ - pam_access \ - pam_afs \ - pam_afsauth \ - pam_afspass \ - pam_afstok \ - pam_cracklib \ - pam_deny \ - pam_desgold \ - pam_env \ - pam_filter \ - pam_ftp \ - pam_group \ - pam_kerberos \ - pam_krb4 \ - pam_lastlog \ - pam_listfile \ - pam_limits \ - pam_mail \ - pam_nologin \ - pam_opie \ - pam_passwd+ \ - pam_permit \ - pam_pwdb \ - pam_radius \ - pam_restrict \ - pam_rhosts \ - pam_rootok \ - pam_securetty \ - pam_shells \ - pam_sid \ - pam_skey \ - pam_skey2 \ - pam_stress \ - pam_syslog \ - pam_tally \ - pam_time \ - pam_unix \ - pam_warn \ - pam_wheel +include ../Make.Rules - -# //////////////////////////////////////////////////// -# // You should not modify anything below this line // -# //////////////////////////////////////////////////// - -dummy: - @echo "*** This is not a top-level Makefile! ***" - -# ----------------------------------------------------------- +MODDIRS=$(shell /bin/ls -d pam_*) all: - @echo modules for $(OS) are: + @echo modules sources available are: @ls -d $(MODDIRS) 2>/dev/null ; echo :-------- @echo ifdef STATIC @@ -98,6 +26,9 @@ endif } fi ; \ done +download: + @./download-all + install: for i in $(MODDIRS) ; do \ if [ -d $$i ]; then { \ @@ -123,10 +54,3 @@ clean: lclean } fi ; \ done -extraclean: lclean - for i in $(MODDIRS) ; do \ - if [ -d $$i ]; then \ - $(MAKE) -C $$i extraclean ; \ - fi ; \ - done - diff --git a/contrib/libpam/modules/README b/contrib/libpam/modules/README index 864159478c65..73d3cf0c2e49 100644 --- a/contrib/libpam/modules/README +++ b/contrib/libpam/modules/README @@ -1,7 +1,7 @@ This directory contains the modules. If you want to reserve a module name please email -and announce its name. Andrew Morgan, , will +and announce its name. Andrew Morgan, , will add it to the Makefile in the next release of Linux-PAM. As of Linux-PAM-0.40 modules can optionally conform to the static diff --git a/contrib/libpam/modules/Simple.Rules b/contrib/libpam/modules/Simple.Rules new file mode 100644 index 000000000000..954641c668a3 --- /dev/null +++ b/contrib/libpam/modules/Simple.Rules @@ -0,0 +1,92 @@ +# $Id: Simple.Rules,v 1.3 2001/02/22 04:55:41 agmorgan Exp $ +# +# For simple modules with no significant dependencies, set $(TITLE) +# and include this file. +# +# There are a few ways to customize this set of rules. Namely, define +# +# $(MODULE_SIMPLE_EXTRACLEAN) +# $(MODULE_SIMPLE_CLEAN) +# $(MODULE_SIMPLE_REMOVE) +# $(MODULE_SIMPLE_INSTALL) +# $(MODULE_SIMPLE_EXTRALIBS) - other things to link with the module +# $(MODULE_SIMPLE_EXTRAFILES) - other files to build (no .c suffix) +# + +LIBFILES = $(TITLE) $(MODULE_SIMPLE_EXTRAFILES) +LIBSRC = $(addsuffix .c,$(LIBFILES)) +LIBOBJ = $(addsuffix .o,$(LIBFILES)) +LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) +LIBOBJS = $(addprefix static/,$(LIBOBJ)) + +ifdef DYNAMIC +LIBSHARED = $(TITLE).so +endif + +ifdef STATIC +LIBSTATIC = lib$(TITLE).o +endif + +####################### don't edit below ####################### + +all: dirs $(LIBSHARED) $(LIBSTATIC) register + +dynamic/%.o : %.c + $(CC) $(CFLAGS) $(DYNAMIC) $(TARGET_ARCH) -c $< -o $@ + +static/%.o : %.c + $(CC) $(CFLAGS) $(STATIC) $(TARGET_ARCH) -c $< -o $@ + +dirs: +ifdef DYNAMIC + $(MKDIR) ./dynamic +endif +ifdef STATIC + $(MKDIR) ./static +endif + +register: +ifdef STATIC + ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) +endif + +ifdef DYNAMIC +$(LIBOBJD): $(LIBSRC) +endif + +ifdef DYNAMIC +$(LIBSHARED): $(LIBOBJD) + $(LD_D) -o $@ $(LIBOBJD) $(MODULE_SIMPLE_EXTRALIBS) $(NEED_LINK_LIB_C) + +endif + +ifdef STATIC +$(LIBOBJS): $(LIBSRC) +endif + +ifdef STATIC +$(LIBSTATIC): $(LIBOBJS) + $(LD) -r -o $@ $(LIBOBJS) $(MODULE_SIMPLE_EXTRALIBS) +endif + +install: all + $(MKDIR) $(FAKEROOT)$(SECUREDIR) +ifdef DYNAMIC + $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) +endif + $(MODULE_SIMPLE_INSTALL) + +remove: + rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so + $(MODULE_SIMPLE_REMOVE) + +clean: + rm -f $(LIBOBJD) $(LIBOBJS) core *~ + $(MODULE_SIMPLE_CLEAN) + rm -f *.a *.o *.so *.bak + rm -rf dynamic static + $(MODULE_SIMPLE_EXTRACLEAN) + +.c.o: + $(CC) $(CFLAGS) -c $< + diff --git a/contrib/libpam/modules/dont_makefile b/contrib/libpam/modules/dont_makefile index f256ce1b3a61..48307f02ecd4 100644 --- a/contrib/libpam/modules/dont_makefile +++ b/contrib/libpam/modules/dont_makefile @@ -1,4 +1,6 @@ ######################################################################### +# $Id: dont_makefile,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ +######################################################################### # This is a makefile that does nothing. It is designed to be included # by module Makefile-s when they are not compatable with the local # system @@ -7,7 +9,7 @@ all: @echo "This module will not be compiled on this system" -extraclean: clean +remove: clean install: clean diff --git a/contrib/libpam/modules/download-all b/contrib/libpam/modules/download-all new file mode 100755 index 000000000000..9b6cf6558136 --- /dev/null +++ b/contrib/libpam/modules/download-all @@ -0,0 +1,30 @@ +#!/bin/sh +# +# $Id: download-all,v 1.1.1.1 2000/06/20 22:11:29 agmorgan Exp $ +# +cat <'): # # Login access control table. # diff --git a/contrib/libpam/modules/pam_access/pam_access.c b/contrib/libpam/modules/pam_access/pam_access.c index 121333928a26..87ad708d81ed 100644 --- a/contrib/libpam/modules/pam_access/pam_access.c +++ b/contrib/libpam/modules/pam_access/pam_access.c @@ -5,12 +5,27 @@ * (I took login_access from logdaemon-5.6 and converted it to PAM * using parts of pam_time code.) * + ************************************************************************ + * Copyright message from logdaemon-5.6 (original file name DISCLAIMER) + ************************************************************************ + * Copyright 1995 by Wietse Venema. All rights reserved. Individual files + * may be covered by other copyrights (as noted in the file itself.) + * + * This material was originally written and compiled by Wietse Venema at + * Eindhoven University of Technology, The Netherlands, in 1990, 1991, + * 1992, 1993, 1994 and 1995. + * + * Redistribution and use in source and binary forms are permitted + * provided that this entire copyright notice is duplicated in all such + * copies. + * + * This software is provided "as is" and without any expressed or implied + * warranties, including, without limitation, the implied warranties of + * merchantibility and fitness for any particular purpose. + ************************************************************************* */ -#ifdef linux -# define _GNU_SOURCE -# include -#endif +#include #include #include @@ -46,21 +61,6 @@ extern int gethostname(char *name, size_t len); #include #include -/* --- static functions for checking whether the user should be let in --- */ - -static void _log_err(const char *format, ... ) -{ - va_list args; - - va_start(args, format); - openlog("pam_access", LOG_CONS|LOG_PID, LOG_AUTH); - vsyslog(LOG_ERR, format, args); - va_end(args); - closelog(); -} - -#define PAM_ACCESS_CONFIG CONFILE - int strcasecmp(const char *s1, const char *s2); /* login_access.c from logdaemon-5.6 with several changes by A.Nogin: */ @@ -77,12 +77,18 @@ int strcasecmp(const char *s1, const char *s2); #if !defined(MAXHOSTNAMELEN) || (MAXHOSTNAMELEN < 64) #undef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 256 +#endif + +#ifdef DEFAULT_CONF_FILE +# define PAM_ACCESS_CONFIG DEFAULT_CONF_FILE +#else +# define PAM_ACCESS_CONFIG "/etc/security/access.conf" #endif /* Delimiters for fields and for lists of users, ttys or hosts. */ -static char fs[] = ":"; /* field separator */ -static char sep[] = ", \t"; /* list-element separator */ +static const char fs[] = ":"; /* field separator */ +static const char sep[] = ", \t"; /* list-element separator */ /* Constants to be used in assignments only, not in comparisons... */ @@ -96,8 +102,50 @@ static char sep[] = ", \t"; /* list-element separator */ struct login_info { struct passwd *user; char *from; + const char *config_file; + const char *service; }; +/* --- static functions for checking whether the user should be let in --- */ + +static void _log_err(const char *format, ... ) +{ + va_list args; + + va_start(args, format); + openlog("pam_access", LOG_CONS|LOG_PID, LOG_AUTH); + vsyslog(LOG_ERR, format, args); + va_end(args); + closelog(); +} + +/* Parse module config arguments */ + +static int parse_args(struct login_info *loginfo, int argc, const char **argv) +{ + int i; + + for (i=0; iconfig_file = 11 + argv[i]; + fclose(fp); + } else { + _log_err("for service [%s] failed to open accessfile=[%s]" + , loginfo->service, 11 + argv[i]); + return 0; + } + + } else { + _log_err("unrecognized option [%s]", argv[i]); + } + } + + return 1; /* OK */ +} + typedef int match_func (char *, struct login_info *); static int list_match (char *, struct login_info *, @@ -108,23 +156,16 @@ static int string_match (char *, char *); /* login_access - match username/group and host/tty with access control file */ -static int login_access(struct passwd *user, char *from) +static int login_access(struct login_info *item) { - struct login_info item; FILE *fp; char line[BUFSIZ]; - char *perm; /* becomes permission field */ - char *users; /* becomes list of login names */ - char *froms; /* becomes list of terminals or hosts */ + char *perm; /* becomes permission field */ + char *users; /* becomes list of login names */ + char *froms; /* becomes list of terminals or hosts */ int match = NO; int end; - int lineno = 0; /* for diagnostics */ - - /* - * Bundle up the arguments to avoid unnecessary clumsiness lateron. - */ - item.user = user; - item.from = from; + int lineno = 0; /* for diagnostics */ /* * Process the table one line at a time and stop at the first match. @@ -134,12 +175,12 @@ static int login_access(struct passwd *user, char *from) * non-existing table means no access control. */ - if ((fp = fopen(PAM_ACCESS_CONFIG, "r"))!=NULL) { + if ((fp = fopen(item->config_file, "r"))!=NULL) { while (!match && fgets(line, sizeof(line), fp)) { lineno++; if (line[end = strlen(line) - 1] != '\n') { _log_err("%s: line %d: missing newline or line too long", - PAM_ACCESS_CONFIG, lineno); + item->config_file, lineno); continue; } if (line[0] == '#') @@ -153,19 +194,21 @@ static int login_access(struct passwd *user, char *from) || !(users = strtok((char *) 0, fs)) || !(froms = strtok((char *) 0, fs)) || strtok((char *) 0, fs)) { - _log_err("%s: line %d: bad field count", PAM_ACCESS_CONFIG, lineno); + _log_err("%s: line %d: bad field count", + item->config_file, lineno); continue; } if (perm[0] != '+' && perm[0] != '-') { - _log_err("%s: line %d: bad first field", PAM_ACCESS_CONFIG, lineno); + _log_err("%s: line %d: bad first field", + item->config_file, lineno); continue; } - match = (list_match(froms, &item, from_match) - && list_match(users, &item, user_match)); + match = (list_match(froms, item, from_match) + && list_match(users, item, user_match)); } (void) fclose(fp); } else if (errno != ENOENT) { - _log_err("cannot open %s: %m", PAM_ACCESS_CONFIG); + _log_err("cannot open %s: %m", item->config_file); } return (match == 0 || (line[0] == '+')); } @@ -356,10 +399,17 @@ int strcasecmp(const char *s1, const char *s2) PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc ,const char **argv) { - const char *user=NULL; + struct login_info loginfo; + const char *user=NULL, *service=NULL; char *from=NULL; struct passwd *user_pw; + if ((pam_get_item(pamh, PAM_SERVICE, (const void **)&service) + != PAM_SUCCESS) || (service == NULL) || (*service == ' ')) { + _log_err("cannot find the service name"); + return PAM_ABORT; + } + /* set username */ if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS || user == NULL @@ -398,8 +448,27 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc } } + if ((user_pw=getpwnam(user))==NULL) return (PAM_USER_UNKNOWN); - if (login_access(user_pw,from)) return (PAM_SUCCESS); else { + + /* + * Bundle up the arguments to avoid unnecessary clumsiness later on. + */ + loginfo.user = user_pw; + loginfo.from = from; + loginfo.service = service; + loginfo.config_file = PAM_ACCESS_CONFIG; + + /* parse the argument list */ + + if (!parse_args(&loginfo, argc, argv)) { + _log_err("failed to parse the module arguments"); + return PAM_ABORT; + } + + if (login_access(&loginfo)) { + return (PAM_SUCCESS); + } else { _log_err("access denied for user `%s' from `%s'",user,from); return (PAM_PERM_DENIED); } diff --git a/contrib/libpam/modules/pam_cracklib/Makefile b/contrib/libpam/modules/pam_cracklib/Makefile index 668f2f846296..371ac0a86c3e 100644 --- a/contrib/libpam/modules/pam_cracklib/Makefile +++ b/contrib/libpam/modules/pam_cracklib/Makefile @@ -1,110 +1,32 @@ # +# $Id: Makefile,v 1.3 2001/02/10 22:15:23 agmorgan Exp $ +# # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# Created by Cristian Gafton 1996/09/10 +# Created by Andrew Morgan 2000/10/08 # -ifndef FULL_LINUX_PAM_SOURCE_TREE -# -# here you should make default variable defines... -# -MKDIR=mkdir -p -LD_D=gcc -shared -Xlinker -x -INSTALL=install -SECUREDIR=/usr/lib/security -# -HAVE_CRACKLIB=yes -endif - -ifeq ($(HAVE_CRACKLIB),yes) +include ../../Make.Rules TITLE=pam_cracklib -CRACKLIB=-lcrack -CRACKLIB_DICTPATH=/usr/lib/cracklib_dict -# -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) +ifeq ($(HAVE_LIBCRACK),yes) +BUILD_THIS_MODULE=yes +MODULE_SIMPLE_EXTRALIBS=-lcrack -ifdef CRACKLIB_DICTPATH +# These two should really be provided by ../../pam_aconf.h CFLAGS+=-DCRACKLIB_DICTPATH=\"$(CRACKLIB_DICTPATH)\" + +ifeq ($(HAVE_LIBCRYPT),yes) + MODULE_SIMPLE_EXTRALIBS += -lcrypt endif -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so endif -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) Makefile - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) $(CRACKLIB) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ *.so - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< - +ifeq ($(BUILD_THIS_MODULE),yes) + include ../Simple.Rules else - -include ../dont_makefile - + include ../dont_makefile endif diff --git a/contrib/libpam/modules/pam_cracklib/README b/contrib/libpam/modules/pam_cracklib/README index e4b02731b523..69662f7385b3 100644 --- a/contrib/libpam/modules/pam_cracklib/README +++ b/contrib/libpam/modules/pam_cracklib/README @@ -13,9 +13,25 @@ RECOGNIZED ARGUMENTS: retry=N Prompt user at most N times before returning with error. Default N=1. + difok=N How many characters can be the same in the new + password relative to the old + difignore=N How many characters long should the password be + before we ignore difok. + + minlen=N The minimum simplicity count for a good password. + + dcredit=N + ucredit=N + lcredit=N + ocredit=N Weight, digits, upper, lower, other characters with + count N. Use these values to compute the + 'unsimplicity' of the password. + + use_authtok Get the proposed password from PAM_AUTHTOK + MODULE SERVICES PROVIDED: passwd chauthtok AUTHOR: - Cristian Gafton + Cristian Gafton diff --git a/contrib/libpam/modules/pam_cracklib/pam_cracklib.c b/contrib/libpam/modules/pam_cracklib/pam_cracklib.c index 3400dfb25209..07725db7ee7b 100644 --- a/contrib/libpam/modules/pam_cracklib/pam_cracklib.c +++ b/contrib/libpam/modules/pam_cracklib/pam_cracklib.c @@ -29,8 +29,12 @@ * S.A.G. in the section on the cracklib module. */ +#include + #include -#define __USE_BSD +#ifdef HAVE_CRYPT_H +# include +#endif #include #include #include @@ -43,7 +47,7 @@ extern char *FascistCheck(char *pw, const char *dictpath); #ifndef CRACKLIB_DICTPATH -#define CRACKLIB_DICTPATH "/usr/lib/cracklib_dict" +#define CRACKLIB_DICTPATH "/usr/share/dict/cracklib_dict" #endif #define PROMPT1 "New %s password: " @@ -82,20 +86,31 @@ static void _pam_log(int err, const char *format, ...) /* argument parsing */ #define PAM_DEBUG_ARG 0x0001 -/* module data - AGM: please remove these static variables... PAM was - * designed to be reentrant based soley on a unique pamh... this - * breaks that. */ +struct cracklib_options { + int retry_times; + int diff_ok; + int diff_ignore; + int min_length; + int dig_credit; + int up_credit; + int low_credit; + int oth_credit; + int use_authtok; + char prompt_type[BUFSIZ]; +}; -static int retry_times = 0; -static int diff_ok = 10; -static int min_length = 9; -static int dig_credit = 1; -static int up_credit = 1; -static int low_credit = 1; -static int oth_credit = 1; -static char prompt_type[BUFSIZ]; +#define CO_RETRY_TIMES 1 +#define CO_DIFF_OK 10 +#define CO_DIFF_IGNORE 23 +#define CO_MIN_LENGTH 9 +# define CO_MIN_LENGTH_BASE 5 +#define CO_DIG_CREDIT 1 +#define CO_UP_CREDIT 1 +#define CO_LOW_CREDIT 1 +#define CO_OTH_CREDIT 1 +#define CO_USE_AUTHTOK 0 -static int _pam_parse(int argc, const char **argv) +static int _pam_parse(struct cracklib_options *opt, int argc, const char **argv) { int ctrl=0; @@ -108,35 +123,41 @@ static int _pam_parse(int argc, const char **argv) if (!strcmp(*argv,"debug")) ctrl |= PAM_DEBUG_ARG; else if (!strncmp(*argv,"type=",5)) - strcpy(prompt_type, *argv+5); + strcpy(opt->prompt_type, *argv+5); else if (!strncmp(*argv,"retry=",6)) { - retry_times = strtol(*argv+6,&ep,10); - if (!ep || (retry_times < 1)) - retry_times = 1; + opt->retry_times = strtol(*argv+6,&ep,10); + if (!ep || (opt->retry_times < 1)) + opt->retry_times = CO_RETRY_TIMES; } else if (!strncmp(*argv,"difok=",6)) { - diff_ok = strtol(*argv+6,&ep,10); - if (!ep || (diff_ok < 0)) - diff_ok = 10; + opt->diff_ok = strtol(*argv+6,&ep,10); + if (!ep || (opt->diff_ok < 0)) + opt->diff_ok = CO_DIFF_OK; + } else if (!strncmp(*argv,"difignore=",10)) { + opt->diff_ignore = strtol(*argv+10,&ep,10); + if (!ep || (opt->diff_ignore < 0)) + opt->diff_ignore = CO_DIFF_IGNORE; } else if (!strncmp(*argv,"minlen=",7)) { - min_length = strtol(*argv+7,&ep,10); - if (!ep || (min_length < 5)) - min_length = 5; + opt->min_length = strtol(*argv+7,&ep,10); + if (!ep || (opt->min_length < CO_MIN_LENGTH_BASE)) + opt->min_length = CO_MIN_LENGTH_BASE; } else if (!strncmp(*argv,"dcredit=",8)) { - dig_credit = strtol(*argv+8,&ep,10); - if (!ep || (dig_credit < 0)) - dig_credit = 0; + opt->dig_credit = strtol(*argv+8,&ep,10); + if (!ep || (opt->dig_credit < 0)) + opt->dig_credit = 0; } else if (!strncmp(*argv,"ucredit=",8)) { - up_credit = strtol(*argv+8,&ep,10); - if (!ep || (up_credit < 0)) - up_credit = 0; + opt->up_credit = strtol(*argv+8,&ep,10); + if (!ep || (opt->up_credit < 0)) + opt->up_credit = 0; } else if (!strncmp(*argv,"lcredit=",8)) { - low_credit = strtol(*argv+8,&ep,10); - if (!ep || (low_credit < 0)) - low_credit = 0; + opt->low_credit = strtol(*argv+8,&ep,10); + if (!ep || (opt->low_credit < 0)) + opt->low_credit = 0; } else if (!strncmp(*argv,"ocredit=",8)) { - oth_credit = strtol(*argv+8,&ep,10); - if (!ep || (oth_credit < 0)) - oth_credit = 0; + opt->oth_credit = strtol(*argv+8,&ep,10); + if (!ep || (opt->oth_credit < 0)) + opt->oth_credit = 0; + } else if (!strncmp(*argv,"use_authtok",11)) { + opt->use_authtok = 1; } else { _pam_log(LOG_ERR,"pam_parse: unknown option; %s",*argv); } @@ -216,32 +237,36 @@ static int palindrome(const char *old, const char *new) } /* - * more than half of the characters are different ones. - * or at least diff_ok are different - * NOTE that the defaults are NOT the same as befor this - * change. as long as there are at least 10 different bytes - * in a new password it will now pass even if the password - * is longer than 20 bytes (MD5) + * This is a reasonably severe check for a different selection of characters + * in the old and new passwords. */ -static int similiar(const char *old, const char *new) +static int similar(struct cracklib_options *opt, + const char *old, const char *new) { - int i, j; + int i, j; - for (i = j = 0;new[i] && old[i];i++) - if (strchr (new, old[i])) - j++; + for (i = j = 0; old[i]; i++) { + if (strchr (new, old[i])) { + j++; + } + } - if (j >= diff_ok || i >= j * 2) - return 0; + if (((i-j) >= opt->diff_ok) + || (strlen(new) >= (j * 2)) + || (strlen(new) >= opt->diff_ignore)) { + /* passwords are not very similar */ + return 0; + } - return 1; + /* passwords are too similar */ + return 1; } /* * a nice mix of characters. */ -static int simple(const char *old, const char *new) +static int simple(struct cracklib_options *opt, const char *old, const char *new) { int digits = 0; int uppers = 0; @@ -269,19 +294,19 @@ static int simple(const char *old, const char *new) * defaults cause the effect to be the same as before the change */ - if (digits > dig_credit) - digits = dig_credit; + if (digits > opt->dig_credit) + digits = opt->dig_credit; - if (uppers > up_credit) - uppers = up_credit; + if (uppers > opt->up_credit) + uppers = opt->up_credit; - if (lowers > low_credit) - lowers = low_credit; + if (lowers > opt->low_credit) + lowers = opt->low_credit; - if (others > oth_credit) - others = oth_credit; + if (others > opt->oth_credit) + others = opt->oth_credit; - size = min_length; + size = opt->min_length; size -= digits; size -= uppers; size -= lowers; @@ -302,7 +327,7 @@ static char * str_lower(char *string) return string; } -static const char * password_check(const char *old, const char *new) +static const char * password_check(struct cracklib_options *opt, const char *old, const char *new) { const char *msg = NULL; char *oldmono, *newmono, *wrapped; @@ -324,10 +349,10 @@ static const char * password_check(const char *old, const char *new) if (!msg && strcmp(oldmono, newmono) == 0) msg = "case changes only"; - if (!msg && similiar(oldmono, newmono)) - msg = "is too similiar to the old one"; + if (!msg && similar(opt, oldmono, newmono)) + msg = "is too similar to the old one"; - if (!msg && simple(old, new)) + if (!msg && simple(opt, old, new)) msg = "is too simple"; if (!msg && strstr(wrapped, newmono)) @@ -344,12 +369,51 @@ static const char * password_check(const char *old, const char *new) } +#define OLD_PASSWORDS_FILE "/etc/security/opasswd" + +static const char * check_old_password(const char *forwho, const char *newpass) +{ + static char buf[16384]; + char *s_luser, *s_uid, *s_npas, *s_pas; + const char *msg = NULL; + FILE *opwfile; + + opwfile = fopen(OLD_PASSWORDS_FILE, "r"); + if (opwfile == NULL) + return NULL; + + while (fgets(buf, 16380, opwfile)) { + if (!strncmp(buf, forwho, strlen(forwho))) { + buf[strlen(buf)-1] = '\0'; + s_luser = strtok(buf, ":,"); + s_uid = strtok(NULL, ":,"); + s_npas = strtok(NULL, ":,"); + s_pas = strtok(NULL, ":,"); + while (s_pas != NULL) { + if (!strcmp(crypt(newpass, s_pas), s_pas)) { + msg = "has been already used"; + break; + } + s_pas = strtok(NULL, ":,"); + } + break; + } + } + fclose(opwfile); + + return msg; +} + + static int _pam_unix_approve_pass(pam_handle_t *pamh, unsigned int ctrl, + struct cracklib_options *opt, const char *pass_old, const char *pass_new) { const char *msg = NULL; + const char *user; + int retval; if (pass_new == NULL || (pass_old && !strcmp(pass_old,pass_new))) { if (ctrl && PAM_DEBUG_ARG) @@ -364,7 +428,18 @@ static int _pam_unix_approve_pass(pam_handle_t *pamh, * if one wanted to hardwire authentication token strength * checking this would be the place */ - msg = password_check(pass_old,pass_new); + msg = password_check(opt, pass_old,pass_new); + if (!msg) { + retval = pam_get_item(pamh, PAM_USER, (const void **)&user); + if (retval != PAM_SUCCESS) { + if (ctrl & PAM_DEBUG_ARG) { + _pam_log(LOG_ERR,"Can not get username"); + return PAM_AUTHTOK_ERR; + } + } + msg = check_old_password(user, pass_new); + } + if (msg) { char remark[BUFSIZ]; @@ -387,14 +462,24 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) { unsigned int ctrl; + struct cracklib_options options; + + options.retry_times = CO_RETRY_TIMES; + options.diff_ok = CO_DIFF_OK; + options.diff_ignore = CO_DIFF_IGNORE; + options.min_length = CO_MIN_LENGTH; + options.dig_credit = CO_DIG_CREDIT; + options.up_credit = CO_UP_CREDIT; + options.low_credit = CO_LOW_CREDIT; + options.oth_credit = CO_OTH_CREDIT; + options.use_authtok = CO_USE_AUTHTOK; + memset(options.prompt_type, 0, BUFSIZ); - retry_times = 1; - memset(prompt_type,0,sizeof(prompt_type)); - ctrl = _pam_parse(argc, argv); + ctrl = _pam_parse(&options, argc, argv); D(("called.")); - if (!prompt_type[0]) - strcpy(prompt_type,"UNIX"); + if (!options.prompt_type[0]) + strcpy(options.prompt_type,"UNIX"); if (flags & PAM_PRELIM_CHECK) { /* Check for passwd dictionary */ @@ -421,7 +506,6 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, } else if (flags & PAM_UPDATE_AUTHTOK) { int retval; char *token1, *token2, *oldtoken; - const char *item; struct pam_message msg[1],*pmsg[1]; struct pam_response *resp; const char *cracklib_dictpath = CRACKLIB_DICTPATH; @@ -443,7 +527,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, */ token1 = token2 = NULL; - if (!retry_times) { + if (!options.retry_times) { D(("returning %s because maxtries reached", pam_strerror(pamh, retval))); return retval; @@ -457,33 +541,51 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, * set PAM_AUTHTOK and return */ - /* Prepare to ask the user for the first time */ - memset(prompt,0,sizeof(prompt)); - sprintf(prompt,PROMPT1,prompt_type); - pmsg[0] = &msg[0]; - msg[0].msg_style = PAM_PROMPT_ECHO_OFF; - msg[0].msg = prompt; + if (options.use_authtok == 1) { + const char *item = NULL; - resp = NULL; - retval = converse(pamh, ctrl, 1, pmsg, &resp); - if (resp != NULL) { - /* interpret the response */ - if (retval == PAM_SUCCESS) { /* a good conversation */ - token1 = x_strdup(resp[0].resp); - if (token1 == NULL) { - _pam_log(LOG_NOTICE, - "could not recover authentication token 1"); - retval = PAM_AUTHTOK_RECOVER_ERR; + retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **) &item); + if (retval != PAM_SUCCESS) { + /* very strange. */ + _pam_log(LOG_ALERT + ,"pam_get_item returned error to pam_cracklib" + ); + } else if (item != NULL) { /* we have a password! */ + token1 = x_strdup(item); + item = NULL; + } else { + retval = PAM_AUTHTOK_RECOVER_ERR; /* didn't work */ + } + + } else { + /* Prepare to ask the user for the first time */ + memset(prompt,0,sizeof(prompt)); + sprintf(prompt,PROMPT1,options.prompt_type); + pmsg[0] = &msg[0]; + msg[0].msg_style = PAM_PROMPT_ECHO_OFF; + msg[0].msg = prompt; + + resp = NULL; + retval = converse(pamh, ctrl, 1, pmsg, &resp); + if (resp != NULL) { + /* interpret the response */ + if (retval == PAM_SUCCESS) { /* a good conversation */ + token1 = x_strdup(resp[0].resp); + if (token1 == NULL) { + _pam_log(LOG_NOTICE, + "could not recover authentication token 1"); + retval = PAM_AUTHTOK_RECOVER_ERR; + } } + /* + * tidy up the conversation (resp_retcode) is ignored + */ + _pam_drop_reply(resp, 1); + } else { + retval = (retval == PAM_SUCCESS) ? + PAM_AUTHTOK_RECOVER_ERR:retval ; } - /* - * tidy up the conversation (resp_retcode) is ignored - */ - _pam_drop_reply(resp, 1); - } else { - retval = (retval == PAM_SUCCESS) ? - PAM_AUTHTOK_RECOVER_ERR:retval ; - } + } if (retval != PAM_SUCCESS) { if (ctrl && PAM_DEBUG_ARG) @@ -512,13 +614,14 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, /* check it for strength too... */ D(("for strength")); if (oldtoken) { - retval = _pam_unix_approve_pass(pamh,ctrl, + retval = _pam_unix_approve_pass(pamh,ctrl,&options, oldtoken,token1); - if (retval != PAM_SUCCESS) + if (retval != PAM_SUCCESS) { if (getuid() || (flags & PAM_CHANGE_EXPIRED_AUTHTOK)) retval = PAM_AUTHTOK_ERR; else retval = PAM_SUCCESS; + } } } } @@ -534,77 +637,81 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, } /* Now we have a good passwd. Ask for it once again */ - - bzero(prompt,sizeof(prompt)); - sprintf(prompt,PROMPT2,prompt_type); - pmsg[0] = &msg[0]; - msg[0].msg_style = PAM_PROMPT_ECHO_OFF; - msg[0].msg = prompt; - resp = NULL; - retval = converse(pamh, ctrl, 1, pmsg, &resp); - if (resp != NULL) { - /* interpret the response */ - if (retval == PAM_SUCCESS) { /* a good conversation */ - token2 = x_strdup(resp[0].resp); - if (token2 == NULL) { - _pam_log(LOG_NOTICE, - "could not recover authentication token 2"); - retval = PAM_AUTHTOK_RECOVER_ERR; + if (options.use_authtok == 0) { + bzero(prompt,sizeof(prompt)); + sprintf(prompt,PROMPT2,options.prompt_type); + pmsg[0] = &msg[0]; + msg[0].msg_style = PAM_PROMPT_ECHO_OFF; + msg[0].msg = prompt; + + resp = NULL; + retval = converse(pamh, ctrl, 1, pmsg, &resp); + if (resp != NULL) { + /* interpret the response */ + if (retval == PAM_SUCCESS) { /* a good conversation */ + token2 = x_strdup(resp[0].resp); + if (token2 == NULL) { + _pam_log(LOG_NOTICE, + "could not recover authentication token 2"); + retval = PAM_AUTHTOK_RECOVER_ERR; + } } + /* + * tidy up the conversation (resp_retcode) is ignored + */ + _pam_drop_reply(resp, 1); + } else { + retval = (retval == PAM_SUCCESS) ? + PAM_AUTHTOK_RECOVER_ERR:retval ; } - /* - * tidy up the conversation (resp_retcode) is ignored - */ - _pam_drop_reply(resp, 1); - } else { - retval = (retval == PAM_SUCCESS) ? - PAM_AUTHTOK_RECOVER_ERR:retval ; - } - if (retval != PAM_SUCCESS) { - if (ctrl && PAM_DEBUG_ARG) - _pam_log(LOG_DEBUG - ,"unable to obtain the password a second time"); - continue; - } - - /* Hopefully now token1 and token2 the same password ... */ - if (strcmp(token1,token2) != 0) { - /* tell the user */ - make_remark(pamh, ctrl, PAM_ERROR_MSG, MISTYPED_PASS); - token1 = _pam_delete(token1); - token2 = _pam_delete(token2); - pam_set_item(pamh, PAM_AUTHTOK, NULL); - if (ctrl & PAM_DEBUG_ARG) - _pam_log(LOG_NOTICE,"Password mistyped"); - retval = PAM_AUTHTOK_RECOVER_ERR; - continue; - } - - /* Yes, the password was typed correct twice - * we store this password as an item - */ - - retval = pam_set_item(pamh, PAM_AUTHTOK, token1); - /* clean it up */ - token1 = _pam_delete(token1); - token2 = _pam_delete(token2); - if ( - (retval != PAM_SUCCESS) || - ( - ( - retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&item) - ) != PAM_SUCCESS - ) - ) { - _pam_log(LOG_CRIT, "error manipulating password"); + if (retval != PAM_SUCCESS) { + if (ctrl && PAM_DEBUG_ARG) + _pam_log(LOG_DEBUG + ,"unable to obtain the password a second time"); continue; - } - item = NULL; /* break link to password */ - return PAM_SUCCESS; + } + + /* Hopefully now token1 and token2 the same password ... */ + if (strcmp(token1,token2) != 0) { + /* tell the user */ + make_remark(pamh, ctrl, PAM_ERROR_MSG, MISTYPED_PASS); + token1 = _pam_delete(token1); + token2 = _pam_delete(token2); + pam_set_item(pamh, PAM_AUTHTOK, NULL); + if (ctrl & PAM_DEBUG_ARG) + _pam_log(LOG_NOTICE,"Password mistyped"); + retval = PAM_AUTHTOK_RECOVER_ERR; + continue; + } - } while (retry_times--); + /* Yes, the password was typed correct twice + * we store this password as an item + */ + + { + const char *item = NULL; + + retval = pam_set_item(pamh, PAM_AUTHTOK, token1); + + /* clean up */ + token1 = _pam_delete(token1); + token2 = _pam_delete(token2); + + if ( (retval != PAM_SUCCESS) || + ((retval = pam_get_item(pamh, PAM_AUTHTOK, + (const void **)&item) + ) != PAM_SUCCESS) ) { + _pam_log(LOG_CRIT, "error manipulating password"); + continue; + } + item = NULL; /* break link to password */ + return PAM_SUCCESS; + } + } + + } while (options.retry_times--); } else { if (ctrl & PAM_DEBUG_ARG) diff --git a/contrib/libpam/modules/pam_deny/Makefile b/contrib/libpam/modules/pam_deny/Makefile index 02506cb38122..2fdd6e1111a5 100644 --- a/contrib/libpam/modules/pam_deny/Makefile +++ b/contrib/libpam/modules/pam_deny/Makefile @@ -1,125 +1,15 @@ # -# $Id: Makefile,v 1.7 1997/04/05 06:43:41 morgan Exp morgan $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.7 1997/04/05 06:43:41 morgan -# full-source-tree and fakeroot -# -# Revision 1.6 1997/02/15 19:04:27 morgan -# fixed email -# -# Revision 1.5 1996/11/10 20:11:48 morgan -# crossplatform support -# -# Revision 1.4 1996/09/05 06:50:12 morgan -# ld --> gcc -# -# Revision 1.3 1996/05/26 15:48:38 morgan -# make dynamic and static dirs -# -# Revision 1.2 1996/05/26 04:00:16 morgan -# changes for automated static/dynamic modules -# -# Revision 1.1 1996/03/16 17:47:36 morgan -# Initial revision -# -# -# Created by Andrew Morgan 1996/3/11 +# Created by Andrew Morgan 2000/08/27 # -# Convenient defaults for compiling independently of the full source -# tree. -ifndef FULL_LINUX_PAM_SOURCE_TREE -export DYNAMIC=-DPAM_DYNAMIC -export CC=gcc -export CFLAGS=-O2 -Dlinux -DLINUX_PAM \ - -ansi -D_POSIX_SOURCE -Wall -Wwrite-strings \ - -Wpointer-arith -Wcast-qual -Wcast-align -Wtraditional \ - -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline \ - -Wshadow -pedantic -fPIC -export MKDIR=mkdir -p -export LD_D=gcc -shared -Xlinker -x -endif - -# +include ../../Make.Rules TITLE=pam_deny -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak - -.c.o: - $(CC) $(CFLAGS) -c $< - +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_deny/README b/contrib/libpam/modules/pam_deny/README index 4f7f6de664fe..2eb96d4e35d1 100644 --- a/contrib/libpam/modules/pam_deny/README +++ b/contrib/libpam/modules/pam_deny/README @@ -1,4 +1,4 @@ -# $Id: README,v 1.1 1996/03/16 18:11:12 morgan Exp $ +# $Id: README,v 1.1.1.1 2000/06/20 22:11:33 agmorgan Exp $ # this module always fails, it ignores all options. diff --git a/contrib/libpam/modules/pam_deny/pam_deny.c b/contrib/libpam/modules/pam_deny/pam_deny.c index 76ba24d3fd90..8be1a8a87f55 100644 --- a/contrib/libpam/modules/pam_deny/pam_deny.c +++ b/contrib/libpam/modules/pam_deny/pam_deny.c @@ -1,23 +1,10 @@ /* pam_permit module */ /* - * $Id: pam_deny.c,v 1.4 1997/02/15 19:05:15 morgan Exp $ + * $Id: pam_deny.c,v 1.2 2000/12/04 19:02:34 baggins Exp $ * * Written by Andrew Morgan 1996/3/11 * - * $Log: pam_deny.c,v $ - * Revision 1.4 1997/02/15 19:05:15 morgan - * fixed email - * - * Revision 1.3 1996/06/02 08:06:19 morgan - * changes for new static protocol - * - * Revision 1.2 1996/05/26 04:01:12 morgan - * added static support - * - * Revision 1.1 1996/03/16 17:47:36 morgan - * Initial revision - * */ /* diff --git a/contrib/libpam/modules/pam_env/Makefile b/contrib/libpam/modules/pam_env/Makefile index df363bc9536b..189f1ee3fe6a 100644 --- a/contrib/libpam/modules/pam_env/Makefile +++ b/contrib/libpam/modules/pam_env/Makefile @@ -1,107 +1,22 @@ # -# $Id: Makefile,v 1.1 1997/04/05 06:42:35 morgan Exp morgan $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.1 1997/04/05 06:42:35 morgan -# Initial revision -# -# Revision 1.1 1997/01/04 20:32:52 morgan -# Initial revision -# -# Created by Andrew Morgan 1996/12/8 -# Adaptations by Dave Kinclea and Cristian Gafton -# + +include ../../Make.Rules TITLE=pam_env +LOCAL_CONFILE=./pam_env.conf-example +INSTALLED_CONFILE=$(SCONFIGD)/pam_env.conf -CONFD=$(CONFIGED)/security -export CONFD -CONFILE=$(CONFD)/pam_env.conf -export CONFILE +DEFS=-DDEFAULT_CONF_FILE=\"$(INSTALLED_CONFILE)\" +CFLAGS += $(DEFS) -#ifeq ($(HAVE_PWDBLIB),yes) -#CFLAGS += -DWANT_PWDB -#EXTRALIB = -lpwdb -#endif - -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) $(EXTRALIB) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) $(EXTRALIB) -endif - -install: all -ifdef DYNAMIC - $(MKDIR) $(FAKEROOT)$(SECUREDIR) - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - $(MKDIR) $(FAKEROOT)$(SCONFIGED) - bash -f ./install_conf - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< +MODULE_SIMPLE_INSTALL=bash -f ../install_conf "$(FAKEROOT)" "$(SCONFIGD)" "$(INSTALLED_CONFILE)" "$(TITLE)" "$(LOCAL_CONFILE)" +MODULE_SIMPLE_REMOVE=rm -f $(FAKEROOT)$(INSTALLED_CONFILE) +MODULE_SIMPLE_CLEAN=rm -f ./.ignore_age +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_env/README b/contrib/libpam/modules/pam_env/README index d6e959cdbee5..5053618a7835 100644 --- a/contrib/libpam/modules/pam_env/README +++ b/contrib/libpam/modules/pam_env/README @@ -1,6 +1,6 @@ -# $Date: 1997/04/05 06:42:35 $ -# $Author: morgan $ -# $Id: README,v 1.1 1997/04/05 06:42:35 morgan Exp $ +# $Date: 2000/06/20 22:11:33 $ +# $Author: agmorgan $ +# $Id: README,v 1.1.1.1 2000/06/20 22:11:33 agmorgan Exp $ # # This is the configuration file for pam_env, a PAM module to load in # a configurable list of environment variables for a diff --git a/contrib/libpam/modules/pam_env/pam_env.c b/contrib/libpam/modules/pam_env/pam_env.c index bd0879c52283..5f5aa815e6be 100644 --- a/contrib/libpam/modules/pam_env/pam_env.c +++ b/contrib/libpam/modules/pam_env/pam_env.c @@ -1,59 +1,21 @@ /* pam_mail module */ /* - * $Id: pam_env.c,v 1.1 1997/04/05 06:42:35 morgan Exp morgan $ + * $Id: pam_env.c,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ * * Written by Dave Kinchlea 1997/01/31 * Inspired by Andrew Morgan -#endif +#define DEFAULT_ETC_ENVFILE "/etc/environment" +#define DEFAULT_READ_ENVFILE 1 + +#include #include #include @@ -67,10 +29,6 @@ #include #include -#ifdef WANT_PWDB -#include -#endif - /* * here, we make a definition for the externally accessible function * in this file (this definition is required for static a module @@ -132,11 +90,13 @@ static void _log_err(int err, const char *format, ...) /* argument parsing */ -#define PAM_DEBUG_ARG 01 -#define PAM_NEW_CONF_FILE 02 -#define PAM_ENV_SILENT 04 +#define PAM_DEBUG_ARG 0x01 +#define PAM_NEW_CONF_FILE 0x02 +#define PAM_ENV_SILENT 0x04 +#define PAM_NEW_ENV_FILE 0x10 -static int _pam_parse(int flags, int argc, const char **argv, char **conffile) +static int _pam_parse(int flags, int argc, const char **argv, char **conffile, + char **envfile, int *readenv) { int ctrl=0; @@ -157,9 +117,19 @@ static int _pam_parse(int flags, int argc, const char **argv, char **conffile) _log_err(LOG_CRIT, "Configuration file specification missing argument - ignored"); } - } else { + } else if (!strncmp(*argv,"envfile=",8)) { + *envfile = x_strdup(8+*argv); + if (*envfile != NULL) { + D(("new Env File: %s", *envfile)); + ctrl |= PAM_NEW_ENV_FILE; + } else { + _log_err(LOG_CRIT, + "Env file specification missing argument - ignored"); + } + } else if (!strncmp(*argv,"readenv=",8)) + *readenv = atoi(8+*argv); + else _log_err(LOG_ERR,"pam_parse: unknown option; %s",*argv); - } } return ctrl; @@ -192,7 +162,7 @@ static int _parse_config_file(pam_handle_t *pamh, int ctrl, char **conffile) if ((conf = fopen(file,"r")) == NULL) { _log_err(LOG_ERR, "Unable to open config file: %s", strerror(errno)); - return PAM_ABORT; + return PAM_IGNORE; } /* _pam_assemble_line will provide a complete line from the config file, with all @@ -230,6 +200,88 @@ static int _parse_config_file(pam_handle_t *pamh, int ctrl, char **conffile) return (retval<0?PAM_ABORT:PAM_SUCCESS); } +static int _parse_env_file(pam_handle_t *pamh, int ctrl, char **env_file) +{ + int retval=PAM_SUCCESS, i, t; + const char *file; + char buffer[BUF_SIZE], *key, *mark; + FILE *conf; + + if (ctrl & PAM_NEW_ENV_FILE) + file = *env_file; + else + file = DEFAULT_ETC_ENVFILE; + + D(("Env file name is: %s", file)); + + if ((conf = fopen(file,"r")) == NULL) { + D(("Unable to open env file: %s", strerror(errno))); + return PAM_ABORT; + } + + while (_assemble_line(conf, buffer, BUF_SIZE) > 0) { + D(("Read line: %s", buffer)); + key = buffer; + + /* skip leading white space */ + key += strspn(key, " \n\t"); + + /* skip blanks lines and comments */ + if (!key || key[0] == '#') + continue; + + /* skip over "export " if present so we can be compat with + bash type declerations */ + if (strncmp(key, "export ", (size_t) 7) == 0) + key += 7; + + /* now find the end of value */ + mark = key; + while(mark[0] != '\n' && mark[0] != '#' && mark[0] != '\0') + mark++; + if (mark[0] != '\0') + mark[0] = '\0'; + + /* + * sanity check, the key must be alpha-numeric + */ + + for ( i = 0 ; key[i] != '=' && key[i] != '\0' ; i++ ) + if (!isalnum(key[i]) && key[i] != '_') { + D(("key is not alpha numeric - '%s', ignoring", key)); + continue; + } + + /* now we try to be smart about quotes around the value, + but not too smart, we can't get all fancy with escaped + values like bash */ + if (key[i] == '=' && (key[++i] == '\"' || key[i] == '\'')) { + for ( t = i+1 ; key[t] != '\0' ; t++) + if (key[t] != '\"' && key[t] != '\'') + key[i++] = key[t]; + else if (key[t+1] != '\0') + key[i++] = key[t]; + key[i] = '\0'; + } + + /* set the env var, if it fails, we break out of the loop */ + retval = pam_putenv(pamh, key); + if (retval != PAM_SUCCESS) { + D(("error setting env \"%s\"", key)); + break; + } + } + + (void) fclose(conf); + + /* tidy up */ + _pam_overwrite(*env_file); + _pam_drop(*env_file); + file = NULL; + D(("Exit.")); + return (retval<0?PAM_IGNORE:PAM_SUCCESS); +} + /* * This is where we read a line of the PAM config file. The line may be * preceeded by lines of comments and also extended with "\\\n" @@ -536,7 +588,7 @@ static int _expand_arg(pam_handle_t *pamh, char **value) _log_err(LOG_ERR, "Unterminated expandable variable: <%s>", orig-2); return PAM_ABORT; } - strcpy(tmpval, orig); + strncpy(tmpval, orig, (size_t) BUF_SIZE); orig=ptr; /* * so, we know we need to expand tmpval, it is either @@ -696,18 +748,21 @@ PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) { - int retval, ctrl; - char *conf_file=NULL; - + int retval, ctrl, readenv=DEFAULT_READ_ENVFILE; + char *conf_file=NULL, *env_file=NULL; + /* * this module sets environment variables read in from a file */ D(("Called.")); - ctrl = _pam_parse(flags, argc, argv, &conf_file); - + ctrl = _pam_parse(flags, argc, argv, &conf_file, &env_file, &readenv); + retval = _parse_config_file(pamh, ctrl, &conf_file); - + + if(readenv) + _parse_env_file(pamh, ctrl, &env_file); + /* indicate success or failure */ D(("Exit.")); @@ -726,18 +781,21 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh,int flags,int argc ,const char **argv) { - int retval, ctrl; - char *conf_file=NULL; + int retval, ctrl, readenv=DEFAULT_READ_ENVFILE; + char *conf_file=NULL, *env_file=NULL; /* * this module sets environment variables read in from a file */ D(("Called.")); - ctrl = _pam_parse(flags, argc, argv, &conf_file); + ctrl = _pam_parse(flags, argc, argv, &conf_file, &env_file, &readenv); retval = _parse_config_file(pamh, ctrl, &conf_file); + if(readenv) + _parse_env_file(pamh, ctrl, &env_file); + /* indicate success or failure */ D(("Exit.")); diff --git a/contrib/libpam/modules/pam_env/pam_env.conf-example b/contrib/libpam/modules/pam_env/pam_env.conf-example index 388e8b6b16d4..89637083be4e 100644 --- a/contrib/libpam/modules/pam_env/pam_env.conf-example +++ b/contrib/libpam/modules/pam_env/pam_env.conf-example @@ -1,6 +1,6 @@ -# $Date: 1997/04/05 06:42:35 $ -# $Author: morgan $ -# $Id: pam_env.conf-example,v 1.1 1997/04/05 06:42:35 morgan Exp $ +# $Date: 2000/06/20 22:11:35 $ +# $Author: agmorgan $ +# $Id: pam_env.conf-example,v 1.1.1.1 2000/06/20 22:11:35 agmorgan Exp $ # # This is the configuration file for pam_env, a PAM module to load in # a configurable list of environment variables for a diff --git a/contrib/libpam/modules/pam_filter/Makefile b/contrib/libpam/modules/pam_filter/Makefile index dbd6452ab285..1126aff9b301 100644 --- a/contrib/libpam/modules/pam_filter/Makefile +++ b/contrib/libpam/modules/pam_filter/Makefile @@ -1,24 +1,11 @@ # -# $Id: Makefile,v 1.10 1997/04/05 06:41:09 morgan Exp $ +# $Id: Makefile,v 1.3 2000/12/21 06:06:34 vorlon Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.10 1997/04/05 06:41:09 morgan -# fakeroot -# -# Revision 1.9 1997/02/15 18:58:48 morgan -# fixed bash syntax -# -# Revision 1.8 1997/01/04 20:24:29 morgan -# don't compile on solaris, make -> $(MAKE) -# -# Revision 1.7 1996/11/10 20:12:09 morgan -# cross platform support -# -# Created by Andrew Morgan 1996/3/11 +# Created by Andrew Morgan 1996/3/11 # ifeq ($(OS),solaris) @@ -27,12 +14,14 @@ include ../dont_makefile else +include ../../Make.Rules + TITLE=pam_filter FILTERS=upperLOWER FILTERSDIR=$(SUPLEMENTED)/pam_filter export FILTERSDIR -# +CFLAGS += -Iinclude LIBSRC = $(TITLE).c LIBOBJ = $(TITLE).o @@ -55,10 +44,6 @@ endif ####################### don't edit below ####################### -dummy: - @echo "**** This is not a top-level Makefile " - exit - # # this is where we compile this module # @@ -66,6 +51,7 @@ dummy: all: dirs $(LIBSHARED) $(LIBSTATIC) register filters dirs: + if [ ! -r include/security ]; then ln -sf . include/security ; fi ifdef DYNAMIC $(MKDIR) ./dynamic endif @@ -104,6 +90,15 @@ $(LIBSTATIC): $(LIBOBJS) $(LD) -r -o $@ $(LIBOBJS) endif +remove: + rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so + rm -f $(FAKEROOT)$(INCLUDED)/pam_filter.h + @for i in $(FILTERS) ; do \ + if [ -d $$i ]; then \ + $(MAKE) -C $$i remove ; \ + fi ; \ + done + install: all @for i in $(FILTERS) ; do \ if [ -d $$i ]; then \ @@ -117,34 +112,15 @@ endif $(MKDIR) $(FAKEROOT)$(INCLUDED) $(INSTALL) -m 644 include/pam_filter.h $(FAKEROOT)$(INCLUDED) -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - rm -f $(FAKEROOT)$(INCLUDED)/pam_filter.h - @for i in $(FILTERS) ; do \ - if [ -d $$i ]; then \ - $(MAKE) -C $$i remove ; \ - fi ; \ - done - -lclean: - rm -f $(LIBSHARED) $(LIBOBJD) $(LIBOBJS) core *~ - -clean: lclean +clean: @for i in $(FILTERS) ; do \ if [ -d $$i ]; then \ $(MAKE) -C $$i clean ; \ fi ; \ done - -extraclean: lclean - @rm -f *.a *.o *.so *.bak - for i in $(FILTERS) ; do \ - if [ -d $$i ]; then \ - $(MAKE) -C $$i extraclean ; \ - fi ; \ - done - -.c.o: - $(CC) $(CFLAGS) -c $< + rm -f $(LIBSHARED) $(LIBOBJD) $(LIBOBJS) core *~ + rm -f include/security + rm -fr dynamic static + rm -f *.a *.o *.so *.bak endif diff --git a/contrib/libpam/modules/pam_filter/README b/contrib/libpam/modules/pam_filter/README index 9d46a56e5c9c..12c4aeb5175b 100644 --- a/contrib/libpam/modules/pam_filter/README +++ b/contrib/libpam/modules/pam_filter/README @@ -1,5 +1,5 @@ # -# $Id: README,v 1.5 1996/12/01 02:53:08 morgan Exp $ +# $Id: README,v 1.1.1.1 2000/06/20 22:11:35 agmorgan Exp $ # # This describes the behavior of this module with respect to the # /etc/pam.conf file. diff --git a/contrib/libpam/modules/pam_filter/include/pam_filter.h b/contrib/libpam/modules/pam_filter/include/pam_filter.h index 3eb2730e768b..69e3a3e298ab 100644 --- a/contrib/libpam/modules/pam_filter/include/pam_filter.h +++ b/contrib/libpam/modules/pam_filter/include/pam_filter.h @@ -1,8 +1,8 @@ /* - * $Id: pam_filter.h,v 1.2 1997/02/15 19:09:09 morgan Exp $ + * $Id: pam_filter.h,v 1.1.1.1 2000/06/20 22:11:36 agmorgan Exp $ * * this file is associated with the Linux-PAM filter module. - * it was written by Andrew G. Morgan + * it was written by Andrew G. Morgan * */ diff --git a/contrib/libpam/modules/pam_filter/pam_filter.c b/contrib/libpam/modules/pam_filter/pam_filter.c index fc3d1f2b53fc..3ab2d8670646 100644 --- a/contrib/libpam/modules/pam_filter/pam_filter.c +++ b/contrib/libpam/modules/pam_filter/pam_filter.c @@ -1,24 +1,12 @@ /* - * $Id: pam_filter.c,v 1.9 1997/02/15 19:07:49 morgan Exp morgan $ - * - * $Log: pam_filter.c,v $ - * Revision 1.9 1997/02/15 19:07:49 morgan - * fixed email - * - * Revision 1.8 1996/11/10 20:59:23 morgan - * gcc warning removed - * - * Revision 1.7 1996/07/08 00:01:17 morgan - * set the PAM_TTY item now - * - * Revision 1.6 1996/06/02 08:08:19 morgan - * completely re-written - * + * $Id: pam_filter.c,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ * * written by Andrew Morgan with much help from * Richard Stevens' UNIX Network Programming book. */ +#include + #include #include #include diff --git a/contrib/libpam/modules/pam_filter/upperLOWER/Makefile b/contrib/libpam/modules/pam_filter/upperLOWER/Makefile index 09b693bf6803..92da2479e0a8 100644 --- a/contrib/libpam/modules/pam_filter/upperLOWER/Makefile +++ b/contrib/libpam/modules/pam_filter/upperLOWER/Makefile @@ -1,44 +1,28 @@ # -# $Id: Makefile,v 1.5 1997/04/05 06:41:35 morgan Exp $ -# -# $Log: Makefile,v $ -# Revision 1.5 1997/04/05 06:41:35 morgan -# fakeroot -# -# Revision 1.4 1997/01/04 20:25:04 morgan -# removed need for make -# -# Revision 1.3 1996/11/10 20:13:08 morgan -# email address -# -# Revision 1.2 1996/11/10 20:12:24 morgan -# cross platform support -# -# Revision 1.1 1996/06/02 08:17:02 morgan -# Initial revision -# +# $Id: Makefile,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ # # This directory contains a pam_filter filter executable # -# Created by Andrew Morgan 1996/3/11 +# Created by Andrew Morgan 1996/3/11 # +include ../../../Make.Rules + TITLE=upperLOWER # +CFLAGS += -I../include + OBJS = $(TITLE).o ####################### don't edit below ####################### -dummy: - @echo "**** This is not a top-level Makefile " - all: $(TITLE) $(TITLE): $(OBJS) $(CC) -o $(TITLE) $(OBJS) - strip $(TITLE) + $(STRIP) $(TITLE) install: $(MKDIR) $(FAKEROOT)$(FILTERSDIR) @@ -50,9 +34,6 @@ remove: clean: rm -f $(TITLE) $(OBJS) core *~ -extraclean: clean - rm -f *.bak - .c.o: $(CC) $(CFLAGS) -c $< diff --git a/contrib/libpam/modules/pam_filter/upperLOWER/upperLOWER.c b/contrib/libpam/modules/pam_filter/upperLOWER/upperLOWER.c index b375c0794edf..6178c2797e2e 100644 --- a/contrib/libpam/modules/pam_filter/upperLOWER/upperLOWER.c +++ b/contrib/libpam/modules/pam_filter/upperLOWER/upperLOWER.c @@ -1,17 +1,14 @@ /* - * $Id: upperLOWER.c,v 1.1 1996/06/02 08:17:02 morgan Exp $ + * $Id: upperLOWER.c,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ * * This is a sample filter program, for use with pam_filter (a module * provided with Linux-PAM). This filter simply transposes upper and * lower case letters, it is intended for demonstration purposes and * it serves no purpose other than to annoy the user... - * - * $Log: upperLOWER.c,v $ - * Revision 1.1 1996/06/02 08:17:02 morgan - * Initial revision - * */ +#include + #include #include #include @@ -52,7 +49,9 @@ static void do_transpose(char *buffer,int len) } } -int main(int argc, char **argv, char **envp) +extern char **environ; + +int main(int argc, char **argv) { char buffer[BUFSIZ]; fd_set readers; @@ -64,8 +63,8 @@ int main(int argc, char **argv, char **envp) int i; fprintf(stderr,"environment :[\r\n"); - for (i=0; envp[i]; ++i) { - fprintf(stderr,"-> %s\r\n",envp[i]); + for (i=0; environ[i]; ++i) { + fprintf(stderr,"-> %s\r\n",environ[i]); } fprintf(stderr,"]: end\r\n"); } diff --git a/contrib/libpam/modules/pam_ftp/Makefile b/contrib/libpam/modules/pam_ftp/Makefile index b5355c68b55e..456161bfe597 100644 --- a/contrib/libpam/modules/pam_ftp/Makefile +++ b/contrib/libpam/modules/pam_ftp/Makefile @@ -1,96 +1,15 @@ # -# $Id: Makefile,v 1.2 1997/04/05 06:40:33 morgan Exp $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.2 1997/04/05 06:40:33 morgan -# fakeroot -# -# Revision 1.1 1996/12/01 03:17:57 morgan -# Initial revision -# -# -# Created by Andrew Morgan 1996/11/14 +# Created by Andrew Morgan 2000/08/27 # +include ../../Make.Rules + TITLE=pam_ftp -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< - +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_ftp/README b/contrib/libpam/modules/pam_ftp/README index 597f9120bd86..6d03330c10ed 100644 --- a/contrib/libpam/modules/pam_ftp/README +++ b/contrib/libpam/modules/pam_ftp/README @@ -1,20 +1,18 @@ -# $Id: README,v 1.1 1996/12/01 03:17:57 morgan Exp $ -# +This is the README for pam_ftp +------------------------------ -This module is an authentication module that does not authenticate. -Instead it always returns PAM_IGNORE, indicating that it does not want -to affect the authentication process. - -Its purpose is to log a message to the syslog indicating the -pam_item's available at the time it was invoked. It is a diagnostic -tool. +This module is an authentication module that does simple ftp +authentication. Recognized arguments: - none + "debug" print debug messages + "users=" comma separated list of users which + could login only with email adress + "ignore" allow invalid email adresses -module services provided: +Options for: +auth: for authentication it provides pam_authenticate() and + pam_setcred() hooks. - auth _authetication and _setcred (blank) - -Andrew Morgan +Thorsten Kukuk , 17. June 1999 diff --git a/contrib/libpam/modules/pam_ftp/pam_ftp.c b/contrib/libpam/modules/pam_ftp/pam_ftp.c index ca2d41545e94..3fcbcec8cd54 100644 --- a/contrib/libpam/modules/pam_ftp/pam_ftp.c +++ b/contrib/libpam/modules/pam_ftp/pam_ftp.c @@ -1,17 +1,9 @@ /* pam_ftp module */ /* - * $Id: pam_ftp.c,v 1.2 1997/02/15 16:23:59 morgan Exp morgan $ - * - * Written by Andrew Morgan 1996/3/11 - * - * $Log: pam_ftp.c,v $ - * Revision 1.2 1997/02/15 16:23:59 morgan - * fixed logging to avoid a fixed buffer size - * - * Revision 1.1 1996/12/01 03:17:57 morgan - * Initial revision + * $Id: pam_ftp.c,v 1.2 2000/11/19 23:54:03 agmorgan Exp $ * + * Written by Andrew Morgan 1996/3/11 * */ @@ -22,10 +14,7 @@ /* the following is a password that "can't be correct" */ #define BLOCK_PASSWORD "\177BAD PASSWPRD\177" -#ifdef linux -# define _GNU_SOURCE -# include -#endif +#include #include #include @@ -76,7 +65,7 @@ static int converse(pam_handle_t *pamh, int nargs D(("returned from application's conversation function\n")); - if (retval != PAM_SUCCESS) { + if ((retval != PAM_SUCCESS) && (retval != PAM_CONV_AGAIN)) { _pam_log(LOG_DEBUG, "conversation failure [%s]" , pam_strerror(pamh, retval)); } @@ -211,24 +200,33 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc char *prompt=NULL; int i=0; - mesg[i] = &msg[i]; - msg[i].msg_style = PAM_PROMPT_ECHO_OFF; - if (anon) { - prompt = malloc(sizeof(PLEASE_ENTER_PASSWORD + strlen(user))); - sprintf(prompt, PLEASE_ENTER_PASSWORD, user); - msg[i].msg = prompt; + if (!anon) { + prompt = malloc(strlen(PLEASE_ENTER_PASSWORD) + strlen(user)); + if (prompt == NULL) { + D(("out of memory!?")); + return PAM_BUF_ERR; + } else { + sprintf(prompt, PLEASE_ENTER_PASSWORD, user); + msg[i].msg = prompt; + } } else { msg[i].msg = GUEST_LOGIN_PROMPT; } + msg[i].msg_style = PAM_PROMPT_ECHO_OFF; + mesg[i] = &msg[i]; + retval = converse(pamh, ++i, mesg, &resp); - _pam_overwrite(prompt); - _pam_drop(prompt); + if (prompt) { + _pam_overwrite(prompt); + _pam_drop(prompt); + } if (retval != PAM_SUCCESS) { if (resp != NULL) _pam_drop_reply(resp,i); - return PAM_AUTHINFO_UNAVAIL; + return ((retval == PAM_CONV_AGAIN) + ? PAM_INCOMPLETE:PAM_AUTHINFO_UNAVAIL); } if (anon) { @@ -238,11 +236,15 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc token = strtok(resp->resp, "@"); retval = pam_set_item(pamh, PAM_RUSER, token); - if (token && retval != PAM_SUCCESS) { + if ((token) && (retval == PAM_SUCCESS)) { token = strtok(NULL, "@"); retval = pam_set_item(pamh, PAM_RHOST, token); } } + + /* we are happy to grant annonymous access to the user */ + retval = PAM_SUCCESS; + } else { /* * we have a password so set AUTHTOK diff --git a/contrib/libpam/modules/pam_group/Makefile b/contrib/libpam/modules/pam_group/Makefile index 5db53ccf1133..afa888803315 100644 --- a/contrib/libpam/modules/pam_group/Makefile +++ b/contrib/libpam/modules/pam_group/Makefile @@ -1,114 +1,21 @@ -# -# $Id: Makefile,v 1.6 1997/04/05 06:39:56 morgan Exp morgan $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.6 1997/04/05 06:39:56 morgan -# fakeroot -# -# Revision 1.5 1997/01/04 20:28:47 morgan -# compile with and without libpwdb -# -# Revision 1.4 1996/11/10 20:13:18 morgan -# cross platform support -# -# Created by Andrew Morgan 1996/6/11 -# + +include ../../Make.Rules TITLE=pam_group -CONFD=$(CONFIGED)/security -export CONFD -CONFILE=$(CONFD)/group.conf -export CONFILE - -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -DEFS=-DCONFILE=\"$(CONFILE)\" -ifndef STATIC -ifeq ($(HAVE_PWDBLIB),yes) - DEFS+=-DWANT_PWDB - ELIBS=-lpwdb -endif -endif +LOCAL_CONFILE=./group.conf +INSTALLED_CONFILE=$(SCONFIGD)/group.conf +DEFS=-DDEFAULT_CONF_FILE=\"$(CONFILE)\" CFLAGS += $(DEFS) -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) $(ELIBS) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) $(ELIBS) -endif - -install: all -ifdef DYNAMIC - $(MKDIR) $(FAKEROOT)$(SECUREDIR) - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - $(MKDIR) $(FAKEROOT)$(SCONFIGED) - bash -f ./install_conf - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - rm -f $(FAKEROOT)$(CONFILE) - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - rm -f ./.ignore_age - -extraclean: clean - rm -f *.a *.o *.so *.bak - -.c.o: - $(CC) $(CFLAGS) -c $< +MODULE_SIMPLE_INSTALL=bash -f ../install_conf "$(FAKEROOT)" "$(SCONFIGD)" "$(INSTALLED_CONFILE)" "$(TITLE)" "$(LOCAL_CONFILE)" +MODULE_SIMPLE_REMOVE=rm -f $(FAKEROOT)$(INSTALLED_CONFILE) +MODULE_SIMPLE_CLEAN=rm -f ./.ignore_age +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_group/group.conf b/contrib/libpam/modules/pam_group/group.conf index bdd76adbe68f..e721b9907eea 100644 --- a/contrib/libpam/modules/pam_group/group.conf +++ b/contrib/libpam/modules/pam_group/group.conf @@ -10,7 +10,7 @@ # *** NOT inherently secure. If a user can create an executable that # *** is setgid a group that they are infrequently given membership # *** of, they can basically obtain group membership any time they -# *** like. Example: games are alowed between the hours of 6pm and 6am +# *** like. Example: games are allowed between the hours of 6pm and 6am # *** user joe logs in at 7pm writes a small C-program toplay.c that # *** invokes their favorite shell, compiles it and does # *** "chgrp games toplay; chmod g+s toplay". They are basically able diff --git a/contrib/libpam/modules/pam_group/pam_group.c b/contrib/libpam/modules/pam_group/pam_group.c index 9e2cf885e9cf..2d04119ad88a 100644 --- a/contrib/libpam/modules/pam_group/pam_group.c +++ b/contrib/libpam/modules/pam_group/pam_group.c @@ -1,32 +1,17 @@ /* pam_group module */ /* - * $Id: pam_group.c,v 1.7 1997/02/15 17:31:48 morgan Exp morgan $ + * $Id: pam_group.c,v 1.3 2000/11/26 07:32:39 agmorgan Exp $ * - * Written by Andrew Morgan 1996/7/6 - * - * $Log: pam_group.c,v $ - * Revision 1.7 1997/02/15 17:31:48 morgan - * time parsing more robust - * - * Revision 1.6 1997/01/04 21:57:49 morgan - * fixed warning about setgroups not being defined - * - * Revision 1.5 1997/01/04 20:26:49 morgan - * can be compiled with and without libpwdb. fixed buffer underwriting - * pays attention to PAM_CRED flags(!) - * - * Revision 1.4 1996/12/01 02:54:37 morgan - * mostly debugging now uses D(()) - * - * Revision 1.3 1996/11/10 21:01:22 morgan - * compatability and pam_get_user changes + * Written by Andrew Morgan 1996/7/6 */ const static char rcsid[] = -"$Id: pam_group.c,v 1.7 1997/02/15 17:31:48 morgan Exp morgan $;\n" +"$Id: pam_group.c,v 1.3 2000/11/26 07:32:39 agmorgan Exp $;\n" "Version 0.5 for Linux-PAM\n" -"Copyright (c) Andrew G. Morgan 1996 \n"; +"Copyright (c) Andrew G. Morgan 1996 \n"; + +#define _BSD_SOURCE #include #include @@ -38,17 +23,16 @@ const static char rcsid[] = #include #include -#define __USE_BSD #include #include #include #include -#ifdef WANT_PWDB -#include +#ifdef DEFAULT_CONF_FILE +# define PAM_GROUP_CONF DEFAULT_CONF_FILE /* from external define */ +#else +# define PAM_GROUP_CONF "/etc/security/group.conf" #endif - -#define PAM_GROUP_CONF CONFILE /* from external define */ #define PAM_GROUP_BUFLEN 1000 #define FIELD_SEPARATOR ';' /* this is new as of .02 */ @@ -137,6 +121,7 @@ static int read_field(int fd, char **buf, int *from, int *to) _log_err("error reading " PAM_GROUP_CONF); return -1; } else if (!i) { + close(fd); fd = -1; /* end of file reached */ } else *to += i; @@ -180,6 +165,8 @@ static int read_field(int fd, char **buf, int *from, int *to) if ((*buf)[i+1] == '\n') { shift_bytes(i + *buf, 2, *to - (i+2)); *to -= 2; + } else { + ++i; /* we don't escape non-newline characters */ } break; case '!': @@ -260,7 +247,7 @@ static int logic_member(const char *string, int *at) default: if (isalpha(c) || c == '*' || isdigit(c) || c == '_' - || c == '-' || c == '.') { + || c == '-' || c == '.' || c == '/') { token = 1; } else if (token) { --to; diff --git a/contrib/libpam/modules/pam_issue/Makefile b/contrib/libpam/modules/pam_issue/Makefile new file mode 100644 index 000000000000..1bd2be217db5 --- /dev/null +++ b/contrib/libpam/modules/pam_issue/Makefile @@ -0,0 +1,15 @@ +# +# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ +# +# This Makefile controls a build process of $(TITLE) module for +# Linux-PAM. You should not modify this Makefile (unless you know +# what you are doing!). +# +# Created by Andrew Morgan 2000/08/27 +# + +include ../../Make.Rules + +TITLE=pam_issue + +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_issue/pam_issue.c b/contrib/libpam/modules/pam_issue/pam_issue.c new file mode 100644 index 000000000000..2cb54bec77d6 --- /dev/null +++ b/contrib/libpam/modules/pam_issue/pam_issue.c @@ -0,0 +1,266 @@ +/* pam_issue module - a simple /etc/issue parser to set PAM_USER_PROMPT + * + * Copyright 1999 by Ben Collins + * + * 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_lastlog/Makefile b/contrib/libpam/modules/pam_lastlog/Makefile index e51a72d31f50..e8062714af81 100644 --- a/contrib/libpam/modules/pam_lastlog/Makefile +++ b/contrib/libpam/modules/pam_lastlog/Makefile @@ -1,106 +1,19 @@ # -# $Id: Makefile,v 1.2 1997/04/05 06:17:14 morgan Exp morgan $ +# $Id: Makefile,v 1.3 2001/02/10 22:33:10 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.2 1997/04/05 06:17:14 morgan -# fakeroot fixed -# -# Revision 1.1 1997/01/04 20:29:28 morgan -# Initial revision -# -# -# -# Created by Andrew Morgan 1996/12/8 +# Created by Andrew Morgan 2000/08/27 # -# Convenient defaults for compiling independently of the full source -# tree. -ifndef FULL_LINUX_PAM_SOURCE_TREE -export DYNAMIC=-DPAM_DYNAMIC -export CC=gcc -export CFLAGS=-O2 -Dlinux -DLINUX_PAM \ - -ansi -D_POSIX_SOURCE -Wall -Wwrite-strings \ - -Wpointer-arith -Wcast-qual -Wcast-align -Wtraditional \ - -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline \ - -Wshadow -pedantic -fPIC -export MKDIR=mkdir -p -export LD_D=gcc -shared -Xlinker -x +include ../../Make.Rules + +ifeq ($(HAVE_LIBUTIL),yes) + MODULE_SIMPLE_EXTRALIBS += -lutil endif TITLE=pam_lastlog -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - - -####################### don't edit below ####################### - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< - +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_lastlog/pam_lastlog.c b/contrib/libpam/modules/pam_lastlog/pam_lastlog.c index 96714f6bc16d..385d96405dd7 100644 --- a/contrib/libpam/modules/pam_lastlog/pam_lastlog.c +++ b/contrib/libpam/modules/pam_lastlog/pam_lastlog.c @@ -1,26 +1,17 @@ /* pam_lastlog module */ /* - * $Id: pam_lastlog.c,v 1.3 1997/04/05 06:18:21 morgan Exp morgan $ + * $Id: pam_lastlog.c,v 1.3 2001/02/10 22:33:10 agmorgan Exp $ * - * Written by Andrew Morgan 1996/3/11 + * Written by Andrew Morgan 1996/3/11 * * This module does the necessary work to display the last login * time+date for this user, it then updates this entry for the * present (login) service. - * - * $Log: pam_lastlog.c,v $ - * Revision 1.3 1997/04/05 06:18:21 morgan - * removed xstrdup - unused - * - * Revision 1.2 1997/02/15 17:18:21 morgan - * removed fixed buffer in logging - * - * Revision 1.1 1997/01/04 20:29:28 morgan - * Initial revision - * */ +#include + #include #include #ifdef HAVE_UTMP_H diff --git a/contrib/libpam/modules/pam_limits/Makefile b/contrib/libpam/modules/pam_limits/Makefile index f6a0e07ca48b..695bc02df2f5 100644 --- a/contrib/libpam/modules/pam_limits/Makefile +++ b/contrib/libpam/modules/pam_limits/Makefile @@ -1,102 +1,31 @@ # +# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ +# # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# Created by Cristian Gafton 1996/09/10 -# + +include ../../Make.Rules + +TITLE=pam_limits ifeq ($(OS),linux) -ifeq ($(HAVE_PWDBLIB),yes) -TITLE=pam_limits -CONFD=$(CONFIGED)/security -export CONFD -CONFILE=$(CONFD)/limits.conf -export CONFILE -CFLAGS+=-DLIMITS_FILE=\"$(CONFILE)\" +LOCAL_CONFILE=./limits.skel +INSTALLED_CONFILE=$(SCONFIGD)/limits.conf -# +DEFS=-DDEFAULT_CONF_FILE=\"$(INSTALLED_CONFILE)\" +CFLAGS += $(DEFS) -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) +MODULE_SIMPLE_INSTALL=bash -f ../install_conf "$(FAKEROOT)" "$(SCONFIGD)" "$(INSTALLED_CONFILE)" "$(TITLE)" "$(LOCAL_CONFILE)" +MODULE_SIMPLE_REMOVE=rm -f $(FAKEROOT)$(INSTALLED_CONFILE) +MODULE_SIMPLE_CLEAN=rm -f ./.ignore_age -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -lpwdb -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all -ifdef DYNAMIC - $(MKDIR) $(FAKEROOT)$(SECUREDIR) - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - $(MKDIR) $(FAKEROOT)$(SCONFIGED) - bash -f ./install_conf - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ *.so - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< +include ../Simple.Rules else + include ../dont_makefile -endif -else -include ../dont_makefile + endif diff --git a/contrib/libpam/modules/pam_limits/README b/contrib/libpam/modules/pam_limits/README index 06a6857a8135..2398334b91e7 100644 --- a/contrib/libpam/modules/pam_limits/README +++ b/contrib/libpam/modules/pam_limits/README @@ -4,9 +4,10 @@ pam_limits module: THEORY OF OPERATION: -First, make a root-only-readable file (/etc/limits by default or LIMITS_FILE -defined Makefile) that describes the resource limits you wish to impose. No -limits are imposed on UID 0 accounts. +First, make a root-only-readable file (/etc/security/limits.conf by +default or INSTALLED_CONFILE defined Makefile) that describes the +resource limits you wish to impose. No limits are imposed on UID 0 +accounts. Each line describes a limit for a user in the form: @@ -18,9 +19,10 @@ Where: - a group name, with @group syntax - the wildcard *, for default entry - can have the two values: - - "soft" for enforcinf the soft limits + can have the three values: + - "soft" for enforcing the soft limits - "hard" for enforcing hard limits + - "-" for enforcing both soft and hard limits can be one of the following: - core - limits the core file size (KB) @@ -35,15 +37,18 @@ Where: - as - address space limit - maxlogins - max number of logins for this user - maxsyslogins - max number of logins on the system - -To completely disable limits for a user (or a group), a single dash (-) -will do (Example: 'bin -', '@admin -'). Please remember that individual -limits have priority over group limits, so if you impose no limits for admin -group, but one of the members in this group have a limits line, the user -will have its limits set according to this line. + +Note, if you specify a type of '-' but neglect to supply the item and +value fields then the module will never enforce any limits on the +specified user/group etc. . + +Please remember that individual limits have priority over group +limits, so if you impose no limits for admin group, but one of the +members in this group has a limits line, the user will have its limits +set according to this line. Also, please note that all limit settings are set PER LOGIN. They are -not global, nor are they permanent (the session only) +not global, nor are they permanent (they apply for the session only). In the LIMITS_FILE, the # character introduces a comment - the rest of the line is ignored. @@ -68,6 +73,12 @@ ARGUMENTS RECOGNIZED: conf=/path/to/file the limits configuration file if different from the one set at compile time. + change_uid change real uid to the user for who the limits + are set up. Use this option if you have problems + like login not forking a shell for user who has + no processes. Be warned that something else + may break when you do this. + MODULE SERVICES PROVIDED: session _open_session and _close_session (blank) diff --git a/contrib/libpam/modules/pam_limits/limits.skel b/contrib/libpam/modules/pam_limits/limits.skel index ea57e42513e4..5ddd9b4c38e5 100644 --- a/contrib/libpam/modules/pam_limits/limits.skel +++ b/contrib/libpam/modules/pam_limits/limits.skel @@ -26,6 +26,7 @@ # - nproc - max number of processes # - as - address space limit # - maxlogins - max number of logins for this user +# - priority - the priority to run user process with # # # diff --git a/contrib/libpam/modules/pam_limits/pam_limits.c b/contrib/libpam/modules/pam_limits/pam_limits.c index 179c43028b4e..7a5ec472579c 100644 --- a/contrib/libpam/modules/pam_limits/pam_limits.c +++ b/contrib/libpam/modules/pam_limits/pam_limits.c @@ -1,6 +1,8 @@ /* * pam_limits - impose resource limits when opening a user session * + * 1.6 - modified for PLD (added process priority settings) + * by Marcin Korzonek + #include #include -#define __USE_POSIX2 #include #include #include @@ -26,11 +29,15 @@ #include #include #include + #include #ifndef UT_USER /* some systems have ut_name instead of ut_user */ #define UT_USER ut_user #endif +#include +#include + /* Module defines */ #define LINE_LENGTH 1024 @@ -39,23 +46,28 @@ #define LIMITS_DEF_DEFAULT 2 /* limit was set by an default entry */ #define LIMITS_DEF_NONE 3 /* this limit was not set yet */ -/* internal data */ -static char conf_file[BUFSIZ]; - struct user_limits_struct { int src_soft; int src_hard; struct rlimit limit; }; -static struct user_limits_struct limits[RLIM_NLIMITS]; -static int login_limit; /* the max logins limit */ -static int login_limit_def; /* which entry set the login limit */ -static int flag_numsyslogins; /* whether to limit logins only for a - specific user or to count all logins */ +/* internal data */ +struct pam_limit_s { + int login_limit; /* the max logins limit */ + int login_limit_def; /* which entry set the login limit */ + int flag_numsyslogins; /* whether to limit logins only for a + specific user or to count all logins */ + int priority; /* the priority to run user process with */ + struct user_limits_struct limits[RLIM_NLIMITS]; + char conf_file[BUFSIZ]; +}; #define LIMIT_LOGIN RLIM_NLIMITS+1 #define LIMIT_NUMSYSLOGINS RLIM_NLIMITS+2 + +#define LIMIT_PRI RLIM_NLIMITS+3 + #define LIMIT_SOFT 1 #define LIMIT_HARD 2 @@ -63,7 +75,6 @@ static int flag_numsyslogins; /* whether to limit logins only for a #include #include -#include /* logging */ static void _pam_log(int err, const char *format, ...) @@ -80,8 +91,9 @@ static void _pam_log(int err, const char *format, ...) /* argument parsing */ #define PAM_DEBUG_ARG 0x0001 +#define PAM_DO_SETREUID 0x0002 -static int _pam_parse(int argc, const char **argv) +static int _pam_parse(int argc, const char **argv, struct pam_limit_s *pl) { int ctrl=0; @@ -93,7 +105,9 @@ static int _pam_parse(int argc, const char **argv) if (!strcmp(*argv,"debug")) ctrl |= PAM_DEBUG_ARG; else if (!strncmp(*argv,"conf=",5)) - strcpy(conf_file,*argv+5); + strcpy(pl->conf_file,*argv+5); + else if (!strncmp(*argv,"change_uid",10)) + ctrl |= PAM_DO_SETREUID; else { _pam_log(LOG_ERR,"pam_parse: unknown option; %s",*argv); } @@ -104,15 +118,18 @@ static int _pam_parse(int argc, const char **argv) /* limits stuff */ -#ifndef LIMITS_FILE -#define LIMITS_FILE "/etc/security/limits.conf" +#ifdef DEFAULT_CONF_FILE +# define LIMITS_FILE DEFAULT_CONF_FILE +#else +# define LIMITS_FILE "/etc/security/limits.conf" #endif #define LIMIT_ERR 1 /* error setting a limit */ #define LOGIN_ERR 2 /* too many logins err */ /* Counts the number of user logins and check against the limit*/ -static int check_logins(const char *name, int limit, int ctrl) +static int check_logins(const char *name, int limit, int ctrl, + struct pam_limit_s *pl) { struct utmp *ut; unsigned int count; @@ -137,7 +154,7 @@ static int check_logins(const char *name, int limit, int ctrl) #endif if (ut->UT_USER[0] == '\0') continue; - if (!flag_numsyslogins + if (!pl->flag_numsyslogins && strncmp(name, ut->UT_USER, sizeof(ut->UT_USER)) != 0) continue; if (++count >= limit) @@ -212,65 +229,61 @@ static int is_on_group(const char *user_name, const char *group_name) return 0; } -static int init_limits(void) +static int init_limits(struct pam_limit_s *pl) { + int i; int retval = PAM_SUCCESS; D(("called.")); - retval |= getrlimit(RLIMIT_CPU, &limits[RLIMIT_CPU].limit); - limits[RLIMIT_CPU].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_CPU].src_hard = LIMITS_DEF_NONE; + for(i = 0; i < RLIM_NLIMITS; i++) + retval |= getrlimit(i, &pl->limits[i].limit); + + pl->limits[RLIMIT_CPU].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_CPU].src_hard = LIMITS_DEF_NONE; - retval |= getrlimit(RLIMIT_FSIZE, &limits[RLIMIT_FSIZE].limit); - limits[RLIMIT_FSIZE].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_FSIZE].src_hard = LIMITS_DEF_NONE; + pl->limits[RLIMIT_FSIZE].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_FSIZE].src_hard = LIMITS_DEF_NONE; - retval |= getrlimit(RLIMIT_DATA, &limits[RLIMIT_DATA].limit); - limits[RLIMIT_DATA].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_DATA].src_hard = LIMITS_DEF_NONE; + pl->limits[RLIMIT_DATA].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_DATA].src_hard = LIMITS_DEF_NONE; - retval |= getrlimit(RLIMIT_STACK, &limits[RLIMIT_STACK].limit); - limits[RLIMIT_STACK].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_STACK].src_hard = LIMITS_DEF_NONE; + pl->limits[RLIMIT_STACK].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_STACK].src_hard = LIMITS_DEF_NONE; - retval |= getrlimit(RLIMIT_CORE, &limits[RLIMIT_CORE].limit); - limits[RLIMIT_CORE].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_CORE].src_hard = LIMITS_DEF_NONE; + pl->limits[RLIMIT_CORE].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_CORE].src_hard = LIMITS_DEF_NONE; - retval |= getrlimit(RLIMIT_RSS, &limits[RLIMIT_RSS].limit); - limits[RLIMIT_RSS].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_RSS].src_hard = LIMITS_DEF_NONE; + pl->limits[RLIMIT_RSS].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_RSS].src_hard = LIMITS_DEF_NONE; - retval |= getrlimit(RLIMIT_NPROC, &limits[RLIMIT_NPROC].limit); - limits[RLIMIT_NPROC].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_NPROC].src_hard = LIMITS_DEF_NONE; + pl->limits[RLIMIT_NPROC].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_NPROC].src_hard = LIMITS_DEF_NONE; - retval |= getrlimit(RLIMIT_NOFILE, &limits[RLIMIT_NOFILE].limit); - limits[RLIMIT_NOFILE].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_NOFILE].src_hard = LIMITS_DEF_NONE; + pl->limits[RLIMIT_NOFILE].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_NOFILE].src_hard = LIMITS_DEF_NONE; - retval |= getrlimit(RLIMIT_MEMLOCK, &limits[RLIMIT_MEMLOCK].limit); - limits[RLIMIT_MEMLOCK].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_MEMLOCK].src_hard = LIMITS_DEF_NONE; + pl->limits[RLIMIT_MEMLOCK].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_MEMLOCK].src_hard = LIMITS_DEF_NONE; - retval |= getrlimit(RLIMIT_AS, &limits[RLIMIT_AS].limit); - limits[RLIMIT_AS].src_soft = LIMITS_DEF_NONE; - limits[RLIMIT_AS].src_hard = LIMITS_DEF_NONE; + pl->limits[RLIMIT_AS].src_soft = LIMITS_DEF_NONE; + pl->limits[RLIMIT_AS].src_hard = LIMITS_DEF_NONE; + + pl->priority = 0; + pl->login_limit = -2; + pl->login_limit_def = LIMITS_DEF_NONE; - login_limit = -2; - login_limit_def = LIMITS_DEF_NONE; return retval; } static void process_limit(int source, const char *lim_type, const char *lim_item, const char *lim_value, - int ctrl) + int ctrl, struct pam_limit_s *pl) { int limit_item; int limit_type = 0; long limit_value; - char **endptr = (char **) &lim_value; + const char **endptr = &lim_value; const char *value_orig = lim_value; if (ctrl & PAM_DEBUG_ARG) @@ -299,10 +312,12 @@ static void process_limit(int source, const char *lim_type, limit_item = RLIMIT_AS; else if (strcmp(lim_item, "maxlogins") == 0) { limit_item = LIMIT_LOGIN; - flag_numsyslogins = 0; + pl->flag_numsyslogins = 0; } else if (strcmp(lim_item, "maxsyslogins") == 0) { limit_item = LIMIT_NUMSYSLOGINS; - flag_numsyslogins = 1; + pl->flag_numsyslogins = 1; + } else if (strcmp(lim_item, "priority") == 0) { + limit_item = LIMIT_PRI; } else { _pam_log(LOG_DEBUG,"unknown limit item '%s'", lim_item); return; @@ -349,38 +364,47 @@ static void process_limit(int source, const char *lim_type, break; } - if (limit_item != LIMIT_LOGIN && limit_item != LIMIT_NUMSYSLOGINS) { - if (limit_type & LIMIT_SOFT) - if (limits[limit_item].src_soft < source) + if (limit_item != LIMIT_LOGIN && limit_item != LIMIT_NUMSYSLOGINS + && limit_item != LIMIT_PRI + ) { + if (limit_type & LIMIT_SOFT) { + if (pl->limits[limit_item].src_soft < source) { return; - else { - limits[limit_item].limit.rlim_cur = limit_value; - limits[limit_item].src_soft = source; + } else { + pl->limits[limit_item].limit.rlim_cur = limit_value; + pl->limits[limit_item].src_soft = source; } - if (limit_type & LIMIT_HARD) - if (limits[limit_item].src_hard < source) + } + if (limit_type & LIMIT_HARD) { + if (pl->limits[limit_item].src_hard < source) { return; - else { - limits[limit_item].limit.rlim_max = limit_value; - limits[limit_item].src_hard = source; + } else { + pl->limits[limit_item].limit.rlim_max = limit_value; + pl->limits[limit_item].src_hard = source; } - } else - if (login_limit_def < source) - return; - else { - login_limit = limit_value; - login_limit_def = source; - } - - return; + } + } else + if (limit_item == LIMIT_PRI) { + /* additional check */ + pl->priority = ((limit_value>0)?limit_value:0); + } else { + if (pl->login_limit_def < source) { + return; + } else { + pl->login_limit = limit_value; + pl->login_limit_def = source; + } + } + return; } -static int parse_config_file(const char *uname, int ctrl) +static int parse_config_file(const char *uname, int ctrl, + struct pam_limit_s *pl) { FILE *fil; char buf[LINE_LENGTH]; -#define CONF_FILE (conf_file[0])?conf_file:LIMITS_FILE +#define CONF_FILE (pl->conf_file[0])?pl->conf_file:LIMITS_FILE /* check for the LIMITS_FILE */ if (ctrl & PAM_DEBUG_ARG) _pam_log(LOG_DEBUG,"reading settings from '%s'", CONF_FILE); @@ -428,6 +452,9 @@ static int parse_config_file(const char *uname, int ctrl) memset(value, 0, sizeof(value)); i = sscanf(buf,"%s%s%s%s", domain, ltype, item, value); + D(("scanned line[%d]: domain[%s], ltype[%s], item[%s], value[%s]", + i, domain, ltype, item, value)); + for(j=0; j < strlen(domain); j++) domain[j]=tolower(domain[j]); for(j=0; j < strlen(ltype); j++) @@ -439,36 +466,56 @@ static int parse_config_file(const char *uname, int ctrl) if (i == 4) { /* a complete line */ if (strcmp(uname, domain) == 0) /* this user have a limit */ - process_limit(LIMITS_DEF_USER, ltype, item, value, ctrl); + process_limit(LIMITS_DEF_USER, ltype, item, value, ctrl, pl); else if (domain[0]=='@') { if (is_on_group(uname, domain+1)) - process_limit(LIMITS_DEF_GROUP, ltype, item, value, ctrl); + process_limit(LIMITS_DEF_GROUP, ltype, item, value, ctrl, + pl); } else if (strcmp(domain, "*") == 0) - process_limit(LIMITS_DEF_DEFAULT, ltype, item, value, ctrl); - } else - _pam_log(LOG_DEBUG,"invalid line '%s'", buf); + process_limit(LIMITS_DEF_DEFAULT, ltype, item, value, ctrl, + pl); + } else if (i == 2 && ltype[0] == '-') { /* Probably a no-limit line */ + if (strcmp(uname, domain) == 0) { + _pam_log(LOG_DEBUG, "no limits for '%s'", uname); + fclose(fil); + return PAM_IGNORE; + } else if (domain[0] == '@' && is_on_group(uname, domain+1)) { + _pam_log(LOG_DEBUG, "no limits for '%s' in group '%s'", + uname, domain+1); + fclose(fil); + return PAM_IGNORE; + } + } else { + _pam_log(LOG_DEBUG,"invalid line '%s' - skipped", buf); + } } fclose(fil); return PAM_SUCCESS; } -static int setup_limits(const char * uname, int ctrl) +static int setup_limits(const char * uname, int ctrl, struct pam_limit_s *pl) { int i; int retval = PAM_SUCCESS; for (i=0; i limits[i].limit.rlim_max) - limits[i].limit.rlim_cur = limits[i].limit.rlim_max; - retval |= setrlimit(i, &limits[i].limit); + if (pl->limits[i].limit.rlim_cur > pl->limits[i].limit.rlim_max) + pl->limits[i].limit.rlim_cur = pl->limits[i].limit.rlim_max; + retval |= setrlimit(i, &pl->limits[i].limit); } if (retval != PAM_SUCCESS) retval = LIMIT_ERR; - if (login_limit > 0) { - if (check_logins(uname, login_limit, ctrl) == LOGIN_ERR) + + retval=setpriority(PRIO_PROCESS, 0, pl->priority); + + if (retval != PAM_SUCCESS) + retval = LIMIT_ERR; + + if (pl->login_limit > 0) { + if (check_logins(uname, pl->login_limit, ctrl, pl) == LOGIN_ERR) retval |= LOGIN_ERR; - } else if (login_limit == 0) + } else if (pl->login_limit == 0) retval |= LOGIN_ERR; return retval; } @@ -481,12 +528,13 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, char *user_name; struct passwd *pwd; int ctrl; - + struct pam_limit_s pl; + D(("called.")); - memset(conf_file, 0, sizeof(conf_file)); - - ctrl = _pam_parse(argc, argv); + memset(&pl, 0, sizeof(pl)); + + ctrl = _pam_parse(argc, argv, &pl); retval = pam_get_item( pamh, PAM_USER, (void*) &user_name ); if ( user_name == NULL || retval != PAM_SUCCESS ) { _pam_log(LOG_CRIT, "open_session - error recovering username"); @@ -511,19 +559,25 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, return PAM_SUCCESS; } - retval = init_limits(); + retval = init_limits(&pl); if (retval != PAM_SUCCESS) { - _pam_log(LOG_WARNING, "can not initialize"); + _pam_log(LOG_WARNING, "cannot initialize"); return PAM_IGNORE; } - retval = parse_config_file(pwd->pw_name,ctrl); + retval = parse_config_file(pwd->pw_name, ctrl, &pl); + if (retval == PAM_IGNORE) { + D(("the configuration file has an applicable ' -' entry")); + return PAM_SUCCESS; + } if (retval != PAM_SUCCESS) { _pam_log(LOG_WARNING, "error parsing the configuration file"); return PAM_IGNORE; } - - retval = setup_limits(pwd->pw_name, ctrl); + + if (ctrl & PAM_DO_SETREUID) + setreuid(pwd->pw_uid, -1); + retval = setup_limits(pwd->pw_name, ctrl, &pl); if (retval & LOGIN_ERR) { printf("\nToo many logins for '%s'\n",pwd->pw_name); sleep(2); diff --git a/contrib/libpam/modules/pam_listfile/Makefile b/contrib/libpam/modules/pam_listfile/Makefile index 02940390b333..c5447c949cf7 100644 --- a/contrib/libpam/modules/pam_listfile/Makefile +++ b/contrib/libpam/modules/pam_listfile/Makefile @@ -1,84 +1,15 @@ # +# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ +# # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # +# Created by Andrew Morgan 2000/08/27 +# + +include ../../Make.Rules TITLE=pam_listfile -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< - +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_listfile/pam_listfile.c b/contrib/libpam/modules/pam_listfile/pam_listfile.c index e54b12aaec0c..2f4f3d0bf98a 100644 --- a/contrib/libpam/modules/pam_listfile/pam_listfile.c +++ b/contrib/libpam/modules/pam_listfile/pam_listfile.c @@ -1,39 +1,16 @@ /* - * $Id: pam_listfile.c,v 1.6 1997/04/05 06:38:35 morgan Exp $ - * - * $Log: pam_listfile.c,v $ - * Revision 1.6 1997/04/05 06:38:35 morgan - * reformat mostly - * - * Revision 1.5 1997/02/15 17:29:41 morgan - * removed fixed length buffer in logging - * - * Revision 1.4 1997/01/04 20:32:10 morgan - * ammendments for pam_listfile handling - * - * Revision 1.3 1996/11/10 21:02:08 morgan - * compiles with .53 - * - * Revision 1.2 1996/09/05 06:22:58 morgan - * Michael's patches + * $Id: pam_listfile.c,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ * */ /* - * by Elliot Lee , Red Hat Software. - * July 25, 1996. - * This code shamelessly ripped from the pam_rootok module. + * by Elliot Lee , Red Hat Software. July 25, 1996. + * log refused access error christopher mccrory 1998/7/11 + * + * This code began life as the pam_rootok module. */ -#ifdef linux -# define _SVID_SOURCE -# define _BSD_SOURCE -# define __USE_BSD -# define __USE_SVID -# define __USE_MISC -# define _GNU_SOURCE -# include -#endif +#include #include #include @@ -64,15 +41,15 @@ /* some syslogging */ +#define LOCAL_LOG_PREFIX "PAM-listfile: " + static void _pam_log(int err, const char *format, ...) { va_list args; - + va_start(args, format); - openlog("PAM-listfile", LOG_CONS|LOG_PID, LOG_AUTH); - vsyslog(err, format, args); + vsyslog(LOG_AUTH | err, format, args); va_end(args); - closelog(); } /* checks if a user is on a list of members */ @@ -223,36 +200,41 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar strncpy(apply_val,myval,sizeof(apply_val)-1); } } else { - _pam_log(LOG_ERR,"Unknown option: %s",mybuf); + _pam_log(LOG_ERR,LOCAL_LOG_PREFIX "Unknown option: %s",mybuf); return onerr; } } if(!citem) { - _pam_log(LOG_ERR,"Unknown item or item not specified"); + _pam_log(LOG_ERR, + LOCAL_LOG_PREFIX "Unknown item or item not specified"); return onerr; } else if(!ifname) { - _pam_log(LOG_ERR,"List filename not specified"); + _pam_log(LOG_ERR,LOCAL_LOG_PREFIX "List filename not specified"); return onerr; } else if(sense == 2) { - _pam_log(LOG_ERR,"Unknown sense or sense not specified"); + _pam_log(LOG_ERR, + LOCAL_LOG_PREFIX "Unknown sense or sense not specified"); return onerr; } else if( (apply_type==APPLY_TYPE_NONE) || ((apply_type!=APPLY_TYPE_NULL) && (*apply_val=='\0')) ) { - _pam_log(LOG_ERR,"Invalid usage for apply= parameter"); + _pam_log(LOG_ERR, + LOCAL_LOG_PREFIX "Invalid usage for apply= parameter"); return onerr; } /* Check if it makes sense to use the apply= parameter */ if (apply_type != APPLY_TYPE_NULL) { if((citem==PAM_USER) || (citem==PAM_RUSER)) { - _pam_log(LOG_WARNING,"Non-sense use for apply= parameter"); + _pam_log(LOG_WARNING, + LOCAL_LOG_PREFIX "Non-sense use for apply= parameter"); apply_type=APPLY_TYPE_NULL; } if(extitem && (extitem==EI_GROUP)) { - _pam_log(LOG_WARNING,"Non-sense use for apply= parameter"); + _pam_log(LOG_WARNING, + LOCAL_LOG_PREFIX "Non-sense use for apply= parameter"); apply_type=APPLY_TYPE_NULL; } } @@ -269,7 +251,8 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar if(strcmp(user_name, apply_val)) { /* Does not apply to this user */ #ifdef DEBUG - _pam_log(LOG_DEBUG,"don't apply: apply=%s, user=%s", + _pam_log(LOG_DEBUG, + LOCAL_LOG_PREFIX "don't apply: apply=%s, user=%s", apply_val,user_name); #endif /* DEBUG */ return PAM_IGNORE; @@ -278,7 +261,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar if(!is_on_group(user_name,apply_val)) { /* Not a member of apply= group */ #ifdef DEBUG - _pam_log(LOG_DEBUG,"don't apply: %s not a member of group %s", + _pam_log(LOG_DEBUG, + LOCAL_LOG_PREFIX + "don't apply: %s not a member of group %s", user_name,apply_val); #endif /* DEBUG */ return PAM_IGNORE; @@ -331,18 +316,21 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar endpwent(); break; default: - _pam_log(LOG_ERR,"Internal weirdness, unknown extended item %d", + _pam_log(LOG_ERR, + LOCAL_LOG_PREFIX + "Internal weirdness, unknown extended item %d", extitem); return onerr; } } #ifdef DEBUG - _pam_log(LOG_INFO,"Got file = %s, item = %d, value = %s, sense = %d", + _pam_log(LOG_INFO, + LOCAL_LOG_PREFIX + "Got file = %s, item = %d, value = %s, sense = %d", ifname, citem, citemp, sense); #endif if(lstat(ifname,&fileinfo)) { - _pam_log(LOG_ERR, - "Couldn't open %s",ifname); + _pam_log(LOG_ERR,LOCAL_LOG_PREFIX "Couldn't open %s",ifname); return onerr; } @@ -350,7 +338,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar || !S_ISREG(fileinfo.st_mode)) { /* If the file is world writable or is not a normal file, return error */ - _pam_log(LOG_ERR, + _pam_log(LOG_ERR,LOCAL_LOG_PREFIX "%s is either world writable or not a normal file", ifname); return PAM_AUTH_ERR; @@ -360,7 +348,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar if(inf == NULL) { /* Check that we opened it successfully */ if (onerr == PAM_SERVICE_ERR) { /* Only report if it's an error... */ - _pam_log(LOG_ERR, "Error opening %s", ifname); + _pam_log(LOG_ERR,LOCAL_LOG_PREFIX "Error opening %s", ifname); } return onerr; } @@ -394,19 +382,24 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar } fclose(inf); free(ifname); - if(retval) { + if ((sense && retval) || (!sense && !retval)) { #ifdef DEBUG - syslog(LOG_INFO,"Returning %d, retval = %d", - sense?PAM_AUTH_ERR:PAM_SUCCESS, retval); + _pam_log(LOG_INFO, LOCAL_LOG_PREFIX + "Returning PAM_SUCCESS, retval = %d", retval); #endif - return sense?PAM_SUCCESS:PAM_AUTH_ERR; + return PAM_SUCCESS; } else { + const char *service, *user_name; #ifdef DEBUG - syslog(LOG_INFO,"Returning %d, retval = %d", - sense?PAM_SUCCESS:PAM_AUTH_ERR, retval); + _pam_log(LOG_INFO,LOCAL_LOG_PREFIX + "Returning PAM_AUTH_ERR, retval = %d", retval); #endif - return sense?PAM_AUTH_ERR:PAM_SUCCESS; + (void) pam_get_item(pamh, PAM_SERVICE, (const void **)&service); + (void) pam_get_user(pamh, &user_name, NULL); + _pam_log(LOG_ALERT,LOCAL_LOG_PREFIX "Refused user %s for service %s", + user_name, service); + return PAM_AUTH_ERR; } } diff --git a/contrib/libpam/modules/pam_mail/Makefile b/contrib/libpam/modules/pam_mail/Makefile index 5a402ea4015b..2d9b8e9a30a3 100644 --- a/contrib/libpam/modules/pam_mail/Makefile +++ b/contrib/libpam/modules/pam_mail/Makefile @@ -1,107 +1,15 @@ # -# $Id: Makefile,v 1.3 1997/04/05 06:37:45 morgan Exp $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.3 1997/04/05 06:37:45 morgan -# fakeroot -# -# Revision 1.2 1997/02/15 16:07:22 morgan -# optional libpwdb compilation -# -# Revision 1.1 1997/01/04 20:32:52 morgan -# Initial revision -# -# -# -# Created by Andrew Morgan 1996/12/8 +# Created by Andrew Morgan 2000/08/27 # +include ../../Make.Rules + TITLE=pam_mail -ifndef STATIC -ifeq ($(HAVE_PWDBLIB),yes) -CFLAGS += -DWANT_PWDB -EXTRALIB = -lpwdb -endif -endif - -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) $(EXTRALIB) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) $(EXTRALIB) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< - +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_mail/README b/contrib/libpam/modules/pam_mail/README new file mode 100644 index 000000000000..155bd1db66dc --- /dev/null +++ b/contrib/libpam/modules/pam_mail/README @@ -0,0 +1,17 @@ +This is the README for pam_mail +------------------------------- + +This PAM module tells the User that he has new/unread email. + +Options for: +auth: for authentication it provides pam_authenticate() and + pam_setcred() hooks. + + "debug" write more information to syslog + "dir=maildir" users mailbox is maildir/ + "hash=count" mail directory hash depth + "close" print message also on logout + "nopen" print message not on login + "noenv" don't set the MAIL environment variable + "empty" also print message if user has no mail + diff --git a/contrib/libpam/modules/pam_mail/pam_mail.c b/contrib/libpam/modules/pam_mail/pam_mail.c index 15160f3d5208..df00315ab304 100644 --- a/contrib/libpam/modules/pam_mail/pam_mail.c +++ b/contrib/libpam/modules/pam_mail/pam_mail.c @@ -1,29 +1,14 @@ /* pam_mail module */ /* - * $Id: pam_mail.c,v 1.2 1997/02/15 16:06:14 morgan Exp morgan $ + * $Id: pam_mail.c,v 1.3 2000/12/04 20:59:13 baggins Exp $ * - * Written by Andrew Morgan 1996/3/11 + * Written by Andrew Morgan 1996/3/11 * $HOME additions by David Kinchlea 1997/1/7 - * - * $Log: pam_mail.c,v $ - * Revision 1.2 1997/02/15 16:06:14 morgan - * session -> setcred, also added "~"=$HOME - * - * Revision 1.1 1997/01/04 20:33:02 morgan - * Initial revision + * mailhash additions by Chris Adams 1998/7/11 */ -#define DEFAULT_MAIL_DIRECTORY "/var/spool/mail" -#define MAIL_FILE_FORMAT "%s/%s" -#define MAIL_ENV_NAME "MAIL" -#define MAIL_ENV_FORMAT MAIL_ENV_NAME "=%s" -#define YOUR_MAIL_FORMAT "You have %s mail in %s" - -#ifdef linux -# define _GNU_SOURCE -# include -#endif +#include #include #include @@ -35,11 +20,20 @@ #include #include #include +#include #ifdef WANT_PWDB #include #endif +#define DEFAULT_MAIL_DIRECTORY PAM_PATH_MAILDIR +#define MAIL_FILE_FORMAT "%s%s/%s" +#define MAIL_ENV_NAME "MAIL" +#define MAIL_ENV_FORMAT MAIL_ENV_NAME "=%s" +#define YOUR_MAIL_VERBOSE_FORMAT "You have %s mail in %s." +#define YOUR_MAIL_STANDARD_FORMAT "You have %smail." +#define NO_MAIL_STANDARD_FORMAT "No mail." + /* * here, we make a definition for the externally accessible function * in this file (this definition is required for static a module @@ -47,6 +41,7 @@ * modules include file to define the function prototypes. */ +#define PAM_SM_SESSION #define PAM_SM_AUTH #include @@ -67,16 +62,19 @@ static void _log_err(int err, const char *format, ...) /* argument parsing */ -#define PAM_DEBUG_ARG 01 -#define PAM_NO_LOGIN 02 -#define PAM_LOGOUT_TOO 04 -#define PAM_NEW_MAIL_DIR 010 -#define PAM_MAIL_SILENT 020 -#define PAM_NO_ENV 040 -#define PAM_HOME_MAIL 0100 -#define PAM_EMPTY_TOO 0200 +#define PAM_DEBUG_ARG 0x0001 +#define PAM_NO_LOGIN 0x0002 +#define PAM_LOGOUT_TOO 0x0004 +#define PAM_NEW_MAIL_DIR 0x0010 +#define PAM_MAIL_SILENT 0x0020 +#define PAM_NO_ENV 0x0040 +#define PAM_HOME_MAIL 0x0100 +#define PAM_EMPTY_TOO 0x0200 +#define PAM_STANDARD_MAIL 0x0400 +#define PAM_QUIET_MAIL 0x1000 -static int _pam_parse(int flags, int argc, const char **argv, char **maildir) +static int _pam_parse(int flags, int argc, const char **argv, char **maildir, + int *hashcount) { int ctrl=0; @@ -84,6 +82,8 @@ static int _pam_parse(int flags, int argc, const char **argv, char **maildir) ctrl |= PAM_MAIL_SILENT; } + *hashcount = 0; + /* step through arguments */ for (; argc-- > 0; ++argv) { @@ -91,6 +91,10 @@ static int _pam_parse(int flags, int argc, const char **argv, char **maildir) if (!strcmp(*argv,"debug")) ctrl |= PAM_DEBUG_ARG; + else if (!strcmp(*argv,"quiet")) + ctrl |= PAM_QUIET_MAIL; + else if (!strcmp(*argv,"standard")) + ctrl |= PAM_STANDARD_MAIL | PAM_EMPTY_TOO; else if (!strncmp(*argv,"dir=",4)) { *maildir = x_strdup(4+*argv); if (*maildir != NULL) { @@ -100,6 +104,12 @@ static int _pam_parse(int flags, int argc, const char **argv, char **maildir) _log_err(LOG_CRIT, "failed to duplicate mail directory - ignored"); } + } else if (!strncmp(*argv,"hash=",5)) { + char *ep = NULL; + *hashcount = strtol(*argv+5,&ep,10); + if (!ep || (*hashcount < 0)) { + *hashcount = 0; + } } else if (!strcmp(*argv,"close")) { ctrl |= PAM_LOGOUT_TOO; } else if (!strcmp(*argv,"nopen")) { @@ -113,6 +123,11 @@ static int _pam_parse(int flags, int argc, const char **argv, char **maildir) } } + if ((*hashcount != 0) && !(ctrl & PAM_NEW_MAIL_DIR)) { + *maildir = x_strdup(DEFAULT_MAIL_DIRECTORY); + ctrl |= PAM_NEW_MAIL_DIR; + } + return ctrl; } @@ -150,8 +165,8 @@ static int converse(pam_handle_t *pamh, int ctrl, int nargs return retval; /* propagate error status */ } -static int get_folder(pam_handle_t *pamh, int ctrl - , char **path_mail, char **folder_p) +static int get_folder(pam_handle_t *pamh, int ctrl, + char **path_mail, char **folder_p, int hashcount) { int retval; const char *user, *path; @@ -184,6 +199,9 @@ static int get_folder(pam_handle_t *pamh, int ctrl return PAM_ABORT; } ctrl |= PAM_HOME_MAIL; + if (hashcount != 0) { + _log_err(LOG_ALERT, "can't do hash= and home directory mail"); + } } } else { path = DEFAULT_MAIL_DIRECTORY; @@ -195,14 +213,29 @@ static int get_folder(pam_handle_t *pamh, int ctrl folder = malloc(sizeof(MAIL_FILE_FORMAT) +strlen(pwd->pw_dir)+strlen(path)); } else { - folder = malloc(sizeof(MAIL_FILE_FORMAT)+strlen(path)+strlen(user)); + folder = malloc(sizeof(MAIL_FILE_FORMAT)+strlen(path)+strlen(user) + +2*hashcount); } if (folder != NULL) { if (ctrl & PAM_HOME_MAIL) { - sprintf(folder, MAIL_FILE_FORMAT, pwd->pw_dir, path); + sprintf(folder, MAIL_FILE_FORMAT, pwd->pw_dir, "", path); } else { - sprintf(folder, MAIL_FILE_FORMAT, path, user); + int i; + char *hash = malloc(2*hashcount+1); + + if (hash) { + for (i = 0; i < hashcount; i++) { + hash[2*i] = '/'; + hash[2*i+1] = user[i]; + } + hash[2*i] = '\0'; + sprintf(folder, MAIL_FILE_FORMAT, path, hash, user); + _pam_overwrite(hash); + _pam_drop(hash); + } else { + sprintf(folder, "error"); + } } D(("folder =[%s]", folder)); } @@ -226,17 +259,52 @@ static int get_folder(pam_handle_t *pamh, int ctrl static const char *get_mail_status(int ctrl, const char *folder) { - const char *type; + const char *type = NULL; + static char dir[256]; struct stat mail_st; + struct dirent **namelist; + int i; - if (stat(folder, &mail_st) == 0 && mail_st.st_size > 0) { - type = (mail_st.st_atime < mail_st.st_mtime) ? "new":"old" ; - } else if (ctrl & PAM_EMPTY_TOO) { - type = "no"; - } else { - type = NULL; + if (stat(folder, &mail_st) == 0) { + if (S_ISDIR(mail_st.st_mode)) { /* Assume Maildir format */ + sprintf(dir, "%.250s/new", folder); + i = scandir(dir, &namelist, 0, alphasort); + if (i > 2) { + type = "new"; + while (--i) + free(namelist[i]); + } else { + while (--i >= 0) + free(namelist[i]); + sprintf(dir, "%.250s/cur", folder); + i = scandir(dir, &namelist, 0, alphasort); + if (i > 2) { + type = "old"; + while (--i) + free(namelist[i]); + } else if (ctrl & PAM_EMPTY_TOO) { + while (--i >= 0) + free(namelist[i]); + type = "no"; + } else { + type = NULL; + } + } + } else { + if (mail_st.st_size > 0) { + if (mail_st.st_atime < mail_st.st_mtime) /* new */ + type = (ctrl & PAM_STANDARD_MAIL) ? "new " : "new"; + else /* old */ + type = (ctrl & PAM_STANDARD_MAIL) ? "" : "old"; + } else if (ctrl & PAM_EMPTY_TOO) { + type = "no"; + } else { + type = NULL; + } + } } + memset(dir, 0, 256); memset(&mail_st, 0, sizeof(mail_st)); D(("user has %s mail in %s folder", type, folder)); return type; @@ -247,17 +315,29 @@ static int report_mail(pam_handle_t *pamh, int ctrl { int retval; - if (!(ctrl & PAM_MAIL_SILENT)) { + if (!(ctrl & PAM_MAIL_SILENT) || ((ctrl & PAM_QUIET_MAIL) && strcmp(type, "new"))) { char *remark; - remark = malloc(sizeof(YOUR_MAIL_FORMAT)+strlen(type)+strlen(folder)); + if (ctrl & PAM_STANDARD_MAIL) + if (!strcmp(type, "no")) + remark = malloc(strlen(NO_MAIL_STANDARD_FORMAT)+1); + else + remark = malloc(strlen(YOUR_MAIL_STANDARD_FORMAT)+strlen(type)+1); + else + remark = malloc(strlen(YOUR_MAIL_VERBOSE_FORMAT)+strlen(type)+strlen(folder)+1); if (remark == NULL) { retval = PAM_BUF_ERR; } else { struct pam_message msg[1], *mesg[1]; struct pam_response *resp=NULL; - sprintf(remark, YOUR_MAIL_FORMAT, type, folder); + if (ctrl & PAM_STANDARD_MAIL) + if (!strcmp(type, "no")) + sprintf(remark, NO_MAIL_STANDARD_FORMAT); + else + sprintf(remark, YOUR_MAIL_STANDARD_FORMAT, type); + else + sprintf(remark, YOUR_MAIL_VERBOSE_FORMAT, type, folder); mesg[0] = &msg[0]; msg[0].msg_style = PAM_TEXT_INFO; @@ -279,28 +359,51 @@ static int report_mail(pam_handle_t *pamh, int ctrl return retval; } -/* --- authentication management functions (only) --- */ +static int _do_mail(pam_handle_t *, int, int, const char **, int); -/* - * Cannot use mail to authenticate yourself - */ +/* --- authentication functions --- */ PAM_EXTERN -int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc - ,const char **argv) +int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc, + const char **argv) { return PAM_IGNORE; } -/* - * MAIL is a "credential" - */ +/* Checking mail as part of authentication */ +PAM_EXTERN +int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + if (!(flags & (PAM_ESTABLISH_CRED|PAM_DELETE_CRED))) + return PAM_IGNORE; + return _do_mail(pamh,flags,argc,argv,(flags & PAM_ESTABLISH_CRED)); +} + +/* --- session management functions --- */ PAM_EXTERN -int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc - , const char **argv) +int pam_sm_close_session(pam_handle_t *pamh,int flags,int argc + ,const char **argv) { - int retval, ctrl; + return _do_mail(pamh,flags,argc,argv,0);; +} + +/* Checking mail as part of the session management */ +PAM_EXTERN +int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + return _do_mail(pamh,flags,argc,argv,1); +} + + +/* --- The Beaf (Tm) --- */ + +static int _do_mail(pam_handle_t *pamh, int flags, int argc, + const char **argv, int est) +{ + int retval, ctrl, hashcount; char *path_mail=NULL, *folder; const char *type; @@ -309,17 +412,16 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc * the user has any new mail. */ - ctrl = _pam_parse(flags, argc, argv, &path_mail); + ctrl = _pam_parse(flags, argc, argv, &path_mail, &hashcount); /* Do we have anything to do? */ - if (!(flags & (PAM_ESTABLISH_CRED|PAM_DELETE_CRED))) { + if (flags & PAM_SILENT) return PAM_SUCCESS; - } /* which folder? */ - retval = get_folder(pamh, ctrl, &path_mail, &folder); + retval = get_folder(pamh, ctrl, &path_mail, &folder, hashcount); if (retval != PAM_SUCCESS) { D(("failed to find folder")); return retval; @@ -327,7 +429,7 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc /* set the MAIL variable? */ - if (!(ctrl & PAM_NO_ENV) && (flags & PAM_ESTABLISH_CRED)) { + if (!(ctrl & PAM_NO_ENV) && est) { char *tmp; tmp = malloc(strlen(folder)+sizeof(MAIL_ENV_FORMAT)); @@ -357,24 +459,20 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc * OK. we've got the mail folder... what about its status? */ - if (((flags & PAM_ESTABLISH_CRED) && !(ctrl & PAM_NO_LOGIN)) - || ((flags & PAM_DELETE_CRED) && (ctrl & PAM_LOGOUT_TOO))) { + if ((est && !(ctrl & PAM_NO_LOGIN)) + || (!est && (ctrl & PAM_LOGOUT_TOO))) { type = get_mail_status(ctrl, folder); if (type != NULL) { retval = report_mail(pamh, ctrl, type, folder); type = NULL; } } - - /* - * Delete environment variable? - */ - - if (flags & PAM_DELETE_CRED) { + + /* Delete environment variable? */ + if (!est) (void) pam_putenv(pamh, MAIL_ENV_NAME); - } - _pam_overwrite(folder); /* clean up */ + _pam_overwrite(folder); /* clean up */ _pam_drop(folder); /* indicate success or failure */ @@ -391,8 +489,8 @@ struct pam_module _pam_mail_modstruct = { pam_sm_authenticate, pam_sm_setcred, NULL, - NULL, - NULL, + pam_sm_open_session, + pam_sm_close_session, NULL, }; diff --git a/contrib/libpam/modules/pam_mkhomedir/Makefile b/contrib/libpam/modules/pam_mkhomedir/Makefile new file mode 100644 index 000000000000..f017f4a469ec --- /dev/null +++ b/contrib/libpam/modules/pam_mkhomedir/Makefile @@ -0,0 +1,15 @@ +# +# $Id: Makefile,v 1.3 2000/11/19 23:54:04 agmorgan Exp $ +# +# This Makefile controls a build process of $(TITLE) module for +# Linux-PAM. You should not modify this Makefile (unless you know +# what you are doing!). +# +# Created by Andrew Morgan 2000/08/27 +# + +include ../../Make.Rules + +TITLE=pam_mkhomedir + +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_mkhomedir/pam_mkhomedir.c b/contrib/libpam/modules/pam_mkhomedir/pam_mkhomedir.c new file mode 100644 index 000000000000..ec05993dfa1e --- /dev/null +++ b/contrib/libpam/modules/pam_mkhomedir/pam_mkhomedir.c @@ -0,0 +1,370 @@ +/* PAM Make Home Dir module + + This module will create a users home directory if it does not exist + when the session begins. This allows users to be present in central + database (such as nis, kerb or ldap) without using a distributed + file system or pre-creating a large number of directories. + + Here is a sample /etc/pam.d/login file for Debian GNU/Linux + 2.1: + + auth requisite pam_securetty.so + auth sufficient pam_ldap.so + auth required pam_pwdb.so + auth optional pam_group.so + auth optional pam_mail.so + account requisite pam_time.so + account sufficient pam_ldap.so + account required pam_pwdb.so + session required pam_mkhomedir.so skel=/etc/skel/ umask=0022 + session required pam_pwdb.so + session optional pam_lastlog.so + password required pam_pwdb.so + + Released under the GNU LGPL version 2 or later + Originally written by Jason Gunthorpe 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 000000000000..fb83807a36da --- /dev/null +++ b/contrib/libpam/modules/pam_motd/Makefile @@ -0,0 +1,15 @@ +# +# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ +# +# This Makefile controls a build process of $(TITLE) module for +# Linux-PAM. You should not modify this Makefile (unless you know +# what you are doing!). +# +# Created by Andrew Morgan 2000/08/27 +# + +include ../../Make.Rules + +TITLE=pam_motd + +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_motd/pam_motd.c b/contrib/libpam/modules/pam_motd/pam_motd.c new file mode 100644 index 000000000000..2434b2986c9b --- /dev/null +++ b/contrib/libpam/modules/pam_motd/pam_motd.c @@ -0,0 +1,119 @@ +/* pam_motd module */ + +/* + * Modified for pam_motd by Ben Collins + * + * 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_nologin/Makefile b/contrib/libpam/modules/pam_nologin/Makefile index 0769bb993120..2ad38ffd9609 100644 --- a/contrib/libpam/modules/pam_nologin/Makefile +++ b/contrib/libpam/modules/pam_nologin/Makefile @@ -1,86 +1,15 @@ # +# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ +# # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# Michael K. Johnson 1996/10/24 +# Created by Andrew Morgan 2000/08/27 # +include ../../Make.Rules + TITLE=pam_nologin -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - mkdir -p ./dynamic -endif -ifdef STATIC - mkdir -p ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - mkdir -p $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - install -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< - +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_nologin/README b/contrib/libpam/modules/pam_nologin/README index ab7ccd7d9803..9b00e6923868 100644 --- a/contrib/libpam/modules/pam_nologin/README +++ b/contrib/libpam/modules/pam_nologin/README @@ -1,4 +1,4 @@ -# $Id: README,v 1.1 1996/10/25 03:19:36 morgan Exp $ +# $Id: README,v 1.1.1.1 2000/06/20 22:11:46 agmorgan Exp $ # This module always lets root in; it lets other users in only if the file diff --git a/contrib/libpam/modules/pam_nologin/pam_nologin.c b/contrib/libpam/modules/pam_nologin/pam_nologin.c index 2788dcf8f39a..1359c18bfaf6 100644 --- a/contrib/libpam/modules/pam_nologin/pam_nologin.c +++ b/contrib/libpam/modules/pam_nologin/pam_nologin.c @@ -1,24 +1,10 @@ /* pam_nologin module */ /* - * $Id: pam_nologin.c,v 1.4 1997/04/05 06:36:47 morgan Exp morgan $ + * $Id: pam_nologin.c,v 1.2 2000/12/04 19:02:34 baggins Exp $ * * Written by Michael K. Johnson 1996/10/24 * - * $Log: pam_nologin.c,v $ - * Revision 1.4 1997/04/05 06:36:47 morgan - * display message when the user is unknown - * - * Revision 1.3 1996/12/01 03:00:54 morgan - * added prototype to conversation, gave static structure name of module - * - * Revision 1.2 1996/11/10 21:02:31 morgan - * compile against .53 - * - * Revision 1.1 1996/10/25 03:19:36 morgan - * Initial revision - * - * */ #include diff --git a/contrib/libpam/modules/pam_permit/Makefile b/contrib/libpam/modules/pam_permit/Makefile index 823b62472e35..49f3b3dd5e20 100644 --- a/contrib/libpam/modules/pam_permit/Makefile +++ b/contrib/libpam/modules/pam_permit/Makefile @@ -1,126 +1,15 @@ # -# $Id: Makefile,v 1.8 1997/04/05 06:33:25 morgan Exp morgan $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.8 1997/04/05 06:33:25 morgan -# fakeroot -# -# Revision 1.7 1997/02/15 19:02:27 morgan -# updated email address -# -# Revision 1.6 1996/11/10 20:14:34 morgan -# cross platform support -# -# Revision 1.5 1996/09/05 06:32:45 morgan -# ld --> gcc -# -# Revision 1.4 1996/05/26 15:49:25 morgan -# make dynamic and static dirs -# -# Revision 1.3 1996/05/26 04:04:26 morgan -# automated static support -# -# Revision 1.2 1996/03/16 17:56:38 morgan -# tidied up -# -# -# Created by Andrew Morgan 1996/3/11 +# Created by Andrew Morgan 2000/08/27 # -# Convenient defaults for compiling independently of the full source -# tree. -ifndef FULL_LINUX_PAM_SOURCE_TREE -export DYNAMIC=-DPAM_DYNAMIC -export CC=gcc -export CFLAGS=-O2 -Dlinux -DLINUX_PAM \ - -ansi -D_POSIX_SOURCE -Wall -Wwrite-strings \ - -Wpointer-arith -Wcast-qual -Wcast-align -Wtraditional \ - -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline \ - -Wshadow -pedantic -fPIC -export MKDIR=mkdir -p -export LD_D=gcc -shared -Xlinker -x -endif - -# -# +include ../../Make.Rules TITLE=pam_permit -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(TARGET_ARCH) -c $< -o $@ - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) -endif - -ifdef DYNAMIC -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) -endif - -ifdef STATIC -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak - -.c.o: - $(CC) $(CFLAGS) -c $< - +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_permit/README b/contrib/libpam/modules/pam_permit/README index da179a34829c..52e7364e8753 100644 --- a/contrib/libpam/modules/pam_permit/README +++ b/contrib/libpam/modules/pam_permit/README @@ -1,4 +1,4 @@ -# $Id: README,v 1.1 1996/03/16 18:12:51 morgan Exp $ +# $Id: README,v 1.1.1.1 2000/06/20 22:11:46 agmorgan Exp $ # this module always returns PAM_SUCCESS, it ignores all options. diff --git a/contrib/libpam/modules/pam_permit/pam_permit.c b/contrib/libpam/modules/pam_permit/pam_permit.c index 1bdd5644a63b..46e36eb97c24 100644 --- a/contrib/libpam/modules/pam_permit/pam_permit.c +++ b/contrib/libpam/modules/pam_permit/pam_permit.c @@ -1,20 +1,10 @@ /* pam_permit module */ /* - * $Id: pam_permit.c,v 1.5 1997/02/15 19:03:15 morgan Exp $ + * $Id: pam_permit.c,v 1.2 2000/12/04 19:02:34 baggins Exp $ * * Written by Andrew Morgan 1996/3/11 * - * $Log: pam_permit.c,v $ - * Revision 1.5 1997/02/15 19:03:15 morgan - * fixed email address - * - * Revision 1.4 1997/02/15 16:03:10 morgan - * force a name for user - * - * Revision 1.3 1996/06/02 08:10:14 morgan - * updated for new static protocol - * */ #define DEFAULT_USER "nobody" diff --git a/contrib/libpam/modules/pam_pwdb/BUGS b/contrib/libpam/modules/pam_pwdb/BUGS index 397f367b5372..d51686e51d76 100644 --- a/contrib/libpam/modules/pam_pwdb/BUGS +++ b/contrib/libpam/modules/pam_pwdb/BUGS @@ -1,8 +1,3 @@ -$Id: BUGS,v 1.2 1996/09/05 06:36:16 morgan Exp $ - -$Log: BUGS,v $ -Revision 1.2 1996/09/05 06:36:16 morgan -revised for .52 to be released - +$Id: BUGS,v 1.2 2000/12/04 19:02:34 baggins Exp $ As of Linux-PAM-0.52 this is new. No known bugs yet. diff --git a/contrib/libpam/modules/pam_pwdb/CHANGELOG b/contrib/libpam/modules/pam_pwdb/CHANGELOG index 0cb21879120b..a36140319933 100644 --- a/contrib/libpam/modules/pam_pwdb/CHANGELOG +++ b/contrib/libpam/modules/pam_pwdb/CHANGELOG @@ -1,4 +1,4 @@ -$Header: /home/morgan/pam/Linux-PAM-0.52/modules/pam_unix/RCS/CHANGELOG,v 1.1 1996/08/29 13:23:29 morgan Exp $ +$Id: CHANGELOG,v 1.1.1.1 2000/06/20 22:11:46 agmorgan Exp $ Tue Apr 23 12:28:09 EDT 1996 (Alexander O. Yuriev alex@bach.cis.temple.edu) diff --git a/contrib/libpam/modules/pam_pwdb/Makefile b/contrib/libpam/modules/pam_pwdb/Makefile index 7428bb439040..ec66f9e8269c 100644 --- a/contrib/libpam/modules/pam_pwdb/Makefile +++ b/contrib/libpam/modules/pam_pwdb/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.7 1997/04/05 06:28:50 morgan Exp morgan $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $ # # This Makefile controls a build process of the pam_unix module # for Linux-PAM. You should not modify this Makefile. @@ -7,42 +7,20 @@ # 1996/11/6 # -# -# Note, the STATIC module is commented out because it doesn't work. -# please fix! -# +include ../../Make.Rules -ifndef FULL_LINUX_PAM_SOURCE_TREE -export DYNAMIC=-DPAM_DYNAMIC -export CC=gcc -export CFLAGS=-O2 -Dlinux -DLINUX_PAM \ - -ansi -D_POSIX_SOURCE -Wall -Wwrite-strings \ - -Wpointer-arith -Wcast-qual -Wcast-align -Wtraditional \ - -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline \ - -Wshadow -pedantic -fPIC -export MKDIR=mkdir -p -export LD_D=gcc -shared -Xlinker -x -export HAVE_PWDBLIB=yes +ifeq ($(HAVE_LIBPWDB),yes) + +EXTRALS += -lpwdb +EXTRAS += -DCHKPWD_HELPER=\"$(SUPLEMENTED)/$(CHKPWD)\" + +ifeq ($(HAVE_LIBCRYPT),yes) + EXTRALS += -lcrypt endif -ifeq ($(HAVE_PWDBLIB),yes) - TITLE=pam_pwdb CHKPWD=pwdb_chkpwd -# compilation flags -EXTRAS= -# extra object files -PLUS= -# extra files that may be needed to be created -CREATE= - -# NOTE: this module links dynamically to the libpwdb library. -EXTRALS += -lpwdb -EXTRAS += -DCHKPWD_HELPER=\"$(SUPLEMENTED)/$(CHKPWD)\" - -########################### don't edit below ########################## - LIBSRC = $(TITLE).c LIBOBJ = $(TITLE).o LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) @@ -50,7 +28,7 @@ LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) LIBDEPS = pam_unix_acct.-c pam_unix_auth.-c pam_unix_passwd.-c \ pam_unix_sess.-c pam_unix_pwupd.-c support.-c bigcrypt.-c -PLUS += md5.o md5_crypt.o +PLUS += md5_good.o md5_broken.o md5_crypt_good.o md5_crypt_broken.o CFLAGS += $(EXTRAS) ifdef DYNAMIC @@ -73,11 +51,28 @@ info: @echo "*** Building PAM_pwdb module..." @echo -$(CHKPWD): pwdb_chkpwd.o md5.o md5_crypt.o +$(CHKPWD): pwdb_chkpwd.o md5_good.o md5_broken.o \ + md5_crypt_good.o md5_crypt_broken.o $(CC) -o $(CHKPWD) $^ -lpwdb pwdb_chkpwd.o: pwdb_chkpwd.c pam_unix_md.-c bigcrypt.-c +md5_good.o: md5.c + $(CC) $(CFLAGS) $(CPPFLAGS) -DHIGHFIRST -D'MD5Name(x)=Good##x' \ + $(TARGET_ARCH) -c $< -o $@ + +md5_broken.o: md5.c + $(CC) $(CFLAGS) $(CPPFLAGS) -D'MD5Name(x)=Broken##x' \ + $(TARGET_ARCH) -c $< -o $@ + +md5_crypt_good.o: md5_crypt.c + $(CC) $(CFLAGS) $(CPPFLAGS) -D'MD5Name(x)=Good##x' \ + $(TARGET_ARCH) -c $< -o $@ + +md5_crypt_broken.o: md5_crypt.c + $(CC) $(CFLAGS) $(CPPFLAGS) -D'MD5Name(x)=Broken##x' \ + $(TARGET_ARCH) -c $< -o $@ + dirs: ifdef DYNAMIC @$(MKDIR) ./dynamic @@ -111,7 +106,7 @@ ifdef DYNAMIC $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) endif $(MKDIR) $(FAKEROOT)$(SUPLEMENTED) - $(INSTALL) -m 4555 -o root -g root $(CHKPWD) $(FAKEROOT)$(SUPLEMENTED) + $(INSTALL) -m 4555 $(CHKPWD) $(FAKEROOT)$(SUPLEMENTED) remove: rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so @@ -119,37 +114,11 @@ remove: clean: rm -f $(CHKPWD) $(LIBOBJD) $(LIBOBJS) $(MOREDELS) core *~ *.o *.so - -extraclean: clean rm -f *.a *.o *.so *.bak + rm -fr dynamic static else include ../dont_makefile endif - -##################################################################### -# $Log: Makefile,v $ -# Revision 1.7 1997/04/05 06:28:50 morgan -# fakeroot -# -# Revision 1.6 1997/02/15 17:25:32 morgan -# update for .56 . extra commands for new helper binary -# -# Revision 1.5 1997/01/04 20:39:08 morgan -# conditional on having libpwdb -# -# Revision 1.4 1996/12/01 03:02:03 morgan -# changed banner, removed linking libraries -# -# Revision 1.3 1996/11/10 20:14:42 morgan -# cross platform support -# -# Revision 1.2 1996/09/05 06:36:49 morgan -# options added and use of LD altered -# -# Revision 1.1 1996/08/29 13:23:29 morgan -# Initial revision -# -# diff --git a/contrib/libpam/modules/pam_pwdb/README b/contrib/libpam/modules/pam_pwdb/README index 351a706008e9..4f420855cded 100644 --- a/contrib/libpam/modules/pam_pwdb/README +++ b/contrib/libpam/modules/pam_pwdb/README @@ -7,7 +7,7 @@ passwords. the license suggests -- use at your own risk.] So far as I am concerned this module is now pretty stable. If you find -any bugs, PLEASE tell me! +any bugs, PLEASE tell me! Options recognized by this module are as follows: @@ -38,4 +38,4 @@ should read the source to find the appropriate #define that you will need. --------------------- -Andrew Morgan +Andrew Morgan diff --git a/contrib/libpam/modules/pam_pwdb/TODO b/contrib/libpam/modules/pam_pwdb/TODO index 23eb4c163d08..520a262ec13c 100644 --- a/contrib/libpam/modules/pam_pwdb/TODO +++ b/contrib/libpam/modules/pam_pwdb/TODO @@ -1,4 +1,4 @@ -$Id: TODO,v 1.3 1996/11/10 21:03:21 morgan Exp $ +$Id: TODO,v 1.1.1.1 2000/06/20 22:11:47 agmorgan Exp $ * get NIS working * .. including "nonis" argument diff --git a/contrib/libpam/modules/pam_pwdb/md5.c b/contrib/libpam/modules/pam_pwdb/md5.c index fdfbdd88f389..4428294178ff 100644 --- a/contrib/libpam/modules/pam_pwdb/md5.c +++ b/contrib/libpam/modules/pam_pwdb/md5.c @@ -1,4 +1,4 @@ -/* $Id: md5.c,v 1.1 1996/09/05 06:43:31 morgan Exp $ +/* $Id: md5.c,v 1.2 2000/12/04 19:02:34 baggins Exp $ * * This code implements the MD5 message-digest algorithm. * The algorithm is due to Ron Rivest. This code was @@ -15,10 +15,6 @@ * needed on buffers full of bytes, and then call MD5Final, which * will fill a supplied 16-byte array with the digest. * - * $Log: md5.c,v $ - * Revision 1.1 1996/09/05 06:43:31 morgan - * Initial revision - * */ #include @@ -27,13 +23,13 @@ #ifndef HIGHFIRST #define byteReverse(buf, len) /* Nothing */ #else -void byteReverse(unsigned char *buf, unsigned longs); +static void byteReverse(unsigned char *buf, unsigned longs); #ifndef ASM_MD5 /* * Note: this code is harmless on little-endian machines. */ -void byteReverse(unsigned char *buf, unsigned longs) +static void byteReverse(unsigned char *buf, unsigned longs) { uint32 t; do { @@ -50,7 +46,7 @@ void byteReverse(unsigned char *buf, unsigned longs) * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * initialization constants. */ -void MD5Init(struct MD5Context *ctx) +void MD5Name(MD5Init)(struct MD5Context *ctx) { ctx->buf[0] = 0x67452301U; ctx->buf[1] = 0xefcdab89U; @@ -65,7 +61,7 @@ void MD5Init(struct MD5Context *ctx) * Update context to reflect the concatenation of another buffer full * of bytes. */ -void MD5Update(struct MD5Context *ctx, unsigned const char *buf, unsigned len) +void MD5Name(MD5Update)(struct MD5Context *ctx, unsigned const char *buf, unsigned len) { uint32 t; @@ -90,7 +86,7 @@ void MD5Update(struct MD5Context *ctx, unsigned const char *buf, unsigned len) } memcpy(p, buf, t); byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32 *) ctx->in); + MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); buf += t; len -= t; } @@ -99,7 +95,7 @@ void MD5Update(struct MD5Context *ctx, unsigned const char *buf, unsigned len) while (len >= 64) { memcpy(ctx->in, buf, 64); byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32 *) ctx->in); + MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); buf += 64; len -= 64; } @@ -113,7 +109,7 @@ void MD5Update(struct MD5Context *ctx, unsigned const char *buf, unsigned len) * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ -void MD5Final(unsigned char digest[16], struct MD5Context *ctx) +void MD5Name(MD5Final)(unsigned char digest[16], struct MD5Context *ctx) { unsigned count; unsigned char *p; @@ -134,7 +130,7 @@ void MD5Final(unsigned char digest[16], struct MD5Context *ctx) /* Two lots of padding: Pad the first block to 64 bytes */ memset(p, 0, count); byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32 *) ctx->in); + MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); /* Now fill the next block with 56 bytes */ memset(ctx->in, 0, 56); @@ -148,7 +144,7 @@ void MD5Final(unsigned char digest[16], struct MD5Context *ctx) ((uint32 *) ctx->in)[14] = ctx->bits[0]; ((uint32 *) ctx->in)[15] = ctx->bits[1]; - MD5Transform(ctx->buf, (uint32 *) ctx->in); + MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); byteReverse((unsigned char *) ctx->buf, 4); memcpy(digest, ctx->buf, 16); memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ @@ -173,7 +169,7 @@ void MD5Final(unsigned char digest[16], struct MD5Context *ctx) * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ -void MD5Transform(uint32 buf[4], uint32 const in[16]) +void MD5Name(MD5Transform)(uint32 buf[4], uint32 const in[16]) { register uint32 a, b, c, d; diff --git a/contrib/libpam/modules/pam_pwdb/md5.h b/contrib/libpam/modules/pam_pwdb/md5.h index 4949ade27e1f..75c4dbac85e1 100644 --- a/contrib/libpam/modules/pam_pwdb/md5.h +++ b/contrib/libpam/modules/pam_pwdb/md5.h @@ -1,11 +1,7 @@ #ifndef MD5_H #define MD5_H -#ifdef __alpha typedef unsigned int uint32; -#else -typedef unsigned long uint32; -#endif struct MD5Context { uint32 buf[4]; @@ -13,13 +9,17 @@ struct MD5Context { unsigned char in[64]; }; -void MD5Init(struct MD5Context *); -void MD5Update(struct MD5Context *, unsigned const char *, unsigned); -void MD5Final(unsigned char digest[16], struct MD5Context *); -void MD5Transform(uint32 buf[4], uint32 const in[16]); -int i64c(int i); +void GoodMD5Init(struct MD5Context *); +void GoodMD5Update(struct MD5Context *, unsigned const char *, unsigned); +void GoodMD5Final(unsigned char digest[16], struct MD5Context *); +void GoodMD5Transform(uint32 buf[4], uint32 const in[16]); +void BrokenMD5Init(struct MD5Context *); +void BrokenMD5Update(struct MD5Context *, unsigned const char *, unsigned); +void BrokenMD5Final(unsigned char digest[16], struct MD5Context *); +void BrokenMD5Transform(uint32 buf[4], uint32 const in[16]); -char *crypt_md5(const char *pw, const char *salt); +char *Goodcrypt_md5(const char *pw, const char *salt); +char *Brokencrypt_md5(const char *pw, const char *salt); /* * This is needed to make RSAREF happy on some MS-DOS compilers. diff --git a/contrib/libpam/modules/pam_pwdb/md5_crypt.c b/contrib/libpam/modules/pam_pwdb/md5_crypt.c index 88be13b7f001..826087f28093 100644 --- a/contrib/libpam/modules/pam_pwdb/md5_crypt.c +++ b/contrib/libpam/modules/pam_pwdb/md5_crypt.c @@ -1,4 +1,4 @@ -/* $Id: md5_crypt.c,v 1.1 1996/09/05 06:43:31 morgan Exp $ +/* $Id: md5_crypt.c,v 1.2 2000/12/04 19:02:34 baggins Exp $ * * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): @@ -9,10 +9,6 @@ * * Origin: Id: crypt.c,v 1.3 1995/05/30 05:42:22 rgrimes Exp * - * $Log: md5_crypt.c,v $ - * Revision 1.1 1996/09/05 06:43:31 morgan - * Initial revision - * */ #include @@ -30,35 +26,13 @@ to64(char *s, unsigned long v, int n) } } -/* - * i64c - convert an integer to a radix 64 character - */ -int i64c(int i) -{ - if (i < 0) - return ('.'); - else if (i > 63) - return ('z'); - if (i == 0) - return ('.'); - if (i == 1) - return ('/'); - if (i >= 2 && i <= 11) - return ('0' - 2 + i); - if (i >= 12 && i <= 37) - return ('A' - 12 + i); - if (i >= 38 && i <= 63) - return ('a' - 38 + i); - return ('\0'); -} - /* * UNIX password * * Use MD5 for what it is best at... */ -char * crypt_md5(const char *pw, const char *salt) +char * MD5Name(crypt_md5)(const char *pw, const char *salt) { const char *magic = "$1$"; /* This string is magic for this algorithm. Having @@ -84,25 +58,25 @@ char * crypt_md5(const char *pw, const char *salt) /* get the length of the true salt */ sl = ep - sp; - MD5Init(&ctx); + MD5Name(MD5Init)(&ctx); /* The password first, since that is what is most unknown */ - MD5Update(&ctx,(unsigned const char *)pw,strlen(pw)); + MD5Name(MD5Update)(&ctx,(unsigned const char *)pw,strlen(pw)); /* Then our magic string */ - MD5Update(&ctx,(unsigned const char *)magic,strlen(magic)); + MD5Name(MD5Update)(&ctx,(unsigned const char *)magic,strlen(magic)); /* Then the raw salt */ - MD5Update(&ctx,(unsigned const char *)sp,sl); + MD5Name(MD5Update)(&ctx,(unsigned const char *)sp,sl); /* Then just as many characters of the MD5(pw,salt,pw) */ - MD5Init(&ctx1); - MD5Update(&ctx1,(unsigned const char *)pw,strlen(pw)); - MD5Update(&ctx1,(unsigned const char *)sp,sl); - MD5Update(&ctx1,(unsigned const char *)pw,strlen(pw)); - MD5Final(final,&ctx1); + MD5Name(MD5Init)(&ctx1); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)sp,sl); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); + MD5Name(MD5Final)(final,&ctx1); for(pl = strlen(pw); pl > 0; pl -= 16) - MD5Update(&ctx,(unsigned const char *)final,pl>16 ? 16 : pl); + MD5Name(MD5Update)(&ctx,(unsigned const char *)final,pl>16 ? 16 : pl); /* Don't leave anything around in vm they could use. */ memset(final,0,sizeof final); @@ -110,16 +84,16 @@ char * crypt_md5(const char *pw, const char *salt) /* Then something really weird... */ for (j=0,i = strlen(pw); i ; i >>= 1) if(i&1) - MD5Update(&ctx, (unsigned const char *)final+j, 1); + MD5Name(MD5Update)(&ctx, (unsigned const char *)final+j, 1); else - MD5Update(&ctx, (unsigned const char *)pw+j, 1); + MD5Name(MD5Update)(&ctx, (unsigned const char *)pw+j, 1); /* Now make the output string */ strcpy(passwd,magic); strncat(passwd,sp,sl); strcat(passwd,"$"); - MD5Final(final,&ctx); + MD5Name(MD5Final)(final,&ctx); /* * and now, just to make sure things don't run too fast @@ -127,23 +101,23 @@ char * crypt_md5(const char *pw, const char *salt) * need 30 seconds to build a 1000 entry dictionary... */ for(i=0;i<1000;i++) { - MD5Init(&ctx1); + MD5Name(MD5Init)(&ctx1); if(i & 1) - MD5Update(&ctx1,(unsigned const char *)pw,strlen(pw)); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); else - MD5Update(&ctx1,(unsigned const char *)final,16); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)final,16); if(i % 3) - MD5Update(&ctx1,(unsigned const char *)sp,sl); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)sp,sl); if(i % 7) - MD5Update(&ctx1,(unsigned const char *)pw,strlen(pw)); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); if(i & 1) - MD5Update(&ctx1,(unsigned const char *)final,16); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)final,16); else - MD5Update(&ctx1,(unsigned const char *)pw,strlen(pw)); - MD5Final(final,&ctx1); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); + MD5Name(MD5Final)(final,&ctx1); } p = passwd + strlen(passwd); diff --git a/contrib/libpam/modules/pam_pwdb/pam_pwdb.c b/contrib/libpam/modules/pam_pwdb/pam_pwdb.c index a612f74037b4..8c75ac232e18 100644 --- a/contrib/libpam/modules/pam_pwdb/pam_pwdb.c +++ b/contrib/libpam/modules/pam_pwdb/pam_pwdb.c @@ -1,5 +1,5 @@ /* - * $Id: pam_pwdb.c,v 1.3 1997/01/04 20:38:33 morgan Exp morgan $ + * $Id: pam_pwdb.c,v 1.3 2000/11/19 23:54:04 agmorgan Exp $ * * This is the single file that will be compiled for pam_unix. * it includes each of the modules that have beed defined in the .-c @@ -13,37 +13,14 @@ * See the end of this file for Copyright information. */ -/* - * $Log: pam_pwdb.c,v $ - * Revision 1.3 1997/01/04 20:38:33 morgan - * this is not the unix module! - * - * Revision 1.2 1996/12/01 03:03:43 morgan - * debugging code uses _pam_malloc - * - * Revision 1.1 1996/11/10 21:21:24 morgan - * Initial revision - * - * Revision 1.3 1996/09/05 06:44:33 morgan - * more debugging, fixed static structure name - * - * Revision 1.2 1996/09/01 01:05:12 morgan - * Cristian Gafton's patches. - * - * Revision 1.1 1996/08/29 13:22:19 morgan - * Initial revision - * - */ - static const char rcsid[] = -"$Id: pam_pwdb.c,v 1.3 1997/01/04 20:38:33 morgan Exp morgan $\n" +"$Id: pam_pwdb.c,v 1.3 2000/11/19 23:54:04 agmorgan Exp $\n" " - PWDB Pluggable Authentication module. " ; -#ifdef linux -# define _GNU_SOURCE -# include -#endif +/* #define DEBUG */ + +#include #include #include @@ -56,9 +33,6 @@ static const char rcsid[] = #include #include -#define _SVID_SOURCE -#define __USE_BSD -#define _BSD_COMPAT #include #include @@ -100,6 +74,13 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags retval = _unix_auth( pamh, ctrl ); pwdb_end(); + if ( on(UNIX_LIKE_AUTH, ctrl) ) { + D(("recording return code for next time [%d]", retval)); + pam_set_data(pamh, "pwdb_setcred_return", (void *) retval, NULL); + } + + D(("done. [%s]", pam_strerror(pamh, retval))); + return retval; } @@ -113,9 +94,17 @@ PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags pwdb_start(); ctrl = set_ctrl(flags, argc, argv); - retval = _unix_set_credentials(pamh, ctrl) ; + retval = _unix_set_credentials(pamh, ctrl); pwdb_end(); + if ( on(UNIX_LIKE_AUTH, ctrl) ) { + int *pretval = &retval; + + D(("recovering return code from auth call")); + pam_get_data(pamh, "pwdb_setcred_return", (const void **) pretval); + D(("recovered data indicates that old retval was %d", retval)); + } + return retval; } @@ -203,6 +192,8 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, retval = _unix_chauthtok(pamh, ctrl); pwdb_end(); + D(("done.")); + return retval; } diff --git a/contrib/libpam/modules/pam_pwdb/pam_unix_acct.-c b/contrib/libpam/modules/pam_pwdb/pam_unix_acct.-c index dbd13855ed3c..adcb6538624f 100644 --- a/contrib/libpam/modules/pam_pwdb/pam_unix_acct.-c +++ b/contrib/libpam/modules/pam_pwdb/pam_unix_acct.-c @@ -1,31 +1,11 @@ /* - * $Id: pam_unix_acct.-c,v 1.6 1997/01/04 20:37:15 morgan Exp morgan $ - * - * $Log: pam_unix_acct.-c,v $ - * Revision 1.6 1997/01/04 20:37:15 morgan - * extra debugging - * - * Revision 1.5 1996/12/01 03:05:54 morgan - * debugging with _pam_macros.h - * - * Revision 1.4 1996/11/10 21:03:57 morgan - * pwdb conversion - * - * Revision 1.3 1996/09/05 06:45:45 morgan - * tidied shadow acct management - * - * Revision 1.2 1996/09/01 01:13:14 morgan - * Cristian Gafton's patches - * - * Revision 1.1 1996/08/29 13:27:51 morgan - * Initial revision - * + * $Id: pam_unix_acct.-c,v 1.2 2000/12/04 19:02:34 baggins Exp $ * * See end of file for copyright information */ static const char rcsid_acct[] = -"$Id: pam_unix_acct.-c,v 1.6 1997/01/04 20:37:15 morgan Exp morgan $\n" +"$Id: pam_unix_acct.-c,v 1.2 2000/12/04 19:02:34 baggins Exp $\n" " - PAM_PWDB account management "; /* the shadow suite has accout managment.. */ diff --git a/contrib/libpam/modules/pam_pwdb/pam_unix_auth.-c b/contrib/libpam/modules/pam_pwdb/pam_unix_auth.-c index 4a1eed0d6387..31230394c65f 100644 --- a/contrib/libpam/modules/pam_pwdb/pam_unix_auth.-c +++ b/contrib/libpam/modules/pam_pwdb/pam_unix_auth.-c @@ -1,25 +1,11 @@ /* - * $Id: pam_unix_auth.-c,v 1.4 1996/12/01 03:05:54 morgan Exp $ + * $Id: pam_unix_auth.-c,v 1.1.1.1 2000/06/20 22:11:49 agmorgan Exp $ * - * $Log: pam_unix_auth.-c,v $ - * Revision 1.4 1996/12/01 03:05:54 morgan - * debugging with _pam_macros.h - * - * Revision 1.3 1996/11/10 21:04:29 morgan - * pwdb conversion - * - * Revision 1.2 1996/09/05 06:46:53 morgan - * fixed comments. Added check for null passwd. - * changed data item name - * - * Revision 1.1 1996/08/29 13:27:51 morgan - * Initial revision - * * See end of file for Copyright information. */ static const char rcsid_auth[] = -"$Id: pam_unix_auth.-c,v 1.4 1996/12/01 03:05:54 morgan Exp $: pam_unix_auth.-c,v 1.2 1996/09/05 06:46:53 morgan Exp morgan $\n" +"$Id: pam_unix_auth.-c,v 1.1.1.1 2000/06/20 22:11:49 agmorgan Exp $: pam_unix_auth.-c,v 1.2 1996/09/05 06:46:53 morgan Exp morgan $\n" " - PAM_PWDB authentication functions. "; /* @@ -42,8 +28,15 @@ static int _unix_auth(pam_handle_t *pamh, unsigned int ctrl) retval = _unix_get_user(pamh, ctrl, NULL, &name); if (retval != PAM_SUCCESS ) { - if ( on(UNIX_DEBUG,ctrl) ) { - _log_err(LOG_DEBUG, "auth could not identify user"); + if (retval != PAM_CONV_AGAIN) { + if ( on(UNIX_DEBUG,ctrl) ) { + _log_err(LOG_DEBUG, "auth could not identify user"); + } + } else { + D(("pam_get_user/conv() function is not ready yet")); + /* it is safe to resume this function so we translate this + retval to the value that indicates we're happy to resume. */ + retval = PAM_INCOMPLETE; } return retval; } @@ -60,18 +53,27 @@ static int _unix_auth(pam_handle_t *pamh, unsigned int ctrl) retval = _unix_read_password(pamh, ctrl, NULL, "Password: ", NULL , _UNIX_AUTHTOK, &p); - if (retval != PAM_SUCCESS ) { - _log_err(LOG_CRIT, "auth could not identify password for [%s]" - , name); + if (retval != PAM_SUCCESS) { + if (retval != PAM_CONV_AGAIN) { + _log_err(LOG_CRIT, "auth could not identify password for [%s]" + , name); + } else { + D(("conversation function is not ready yet")); + /* it is safe to resume this function so we translate this + retval to the value that indicates we're happy to resume. */ + retval = PAM_INCOMPLETE; + } name = NULL; return retval; } + D(("user=%s, password=[%s]", name, p)); /* verify the password of this user */ - retval = _unix_verify_password(pamh, name, p, ctrl); name = p = NULL; + D(("done [%d]", retval)); + return retval; } diff --git a/contrib/libpam/modules/pam_pwdb/pam_unix_md.-c b/contrib/libpam/modules/pam_pwdb/pam_unix_md.-c index cd90b0ff339b..d9b2c51b205a 100644 --- a/contrib/libpam/modules/pam_pwdb/pam_unix_md.-c +++ b/contrib/libpam/modules/pam_pwdb/pam_unix_md.-c @@ -25,7 +25,7 @@ struct cfns { #define N_MDS 1 const static struct cfns cfn_list[N_MDS] = { - { "$1$", 3, crypt_md5 }, + { "$1$", 3, Goodcrypt_md5 }, }; static char *_pam_md(const char *key, const char *salt) @@ -53,3 +53,21 @@ static char *_pam_md(const char *key, const char *salt) return x; /* this must be deleted elsewhere */ } +#ifndef PWDB_NO_MD_COMPAT +static char *_pam_md_compat(const char *key, const char *salt) +{ + char *x,*e=NULL; + + D(("called with key='%s', salt='%s'", key, salt)); + + if ( !strncmp("$1$", salt, 3) ) { + e = Brokencrypt_md5(key, salt); + x = x_strdup(e); /* put e in malloc()ed memory */ + _pam_overwrite(e); /* clean up */ + } else { + x = x_strdup("*"); + } + + return x; /* this must be deleted elsewhere */ +} +#endif /* PWDB_NO_MD_COMPAT */ diff --git a/contrib/libpam/modules/pam_pwdb/pam_unix_passwd.-c b/contrib/libpam/modules/pam_pwdb/pam_unix_passwd.-c index 402f7f349f88..eb43bcfa713f 100644 --- a/contrib/libpam/modules/pam_pwdb/pam_unix_passwd.-c +++ b/contrib/libpam/modules/pam_pwdb/pam_unix_passwd.-c @@ -1,29 +1,7 @@ -/* $Id: pam_unix_passwd.-c,v 1.6 1997/04/05 06:31:06 morgan Exp morgan $ */ - -/* - * $Log: pam_unix_passwd.-c,v $ - * Revision 1.6 1997/04/05 06:31:06 morgan - * mostly a reformat. - * - * Revision 1.5 1996/12/01 03:05:54 morgan - * debugging with _pam_macros.h - * - * Revision 1.4 1996/11/10 21:04:51 morgan - * pwdb conversion - * - * Revision 1.3 1996/09/05 06:48:15 morgan - * A lot has changed. I'd recommend you study the diff. - * - * Revision 1.2 1996/09/01 16:33:27 morgan - * Cristian Gafton's changes - * - * Revision 1.1 1996/08/29 13:21:27 morgan - * Initial revision - * - */ +/* $Id: pam_unix_passwd.-c,v 1.2 2000/12/04 19:02:34 baggins Exp $ */ static const char rcsid_pass[] = -"$Id: pam_unix_passwd.-c,v 1.6 1997/04/05 06:31:06 morgan Exp morgan $\n" +"$Id: pam_unix_passwd.-c,v 1.2 2000/12/04 19:02:34 baggins Exp $\n" " - PAM_PWDB password module " ; @@ -41,6 +19,28 @@ static const char rcsid_pass[] = /* Implementation */ +/* + * i64c - convert an integer to a radix 64 character + */ +static int i64c(int i) +{ + if (i < 0) + return ('.'); + else if (i > 63) + return ('z'); + if (i == 0) + return ('.'); + if (i == 1) + return ('/'); + if (i >= 2 && i <= 11) + return ('0' - 2 + i); + if (i >= 12 && i <= 37) + return ('A' - 12 + i); + if (i >= 38 && i <= 63) + return ('a' - 38 + i); + return ('\0'); +} + /* * FUNCTION: _pam_unix_chauthtok() * @@ -259,15 +259,15 @@ static int _unix_chauthtok(pam_handle_t *pamh, unsigned int ctrl) unsigned char tmp[16]; int i; - MD5Init(&ctx); + GoodMD5Init(&ctx); gettimeofday(&tv, (struct timezone *) 0); - MD5Update(&ctx, (void *) &tv, sizeof tv); + GoodMD5Update(&ctx, (void *) &tv, sizeof tv); i = getpid(); - MD5Update(&ctx, (void *) &i, sizeof i); + GoodMD5Update(&ctx, (void *) &i, sizeof i); i = clock(); - MD5Update(&ctx, (void *) &i, sizeof i); - MD5Update(&ctx, result, sizeof result); - MD5Final(tmp, &ctx); + GoodMD5Update(&ctx, (void *) &i, sizeof i); + GoodMD5Update(&ctx, result, sizeof result); + GoodMD5Final(tmp, &ctx); strcpy(cp, "$1$"); /* magic for the MD5 */ cp += strlen(cp); for (i = 0; i < 8; i++) diff --git a/contrib/libpam/modules/pam_pwdb/pam_unix_pwupd.-c b/contrib/libpam/modules/pam_pwdb/pam_unix_pwupd.-c index d50031dcb919..a1fc65ff5163 100644 --- a/contrib/libpam/modules/pam_pwdb/pam_unix_pwupd.-c +++ b/contrib/libpam/modules/pam_pwdb/pam_unix_pwupd.-c @@ -1,19 +1,7 @@ /* - * $Id: pam_unix_pwupd.-c,v 1.4 1997/01/04 20:35:32 morgan Exp morgan $ + * $Id: pam_unix_pwupd.-c,v 1.1.1.1 2000/06/20 22:11:51 agmorgan Exp $ * * This file contains the routines to update the passwd databases. - * - * $Log: pam_unix_pwupd.-c,v $ - * Revision 1.4 1997/01/04 20:35:32 morgan - * minor comment change - * - * Revision 1.3 1996/12/01 03:05:54 morgan - * debugging with _pam_macros.h - * - * Revision 1.2 1996/11/10 21:05:09 morgan - * pwdb conversion - * - * */ /* Implementation */ diff --git a/contrib/libpam/modules/pam_pwdb/pam_unix_sess.-c b/contrib/libpam/modules/pam_pwdb/pam_unix_sess.-c index 49ce96cbd16c..395bd9bba3a7 100644 --- a/contrib/libpam/modules/pam_pwdb/pam_unix_sess.-c +++ b/contrib/libpam/modules/pam_pwdb/pam_unix_sess.-c @@ -1,25 +1,11 @@ /* - * $Id: pam_unix_sess.-c,v 1.4 1996/12/01 03:05:54 morgan Exp morgan $ - * - * $Log: pam_unix_sess.-c,v $ - * Revision 1.4 1996/12/01 03:05:54 morgan - * debugging with _pam_macros.h - * - * Revision 1.3 1996/11/10 21:05:33 morgan - * pwdb conversion - * - * Revision 1.2 1996/09/05 06:49:02 morgan - * more informative logging - * - * Revision 1.1 1996/08/29 13:27:51 morgan - * Initial revision - * + * $Id: pam_unix_sess.-c,v 1.2 2000/12/04 19:02:34 baggins Exp $ * * See end for Copyright information */ static const char rcsid_sess[] = -"$Id: pam_unix_sess.-c,v 1.4 1996/12/01 03:05:54 morgan Exp morgan $\n" +"$Id: pam_unix_sess.-c,v 1.2 2000/12/04 19:02:34 baggins Exp $\n" " - PAM_PWDB session management. morgan@parc.power.net"; /* Define internal functions */ diff --git a/contrib/libpam/modules/pam_pwdb/pwdb_chkpwd.c b/contrib/libpam/modules/pam_pwdb/pwdb_chkpwd.c index 6332eaa7e865..3b3c1d5f0f51 100644 --- a/contrib/libpam/modules/pam_pwdb/pwdb_chkpwd.c +++ b/contrib/libpam/modules/pam_pwdb/pwdb_chkpwd.c @@ -1,5 +1,5 @@ /* - * $Id: pwdb_chkpwd.c,v 1.1 1997/02/15 17:26:18 morgan Exp $ + * $Id: pwdb_chkpwd.c,v 1.3 2001/02/11 06:33:53 agmorgan Exp $ * * This program is designed to run setuid(root) or with sufficient * privilege to read all of the unix password databases. It is designed @@ -11,19 +11,9 @@ * * Copyright information is located at the end of the file. * - * $Log: pwdb_chkpwd.c,v $ - * Revision 1.1 1997/02/15 17:26:18 morgan - * Initial revision - * - * Revision 1.1 1996/11/10 21:20:51 morgan - * Initial revision - * */ -#ifdef linux -# define _GNU_SOURCE -# include -#endif +#include #include #include @@ -54,6 +44,7 @@ static void _log_err(int err, const char *format, ...) closelog(); } +#define PWDB_NO_MD_COMPAT #include "pam_unix_md.-c" static int _unix_verify_passwd(const char *salt, const char *p) @@ -92,12 +83,12 @@ static int _unix_verify_passwd(const char *salt, const char *p) return retval; } -void main(void) +int main(int argc, char **argv) { const struct pwdb *pw=NULL; const struct pwdb_entry *pwe=NULL; char pass[MAXPASS+1]; - int npass; + int npass, force_failure=0; int retval=UNIX_FAILED; /* @@ -129,14 +120,26 @@ void main(void) retval = UNIX_FAILED; } if (retval != UNIX_FAILED) { - retval = pwdb_locate("user", PWDB_DEFAULT, PWDB_NAME_UNKNOWN - , getuid(), &pw); + retval = pwdb_locate("user", PWDB_DEFAULT, PWDB_NAME_UNKNOWN, + getuid(), &pw); } if (retval != PWDB_SUCCESS) { _log_err(LOG_ALERT, "could not identify user"); while (pwdb_end() != PWDB_SUCCESS); exit(UNIX_FAILED); } + if (argc == 2) { + if (pwdb_get_entry(pw, "user", &pwe) == PWDB_SUCCESS) { + if (pwe == NULL) { + force_failure = 1; + } else { + if (strcmp((const char *) pwe->value, argv[1])) { + force_failure = 1; + } + pwdb_entry_delete(&pwe); + } + } + } /* read the password from stdin (a pipe from the pam_pwdb module) */ @@ -167,6 +170,10 @@ void main(void) memset(pass, '\0', MAXPASS); /* clear memory of the password */ while (pwdb_end() != PWDB_SUCCESS); + if ((retval != UNIX_FAILED) && force_failure) { + retval = UNIX_FAILED; + } + /* return pass or fail */ exit(retval); diff --git a/contrib/libpam/modules/pam_pwdb/support.-c b/contrib/libpam/modules/pam_pwdb/support.-c index 71e212d64195..2b80f960cde7 100644 --- a/contrib/libpam/modules/pam_pwdb/support.-c +++ b/contrib/libpam/modules/pam_pwdb/support.-c @@ -1,18 +1,5 @@ /* - * $Id: support.-c,v 1.7 1997/04/05 06:32:06 morgan Exp morgan $ - * - * $Log: support.-c,v $ - * Revision 1.7 1997/04/05 06:32:06 morgan - * new option and also deleted _readto - * - * Revision 1.6 1997/02/15 17:27:20 morgan - * added helper binary to password checking - * - * Revision 1.5 1996/12/01 03:05:54 morgan - * debugging with _pam_macros.h - * - * Revision 1.4 1996/11/10 21:06:07 morgan - * pwdb conversion + * $Id: support.-c,v 1.3 2001/02/11 06:33:53 agmorgan Exp $ * * Copyright information at end of file. */ @@ -91,8 +78,9 @@ typedef struct { #define UNIX_NODELAY 18 /* admin does not want a fail-delay */ #define UNIX_UNIX 19 /* wish to use /etc/passwd for pwd */ #define UNIX_BIGCRYPT 20 /* use DEC-C2 crypt()^x function */ +#define UNIX_LIKE_AUTH 21 /* need to auth for setcred to work */ /* -------------- */ -#define UNIX_CTRLS_ 21 /* number of ctrl arguments defined */ +#define UNIX_CTRLS_ 22 /* number of ctrl arguments defined */ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = { @@ -118,8 +106,9 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = { /* UNIX__SET_DB */ { NULL, _ALL_ON_, 0100000 }, /* UNIX_DEBUG */ { "debug", _ALL_ON_, 0200000 }, /* UNIX_NODELAY */ { "nodelay", _ALL_ON_, 0400000 }, -/* UNIX_UNIX */ { "unix", _ALL_ON_^(050000), 01000000 }, +/* UNIX_UNIX */ { "unix", _ALL_ON_^(050000), 01000000 }, /* UNIX_BIGCRYPT */ { "bigcrypt", _ALL_ON_^(020000), 02000000 }, +/* UNIX_LIKE_AUTH */ { "likeauth", _ALL_ON_, 04000000 }, }; #define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag) @@ -161,7 +150,7 @@ static int converse(pam_handle_t *pamh, int ctrl, int nargs , pam_strerror(pamh, retval)); } - } else { + } else if (retval != PAM_CONV_AGAIN) { _log_err(LOG_ERR, "couldn't obtain coversation function [%s]" , pam_strerror(pamh, retval)); } @@ -322,13 +311,13 @@ static void _cleanup_failures(pam_handle_t *pamh, void *fl, int err) if ( !quiet && !err ) { /* under advisement from Sun,may go away */ /* log the number of authentication failures */ - if ( failure->count != 0 ) { + if ( failure->count > 1 ) { (void) pam_get_item(pamh, PAM_SERVICE , (const void **)&service); _log_err(LOG_NOTICE - , "%d authentication failure%s; %s(uid=%d) -> " + , "%d more authentication failure%s; %s(uid=%d) -> " "%s for %s service" - , failure->count, failure->count==1 ? "":"s" + , failure->count-1, failure->count==2 ? "":"s" , failure->name , failure->id , failure->user @@ -356,7 +345,8 @@ static void _cleanup_failures(pam_handle_t *pamh, void *fl, int err) #include #include -static int pwdb_run_helper_binary(pam_handle_t *pamh, const char *passwd) +static int pwdb_run_helper_binary(pam_handle_t *pamh, const char *passwd, + const char *user) { int retval, child, fds[2]; @@ -370,7 +360,7 @@ static int pwdb_run_helper_binary(pam_handle_t *pamh, const char *passwd) /* fork */ child = fork(); if (child == 0) { - static char *args[] = { NULL, NULL }; + static char *args[] = { NULL, NULL, NULL }; static char *envp[] = { NULL }; /* XXX - should really tidy up PAM here too */ @@ -382,6 +372,8 @@ static int pwdb_run_helper_binary(pam_handle_t *pamh, const char *passwd) /* exec binary helper */ args[0] = x_strdup(CHKPWD_HELPER); + args[1] = x_strdup(user); + execve(CHKPWD_HELPER, args, envp); /* should not get here: exit with error */ @@ -389,13 +381,14 @@ static int pwdb_run_helper_binary(pam_handle_t *pamh, const char *passwd) exit(PWDB_SUCCESS+1); } else if (child > 0) { /* wait for child */ - close(fds[0]); if (passwd != NULL) { /* send the password to the child */ write(fds[1], passwd, strlen(passwd)+1); passwd = NULL; } else { write(fds[1], "", 1); /* blank password */ } + close(fds[0]); /* we close this after the write because we want + to avoid a possible SIGPIPE. */ close(fds[1]); (void) waitpid(child, &retval, 0); /* wait for helper to complete */ retval = (retval == PWDB_SUCCESS) ? PAM_SUCCESS:PAM_AUTH_ERR; @@ -408,8 +401,8 @@ static int pwdb_run_helper_binary(pam_handle_t *pamh, const char *passwd) return retval; } -static int _unix_verify_password(pam_handle_t *pamh, const char *name - , const char *p, unsigned int ctrl) +static int _unix_verify_password(pam_handle_t *pamh, const char *name, + const char *p, unsigned int ctrl) { const struct pwdb *pw=NULL; const struct pwdb_entry *pwe=NULL; @@ -418,6 +411,7 @@ static int _unix_verify_password(pam_handle_t *pamh, const char *name char *pp; char *data_name; int retval; + int verify_result; D(("called")); @@ -474,7 +468,7 @@ static int _unix_verify_password(pam_handle_t *pamh, const char *name if (geteuid()) { /* we are not root perhaps this is the reason? Run helper */ D(("running helper binary")); - retval = pwdb_run_helper_binary(pamh, p); + retval = pwdb_run_helper_binary(pamh, p, name); } else { retval = PAM_AUTHINFO_UNAVAIL; _log_err(LOG_ALERT, "get passwd; %s", pwdb_strerror(retval)); @@ -491,23 +485,6 @@ static int _unix_verify_password(pam_handle_t *pamh, const char *name * clear text... */ - if ( ( !salt ) && ( !p ) ) { - - /* the stored password is NULL */ - - (void) pwdb_entry_delete(&pwe); - (void) pwdb_delete(&pw); - - if ( off(UNIX__NONULL, ctrl ) ) { /* this means we've succeeded */ - return PAM_SUCCESS; - } else { - return PAM_AUTH_ERR; - } - } - - pp = _pam_md(p, salt); - p = NULL; /* no longer needed here */ - data_name = (char *) malloc(sizeof(FAIL_PREFIX)+strlen(name)); if ( data_name == NULL ) { _log_err(LOG_CRIT, "no memory for data-name"); @@ -515,9 +492,49 @@ static int _unix_verify_password(pam_handle_t *pamh, const char *name strcpy(data_name, FAIL_PREFIX); strcpy(data_name + sizeof(FAIL_PREFIX)-1, name); - /* the moment of truth -- do we agree with the password? */ + if ( !( (salt && *salt) || (p && *p) ) ) { - if ( strcmp( pp, salt ) == 0 ) { + D(("two null passwords to compare")); + + /* the stored password is NULL */ + pp = NULL; + if ( off(UNIX__NONULL, ctrl ) ) { /* this means we've succeeded */ + verify_result = PAM_SUCCESS; + } else { + verify_result = PAM_AUTH_ERR; + } + + } else if ( !( salt && p ) ) { + + D(("one of the two to compare are NULL")); + + pp = NULL; + verify_result = PAM_AUTH_ERR; + + } else { + + pp = _pam_md(p, salt); + + /* the moment of truth -- do we agree with the password? */ + D(("comparing state of pp[%s] and salt[%s]", pp, salt)); + + if ( strcmp( pp, salt ) == 0 ) { + verify_result = PAM_SUCCESS; + } else { + _pam_delete(pp); + pp = _pam_md_compat(p, salt); + if ( strcmp( pp, salt ) == 0 ) { + verify_result = PAM_SUCCESS; + } else { + verify_result = PAM_AUTH_ERR; + } + } + + p = NULL; /* no longer needed here */ + + } + + if ( verify_result == PAM_SUCCESS ) { retval = PAM_SUCCESS; if (data_name) { /* reset failures */ @@ -538,7 +555,11 @@ static int _unix_verify_password(pam_handle_t *pamh, const char *name if (new != NULL) { - /* any previous failures for this user ? */ + new->user = x_strdup(name); + new->id = getuid(); + new->name = x_strdup(getlogin() ? getlogin():"" ); + + /* any previous failures for this user ? */ pam_get_data(pamh, data_name, (const void **)&old ); if (old != NULL) { @@ -547,11 +568,19 @@ static int _unix_verify_password(pam_handle_t *pamh, const char *name retval = PAM_MAXTRIES; } } else { + const char *service=NULL; + (void) pam_get_item(pamh, PAM_SERVICE + , (const void **)&service); + _log_err(LOG_NOTICE + , "authentication failure; %s(uid=%d) -> " + "%s for %s service" + , new->name + , new->id + , new->user + , service == NULL ? "**unknown**":service + ); new->count = 1; } - new->user = x_strdup(name); - new->id = getuid(); - new->name = x_strdup(getlogin() ? getlogin():"" ); pam_set_data(pamh, data_name, new, _cleanup_failures); @@ -568,6 +597,8 @@ static int _unix_verify_password(pam_handle_t *pamh, const char *name _pam_delete(data_name); _pam_delete(pp); + D(("done [%d].", retval)); + return retval; } @@ -596,8 +627,9 @@ static int _unix_get_user(pam_handle_t *pamh, unsigned int ctrl * alphanumeric character. */ - if (!isalnum(**user)) { - if (on(UNIX_DEBUG,ctrl) || **user) { + if (*user == NULL || !isalnum(**user)) { + D(("bad username")); + if (on(UNIX_DEBUG,ctrl)) { _log_err(LOG_ERR, "bad username [%s]", *user); } return PAM_USER_UNKNOWN; @@ -872,7 +904,7 @@ static int _pam_unix_approve_pass(pam_handle_t *pamh } /* ****************************************************************** * - * Copyright (c) Andrew G. Morgan, 1996. + * Copyright (c) Andrew G. Morgan 1996-8. * Copyright (c) Alex O. Yuriev, 1996. * Copyright (c) Cristian Gafton 1996. * diff --git a/contrib/libpam/modules/pam_radius/Makefile b/contrib/libpam/modules/pam_radius/Makefile index a74b911f4e3b..aa149d3ee9b5 100644 --- a/contrib/libpam/modules/pam_radius/Makefile +++ b/contrib/libpam/modules/pam_radius/Makefile @@ -8,13 +8,15 @@ # STATIC modules are not supported # +include ../../Make.Rules + TITLE=pam_radius CONFD=$(CONFIGED)/security export CONFD CONFILE=$(CONFD)/radius.conf export CONFILE -ifeq ($(HAVE_PWDBLIB),yes) +ifeq ($(HAVE_LIBPWDB),yes) # @@ -41,11 +43,6 @@ endif ####################### don't edit below ####################### -dummy: - - @echo "**** This is not a top-level Makefile " - exit - all: dirs $(LIBSHARED) $(LIBSTATIC) register dirs: @@ -85,9 +82,8 @@ remove: clean: rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean rm -f *.a *.o *.so *.bak dynamic/* static/* + rm -rf dynamic static .c.o: $(CC) $(CFLAGS) -c $< diff --git a/contrib/libpam/modules/pam_radius/pam_radius.h b/contrib/libpam/modules/pam_radius/pam_radius.h index 72b1da8aa0cb..67230243eed8 100644 --- a/contrib/libpam/modules/pam_radius/pam_radius.h +++ b/contrib/libpam/modules/pam_radius/pam_radius.h @@ -1,12 +1,17 @@ +/* + * $Id: pam_radius.h,v 1.2 2000/11/19 23:54:05 agmorgan Exp $ + */ #ifndef PAM_RADIUS_H #define PAM_RADIUS_H -#define _GNU_SOURCE -#include +#include #include + +#ifndef __USE_POSIX2 #define __USE_POSIX2 +#endif /* __USE_POSIX2 */ #include diff --git a/contrib/libpam/modules/pam_rhosts/Makefile b/contrib/libpam/modules/pam_rhosts/Makefile index 93addbb68119..d12e00c0680e 100644 --- a/contrib/libpam/modules/pam_rhosts/Makefile +++ b/contrib/libpam/modules/pam_rhosts/Makefile @@ -1,94 +1,15 @@ -# This Makefile controls a build process of the pam_rhosts modules -# for Linux-PAM. You should not modify this Makefile. +# +# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $ +# +# This Makefile controls a build process of $(TITLE) module for +# Linux-PAM. You should not modify this Makefile (unless you know +# what you are doing!). +# +# Created by Andrew Morgan 2000/08/27 +# -LIBAUTHOBJ = pam_rhosts_auth.o -LIBAUTHSRC = pam_rhosts_auth.c -LIBSESSOBJ = -LIBSESSSRC = -LIBPASSWDSRC = -LIBPASSWDOBJ = -LIBOBJ = $(LIBAUTHOBJ) $(LIBSESSOBJ) $(LIBPASSWDOBJ) -LIBSRC = $(LIBAUTHSRC) $(LIBSESSSRC) $(LIBPASSWDSRC) +include ../../Make.Rules -ifdef STATIC -LIBSTATIC = libpam_rhosts.o -LIBOBJS = $(addprefix static/,$(LIBOBJ)) -endif +TITLE=pam_rhosts_auth -ifdef DYNAMIC -LIBSESSSH = -LIBAUTHSH = pam_rhosts_auth.so -LIBPASSWDSH = -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBSHARED = $(LIBSESSSH) $(LIBAUTHSH) $(LIBPASSWDSH) -endif - -####################### don't edit below ####################### - -dummy: - @echo "**** This is not a top-level Makefile " - exit - - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; \ - ./register_static pam_rhosts_auth pam_rhosts/libpam_rhosts.o ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -endif - -ifdef DYNAMIC -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -endif - -ifdef STATIC -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) - -endif - -#.c.o: -# $(CC) -c $(CFLAGS) $< - -install: all -ifdef DYNAMIC - $(MKDIR) $(FAKEROOT)$(SECUREDIR) - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -# tidy up - -remove: - cd $(FAKEROOT)$(SECUREDIR) && rm -f $(LIBSHARED) - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) a.out core *~ - -extraclean: - rm -f *.a *.out *.o *.so *.bak dynamic/* static/* - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_rhosts/pam_rhosts_auth.c b/contrib/libpam/modules/pam_rhosts/pam_rhosts_auth.c index 10dfcf797119..b633a52989d7 100644 --- a/contrib/libpam/modules/pam_rhosts/pam_rhosts_auth.c +++ b/contrib/libpam/modules/pam_rhosts/pam_rhosts_auth.c @@ -46,6 +46,10 @@ #include #endif +#ifdef NEED_FSUID_H +#include +#endif /* NEED_FSUID_H */ + #include #include #include @@ -103,6 +107,7 @@ int innetgr(const char *, const char *, const char *,const char *); struct _options { int opt_no_hosts_equiv; + int opt_hosts_equiv_rootok; int opt_no_rhosts; int opt_debug; int opt_nowarn; @@ -111,6 +116,8 @@ struct _options { int opt_promiscuous; int opt_suppress; int opt_private_group; + int opt_no_uid_check; + const char *superuser; const char *last_error; }; @@ -133,6 +140,11 @@ static void set_option (struct _options *opts, const char *arg) return; } + if (strcmp(arg, "hosts_equiv_rootok") == 0) { + opts->opt_hosts_equiv_rootok = 1; + return; + } + if (strcmp(arg, "no_rhosts") == 0) { opts->opt_no_rhosts = 1; return; @@ -165,6 +177,15 @@ static void set_option (struct _options *opts, const char *arg) return; } + if (strcmp(arg, "no_uid_check") == 0) { + opts->opt_no_uid_check = 1; /* NIS optimization */ + return; + } + + if (strcmp(arg, "superuser=") == 0) { + opts->superuser = arg+sizeof("superuser=")-1; + return; + } /* * All other options are ignored at the present time. */ @@ -444,7 +465,7 @@ pam_iruserok(pam_handle_t *pamh, int answer; char pbuf[MAXPATHLEN]; /* potential buffer overrun */ - if ( !superuser && !opts->opt_no_hosts_equiv ) { + if ((!superuser||opts->opt_hosts_equiv_rootok) && !opts->opt_no_hosts_equiv ) { /* try to open system hosts.equiv file */ hostf = fopen (_PATH_HEQUIV, "r"); @@ -677,8 +698,12 @@ static int _pam_auth_rhosts (pam_handle_t *pamh, break; } + if (opts.superuser && !strcmp(opts.superuser, luser)) { + as_root = 1; + } + /* check if the luser uid == 0... --cristiang */ - { + if (! opts.opt_no_uid_check) { struct passwd *luser_pwd; luser_pwd = getpwnam(luser); @@ -759,30 +784,3 @@ struct pam_module _pam_rhosts_auth_modstruct = { }; #endif - -/* - * $Log: pam_rhosts_auth.c,v $ - * Revision 1.12 1997/09/27 14:34:01 morgan - * fixed comment and renamed iruserok to pam_iruserok. - * - * Revision 1.11 1997/04/05 06:26:39 morgan - * fairly major fixes and enhancements (see CHANGELOG for 0.57 release) - * - * Revision 1.10 1997/02/09 02:09:30 morgan - * - implementation of 'debug' argument (Cristian Gafton) - * - we check for uid=0 accounts instead of hardcoded 'root' (Cristian Gafton) - * - * Revision 1.9 1996/12/01 03:09:47 morgan - * *** empty log message *** - * - * Revision 1.8 1996/11/12 06:08:59 morgan - * Oliver Crow's "rootok" patch plus a little clean up of set_option - * (AGM) - * - * Revision 1.7 1996/11/10 20:15:56 morgan - * cross platform support - * - * Revision 1.6 1996/08/09 05:46:29 morgan - * removed code for manually setting the remote username etc.. - * - */ diff --git a/contrib/libpam/modules/pam_rootok/Makefile b/contrib/libpam/modules/pam_rootok/Makefile index b37870801193..b908b1157ac2 100644 --- a/contrib/libpam/modules/pam_rootok/Makefile +++ b/contrib/libpam/modules/pam_rootok/Makefile @@ -1,111 +1,15 @@ # -# $Id: Makefile,v 1.7 1997/04/05 06:25:20 morgan Exp $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.7 1997/04/05 06:25:20 morgan -# fakeroot -# -# Revision 1.6 1997/02/15 19:15:50 morgan -# fixed email -# -# Revision 1.5 1996/11/10 20:16:10 morgan -# cross platform support -# -# Revision 1.4 1996/09/05 06:29:36 morgan -# ld --> gcc -# -# Revision 1.3 1996/05/26 15:47:46 morgan -# make dynamic/static dirs! -# -# Revision 1.2 1996/05/26 04:04:53 morgan -# automated static support -# -# Revision 1.1 1996/05/05 17:14:15 morgan -# Initial revision -# -# -# Created by Andrew Morgan 1996/5/5 +# Created by Andrew Morgan 2000/08/27 # +include ../../Make.Rules + TITLE=pam_rootok -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< - +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_rootok/README b/contrib/libpam/modules/pam_rootok/README index d7010dd9738d..eee59ff02b0c 100644 --- a/contrib/libpam/modules/pam_rootok/README +++ b/contrib/libpam/modules/pam_rootok/README @@ -1,4 +1,4 @@ -# $Id: README,v 1.1 1996/05/10 04:15:31 morgan Exp $ +# $Id: README,v 1.1.1.1 2000/06/20 22:11:56 agmorgan Exp $ # this module is an authentication module that performs one task: if the diff --git a/contrib/libpam/modules/pam_rootok/pam_rootok.c b/contrib/libpam/modules/pam_rootok/pam_rootok.c index 21327d42e5ea..54795e3c2b3d 100644 --- a/contrib/libpam/modules/pam_rootok/pam_rootok.c +++ b/contrib/libpam/modules/pam_rootok/pam_rootok.c @@ -1,22 +1,13 @@ /* pam_rootok module */ /* - * $Id: pam_rootok.c,v 1.5 1997/02/15 17:32:47 morgan Exp $ - * - * Written by Andrew Morgan 1996/3/11 - * - * $Log: pam_rootok.c,v $ - * Revision 1.5 1997/02/15 17:32:47 morgan - * removed fixed syslog buffer - * - * Revision 1.4 1996/12/01 03:10:14 morgan - * reformatted - * - * Revision 1.3 1996/06/02 08:11:01 morgan - * updated for new static protocol + * $Id: pam_rootok.c,v 1.1.1.1 2000/06/20 22:11:56 agmorgan Exp $ * + * Written by Andrew Morgan 1996/3/11 */ +#define _GNU_SOURCE + #include #include #include diff --git a/contrib/libpam/modules/pam_securetty/Makefile b/contrib/libpam/modules/pam_securetty/Makefile index d8a09ea13377..8ac853c595ff 100644 --- a/contrib/libpam/modules/pam_securetty/Makefile +++ b/contrib/libpam/modules/pam_securetty/Makefile @@ -1,83 +1,15 @@ # +# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $ +# # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # +# Created by Andrew Morgan 2000/08/27 +# + +include ../../Make.Rules TITLE=pam_securetty -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_securetty/pam_securetty.c b/contrib/libpam/modules/pam_securetty/pam_securetty.c index 369fb03dd060..9e6121e8be97 100644 --- a/contrib/libpam/modules/pam_securetty/pam_securetty.c +++ b/contrib/libpam/modules/pam_securetty/pam_securetty.c @@ -8,18 +8,10 @@ * July 25, 1996. * This code shamelessly ripped from the pam_rootok module. * Slight modifications AGM. 1996/12/3 - * $Log: pam_securetty.c,v $ - * Revision 1.7 1997/04/05 06:24:23 morgan - * changed return value on user unknown error - * - * Revision 1.6 1997/02/15 17:30:36 morgan - * removed fixed length syslog buffer - * - * Revision 1.5 1997/02/09 02:22:24 morgan - * added "debug" flag handling (Cristian Gafton) - * */ +#define _GNU_SOURCE + #include #include #include @@ -28,7 +20,7 @@ #include #include #include -#include +#include #define PAM_SM_AUTH @@ -97,13 +89,20 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc /* parse the arguments */ ctrl = _pam_parse(argc, argv); - retval = pam_get_item(pamh,PAM_USER,(const void **)&username); - if (retval == PAM_SUCCESS) - retval = pam_get_item(pamh,PAM_TTY,(const void **)&uttyname); + retval = pam_get_user(pamh, &username, NULL); + if (retval != PAM_SUCCESS || username == NULL) { + if (ctrl & PAM_DEBUG_ARG) { + _pam_log(LOG_WARNING, "cannot determine username"); + } + return (retval == PAM_CONV_AGAIN + ? PAM_INCOMPLETE:PAM_SERVICE_ERR); + } + + retval = pam_get_item(pamh, PAM_TTY, (const void **)&uttyname); if (retval != PAM_SUCCESS || uttyname == NULL) { - /* If we couldn't get the username or the tty return error */ - if (ctrl & PAM_DEBUG_ARG) - _pam_log(LOG_WARNING, "can not determine tty I'm running on !"); + if (ctrl & PAM_DEBUG_ARG) { + _pam_log(LOG_WARNING, "cannot determine user's tty"); + } return PAM_SERVICE_ERR; } @@ -111,36 +110,24 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc if (strncmp(TTY_PREFIX, uttyname, sizeof(TTY_PREFIX)-1) == 0) uttyname += sizeof(TTY_PREFIX)-1; - /* If we didn't get a username, get one */ - if(!username || (strlen(username) <= 0)) { - /* Don't let them use a NULL username... */ - (void) pam_set_item(pamh, PAM_USER, NULL); - pam_get_user(pamh,&username,NULL); - if (retval != PAM_SUCCESS || username == NULL || *username == '\0') { - if (ctrl & PAM_DEBUG_ARG) - _pam_log(LOG_WARNING, - "can not determine username for this service!"); - return PAM_SERVICE_ERR; - } + user_pwd = getpwnam(username); + if (user_pwd == NULL) { + return PAM_IGNORE; + } else if (user_pwd->pw_uid != 0) { /* If the user is not root, + securetty's does not apply + to them */ + return PAM_SUCCESS; } - user_pwd = getpwnam(username); - if (user_pwd == NULL) - return PAM_IGNORE; - else if (user_pwd->pw_uid != 0) /* If the user is not root, - securetty's does not apply to them */ - return PAM_SUCCESS; - - if(stat(SECURETTY_FILE,&ttyfileinfo)) { - _pam_log(LOG_NOTICE, - "Couldn't open " SECURETTY_FILE); + if (stat(SECURETTY_FILE, &ttyfileinfo)) { + _pam_log(LOG_NOTICE, "Couldn't open " SECURETTY_FILE); return PAM_SUCCESS; /* for compatibility with old securetty handling, this needs to succeed. But we still log the error. */ } - if((ttyfileinfo.st_mode & S_IWOTH) - || !S_ISREG(ttyfileinfo.st_mode)) { + if ((ttyfileinfo.st_mode & S_IWOTH) + || !S_ISREG(ttyfileinfo.st_mode)) { /* If the file is world writable or is not a normal file, return error */ _pam_log(LOG_ERR, SECURETTY_FILE diff --git a/contrib/libpam/modules/pam_shells/Makefile b/contrib/libpam/modules/pam_shells/Makefile index 121b19a00863..f1d7ff515187 100644 --- a/contrib/libpam/modules/pam_shells/Makefile +++ b/contrib/libpam/modules/pam_shells/Makefile @@ -1,84 +1,15 @@ # +# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $ +# # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # +# Created by Andrew Morgan 2000/08/27 +# + +include ../../Make.Rules TITLE=pam_shells -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< - +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_shells/pam_shells.c b/contrib/libpam/modules/pam_shells/pam_shells.c index edc9134b3274..36dd1a917e4e 100644 --- a/contrib/libpam/modules/pam_shells/pam_shells.c +++ b/contrib/libpam/modules/pam_shells/pam_shells.c @@ -1,4 +1,4 @@ -/* pam_securetty module */ +/* pam_shells module */ #define SHELL_FILE "/etc/shells" @@ -8,6 +8,8 @@ * This code shamelessly ripped from the pam_securetty module. */ +#define _BSD_SOURCE + #include #include #include @@ -71,21 +73,21 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc userShell = pw->pw_shell; if(stat(SHELL_FILE,&sb)) { - _pam_log(LOG_ERR, SHELL_FILE, " cannot be stat'd (it probably does " - "not exist)"); + _pam_log(LOG_ERR, + "%s cannot be stat'd (it probably does not exist)", SHELL_FILE); return PAM_AUTH_ERR; /* must have /etc/shells */ } if((sb.st_mode & S_IWOTH) || !S_ISREG(sb.st_mode)) { - _pam_log(LOG_ERR, - SHELL_FILE " is either world writable or not a normal file"); - return PAM_AUTH_ERR; + _pam_log(LOG_ERR, + "%s is either world writable or not a normal file", SHELL_FILE); + return PAM_AUTH_ERR; } shellFile = fopen(SHELL_FILE,"r"); if(shellFile == NULL) { /* Check that we opened it successfully */ - _pam_log(LOG_ERR, - "Error opening " SHELL_FILE); + _pam_log(LOG_ERR, + "Error opening %s", SHELL_FILE); return PAM_SERVICE_ERR; } /* There should be no more errors from here on */ diff --git a/contrib/libpam/modules/pam_stress/Makefile b/contrib/libpam/modules/pam_stress/Makefile index 52e8e21881a3..3512c853aef9 100644 --- a/contrib/libpam/modules/pam_stress/Makefile +++ b/contrib/libpam/modules/pam_stress/Makefile @@ -1,109 +1,15 @@ # -# $Id: Makefile,v 1.7 1997/04/05 06:23:08 morgan Exp $ -# -# Created by Andrew Morgan 1996/3/11 +# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.7 1997/04/05 06:23:08 morgan -# fakeroot -# -# Revision 1.6 1997/02/15 19:05:55 morgan -# fixed email -# -# Revision 1.5 1996/11/10 20:17:55 morgan -# cross platform support -# -# Revision 1.4 1996/09/05 06:31:09 morgan -# ld --> gcc -# -# Revision 1.3 1996/05/26 15:50:43 morgan -# make dynamic and static dirs -# -# Revision 1.2 1996/05/26 04:11:56 morgan -# automated static support -# -# +# Created by Andrew Morgan 2000/08/27 # +include ../../Make.Rules + TITLE=pam_stress -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak - -.c.o: - $(CC) $(CFLAGS) -c $< - +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_stress/README b/contrib/libpam/modules/pam_stress/README index 1cb7c14b73c3..b4273f501ff4 100644 --- a/contrib/libpam/modules/pam_stress/README +++ b/contrib/libpam/modules/pam_stress/README @@ -1,5 +1,5 @@ # -# $Id: README,v 1.7 1997/02/15 19:07:08 morgan Exp $ +# $Id: README,v 1.1.1.1 2000/06/20 22:11:57 agmorgan Exp $ # # This describes the behavior of this module with respect to the # /etc/pam.conf file. diff --git a/contrib/libpam/modules/pam_stress/pam_stress.c b/contrib/libpam/modules/pam_stress/pam_stress.c index 501541850461..52d9e8041ec8 100644 --- a/contrib/libpam/modules/pam_stress/pam_stress.c +++ b/contrib/libpam/modules/pam_stress/pam_stress.c @@ -1,34 +1,18 @@ /* pam_stress module */ -/* $Id: pam_stress.c,v 1.12 1997/02/15 19:06:30 morgan Exp morgan $ - * - * created by Andrew Morgan 1996/3/12 - * - * $Log: pam_stress.c,v $ - * Revision 1.12 1997/02/15 19:06:30 morgan - * fixed email - * - * Revision 1.11 1997/02/15 17:33:24 morgan - * removed fixed syslog buffer - * - * Revision 1.10 1996/12/01 03:11:35 morgan - * using _pam_macros.h now - * - * Revision 1.9 1996/11/10 20:18:10 morgan - * changes for .53 compilation - * - * Revision 1.8 1996/09/05 06:31:59 morgan - * changed return value of wipe_up from int to void - * - * Revision 1.7 1996/06/02 08:12:28 morgan - * updated for new static protocol, added STRESS to various user prompts - * and added rootok flag for pam_sm_chauthtok to look out for +/* $Id: pam_stress.c,v 1.2 2000/11/19 23:54:05 agmorgan Exp $ * + * created by Andrew Morgan 1996/3/12 */ +#include + #include #include + +#define __USE_BSD #include + #include #include #include diff --git a/contrib/libpam/modules/pam_tally/Makefile b/contrib/libpam/modules/pam_tally/Makefile index ec17ff31fa8e..032b93416bd9 100644 --- a/contrib/libpam/modules/pam_tally/Makefile +++ b/contrib/libpam/modules/pam_tally/Makefile @@ -1,20 +1,19 @@ # -# $Id: Makefile,v 1.1 1997/04/05 06:19:04 morgan Exp $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $ # -# This Makefile controls a build process of $(TITLE) module for -# Linux-PAM. You should not modify this Makefile (unless you know -# what you are doing!). -# -# $Log: Makefile,v $ -# Revision 1.1 1997/04/05 06:19:04 morgan -# Initial revision +# This Makefile controls a build process of $(TITLE) module and +# application for Linux-PAM. You should not modify this Makefile +# (unless you know what you are doing!). # # +include ../../Make.Rules + TITLE=pam_tally # -## Should add some more rules to make the application too. +## Additional rules for making (and moving) the application added. +## Assuming that all modules' applications are called $TITLE # LIBSRC = $(TITLE).c @@ -22,6 +21,11 @@ LIBOBJ = $(TITLE).o LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) LIBOBJS = $(addprefix static/,$(LIBOBJ)) +APPSRC = $(TITLE)_app.c +APPOBJ = $(TITLE)_app.o +APPOBJD = $(addprefix dynamic/,$(APPOBJ)) +APPOBJS = $(addprefix static/,$(APPOBJ)) + dynamic/%.o : %.c $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ @@ -37,14 +41,12 @@ ifdef STATIC LIBSTATIC = lib$(TITLE).o endif +APPLICATION = $(TITLE) +APPMODE = 755 + ####################### don't edit below ####################### -dummy: - - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register +all: dirs $(LIBSHARED) $(LIBSTATIC) register $(APPLICATION) dirs: ifdef DYNAMIC @@ -62,8 +64,12 @@ endif ifdef DYNAMIC $(LIBOBJD): $(LIBSRC) -$(LIBSHARED): $(LIBOBJD) +$(LIBSHARED): $(LIBOBJD) $(LD_D) -o $@ $(LIBOBJD) + +$(APPLICATION): $(APPOBJD) + $(CC) $(CFLAGS) -o $@ $< $(LOADLIBES) + endif ifdef STATIC @@ -71,6 +77,9 @@ $(LIBOBJS): $(LIBSRC) $(LIBSTATIC): $(LIBOBJS) $(LD) -r -o $@ $(LIBOBJS) + +$(APPLICATION): $(APPOBJS) + $(CC) $(CFLAGS) -o $@ $< $(LOADLIBES) endif install: all @@ -78,16 +87,17 @@ install: all ifdef DYNAMIC $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) endif + $(MKDIR) $(FAKEROOT)$(SUPLEMENTED) +# $(INSTALL) -m $(APPMODE) $(APPLICATION) $(FAKEROOT)$(SUPLEMENTED) remove: rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so + rm -f $(FAKEROOT)$(SUPLEMENTED)/$(TITLE) clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ + rm -f $(LIBOBJD) $(LIBOBJS) $(APPOBJD) $(APPOBJS) core *~ + rm -f *.a *.o *.so *.bak dynamic/* static/* $(APPLICATION) + rm -rf dynamic static -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: +.c.o: $(CC) $(CFLAGS) -c $< - diff --git a/contrib/libpam/modules/pam_tally/README b/contrib/libpam/modules/pam_tally/README index aaa8512bade4..b58b24e45793 100644 --- a/contrib/libpam/modules/pam_tally/README +++ b/contrib/libpam/modules/pam_tally/README @@ -1,4 +1,3 @@ - SUMMARY: pam_tally: @@ -12,10 +11,12 @@ SUMMARY: * file=/where/to/keep/counts (default /var/log/faillog) (auth) + Authentication phase increments attempted login counter. * no_magic_root (root DOES increment counter. Use for daemon-based stuff, like telnet/rsh/login) (account) + Account phase can deny access and/or reset attempts counter. * deny=n (deny access if tally for this user exceeds n; The presence of deny=n changes the default for reset/no_reset to reset, unless the user trying to @@ -34,11 +35,54 @@ SUMMARY: This is the default unless deny exists and the user attempting access is NOT magic root. - Also checks to make sure that the list file is a plain + * per_user (If /var/log/faillog contains a non-zero + .fail_max field for this user then use it + instead of deny=n parameter) + + * no_lock_time (Don't use .fail_locktime filed in + /var/log/faillog for this user) + + Also checks to make sure that the counts file is a plain file and not world writable. - - Tim Baverstock , Multi Media Machine Ltd. - v0.1 5 March 1997 + - Tim Baverstock , v0.1 5 March 1997 + +LONGER: + +pam_tally comes in two parts: pam_tally.so and pam_tally. + +pam_tally.so sits in a pam config file, in the auth and account sections. + +In the auth section, it increments a per-uid counter for each attempted +login, in the account section, it denies access if attempted logins +exceed some threashold and/or resets that counter to zero on successful +login. + +Root is treated specially: + +1. When a process already running as root tries to access some service, the +access is `magic', and bypasses pam_tally's checks: handy for `su'ing from +root into an account otherwise blocked. However, for services like telnet or +login which always effectively run from the root account, root (ie everyone) +shouldn't be granted this magic status, and the flag `no_magic_root' should +be set in this situation, as noted in the summary above. [This option may +be obsolete, with `sufficient root' processing.] + +2. Normally, failed attempts to access root will NOT cause the root +account to become blocked, to prevent denial-of-service: if your users aren't +given shell accounts and root may only login via `su' or at the machine +console (not telnet/rsh, etc), this is safe. If you really want root to be +blocked for some given service, use even_deny_root_account. + +pam_tally is an (optional) application which can be used to interrogate and +manipulate the counter file. It can display users' counts, set individual +counts, or clear all counts. Setting artificially high counts may be useful +for blocking users without changing their passwords. I found it useful to +clear all counts every midnight from a cron.. + +The counts file is organised as a binary-word array, indexed by uid. You +can probably make sense of it with `od', if you don't want to use the +supplied appliction. BUGS: diff --git a/contrib/libpam/modules/pam_tally/faillog.h b/contrib/libpam/modules/pam_tally/faillog.h new file mode 100644 index 000000000000..0f16261bbd9c --- /dev/null +++ b/contrib/libpam/modules/pam_tally/faillog.h @@ -0,0 +1,55 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * faillog.h - login failure logging file format + * + * $Id: faillog.h,v 1.1.1.1 2000/06/20 22:11:59 agmorgan Exp $ + * + * The login failure file is maintained by login(1) and faillog(8) + * Each record in the file represents a separate UID and the file + * is indexed in that fashion. + */ + +#ifndef _FAILLOG_H +#define _FAILLOG_H + +struct faillog { + short fail_cnt; /* failures since last success */ + short fail_max; /* failures before turning account off */ + char fail_line[12]; /* last failure occured here */ + time_t fail_time; /* last failure occured then */ + /* + * If nonzero, the account will be re-enabled if there are no + * failures for fail_locktime seconds since last failure. + */ + long fail_locktime; +}; + +#endif diff --git a/contrib/libpam/modules/pam_tally/pam_tally.c b/contrib/libpam/modules/pam_tally/pam_tally.c index a1b65c04e958..23067f794e6a 100644 --- a/contrib/libpam/modules/pam_tally/pam_tally.c +++ b/contrib/libpam/modules/pam_tally/pam_tally.c @@ -1,7 +1,7 @@ /* * pam_tally.c * - * Revision history? :) 0.1 + * $Id: pam_tally.c,v 1.5 2001/01/20 22:21:22 agmorgan Exp $ */ @@ -11,21 +11,20 @@ * Stuff stolen from pam_rootok and pam_listfile */ -#ifdef linux -# define _GNU_SOURCE -# include -#endif +#include #include -#include +#include #include #include #include #include +#include #include #include #include +#include "faillog.h" #ifndef TRUE #define TRUE 1L @@ -67,6 +66,13 @@ enum TALLY_RESET { # define FILENAME_MAX MAXPATHLEN #endif +struct fail_s { + struct faillog fs_faillog; +#ifndef MAIN + time_t fs_fail_time; +#endif /* ndef MAIN */ +}; + /*---------------------------------------------------------------------*/ /* some syslogging */ @@ -131,19 +137,23 @@ static int pam_get_uid( pam_handle_t *pamh, uid_t *uid, const char **userp ) static int get_tally( tally_t *tally, uid_t uid, const char *filename, - FILE **TALLY ) + FILE **TALLY, + struct fail_s *fsp) { struct stat fileinfo; int lstat_ret = lstat(filename,&fileinfo); if ( lstat_ret && *tally!=TALLY_HI ) { - if ( ( *TALLY=fopen(filename, "a") ) ) { - /* Create file, or append-open in pathological case. */ + int oldmask = umask(077); + *TALLY=fopen(filename, "a"); + /* Create file, or append-open in pathological case. */ + umask(oldmask); + if ( !*TALLY ) { _pam_log(LOG_ALERT, "Couldn't create %s",filename); return PAM_AUTH_ERR; } + lstat_ret = fstat(fileno(*TALLY),&fileinfo); fclose(*TALLY); - lstat_ret = lstat(filename,&fileinfo); } if ( lstat_ret ) { @@ -171,14 +181,18 @@ static int get_tally( tally_t *tally, return PAM_AUTH_ERR; } - if ( fseek( *TALLY, uid * sizeof (tally_t), SEEK_SET ) ) { - _pam_log(LOG_ALERT, "fseek failed %s", filename); - return PAM_AUTH_ERR; - } - - if ( ( fread(tally, sizeof(tally_t), 1, *TALLY) )==0 ) { - *tally=0; /* Assuming a gappy filesystem */ + if ( fseek( *TALLY, uid * sizeof(struct faillog), SEEK_SET ) ) { + _pam_log(LOG_ALERT, "fseek failed %s", filename); + return PAM_AUTH_ERR; + } + + + if (( fread((char *) &fsp->fs_faillog, + sizeof(struct faillog), 1, *TALLY) )==0 ) { + *tally=0; /* Assuming a gappy filesystem */ } + *tally = fsp->fs_faillog.fail_cnt; + return PAM_SUCCESS; } @@ -189,16 +203,18 @@ static int get_tally( tally_t *tally, static int set_tally( tally_t tally, uid_t uid, const char *filename, - FILE **TALLY ) + FILE **TALLY, + struct fail_s *fsp) { if ( tally!=TALLY_HI ) { - if ( fseek( *TALLY, uid * sizeof(tally_t), SEEK_SET ) ) { - _pam_log(LOG_ALERT, "fseek failed %s", filename); - return PAM_AUTH_ERR; + if ( fseek( *TALLY, uid * sizeof(struct faillog), SEEK_SET ) ) { + _pam_log(LOG_ALERT, "fseek failed %s", filename); + return PAM_AUTH_ERR; } - - if ( fwrite(&tally, sizeof(tally_t), 1, *TALLY)==0 ) { + fsp->fs_faillog.fail_cnt = tally; + if (fwrite((char *) &fsp->fs_faillog, + sizeof(struct faillog), 1, *TALLY)==0 ) { _pam_log(LOG_ALERT, "tally update (fputc) failed.", filename); return PAM_AUTH_ERR; } @@ -284,12 +300,37 @@ static int tally_bump (int inc, FILE *TALLY = NULL; const char - *user = NULL; + *user = NULL, + *remote_host = NULL, + *cur_tty = NULL; + struct fail_s fs, *fsp = &fs; int i=pam_get_uid(pamh, &uid, &user); if ( i != PAM_SUCCESS ) RETURN_ERROR( i ); - i=get_tally( &tally, uid, filename, &TALLY ); + i=get_tally( &tally, uid, filename, &TALLY, fsp ); + + /* to remember old fail time (for locktime) */ + fsp->fs_fail_time = fsp->fs_faillog.fail_time; + fsp->fs_faillog.fail_time = (time_t) time( (time_t *) 0); + (void) pam_get_item(pamh, PAM_RHOST, (const void **)&remote_host); + if (!remote_host) + { + (void) pam_get_item(pamh, PAM_TTY, (const void **)&cur_tty); + if (!cur_tty) + strcpy(fsp->fs_faillog.fail_line, "unknown"); + else { + strncpy(fsp->fs_faillog.fail_line, cur_tty, + (size_t)sizeof(fsp->fs_faillog.fail_line)); + fsp->fs_faillog.fail_line[sizeof(fsp->fs_faillog.fail_line)-1] = 0; + } + } + else + { + strncpy(fsp->fs_faillog.fail_line, remote_host, + (size_t)sizeof(fsp->fs_faillog.fail_line)); + fsp->fs_faillog.fail_line[sizeof(fsp->fs_faillog.fail_line)-1] = 0; + } if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); RETURN_ERROR( i ); } if ( no_magic_root || getuid() ) { /* no_magic_root kills uid test */ @@ -303,7 +344,7 @@ static int tally_bump (int inc, } } - i=set_tally( tally, uid, filename, &TALLY ); + i=set_tally( tally, uid, filename, &TALLY, fsp ); if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); RETURN_ERROR( i ); } } @@ -370,6 +411,8 @@ PAM_FUNCTION( pam_sm_acct_mgmt ) { char no_magic_root = FALSE, even_deny_root_account = FALSE; + char per_user = FALSE; /* if true then deny=.fail_max for user */ + char no_lock_time = FALSE; /* if true then don't use .fail_locktime */ const char *user = NULL; @@ -424,6 +467,14 @@ PAM_FUNCTION( pam_sm_acct_mgmt ) { else if ( ! strcmp( *argv, "onerr=succeed" ) ) { fail_on_error=FALSE; } + else if ( ! strcmp( *argv, "per_user" ) ) + { + per_user = TRUE; + } + else if ( ! strcmp( *argv, "no_lock_time") ) + { + no_lock_time = TRUE; + } else { _pam_log(LOG_ERR, MODULE_NAME ": unknown option; %s",*argv); } @@ -431,17 +482,38 @@ PAM_FUNCTION( pam_sm_acct_mgmt ) { } { + struct fail_s fs, *fsp = &fs; FILE *TALLY=0; int i=pam_get_uid(pamh, &uid, &user); if ( i != PAM_SUCCESS ) RETURN_ERROR( i ); - i=get_tally( &tally, uid, filename, &TALLY ); + i=get_tally( &tally, uid, filename, &TALLY, fsp ); if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); RETURN_ERROR( i ); } if ( no_magic_root || getuid() ) { /* no_magic_root kills uid test */ /* To deny or not to deny; that is the question */ + /* if there's .fail_max entry and per_user=TRUE then deny=.fail_max */ + + if ( (fsp->fs_faillog.fail_max) && (per_user) ) { + deny = fsp->fs_faillog.fail_max; + } + if (fsp->fs_faillog.fail_locktime && fsp->fs_fail_time + && (!no_lock_time) ) + { + if ( (fsp->fs_faillog.fail_locktime + fsp->fs_fail_time) + > (time_t)time((time_t)0) ) + { + _pam_log(LOG_NOTICE, + "user %s ("UID_FMT") has time limit [%lds left]" + " since last failure.", + user,uid, + fsp->fs_fail_time+fsp->fs_faillog.fail_locktime + -(time_t)time((time_t)0)); + return PAM_AUTH_ERR; + } + } if ( ( deny != 0 ) && /* deny==0 means no deny */ ( tally > deny ) && /* tally>deny means exceeded */ @@ -467,8 +539,12 @@ PAM_FUNCTION( pam_sm_acct_mgmt ) { if ( reset == TALLY_RESET_RESET ) { tally=0; } } - - i=set_tally( tally, uid, filename, &TALLY ); + if (tally == 0) + { + fsp->fs_faillog.fail_time = (time_t) 0; + strcpy(fsp->fs_faillog.fail_line, ""); + } + i=set_tally( tally, uid, filename, &TALLY, fsp ); if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); RETURN_ERROR( i ); } } @@ -557,6 +633,8 @@ static int getopts( int argc, char **argv ) { int main ( int argc, char **argv ) { + struct fail_s fs, *fsp = &fs; + if ( ! getopts( argc, argv+1 ) ) { printf("%s: [--file rooted-filename] [--user username] " "[--reset[=n]] [--quiet]\n", @@ -564,6 +642,8 @@ int main ( int argc, char **argv ) { exit(0); } + umask(077); + /* * Major difference between individual user and all users: * --user just handles one user, just like PAM. @@ -580,7 +660,7 @@ int main ( int argc, char **argv ) { exit(0); } - i=get_tally( &tally, uid, cline_filename, &TALLY ); + i=get_tally( &tally, uid, cline_filename, &TALLY, fsp ); if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); fprintf(stderr,"%s: %s\n",*argv,pam_errors(i)); @@ -591,7 +671,7 @@ int main ( int argc, char **argv ) { printf("User %s\t("UID_FMT")\t%s "TALLY_FMT"\n",cline_user,uid, (cline_reset!=TALLY_HI)?"had":"has",tally); - i=set_tally( cline_reset, uid, cline_filename, &TALLY ); + i=set_tally( cline_reset, uid, cline_filename, &TALLY, fsp ); if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); fprintf(stderr,"%s: %s\n",*argv,pam_errors(i)); @@ -606,7 +686,13 @@ int main ( int argc, char **argv ) { for ( ; !feof(TALLY); uid++ ) { tally_t tally; struct passwd *pw; - if ( ! fread(&tally, sizeof(tally_t), 1, TALLY) || ! tally ) continue; + if ( ! fread((char *) &fsp->fs_faillog, + sizeof (struct faillog), 1, TALLY) + || ! fsp->fs_faillog.fail_cnt ) { + tally=fsp->fs_faillog.fail_cnt; + continue; + } + tally = fsp->fs_faillog.fail_cnt; if ( ( pw=getpwuid(uid) ) ) { printf("User %s\t("UID_FMT")\t%s "TALLY_FMT"\n",pw->pw_name,uid, diff --git a/contrib/libpam/modules/pam_tally/pam_tally_app.c b/contrib/libpam/modules/pam_tally/pam_tally_app.c new file mode 100644 index 000000000000..9e6e1fafd062 --- /dev/null +++ b/contrib/libpam/modules/pam_tally/pam_tally_app.c @@ -0,0 +1,7 @@ +/* + # This seemed like such a good idea at the time. :) + */ + +#define MAIN +#include "pam_tally.c" + diff --git a/contrib/libpam/modules/pam_time/Makefile b/contrib/libpam/modules/pam_time/Makefile index bc297d4f9853..4aa4e2761ee0 100644 --- a/contrib/libpam/modules/pam_time/Makefile +++ b/contrib/libpam/modules/pam_time/Makefile @@ -1,121 +1,21 @@ -# -# $Id: Makefile,v 1.6 1997/04/05 06:22:32 morgan Exp morgan $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.6 1997/04/05 06:22:32 morgan -# fakeroot -# -# Revision 1.5 1997/02/15 19:16:16 morgan -# fixed email -# -# Revision 1.4 1996/11/10 20:18:21 morgan -# cross platform support -# -# Revision 1.3 1996/09/05 06:27:37 morgan -# ld --> gcc -# -# Revision 1.2 1996/08/09 05:48:19 morgan -# inherit installation files from parent -# -# Revision 1.1 1996/07/07 23:42:48 morgan -# Initial revision -# -# Revision 1.1 1996/06/24 05:48:49 morgan -# Initial revision -# -# -# Created by Andrew Morgan 1996/6/11 -# + +include ../../Make.Rules TITLE=pam_time -CONFD=$(CONFIGED)/security -export CONFD -CONFILE=$(CONFD)/time.conf -export CONFILE - -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -DEFS=-DCONFILE=\"$(CONFILE)\" +LOCAL_CONFILE=./time.conf +INSTALLED_CONFILE=$(SCONFIGD)/time.conf +DEFS=-DDEFAULT_CONF_FILE=\"$(INSTALLED_CONFILE)\" CFLAGS += $(DEFS) -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all -ifdef DYNAMIC - $(MKDIR) $(FAKEROOT)$(SECUREDIR) - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - $(MKDIR) $(FAKEROOT)$(SCONFIGED) - bash -f ./install_conf - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - rm -f $(FAKEROOT)$(CONFILE) - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - rm -f ./.ignore_age - -extraclean: clean - rm -f *.a *.o *.so *.bak - -.c.o: - $(CC) $(CFLAGS) -c $< +MODULE_SIMPLE_INSTALL=bash -f ../install_conf "$(FAKEROOT)" "$(SCONFIGD)" "$(INSTALLED_CONFILE)" "$(TITLE)" "$(LOCAL_CONFILE)" +MODULE_SIMPLE_REMOVE=rm -f $(FAKEROOT)$(INSTALLED_CONFILE) +MODULE_SIMPLE_CLEAN=rm -f ./.ignore_age +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_time/README b/contrib/libpam/modules/pam_time/README index 0c3f976b4012..0228b907fc21 100644 --- a/contrib/libpam/modules/pam_time/README +++ b/contrib/libpam/modules/pam_time/README @@ -1,4 +1,4 @@ -$Id: README,v 1.3 1997/01/04 20:42:43 morgan Exp $ +$Id: README,v 1.2 2000/12/04 19:02:35 baggins Exp $ This is a help file for the pam_time module. It explains the need for pam_time and also the syntax of the /etc/security/time.conf file. @@ -28,10 +28,3 @@ unrecognised rules are ignored (but an error is logged to syslog(3)) -------------------- Bugs to Andrew or the list - -######################################################################## -# $Log: README,v $ -# Revision 1.3 1997/01/04 20:42:43 morgan -# I want email on parc now -# -# \ No newline at end of file diff --git a/contrib/libpam/modules/pam_time/pam_time.c b/contrib/libpam/modules/pam_time/pam_time.c index 489c1d734ae0..a517abf0e3d2 100644 --- a/contrib/libpam/modules/pam_time/pam_time.c +++ b/contrib/libpam/modules/pam_time/pam_time.c @@ -1,25 +1,19 @@ /* pam_time module */ /* - * $Id: pam_time.c,v 1.7 1997/02/15 17:32:21 morgan Exp $ + * $Id: pam_time.c,v 1.3 2000/11/26 07:32:39 agmorgan Exp $ * - * Written by Andrew Morgan 1996/6/22 + * Written by Andrew Morgan 1996/6/22 * (File syntax and much other inspiration from the shadow package * shadow-960129) - * - * $Log: pam_time.c,v $ - * Revision 1.7 1997/02/15 17:32:21 morgan - * time parsing more robust - * - * Revision 1.6 1997/01/04 20:43:15 morgan - * fixed buffer underflow, reformatted to 4 spaces - * */ const static char rcsid[] = -"$Id: pam_time.c,v 1.7 1997/02/15 17:32:21 morgan Exp $;\n" +"$Id: pam_time.c,v 1.3 2000/11/26 07:32:39 agmorgan Exp $;\n" "\t\tVersion 0.22 for Linux-PAM\n" -"Copyright (C) Andrew G. Morgan 1996 \n"; +"Copyright (C) Andrew G. Morgan 1996 \n"; + +#include #include #include @@ -34,7 +28,11 @@ const static char rcsid[] = #include #include -#define PAM_TIME_CONF CONFILE /* from external define */ +#ifdef DEFAULT_CONF_FILE +# define PAM_TIME_CONF DEFAULT_CONF_FILE /* from external define */ +#else +# define PAM_TIME_CONF "/etc/security/time.conf" +#endif #define PAM_TIME_BUFLEN 1000 #define FIELD_SEPARATOR ';' /* this is new as of .02 */ @@ -124,6 +122,7 @@ static int read_field(int fd, char **buf, int *from, int *to) _log_err("error reading " PAM_TIME_CONF); return -1; } else if (!i) { + close(fd); fd = -1; /* end of file reached */ } else *to += i; @@ -167,6 +166,8 @@ static int read_field(int fd, char **buf, int *from, int *to) if ((*buf)[i+1] == '\n') { shift_bytes(i + *buf, 2, *to - (i+2)); *to -= 2; + } else { + ++i; /* we don't escape non-newline characters */ } break; case '!': @@ -248,7 +249,7 @@ static int logic_member(const char *string, int *at) default: if (isalpha(c) || c == '*' || isdigit(c) || c == '_' - || c == '-' || c == '.') { + || c == '-' || c == '.' || c == '/') { token = 1; } else if (token) { --to; diff --git a/contrib/libpam/modules/pam_unix/CHANGELOG b/contrib/libpam/modules/pam_unix/CHANGELOG index 37e4c8501c9d..509ce0a31a62 100644 --- a/contrib/libpam/modules/pam_unix/CHANGELOG +++ b/contrib/libpam/modules/pam_unix/CHANGELOG @@ -1,6 +1,55 @@ -$Id: CHANGELOG,v 1.1 1996/11/09 19:42:41 morgan Exp $ +$Id: CHANGELOG,v 1.1.1.1 2000/06/20 22:12:01 agmorgan Exp $ -$Log: CHANGELOG,v $ -Revision 1.1 1996/11/09 19:42:41 morgan -Initial revision +* Mon Aug 16 1999 Jan Rêkorajski +- fixed reentrancy problems + +* Sun Jul 4 21:03:42 PDT 1999 + +- temporarily removed the crypt16 stuff. I'm really paranoid about + crypto stuff and exporting it, and there are a few too many 's-box' + references in the code for my liking.. + +* Wed Jun 30 1999 Steve Langasek +- further NIS+ fixes + +* Sun Jun 27 1999 Steve Langasek +- fix to uid-handling code for NIS+ + +* Sat Jun 26 1999 Jan Rêkorajski +- merged MD5 fix and early failure syslog + by Andrey Vladimirovich Savochkin +- minor fixes +- added signal handler to unix_chkpwd + +* Fri Jun 25 1999 Stephen Langasek +- reorganized the code to let it build as separate C files + +* Sun Jun 20 1999 Jan Rêkorajski +- fixes in pam_unix_auth, it incorrectly saved and restored return + value when likeauth option was used + +* Tue Jun 15 1999 Jan Rêkorajski +- added NIS+ support + +* Mon Jun 14 1999 Jan Rêkorajski +- total rewrite based on pam_pwdb module, now there is ONE pam_unix.so + module, it accepts the same options as pam_pwdb - all of them correctly ;) + (pam_pwdb dosn't understand what DISALLOW_NULL_AUTHTOK means) + +* Tue Apr 20 1999 Jan Rêkorajski +- Arghhh, pam_unix_passwd was not updating /etc/shadow when used with + pam_cracklib. + +* Mon Apr 19 1999 Jan Rêkorajski +- added "remember=XXX" option that means 'remember XXX old passwords' + Old passwords are stored in /etc/security/opasswd, there can be + maximum of 400 passwords per user. + +* Sat Mar 27 1999 Jan Rêkorajski +- added crypt16 to pam_unix_auth and pam_unix_passwd (check only, this algorithm + is too lame to use it in real life) + +* Sun Mar 21 1999 Jan Rêkorajski +- pam_unix_auth now correctly behave when user has NULL AUTHTOK +- pam_unix_auth returns PAM_PERM_DENIED when seteuid fails diff --git a/contrib/libpam/modules/pam_unix/Makefile b/contrib/libpam/modules/pam_unix/Makefile index ad1f47f185e4..9329aa6e1006 100644 --- a/contrib/libpam/modules/pam_unix/Makefile +++ b/contrib/libpam/modules/pam_unix/Makefile @@ -1,100 +1,91 @@ -# $Header$ +# $Id: Makefile,v 1.3 2001/02/11 06:33:53 agmorgan Exp $ # # This Makefile controls a build process of the pam_unix modules # for Linux-PAM. You should not modify this Makefile. # -# $Log$ -# Revision 1.1.1.2 1998/06/03 03:43:56 adam -# Import from archive -# -# Revision 1.3 1998/05/31 23:48:13 adam -# Link crypt library as necessary. -# -# Revision 1.3 1997/04/05 06:20:58 morgan -# fakeroot and also lockpwdf is in libc now -# -# Revision 1.2 1996/11/10 20:18:59 morgan -# cross platform support -# -# Revision 1.1 1996/11/09 19:44:16 morgan -# Initial revision -# -# + +include ../../Make.Rules ######################################################################## # some options... uncomment to take effect ######################################################################## -# do you want shadow? -USE_SHADOW=-D"HAVE_SHADOW_H" - +# Unless someone wants to work out how to make this work with the new +# autoconf stuff, you should use a separate module for this type of thing +# pam_cracklib perhaps..? # do you want cracklib? -ifeq ($(HAVE_CRACKLIB),yes) -USE_CRACKLIB=-D"USE_CRACKLIB" -endif +#ifeq ($(HAVE_CRACKLIB),yes) +#USE_CRACKLIB=-D"USE_CRACKLIB" +#endif # do you want to use lckpwdf? +ifeq ($(WITH_LCKPWDF),yes) USE_LCKPWDF=-D"USE_LCKPWDF" - # do you need to include the locking functions in the source? -#NEED_LCKPWDF=-D"NEED_LCKPWDF" +ifeq ($(HAVE_LCKPWDF),no) + NEED_LCKPWDF=-D"NEED_LCKPWDF" +endif +endif + +ifeq ($(HAVE_LIBNSL),yes) + LIBNSL = -lnsl +endif + +ifeq ($(HAVE_LIBCRYPT),yes) + LIBCRYPT=-lcrypt +endif + +CHKPWD=unix_chkpwd + +EXTRAS += -DCHKPWD_HELPER=\"$(SUPLEMENTED)/$(CHKPWD)\" ######################################################################## -CFLAGS += $(USE_SHADOW) $(USE_CRACKLIB) $(USE_LCKPWDF) $(NEED_LCKPWDF) - -ifdef DYNAMIC -LIBSESSSH = pam_unix_session.so -LIBAUTHSH = pam_unix_auth.so -LIBPASSWDSH = pam_unix_passwd.so -LIBACCOUNT = pam_unix_acct.so -endif - -ifdef STATIC -LIBSTATIC = libpam_unix.o -endif +CFLAGS += $(USE_CRACKLIB) $(USE_LCKPWDF) $(NEED_LCKPWDF) $(EXTRAS) +LDLIBS = $(EXTRALS) ifdef USE_CRACKLIB CRACKLIB = -lcrack endif -LIBAUTHOBJ = pam_unix_auth.o support.o -LIBAUTHSRC = pam_unix_auth.c support.c -LIBSESSOBJ = pam_unix_sess.o -LIBSESSSRC = pam_unix_sess.c -LIBPASSWDSRC = pam_unix_passwd.c -LIBPASSWDOBJ = pam_unix_passwd.o -LIBACCOUNTSRC = pam_unix_acct.c -LIBACCOUNTOBJ = pam_unix_acct.o -LIBOBJ = $(LIBAUTHOBJ) $(LIBSESSOBJ) $(LIBPASSWDOBJ) $(LIBACCOUNTOBJ) -LIBSRC = $(LIBAUTHSRC) $(LIBSESSSRC) $(LIBPASSWDSRC) $(LIBACCOUNTSRC) - -LIBSHARED = $(LIBSESSSH) $(LIBAUTHSH) $(LIBPASSWDSH) $(LIBACCOUNT) +LIBOBJ = pam_unix_auth.o pam_unix_acct.o pam_unix_sess.o pam_unix_passwd.o \ + support.o +LIBSRC = pam_unix_auth.c pam_unix_acct.c pam_unix_sess.c pam_unix_passwd.c \ + support.c LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) LIBOBJS = $(addprefix static/,$(LIBOBJ)) -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) -c $< -o $@ +PLUS = md5_good.o md5_broken.o md5_crypt_good.o md5_crypt_broken.o \ + yppasswd_xdr.o bigcrypt.o -static/%.o: %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) -c $< -o $@ +ifdef DYNAMIC +LIBSHARED = pam_unix.so +endif +ifdef STATIC +LIBSTATIC = libpam_unix.o +endif ########################### don't edit below ####################### -dummy: +all: dirs info $(PLUS) $(LIBSHARED) $(LIBSTATIC) $(CHKPWD) register +dynamic/%.o : %.c + $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +static/%.o: %.c + $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +dummy: @echo "**** This is not a top-level Makefile " exit info: @echo - @echo "*** Building pam-unix(alpha) module of the framework..." + @echo "*** Building pam-unix module of the framework..." @echo -all: dirs info $(LIBSHARED) $(LIBSTATIC) register - dirs: ifdef DYNAMIC mkdir -p ./dynamic @@ -105,50 +96,71 @@ endif register: ifdef STATIC - ( cd .. ; \ - ./register_static pam_unix_auth pam_unix/$(LIBSTATIC) ; \ - ./register_static pam_unix_acct "" ; \ + ( cd .. ; ./register_static pam_unix_auth pam_unix/$(LIBSTATIC) ; \ + ./register_static pam_unix_acct "" ; \ + ./register_static pam_unix_session "" ; \ + ./register_static pam_unix_passwd "" ; \ ) endif ifdef DYNAMIC $(LIBOBJD): $(LIBSRC) -$(LIBAUTHSH): $(LIBAUTHSRC) $(LIBOBJD) - $(LD_D) -o $@ $(addprefix dynamic/,$(LIBAUTHOBJ)) -lcrypt - -$(LIBSESSSH): $(LIBSESSSRC) $(LIBOBJD) - $(LD_D) -o $@ $(addprefix dynamic/,$(LIBSESSOBJ)) - -$(LIBPASSWDSH): $(LIBPASSWDSRC) $(LIBOBJD) - $(LD_D) -o $@ $(addprefix dynamic/,$(LIBPASSWDOBJ)) $(CRACKLIB) -lcrypt - -$(LIBACCOUNT): $(LIBACCOUNTSRC) $(LIBOBJD) - $(LD_D) -o $@ $(addprefix dynamic/,$(LIBACCOUNTOBJ)) +$(LIBSHARED): $(LIBOBJD) + $(LD_D) -o $@ $(LIBOBJD) $(PLUS) $(CRACKLIB) $(LDLIBS) $(LIBNSL) $(LIBCRYPT) endif - ifdef STATIC $(LIBOBJS): $(LIBSRC) $(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) + $(LD) -r -o $@ $(LIBOBJS) $(PLUS) $(CRACKLIB) $(LDLIBS) $(LIBNSL) $(LIBCRYPT) endif +$(CHKPWD): unix_chkpwd.o md5_good.o md5_broken.o \ + md5_crypt_good.o md5_crypt_broken.o \ + bigcrypt.o + $(CC) -o $(CHKPWD) $^ $(LDLIBS) $(LIBCRYPT) + +unix_chkpwd.o: unix_chkpwd.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +md5_good.o: md5.c + $(CC) $(CFLAGS) $(CPPFLAGS) -DHIGHFIRST -D'MD5Name(x)=Good##x' \ + $(TARGET_ARCH) -c $< -o $@ + +md5_broken.o: md5.c + $(CC) $(CFLAGS) $(CPPFLAGS) -D'MD5Name(x)=Broken##x' \ + $(TARGET_ARCH) -c $< -o $@ + +md5_crypt_good.o: md5_crypt.c + $(CC) $(CFLAGS) $(CPPFLAGS) -D'MD5Name(x)=Good##x' \ + $(TARGET_ARCH) -c $< -o $@ + +md5_crypt_broken.o: md5_crypt.c + $(CC) $(CFLAGS) $(CPPFLAGS) -D'MD5Name(x)=Broken##x' \ + $(TARGET_ARCH) -c $< -o $@ + install: all mkdir -p $(FAKEROOT)$(SECUREDIR) ifdef DYNAMIC install -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) + for x in pam_unix_auth pam_unix_acct pam_unix_passwd pam_unix_session;\ + do ln -sf $(LIBSHARED) $(FAKEROOT)$(SECUREDIR)/$$x.so ; done endif + $(MKDIR) $(FAKEROOT)$(SUPLEMENTED) + install -m 4555 $(CHKPWD) $(FAKEROOT)$(SUPLEMENTED) remove: - cd $(FAKEROOT)$(SECUREDIR) && rm -f $(LIBSHARED) + rm -f $(FAKEROOT)$(SECUREDIR)/$(LIBSHARED) + for x in pam_unix_auth pam_unix_acct pam_unix_passwd pam_unix_session;\ + do rm -f $(FAKEROOT)$(SECUREDIR)/$$x.so ; done + rm -f $(FAKEROOT)$(SUPLEMENTED)/$(CHKPWD) clean: - rm -f $(LIBOBJD) $(LIBOBJS) a.out core *~ - -extraclean: clean - rm -f *.a *.out *.o *.so *.bak + rm -f $(LIBOBJD) $(LIBOBJS) $(CHKPWD) *.o *.so core + rm -f *~ *.a *.out *.bak + rm -rf dynamic static .c.o: $(CC) -c $(CFLAGS) $< diff --git a/contrib/libpam/modules/pam_unix/README b/contrib/libpam/modules/pam_unix/README index 082e99697da2..ad4bc35e488a 100644 --- a/contrib/libpam/modules/pam_unix/README +++ b/contrib/libpam/modules/pam_unix/README @@ -1,39 +1,39 @@ -This is the README for pam_unix in Linux-PAM-0.53. +This is the README for pam_unix in Linux-PAM-0.67. -------------------------------------------------- -pam_unix comes as four separate modules: +pam_unix now comes as one module pam_unix.so. +The following links are left for compatibility with old versions: pam_unix_auth: authentication module providing - pam_authenticate() and pam_setcred() hooks - - NO options are recognized. Credential facilities are trivial - (function simply returns) - + pam_authenticate() and pam_setcred() hooks pam_unix_sess: session module, providing session logging - - "debug" and "trace" arguments are accepted, which indicate the - logging-level for syslog. - - "debug" -> LOG_DEBUG [ also default ] - "trace" -> LOG_AUTHPRIV - pam_unix_acct: account management, providing shadow account - managment features, password aging etc.. - - NO options are recognized. Account managment trivial without - shadow active. - + managment features, password aging etc.. pam_unix_passwd: password updating facilities providing - cracklib password strength checking facilities. + cracklib password strength checking facilities. - if compiled, the default behavior is to check passwords - strictly using CrackLib. This behavior can be turned off - with the argument - - "strict=false" +The following options are recognized: + debug - log more debugging info + audit - a little more extreme than debug + use_first_pass - don 't prompt the user for passwords + take them from PAM_ items instead + try_first_pass - don 't prompt the user for the passwords + unless PAM_(OLD)AUTHTOK is unset + use_authtok - like try_first_pass, but * fail * if the new + PAM_AUTHTOK has not been previously set. + (intended for stacking password modules only) + not_set_pass - don 't set the PAM_ items with the passwords + used by this module. + shadow - try to maintian a shadow based system. + md5 - when a user changes their password next, + encrypt it with the md5 algorithm. + bigcrypt - when a user changes their password next, + excrypt it with the DEC C2 - algorithm(0). + nodelay - used to prevent failed authentication + resulting in a delay of about 1 second. + nis - use NIS RPC for setting new password + remember=X - remember X old passwords, they are kept in + /etc/security/opasswd in MD5 crypted form invalid arguments are logged to syslog. ------------------------------- -- Andrew 1996/11/9 ------------------------------- diff --git a/contrib/libpam/modules/pam_unix/bigcrypt.c b/contrib/libpam/modules/pam_unix/bigcrypt.c new file mode 100644 index 000000000000..b1568d6b340a --- /dev/null +++ b/contrib/libpam/modules/pam_unix/bigcrypt.c @@ -0,0 +1,119 @@ +/* + * This function implements the "bigcrypt" algorithm specifically for + * Linux-PAM. + * + * This algorithm is algorithm 0 (default) shipped with the C2 secure + * implementation of Digital UNIX. + * + * Disclaimer: This work is not based on the source code to Digital + * UNIX, nor am I connected to Digital Equipment Corp, in any way + * other than as a customer. This code is based on published + * interfaces and reasonable guesswork. + * + * Description: The cleartext is divided into blocks of SEGMENT_SIZE=8 + * characters or less. Each block is encrypted using the standard UNIX + * libc crypt function. The result of the encryption for one block + * provides the salt for the suceeding block. + * + * Restrictions: The buffer used to hold the encrypted result is + * statically allocated. (see MAX_PASS_LEN below). This is necessary, + * as the returned pointer points to "static data that are overwritten + * by each call", (XPG3: XSI System Interface + Headers pg 109), and + * this is a drop in replacement for crypt(); + * + * Andy Phillips + */ + +#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 000000000000..b5ff45850b4b --- /dev/null +++ b/contrib/libpam/modules/pam_unix/lckpwdf.-c @@ -0,0 +1,117 @@ +/* + * This is a hack, but until libc and glibc both include this function + * by default (libc only includes it if nys is not being used, at the + * moment, and glibc doesn't appear to have it at all) we need to have + * it here, too. :-( + * + * This should not become an official part of PAM. + * + * BEGIN_HACK + */ + +/* + * lckpwdf.c -- prevent simultaneous updates of password files + * + * Before modifying any of the password files, call lckpwdf(). It may block + * for up to 15 seconds trying to get the lock. Return value is 0 on success + * or -1 on failure. When you are done, call ulckpwdf() to release the lock. + * The lock is also released automatically when the process exits. Only one + * process at a time may hold the lock. + * + * These functions are supposed to be conformant with AT&T SVID Issue 3. + * + * Written by Marek Michalkiewicz , + * 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 000000000000..7ee9ed00cdea --- /dev/null +++ b/contrib/libpam/modules/pam_unix/md5.c @@ -0,0 +1,256 @@ +/* + * $Id: md5.c,v 1.1.1.1 2000/06/20 22:12:03 agmorgan Exp $ + * + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + * + */ + +#include +#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 000000000000..103f168a91c6 --- /dev/null +++ b/contrib/libpam/modules/pam_unix/md5.h @@ -0,0 +1,31 @@ + +#ifndef MD5_H +#define MD5_H + +typedef unsigned int uint32; + +struct MD5Context { + uint32 buf[4]; + uint32 bits[2]; + unsigned char in[64]; +}; + +void GoodMD5Init(struct MD5Context *); +void GoodMD5Update(struct MD5Context *, unsigned const char *, unsigned); +void GoodMD5Final(unsigned char digest[16], struct MD5Context *); +void GoodMD5Transform(uint32 buf[4], uint32 const in[16]); +void BrokenMD5Init(struct MD5Context *); +void BrokenMD5Update(struct MD5Context *, unsigned const char *, unsigned); +void BrokenMD5Final(unsigned char digest[16], struct MD5Context *); +void BrokenMD5Transform(uint32 buf[4], uint32 const in[16]); + +char *Goodcrypt_md5(const char *pw, const char *salt); +char *Brokencrypt_md5(const char *pw, const char *salt); + +/* + * This is needed to make RSAREF happy on some MS-DOS compilers. + */ + +typedef struct MD5Context MD5_CTX; + +#endif /* MD5_H */ diff --git a/contrib/libpam/modules/pam_unix/md5_crypt.c b/contrib/libpam/modules/pam_unix/md5_crypt.c new file mode 100644 index 000000000000..257e4bb6bd06 --- /dev/null +++ b/contrib/libpam/modules/pam_unix/md5_crypt.c @@ -0,0 +1,149 @@ +/* + * $Id: md5_crypt.c,v 1.1.1.1 2000/06/20 22:12:03 agmorgan Exp $ + * + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * 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/pam_unix_acct.c b/contrib/libpam/modules/pam_unix/pam_unix_acct.c index 5c0546aa1f8f..178b6037465a 100644 --- a/contrib/libpam/modules/pam_unix/pam_unix_acct.c +++ b/contrib/libpam/modules/pam_unix/pam_unix_acct.c @@ -1,5 +1,6 @@ /* * Copyright Elliot Lee, 1996. All rights reserved. + * Copyright Jan Rêkorajski, 1999. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,73 +34,159 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* pam_unix_acct.c module, different track */ - -#ifdef linux -# define _GNU_SOURCE -# include -#endif +#include #include #include #include -#define __USE_MISC -#include +#include #include #include -#include -#ifdef HAVE_SHADOW_H +#include #include -#endif -#include +#include /* for time() */ + +#include + +/* indicate that the following groups are defined */ #define PAM_SM_ACCOUNT -#ifndef LINUX -# include -#endif - -#define _PAM_EXTERN_FUNCTIONS #include -PAM_EXTERN -int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ -#ifdef HAVE_SHADOW_H - const char *uname; - int retval; - time_t curdays; - struct spwd *spent; - struct passwd *pwent; +#ifndef LINUX_PAM +#include +#endif /* LINUX_PAM */ - setpwent(); - setspent(); - retval = pam_get_item(pamh,PAM_USER,(const void **)&uname); - if(retval != PAM_SUCCESS || uname == NULL) { - return PAM_SUCCESS; /* Couldn't get username, just ignore this - (i.e. they don't have any expiry info available */ - } - pwent = getpwnam(uname); - if(!pwent) - return PAM_USER_UNKNOWN; - if(strcmp(pwent->pw_passwd,"x")) - return PAM_SUCCESS; /* They aren't using shadow passwords & expiry - info */ - spent = getspnam(uname); - if(!spent) - return PAM_SUCCESS; /* Couldn't get username from shadow, just ignore this - (i.e. they don't have any expiry info available */ - curdays = time(NULL)/(60*60*24); - if((curdays > (spent->sp_lstchg + spent->sp_max + spent->sp_inact)) - && (spent->sp_max != -1) && (spent->sp_inact != -1)) - return PAM_ACCT_EXPIRED; - if((curdays > spent->sp_expire) && (spent->sp_expire != -1)) - return PAM_ACCT_EXPIRED; - endspent(); - endpwent(); -#endif - return PAM_SUCCESS; +#include "support.h" + +/* + * PAM framework looks for this entry-point to pass control to the + * account management module. + */ + +PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags, + int argc, const char **argv) +{ + unsigned int ctrl; + const char *uname; + int retval, daysleft; + time_t curdays; + struct spwd *spent; + struct passwd *pwent; + char buf[80]; + + D(("called.")); + + ctrl = _set_ctrl(pamh, flags, NULL, argc, argv); + + retval = pam_get_item(pamh, PAM_USER, (const void **) &uname); + D(("user = `%s'", uname)); + if (retval != PAM_SUCCESS || uname == NULL) { + _log_err(LOG_ALERT, pamh + ,"could not identify user (from uid=%d)" + ,getuid()); + return PAM_USER_UNKNOWN; + } + + pwent = getpwnam(uname); + if (!pwent) { + _log_err(LOG_ALERT, pamh + ,"could not identify user (from getpwnam(%s))" + ,uname); + return PAM_USER_UNKNOWN; + } + + if (!strcmp( pwent->pw_passwd, "*NP*" )) { /* NIS+ */ + uid_t save_euid, save_uid; + + save_euid = geteuid(); + save_uid = getuid(); + if (save_uid == pwent->pw_uid) + setreuid( save_euid, save_uid ); + else { + setreuid( 0, -1 ); + if (setreuid( -1, pwent->pw_uid ) == -1) { + setreuid( -1, 0 ); + setreuid( 0, -1 ); + if(setreuid( -1, pwent->pw_uid ) == -1) + return PAM_CRED_INSUFFICIENT; + } + } + spent = getspnam( uname ); + if (save_uid == pwent->pw_uid) + setreuid( save_uid, save_euid ); + else { + if (setreuid( -1, 0 ) == -1) + setreuid( save_uid, -1 ); + setreuid( -1, save_euid ); + } + + } else if (!strcmp( pwent->pw_passwd, "x" )) { + spent = getspnam(uname); + } else { + return PAM_SUCCESS; + } + + if (!spent) + return PAM_AUTHINFO_UNAVAIL; /* Couldn't get username from shadow */ + + curdays = time(NULL) / (60 * 60 * 24); + D(("today is %d, last change %d", curdays, spent->sp_lstchg)); + if ((curdays > spent->sp_expire) && (spent->sp_expire != -1) + && (spent->sp_lstchg != 0)) { + _log_err(LOG_NOTICE, pamh + ,"account %s has expired (account expired)" + ,uname); + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + "Your account has expired; please contact your system administrator"); + D(("account expired")); + return PAM_ACCT_EXPIRED; + } + if ((curdays > (spent->sp_lstchg + spent->sp_max + spent->sp_inact)) + && (spent->sp_max != -1) && (spent->sp_inact != -1) + && (spent->sp_lstchg != 0)) { + _log_err(LOG_NOTICE, pamh + ,"account %s has expired (failed to change password)" + ,uname); + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + "Your account has expired; please contact your system administrator"); + D(("account expired 2")); + return PAM_ACCT_EXPIRED; + } + D(("when was the last change")); + if (spent->sp_lstchg == 0) { + _log_err(LOG_NOTICE, pamh + ,"expired password for user %s (root enforced)" + ,uname); + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + "You are required to change your password immediately (root enforced)"); + D(("need a new password")); + return PAM_NEW_AUTHTOK_REQD; + } + if (((spent->sp_lstchg + spent->sp_max) < curdays) && (spent->sp_max != -1)) { + _log_err(LOG_DEBUG, pamh + ,"expired password for user %s (password aged)" + ,uname); + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + "You are required to change your password immediately (password aged)"); + D(("need a new password 2")); + return PAM_NEW_AUTHTOK_REQD; + } + if ((curdays > (spent->sp_lstchg + spent->sp_max - spent->sp_warn)) + && (spent->sp_max != -1) && (spent->sp_warn != -1)) { + daysleft = (spent->sp_lstchg + spent->sp_max) - curdays; + _log_err(LOG_DEBUG, pamh + ,"password for user %s will expire in %d days" + ,uname, daysleft); + snprintf(buf, 80, "Warning: your password will expire in %d day%.2s", + daysleft, daysleft == 1 ? "" : "s"); + _make_remark(pamh, ctrl, PAM_TEXT_INFO, buf); + } + + D(("all done")); + + return PAM_SUCCESS; } diff --git a/contrib/libpam/modules/pam_unix/pam_unix_auth.c b/contrib/libpam/modules/pam_unix/pam_unix_auth.c index 95f13d0abdc6..f08ea515b4d4 100644 --- a/contrib/libpam/modules/pam_unix/pam_unix_auth.c +++ b/contrib/libpam/modules/pam_unix/pam_unix_auth.c @@ -1,8 +1,7 @@ -/* $Header: /home/morgan/pam/Linux-PAM-0.59/modules/pam_unix/RCS/pam_unix_auth.c,v 1.1 1996/11/09 19:44:35 morgan Exp morgan $ */ - /* * Copyright Alexander O. Yuriev, 1996. All rights reserved. * NIS+ support by Thorsten Kukuk + * Copyright Jan Rêkorajski, 1999. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,217 +34,145 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ - -/* - * $Log: pam_unix_auth.c,v $ - * - * Revision 1.9 1996/05/26 04:13:04 morgan - * added static support - * - * Revision 1.8 1996/05/21 03:51:58 morgan - * added "const" to rcsid[] definition - * - * Revision 1.7 1996/04/19 03:25:57 alex - * minor corrections. - * - * Revision 1.6 1996/04/17 01:05:05 alex - * _pam_auth_unix() cleaned up - non-authentication code is made into funcs - * and mostly moved out to support.c. - * - * Revision 1.5 1996/04/16 21:12:46 alex - * unix authentication works on Bach again. This is a tranitional stage. - * I really don't like that _pam_unix_auth() grew into a monster that does - * prompts etc etc. They should go into other functions. - * - * Revision 1.4 1996/04/07 08:06:12 morgan - * tidied up a little - * - * Revision 1.3 1996/04/07 07:34:07 morgan - * added conversation support. Now the module is capable of obtaining a - * username and a password all by itself. - * - * Revision 1.2 1996/03/29 02:31:19 morgan - * Marek Michalkiewicz's small patches for shadow support. - * - * Revision 1.1 1996/03/09 09:10:57 morgan - * Initial revision - * - */ -#ifdef linux -# define _GNU_SOURCE -# include -#endif +/* #define DEBUG */ + +#include -#include #include +#include +#include #include -#define __USE_BSD #include -#include +#include +#include #include +#include -#ifndef NDEBUG +/* indicate the following groups are defined */ -#include - -#endif /* NDEBUG */ - -#ifdef HAVE_SHADOW_H - -#include - -#endif /* HAVE_SHADOW_H */ - -#ifndef LINUX - -#include - -#endif /* LINUX */ +#define PAM_SM_AUTH #define _PAM_EXTERN_FUNCTIONS +#include #include -static const char rcsid[] = "$Id: pam_unix_auth.c,v 1.1 1996/11/09 19:44:35 morgan Exp morgan $ pam_unix authentication functions. alex@bach.cis.temple.edu"; +#ifndef LINUX_PAM +#include +#endif /* LINUX_PAM */ -/* Define function phototypes */ +#include "support.h" -extern char *crypt(const char *key, const char *salt); /* This should have - been in unistd.h - but it is not */ -extern int converse( pam_handle_t *pamh, - int nargs, - struct pam_message **message, - struct pam_response **response ); - -extern int _set_auth_tok( pam_handle_t *pamh, - int flags, int argc, - const char **argv ); - -static int _pam_auth_unix( pam_handle_t *pamh, - int flags, int argc, - const char **argv ); - -static int _pam_set_credentials_unix ( pam_handle_t *pamh, - int flags, - int argc, - const char ** argv ) ; - - -/* Fun starts here :) - * - * _pam_auth_unix() actually performs UNIX/shadow authentication - * - * First, if shadow support is available, attempt to perform - * authentication using shadow passwords. If shadow is not - * available, or user does not have a shadow password, fallback - * onto a normal UNIX authentication +/* + * PAM framework looks for these entry-points to pass control to the + * authentication module. */ -static int _pam_auth_unix( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ) +/* Fun starts here :) + + * pam_sm_authenticate() performs UNIX/shadow authentication + * + * First, if shadow support is available, attempt to perform + * authentication using shadow passwords. If shadow is not + * available, or user does not have a shadow password, fallback + * onto a normal UNIX authentication + */ + +#define _UNIX_AUTHTOK "-UN*X-PASS" + +#define AUTH_RETURN \ +{ \ + if (on(UNIX_LIKE_AUTH, ctrl) && ret_data) { \ + D(("recording return code for next time [%d]", \ + retval)); \ + pam_set_data(pamh, "unix_setcred_return", \ + (void *) retval, NULL); \ + } \ + D(("done. [%s]", pam_strerror(pamh, retval))); \ + return retval; \ +} + +PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags + ,int argc, const char **argv) { - int retval; - struct passwd *pw; - const char *name; - char *p, *pp; - const char *salt; + unsigned int ctrl; + int retval, *ret_data = NULL; + const char *name, *p; -#ifdef HAVE_SHADOW_H + D(("called.")); - struct spwd *sp; + ctrl = _set_ctrl(pamh, flags, NULL, argc, argv); -#endif + /* Get a few bytes so we can pass our return value to + pam_sm_setcred(). */ + ret_data = malloc(sizeof(int)); /* get the user'name' */ - if ( (retval = pam_get_user( pamh, &name, "login: ") ) != PAM_SUCCESS ) - return retval; - - /* - * at some point we will have to make this module pay - * attention to arguments, like 'pam_first_pass' etc... - */ - - pw = getpwnam ( name ); - - /* For NIS+, root cannot get password for lesser user */ - if (pw) { - uid_t save_euid, save_uid; - - save_uid = getuid (); - save_euid = geteuid(); - if (setreuid (0,pw->pw_uid) >= 0) { - pw = getpwnam ( name ); - setreuid (save_uid,save_euid); - } - } - - if ( pw && (!pw->pw_passwd || pw->pw_passwd[0] == '\0') && - !(flags & PAM_DISALLOW_NULL_AUTHTOK)) { - return PAM_SUCCESS; - } - pam_get_item( pamh, PAM_AUTHTOK, (void*) &p ); - - if ( !p ) - { - retval = _set_auth_tok( pamh, flags, argc, argv ); - if ( retval != PAM_SUCCESS ) - return retval; - } - - /* - We have to call pam_get_item() again because value of p should - change - */ - - pam_get_item( pamh, PAM_AUTHTOK, (void*) &p ); - - - if (pw) - { - -#ifdef HAVE_SHADOW_H - + retval = pam_get_user(pamh, &name, "login: "); + if (retval == PAM_SUCCESS) { /* - * Support for shadow passwords on Linux and SVR4-based - * systems. Shadow passwords are optional on Linux - if - * there is no shadow password, use the non-shadow one. + * Various libraries at various times have had bugs related to + * '+' or '-' as the first character of a user name. Don't take + * any chances here. Require that the username starts with an + * alphanumeric character. */ + if (name == NULL || !isalnum(*name)) { + _log_err(LOG_ERR, pamh, "bad username [%s]", name); + retval = PAM_USER_UNKNOWN; + AUTH_RETURN + } + if (retval == PAM_SUCCESS && on(UNIX_DEBUG, ctrl)) + D(("username [%s] obtained", name)); + } else { + D(("trouble reading username")); + if (retval == PAM_CONV_AGAIN) { + D(("pam_get_user/conv() function is not ready yet")); + /* it is safe to resume this function so we translate this + * retval to the value that indicates we're happy to resume. + */ + retval = PAM_INCOMPLETE; + } + AUTH_RETURN + } - sp = getspnam( name ); - if (sp && (!strcmp(pw->pw_passwd,"x"))) - { - /* TODO: check if password has expired etc. */ - salt = sp->sp_pwdp; - } - else -#endif - salt = pw->pw_passwd; - } - else - return PAM_USER_UNKNOWN; - - /* The 'always-encrypt' method does not make sense in PAM - because the framework requires return of a different - error code for non-existant users -- alex */ - - if ( ( !pw->pw_passwd ) && ( !p ) ) - if ( flags && PAM_DISALLOW_NULL_AUTHTOK ) - return PAM_SUCCESS; - else - return PAM_AUTH_ERR; - - pp = crypt(p, salt); - - if ( strcmp( pp, salt ) == 0 ) - return PAM_SUCCESS; + /* if this user does not have a password... */ - return PAM_AUTH_ERR; + if (_unix_blankpasswd(ctrl, name)) { + D(("user '%s' has blank passwd", name)); + name = NULL; + retval = PAM_SUCCESS; + AUTH_RETURN + } + /* get this user's authentication token */ + + retval = _unix_read_password(pamh, ctrl, NULL, "Password: ", NULL + ,_UNIX_AUTHTOK, &p); + if (retval != PAM_SUCCESS) { + if (retval != PAM_CONV_AGAIN) { + _log_err(LOG_CRIT, pamh, "auth could not identify password for [%s]" + ,name); + } else { + D(("conversation function is not ready yet")); + /* + * it is safe to resume this function so we translate this + * retval to the value that indicates we're happy to resume. + */ + retval = PAM_INCOMPLETE; + } + name = NULL; + AUTH_RETURN + } + D(("user=%s, password=[%s]", name, p)); + + /* verify the password of this user */ + retval = _unix_verify_password(pamh, name, p, ctrl); + name = p = NULL; + + AUTH_RETURN } + /* * The only thing _pam_set_credentials_unix() does is initialization of * UNIX group IDs. @@ -255,45 +182,35 @@ static int _pam_auth_unix( pam_handle_t *pamh, * warned you. -- AOY */ -static int _pam_set_credentials_unix ( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ) - -{ /* FIX ME: incorrect error code */ - - return PAM_SUCCESS; /* This is a wrong result code. From what I - remember from reafing one of the guides - there's an error-level saying 'N/A func' - -- AOY - */ -} - -/* - * PAM framework looks for these entry-points to pass control to the - * authentication module. - */ - -PAM_EXTERN -int pam_sm_authenticate( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ) +PAM_EXTERN int pam_sm_setcred(pam_handle_t * pamh, int flags + ,int argc, const char **argv) { - return _pam_auth_unix( pamh, flags, argc, argv ); + unsigned int ctrl; + int retval; + + D(("called.")); + + /* FIXME: it shouldn't be necessary to parse the arguments again. The + only argument we need is UNIX_LIKE_AUTH: if it was set, + pam_get_data will succeed. If it wasn't, it will fail, and we + return PAM_SUCCESS. -SRL */ + ctrl = _set_ctrl(pamh, flags, NULL, argc, argv); + retval = PAM_SUCCESS; + + if (on(UNIX_LIKE_AUTH, ctrl)) { + int *pretval = NULL; + + D(("recovering return code from auth call")); + pam_get_data(pamh, "unix_setcred_return", (const void **) pretval); + if(pretval) { + retval = *pretval; + free(pretval); + D(("recovered data indicates that old retval was %d", retval)); + } + } + return retval; } -PAM_EXTERN -int pam_sm_setcred( pam_handle_t *pamh, - int flags, - int argc, - const char **argv) -{ - return _pam_set_credentials_unix ( pamh, flags, argc, argv ) ; -} - - -/* static module data */ #ifdef PAM_STATIC struct pam_module _pam_unix_auth_modstruct = { "pam_unix_auth", diff --git a/contrib/libpam/modules/pam_unix/pam_unix_passwd.c b/contrib/libpam/modules/pam_unix/pam_unix_passwd.c index de1345e85285..3fe8a27a6997 100644 --- a/contrib/libpam/modules/pam_unix/pam_unix_passwd.c +++ b/contrib/libpam/modules/pam_unix/pam_unix_passwd.c @@ -1,8 +1,7 @@ - -/* Main coding by Elliot Lee , Red Hat Software. - Copyright (C) 1996. */ - /* + * Main coding by Elliot Lee , Red Hat Software. + * Copyright (C) 1996. + * Copyright (c) Jan Rêkorajski, 1999. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -16,13 +15,13 @@ * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. - * + * * ALTERNATIVELY, this product may be distributed under the terms of * the GNU Public License, in which case the provisions of the GPL are * required INSTEAD OF the above restrictions. (This clause is * necessary due to a potential bad interaction between the GPL and * the restrictions contained in a BSD-style copyright.) - * + * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -36,778 +35,970 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - How it works: - Gets in username (has to be done) from the calling program - Does authentication of user (only if we are not running as root) - Gets new password/checks for sanity - Sets it. - */ - -#define PAM_SM_PASSWORD - -/* #define DEBUG 1 */ +#include #include -#include -#define _BSD_SOURCE -#define _SVID_SOURCE -#include -#define __USE_BSD -#define _BSD_SOURCE -#include -#include - -/* why not defined? */ -void setpwent(void); -void endpwent(void); -int chmod(const char *path, mode_t mode); -struct passwd *fgetpwent(FILE *stream); -int putpwent(const struct passwd *p, FILE *stream); - +#include +#include +#include +#include #include -char *crypt(const char *key, const char *salt); +#include +#include +#include +#include +#include +#include /* for time() */ +#include +#include +#include +#include +#include +#include +#include + #ifdef USE_CRACKLIB #include #endif -#include -#include -#include -#include -#include -#include -#include + #include -#ifndef LINUX /* AGM added this as of 0.2 */ -#include -#endif /* ditto */ +/* indicate the following groups are defined */ + +#define PAM_SM_PASSWORD + #include -#ifdef HAVE_SHADOW_H -#include -#endif -#define MAX_PASSWD_TRIES 3 -#define OLD_PASSWORD_PROMPT "Password: " -#define NEW_PASSWORD_PROMPT "New password: " -#define AGAIN_PASSWORD_PROMPT "New password (again): " -#define PW_TMPFILE "/etc/npasswd" -#define SH_TMPFILE "/etc/nshadow" -#define CRACKLIB_DICTS "/usr/lib/cracklib_dict" +#ifndef LINUX_PAM +#include +#endif /* LINUX_PAM */ -/* Various flags for the getpass routine to send back in... */ -#define PPW_EXPIRED 1 -#define PPW_EXPIRING 2 -#define PPW_WILLEXPIRE 4 -#define PPW_NOSUCHUSER 8 -#define PPW_SHADOW 16 -#define PPW_TOOEARLY 32 -#define PPW_ERROR 64 +#include "yppasswd.h" +#include "md5.h" +#include "support.h" -#ifndef DO_TEST -#define STATIC static -#else -#define STATIC -#endif -/* Sets a password for the specified user to the specified password - Returns flags PPW_*, or'd. */ -STATIC int _do_setpass(char *forwho, char *towhat, int flags); -/* Gets a password for the specified user - Returns flags PPW_*, or'd. */ -STATIC int _do_getpass(char *forwho, char **theirpass); -/* Checks whether the password entered is same as listed in the database - 'entered' should not be crypt()'d or anything (it should be as the - user entered it...), 'listed' should be as it is listed in the - password database file */ -STATIC int _do_checkpass(const char *entered, char *listed); - -/* sends a one-way message to the user, either error or info... */ -STATIC int conv_sendmsg(struct pam_conv *aconv, const char *message, int style); -/* sends a message and returns the results of the conversation */ -STATIC int conv_getitem(struct pam_conv *aconv, char *message, int style, - char **result); - -PAM_EXTERN -int pam_sm_chauthtok( pam_handle_t *pamh, - int flags, - int argc, - const char **argv); - -static void _pam_log(int err, const char *format, ...) -{ - va_list args; - - va_start(args, format); - openlog("PAM-unix_passwd", LOG_CONS|LOG_PID, LOG_AUTH); - vsyslog(err, format, args); - va_end(args); - closelog(); -} - -#ifdef NEED_LCKPWDF -/* This is a hack, but until libc and glibc both include this function - * by default (libc only includes it if nys is not being used, at the - * moment, and glibc doesn't appear to have it at all) we need to have - * it here, too. :-( - * - * This should not become an official part of PAM. - * - * BEGIN_HACK -*/ +#if !((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1)) +extern int getrpcport(const char *host, unsigned long prognum, + unsigned long versnum, unsigned int proto); +#endif /* GNU libc 2.1 */ /* - * 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. + * PAM framework looks for these entry-points to pass control to the + * password changing module. */ -#include -#include +#ifdef NEED_LCKPWDF +#include "./lckpwdf.-c" +#endif -#define LOCKFILE "/etc/.pwd.lock" -#define TIMEOUT 15 +extern char *bigcrypt(const char *key, const char *salt); -static int lockfd = -1; +/* + How it works: + Gets in username (has to be done) from the calling program + Does authentication of user (only if we are not running as root) + Gets new password/checks for sanity + Sets it. + */ -static int -set_close_on_exec(int fd) +/* passwd/salt conversion macros */ + +#define ascii_to_bin(c) ((c)>='a'?(c-59):(c)>='A'?((c)-53):(c)-'.') +#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.') + +/* data tokens */ + +#define _UNIX_OLD_AUTHTOK "-UN*X-OLD-PASS" +#define _UNIX_NEW_AUTHTOK "-UN*X-NEW-PASS" + +#define MAX_PASSWD_TRIES 3 +#define PW_TMPFILE "/etc/npasswd" +#define SH_TMPFILE "/etc/nshadow" +#define CRACKLIB_DICTS "/usr/share/dict/cracklib_dict" +#define OPW_TMPFILE "/etc/security/nopasswd" +#define OLD_PASSWORDS_FILE "/etc/security/opasswd" + +/* + * i64c - convert an integer to a radix 64 character + */ +static int i64c(int i) { - int flags = fcntl(fd, F_GETFD, 0); - if (flags == -1) - return -1; - flags |= FD_CLOEXEC; - return fcntl(fd, F_SETFD, flags); + if (i < 0) + return ('.'); + else if (i > 63) + return ('z'); + if (i == 0) + return ('.'); + if (i == 1) + return ('/'); + if (i >= 2 && i <= 11) + return ('0' - 2 + i); + if (i >= 12 && i <= 37) + return ('A' - 12 + i); + if (i >= 38 && i <= 63) + return ('a' - 38 + i); + return ('\0'); } -static int -do_lock(int fd) +static char *crypt_md5_wrapper(const char *pass_new) { - struct flock fl; + /* + * Code lifted from Marek Michalkiewicz's shadow suite. (CG) + * removed use of static variables (AGM) + */ - memset(&fl, 0, sizeof fl); - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - return fcntl(fd, F_SETLKW, &fl); + struct timeval tv; + MD5_CTX ctx; + unsigned char result[16]; + char *cp = (char *) result; + unsigned char tmp[16]; + int i; + char *x, *e = NULL; + + GoodMD5Init(&ctx); + gettimeofday(&tv, (struct timezone *) 0); + GoodMD5Update(&ctx, (void *) &tv, sizeof tv); + i = getpid(); + GoodMD5Update(&ctx, (void *) &i, sizeof i); + i = clock(); + GoodMD5Update(&ctx, (void *) &i, sizeof i); + GoodMD5Update(&ctx, result, sizeof result); + GoodMD5Final(tmp, &ctx); + strcpy(cp, "$1$"); /* magic for the MD5 */ + cp += strlen(cp); + for (i = 0; i < 8; i++) + *cp++ = i64c(tmp[i] & 077); + *cp = '\0'; + + /* no longer need cleartext */ + e = Goodcrypt_md5(pass_new, (const char *) result); + x = x_strdup(e); /* put e in malloc()ed memory */ + _pam_overwrite(e); /* clean up */ + + return x; } -static void -alarm_catch(int sig) +static char *getNISserver(pam_handle_t *pamh) { -/* does nothing, but fcntl F_SETLKW will fail with EINTR */ -} + char *master; + char *domainname; + int port, err; -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; + if ((err = yp_get_default_domain(&domainname)) != 0) { + _log_err(LOG_WARNING, pamh, "can't get local yp domain: %s\n", + yperr_string(err)); + return NULL; } - lockfd = -1; - return 0; + if ((err = yp_master(domainname, "passwd.byname", &master)) != 0) { + _log_err(LOG_WARNING, pamh, "can't find the master ypserver: %s\n", + yperr_string(err)); + return NULL; + } + port = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP); + if (port == 0) { + _log_err(LOG_WARNING, pamh, + "yppasswdd not running on NIS master host\n"); + return NULL; + } + if (port >= IPPORT_RESERVED) { + _log_err(LOG_WARNING, pamh, + "yppasswd daemon running on illegal port.\n"); + return NULL; + } + return master; } -/* END_HACK */ -#endif -#define PAM_FAIL_CHECK if(retval != PAM_SUCCESS) { return retval; } - -PAM_EXTERN -int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) +static int check_old_password(const char *forwho, const char *newpass) { - char *usrname, *curpass, *newpass; /* pointers to the username, - current password, and new password */ + static char buf[16384]; + char *s_luser, *s_uid, *s_npas, *s_pas; + int retval = PAM_SUCCESS; + FILE *opwfile; - struct pam_conv *appconv; /* conversation with the app */ - struct pam_message msg, *pmsg; /* Misc for conversations */ - struct pam_response *resp; + opwfile = fopen(OLD_PASSWORDS_FILE, "r"); + if (opwfile == NULL) + return PAM_AUTHTOK_ERR; - int retval=0; /* Gets the return values for all our function calls */ - unsigned int pflags=0; /* Holds the flags from our getpass & setpass - functions */ + while (fgets(buf, 16380, opwfile)) { + if (!strncmp(buf, forwho, strlen(forwho))) { + buf[strlen(buf) - 1] = '\0'; + s_luser = strtok(buf, ":,"); + s_uid = strtok(NULL, ":,"); + s_npas = strtok(NULL, ":,"); + s_pas = strtok(NULL, ":,"); + while (s_pas != NULL) { + if (!strcmp(Goodcrypt_md5(newpass, s_pas), s_pas)) { + retval = PAM_AUTHTOK_ERR; + break; + } + s_pas = strtok(NULL, ":,"); + } + break; + } + } + fclose(opwfile); - const char *cmiscptr; /* Utility variables, used for different purposes at - different times */ - char *miscptr; /* Utility variables, used for different purposes at - different times */ - unsigned int miscint; - int fascist = 1; /* Be fascist by default. If compiled with cracklib, - call cracklib. Otherwise just check length... */ + return retval; +} - char argbuf[256],argval[256]; - int i; +static int save_old_password(const char *forwho, const char *oldpass, int howmany) +{ + static char buf[16384]; + static char nbuf[16384]; + char *s_luser, *s_uid, *s_npas, *s_pas, *pass; + int retval = 0, npas; + FILE *pwfile, *opwfile; + int err = 0; + int oldmask; + int found = 0; + struct passwd *pwd = NULL; + if (howmany < 0) + return retval; - retval = pam_get_item(pamh,PAM_CONV,(const void **) &appconv); - PAM_FAIL_CHECK; + if (oldpass == NULL) + return retval; - retval = pam_get_item(pamh,PAM_USER,(const void **) &usrname); - PAM_FAIL_CHECK; - if(flags & PAM_PRELIM_CHECK) { - pflags = _do_getpass(usrname,&miscptr); - if(pflags & PPW_NOSUCHUSER) - return PAM_USER_UNKNOWN; - else if(pflags & ~(PPW_SHADOW|PPW_EXPIRING|PPW_WILLEXPIRE)) - return PAM_AUTHTOK_ERR; - else - return PAM_SUCCESS; - } /* else... */ + oldmask = umask(077); + pwfile = fopen(OPW_TMPFILE, "w"); + umask(oldmask); + opwfile = fopen(OLD_PASSWORDS_FILE, "r"); + if (pwfile == NULL || opwfile == NULL) + return PAM_AUTHTOK_ERR; + chown(OPW_TMPFILE, 0, 0); + chmod(OPW_TMPFILE, 0600); + + while (fgets(buf, 16380, opwfile)) { + if (!strncmp(buf, forwho, strlen(forwho))) { + buf[strlen(buf) - 1] = '\0'; + s_luser = strtok(buf, ":"); + s_uid = strtok(NULL, ":"); + s_npas = strtok(NULL, ":"); + s_pas = strtok(NULL, ":"); + npas = strtol(s_npas, NULL, 10) + 1; + while (npas > howmany) { + s_pas = strpbrk(s_pas, ","); + if (s_pas != NULL) + s_pas++; + npas--; + } + pass = crypt_md5_wrapper(oldpass); + if (s_pas == NULL) + sprintf(nbuf, "%s:%s:%d:%s\n", s_luser, s_uid, npas, pass); + else + sprintf(nbuf, "%s:%s:%d:%s,%s\n", s_luser, s_uid, npas, s_pas, pass); + if (fputs(nbuf, pwfile) < 0) { + retval = PAM_AUTHTOK_ERR; + err = 1; + break; + } + found = 1; + } else if (fputs(buf, pwfile) < 0) { + retval = PAM_AUTHTOK_ERR; + err = 1; + break; + } + } + fclose(opwfile); + if (!found) { + pwd = getpwnam(forwho); + if (pwd == NULL) { + retval = PAM_AUTHTOK_ERR; + err = 1; + } else { + pass = crypt_md5_wrapper(oldpass); + sprintf(nbuf, "%s:%d:1:%s\n", forwho, pwd->pw_uid, pass); + if (fputs(nbuf, pwfile) < 0) { + retval = PAM_AUTHTOK_ERR; + err = 1; + } + } + } + if (fclose(pwfile)) { + fprintf(stderr, "error writing entries to old passwords file: %s\n", + strerror(errno)); + retval = PAM_AUTHTOK_ERR; + err = 1; + } + if (!err) + rename(OPW_TMPFILE, OLD_PASSWORDS_FILE); + else + unlink(OPW_TMPFILE); + + return retval; +} + +static int _update_passwd(const char *forwho, const char *towhat) +{ + struct passwd *tmpent = NULL; + FILE *pwfile, *opwfile; + int retval = 0; + int err = 0; + int oldmask; + + oldmask = umask(077); + pwfile = fopen(PW_TMPFILE, "w"); + umask(oldmask); + opwfile = fopen("/etc/passwd", "r"); + if (pwfile == NULL || opwfile == NULL) + return PAM_AUTHTOK_ERR; + chown(PW_TMPFILE, 0, 0); + chmod(PW_TMPFILE, 0644); + tmpent = fgetpwent(opwfile); + while (tmpent) { + if (!strcmp(tmpent->pw_name, forwho)) { + tmpent->pw_passwd = towhat; + } + if (putpwent(tmpent, pwfile)) { + fprintf(stderr, "error writing entry to password file: %s\n", + strerror(errno)); + err = 1; + retval = PAM_AUTHTOK_ERR; + break; + } + tmpent = fgetpwent(opwfile); + } + fclose(opwfile); + + if (fclose(pwfile)) { + fprintf(stderr, "error writing entries to password file: %s\n", + strerror(errno)); + retval = PAM_AUTHTOK_ERR; + err = 1; + } + if (!err) + rename(PW_TMPFILE, "/etc/passwd"); + else + unlink(PW_TMPFILE); + + return retval; +} + +static int _update_shadow(const char *forwho, char *towhat) +{ + struct spwd *spwdent = NULL, *stmpent = NULL; + FILE *pwfile, *opwfile; + int retval = 0; + int err = 0; + int oldmask; + + spwdent = getspnam(forwho); + if (spwdent == NULL) + return PAM_USER_UNKNOWN; + oldmask = umask(077); + pwfile = fopen(SH_TMPFILE, "w"); + umask(oldmask); + opwfile = fopen("/etc/shadow", "r"); + if (pwfile == NULL || opwfile == NULL) + return PAM_AUTHTOK_ERR; + chown(SH_TMPFILE, 0, 0); + chmod(SH_TMPFILE, 0600); + stmpent = fgetspent(opwfile); + while (stmpent) { + if (!strcmp(stmpent->sp_namp, forwho)) { + stmpent->sp_pwdp = towhat; + stmpent->sp_lstchg = time(NULL) / (60 * 60 * 24); + + D(("Set password %s for %s", stmpent->sp_pwdp, forwho)); + } + if (putspent(stmpent, pwfile)) { + fprintf(stderr, "error writing entry to shadow file: %s\n", + strerror(errno)); + err = 1; + retval = PAM_AUTHTOK_ERR; + break; + } + stmpent = fgetspent(opwfile); + } + fclose(opwfile); + + if (fclose(pwfile)) { + fprintf(stderr, "error writing entries to shadow file: %s\n", + strerror(errno)); + retval = PAM_AUTHTOK_ERR; + err = 1; + } + if (!err) + rename(SH_TMPFILE, "/etc/shadow"); + else + unlink(SH_TMPFILE); + + return retval; +} + +static int _do_setpass(pam_handle_t* pamh, const char *forwho, char *fromwhat, + char *towhat, unsigned int ctrl, int remember) +{ + struct passwd *pwd = NULL; + int retval = 0; + + D(("called")); + + setpwent(); + pwd = getpwnam(forwho); + endpwent(); + + if (pwd == NULL) + return PAM_AUTHTOK_ERR; + + if (on(UNIX_NIS, ctrl)) { + struct timeval timeout; + struct yppasswd yppwd; + CLIENT *clnt; + char *master; + int status; + int err = 0; + + /* Make RPC call to NIS server */ + if ((master = getNISserver(pamh)) == NULL) + return PAM_TRY_AGAIN; + + /* Initialize password information */ + yppwd.newpw.pw_passwd = pwd->pw_passwd; + yppwd.newpw.pw_name = pwd->pw_name; + yppwd.newpw.pw_uid = pwd->pw_uid; + yppwd.newpw.pw_gid = pwd->pw_gid; + yppwd.newpw.pw_gecos = pwd->pw_gecos; + yppwd.newpw.pw_dir = pwd->pw_dir; + yppwd.newpw.pw_shell = pwd->pw_shell; + yppwd.oldpass = fromwhat; + yppwd.newpw.pw_passwd = towhat; + + D(("Set password %s for %s", yppwd.newpw.pw_passwd, forwho)); + + /* The yppasswd.x file said `unix authentication required', + * so I added it. This is the only reason it is in here. + * My yppasswdd doesn't use it, but maybe some others out there + * do. --okir + */ + clnt = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp"); + clnt->cl_auth = authunix_create_default(); + memset((char *) &status, '\0', sizeof(status)); + timeout.tv_sec = 25; + timeout.tv_usec = 0; + err = clnt_call(clnt, YPPASSWDPROC_UPDATE, + (xdrproc_t) xdr_yppasswd, (char *) &yppwd, + (xdrproc_t) xdr_int, (char *) &status, + timeout); + + if (err) { + clnt_perrno(err); + retval = PAM_TRY_AGAIN; + } else if (status) { + fprintf(stderr, "Error while changing NIS password.\n"); + retval = PAM_TRY_AGAIN; + } + printf("\nThe password has%s been changed on %s.\n", + (err || status) ? " not" : "", master); + + auth_destroy(clnt->cl_auth); + clnt_destroy(clnt); + if ((err || status) != 0) { + retval = PAM_TRY_AGAIN; + } #ifdef DEBUG - fprintf(stderr,"Got username of %s\n",usrname); + sleep(5); #endif - if((usrname == NULL) || (strlen(usrname) < 1)) { - /* The app is supposed to get us the username! */ - retval = PAM_USER_UNKNOWN; - PAM_FAIL_CHECK; - } + return retval; + } + /* first, save old password */ + if (save_old_password(forwho, fromwhat, remember)) { + return PAM_AUTHTOK_ERR; + } + if (on(UNIX_SHADOW, ctrl) || (strcmp(pwd->pw_passwd, "x") == 0)) { + retval = _update_shadow(forwho, towhat); + if (retval == PAM_SUCCESS) + retval = _update_passwd(forwho, "x"); + } else { + retval = _update_passwd(forwho, towhat); + } - for(i=0; i < argc; i++) { - { - char *tmp = x_strdup(argv[i]); - strncpy(argbuf,strtok(tmp ,"="),255); - strncpy(argval,strtok(NULL,"="),255); - free(tmp); - } + return retval; +} - /* For PC functionality use "strict" -- historically "fascist" */ - if(!strcmp(argbuf,"strict") || !strcmp(argbuf, "fascist")) +static int _unix_verify_shadow(const char *user, unsigned int ctrl) +{ + struct passwd *pwd = NULL; /* Password and shadow password */ + struct spwd *spwdent = NULL; /* file entries for the user */ + time_t curdays; + int retval = PAM_SUCCESS; - if(!strcmp(argval,"true")) - fascist = 1; - else if(!strcmp(argval,"false")) - fascist = 0; - else - return PAM_SERVICE_ERR; - else { - _pam_log(LOG_ERR,"Unknown option: %s",argbuf); - return PAM_SERVICE_ERR; - } - } + /* UNIX passwords area */ + setpwent(); + pwd = getpwnam(user); /* Get password file entry... */ + endpwent(); + if (pwd == NULL) + return PAM_AUTHINFO_UNAVAIL; /* We don't need to do the rest... */ + if (strcmp(pwd->pw_passwd, "x") == 0) { + /* ...and shadow password file entry for this user, if shadowing + is enabled */ + setspent(); + spwdent = getspnam(user); + endspent(); - /* Now we have all the initial information we need from the app to - set things up (we assume that getting the username succeeded...) */ - retval = pam_get_item(pamh,PAM_OLDAUTHTOK,(const void **) &curpass); - PAM_FAIL_CHECK; - if(getuid()) { /* If this is being run by root, we don't need to get their - old password. - note */ - /* If we haven't been given a password yet, prompt for one... */ - miscint=0; - while((curpass == NULL) && (miscint++ < MAX_PASSWD_TRIES)) { - pflags = _do_getpass(usrname,&miscptr); - if(pflags & PPW_NOSUCHUSER) - return PAM_USER_UNKNOWN; /* If the user that was passed in doesn't - exist, say so and exit (app passes in - username) */ - - /* Get the password from the user... */ - pmsg = &msg; - - msg.msg_style = PAM_PROMPT_ECHO_OFF; - msg.msg = OLD_PASSWORD_PROMPT; - resp = NULL; + if (spwdent == NULL) + return PAM_AUTHINFO_UNAVAIL; + } else { + if (strcmp(pwd->pw_passwd,"*NP*") == 0) { /* NIS+ */ + uid_t save_uid; - retval = appconv->conv(1, (const struct pam_message **) &pmsg, - &resp, appconv->appdata_ptr); - - PAM_FAIL_CHECK; - curpass = resp->resp; - free (resp); - if(_do_checkpass(curpass?curpass:"",miscptr)) { - int abortme = 0; + save_uid = geteuid(); + seteuid (pwd->pw_uid); + spwdent = getspnam( user ); + seteuid (save_uid); - /* password is incorrect... */ - if (curpass && curpass[0] == '\0') { - /* ...and it was zero-length; user wishes to abort change */ - abortme = 1; - } - if (curpass) { free (curpass); } - curpass = NULL; - if (abortme) { - conv_sendmsg(appconv,"Password change aborted.",PAM_ERROR_MSG); - return PAM_AUTHTOK_ERR; - } - } - } + if (spwdent == NULL) + return PAM_AUTHINFO_UNAVAIL; + } else + spwdent = NULL; + } - if(curpass == NULL) - return PAM_AUTH_ERR; /* They didn't seem to enter the right password - for three tries - error */ - pam_set_item(pamh, PAM_OLDAUTHTOK, (void *)curpass); - } else { -#ifdef DEBUG - fprintf(stderr,"I am ROOT!\n"); -#endif - pflags = _do_getpass(usrname,&curpass); - if(curpass == NULL) - curpass = x_strdup(""); - } - if(pflags & PPW_TOOEARLY) { - conv_sendmsg(appconv,"You must wait longer to change your password", - PAM_ERROR_MSG); - return PAM_AUTHTOK_ERR; - } - if(pflags & PPW_WILLEXPIRE) - conv_sendmsg(appconv,"Your password is about to expire",PAM_TEXT_INFO); - else if(pflags & PPW_EXPIRED) - return PAM_ACCT_EXPIRED; /* If their account has expired, we can't auth - them to change their password */ - if(!(pflags & PPW_EXPIRING) && (flags & PAM_CHANGE_EXPIRED_AUTHTOK)) - return PAM_SUCCESS; - /* If we haven't been given a password yet, prompt for one... */ - miscint=0; - pam_get_item(pamh,PAM_AUTHTOK,(const void **)&newpass); - cmiscptr = NULL; - while((newpass == NULL) && (miscint++ < MAX_PASSWD_TRIES)) { + if (spwdent != NULL) { + /* We have the user's information, now let's check if their account + has expired (60 * 60 * 24 = number of seconds in a day) */ - /* Get the password from the user... */ - pmsg = &msg; - - msg.msg_style = PAM_PROMPT_ECHO_OFF; - msg.msg = NEW_PASSWORD_PROMPT; - resp = NULL; + if (off(UNIX__IAMROOT, ctrl)) { + /* Get the current number of days since 1970 */ + curdays = time(NULL) / (60 * 60 * 24); + if ((curdays < (spwdent->sp_lstchg + spwdent->sp_min)) + && (spwdent->sp_min != -1)) + retval = PAM_AUTHTOK_ERR; + else if ((curdays > (spwdent->sp_lstchg + spwdent->sp_max + spwdent->sp_inact)) + && (spwdent->sp_max != -1) && (spwdent->sp_inact != -1) + && (spwdent->sp_lstchg != 0)) + /* + * Their password change has been put off too long, + */ + retval = PAM_ACCT_EXPIRED; + else if ((curdays > spwdent->sp_expire) && (spwdent->sp_expire != -1) + && (spwdent->sp_lstchg != 0)) + /* + * OR their account has just plain expired + */ + retval = PAM_ACCT_EXPIRED; + } + } + return retval; +} - retval = appconv->conv(1, (const struct pam_message **) &pmsg, - &resp, appconv->appdata_ptr); - - PAM_FAIL_CHECK; - newpass = resp->resp; - free (resp); +static int _pam_unix_approve_pass(pam_handle_t * pamh + ,unsigned int ctrl + ,const char *pass_old + ,const char *pass_new) +{ + const char *user; + const char *remark = NULL; + int retval = PAM_SUCCESS; -#ifdef DEBUG - if(newpass) - fprintf(stderr,"Got password of %s\n",newpass); - else - fprintf(stderr,"No new password...\n"); -#endif - if (newpass[0] == '\0') { free (newpass); newpass = (char *) 0; } - cmiscptr=NULL; - if(newpass) { + D(("&new=%p, &old=%p", pass_old, pass_new)); + D(("new=[%s]", pass_new)); + D(("old=[%s]", pass_old)); + + if (pass_new == NULL || (pass_old && !strcmp(pass_old, pass_new))) { + if (on(UNIX_DEBUG, ctrl)) { + _log_err(LOG_DEBUG, pamh, "bad authentication token"); + } + _make_remark(pamh, ctrl, PAM_ERROR_MSG, pass_new == NULL ? + "No password supplied" : "Password unchanged"); + return PAM_AUTHTOK_ERR; + } + /* + * if one wanted to hardwire authentication token strength + * checking this would be the place - AGM + */ + + retval = pam_get_item(pamh, PAM_USER, (const void **) &user); + if (retval != PAM_SUCCESS) { + if (on(UNIX_DEBUG, ctrl)) { + _log_err(LOG_ERR, pamh, "Can not get username"); + return PAM_AUTHTOK_ERR; + } + } + if (off(UNIX__IAMROOT, ctrl)) { #ifdef USE_CRACKLIB - if(fascist && getuid()) - cmiscptr = FascistCheck(newpass,CRACKLIB_DICTS); + remark = FascistCheck(pass_new, CRACKLIB_DICTS); + D(("called cracklib [%s]", remark)); #else - if(fascist && getuid() && strlen(newpass) < 6) - cmiscptr = "You must choose a longer password"; + if (strlen(pass_new) < 6) + remark = "You must choose a longer password"; + D(("lenth check [%s]", remark)); #endif - if(curpass) - if(!strcmp(curpass,newpass)) { - cmiscptr="You must choose a new password."; - newpass=NULL; + if (on(UNIX_REMEMBER_PASSWD, ctrl)) + if ((retval = check_old_password(user, pass_new)) != PAM_SUCCESS) + remark = "Password has been already used. Choose another."; } - } else { - /* We want to abort the password change */ - conv_sendmsg(appconv,"Password change aborted",PAM_ERROR_MSG); - return PAM_AUTHTOK_ERR; - } - if(!cmiscptr) { - /* We ask them to enter their password again... */ - /* Get the password from the user... */ - pmsg = &msg; - - msg.msg_style = PAM_PROMPT_ECHO_OFF; - msg.msg = AGAIN_PASSWORD_PROMPT; - resp = NULL; - - retval = appconv->conv(1, (const struct pam_message **) &pmsg, - &resp, appconv->appdata_ptr); - - PAM_FAIL_CHECK; - miscptr = resp->resp; - free (resp); - if (miscptr[0] == '\0') { free (miscptr); miscptr = (char *) 0; } - if(!miscptr) { /* Aborting password change... */ - conv_sendmsg(appconv,"Password change aborted",PAM_ERROR_MSG); - return PAM_AUTHTOK_ERR; - } - if(!strcmp(newpass,miscptr)) { - miscptr=NULL; - break; - } - conv_sendmsg(appconv,"You must enter the same password twice.", - PAM_ERROR_MSG); - miscptr=NULL; - newpass=NULL; - } - else { - conv_sendmsg(appconv,cmiscptr,PAM_ERROR_MSG); - newpass = NULL; - } - } - if(cmiscptr) { - /* conv_sendmsg(appconv,cmiscptr,PAM_ERROR_MSG); */ - return PAM_AUTHTOK_ERR; - } else if(newpass == NULL) - return PAM_AUTHTOK_ERR; /* They didn't seem to enter the right password - for three tries - error */ -#ifdef DEBUG - printf("Changing password for sure!\n"); -#endif - /* From now on, we are bound and determined to get their password - changed :-) */ - pam_set_item(pamh, PAM_AUTHTOK, (void *)newpass); - retval = _do_setpass(usrname,newpass,pflags); -#ifdef DEBUG - fprintf(stderr,"retval was %d\n",retval); -#endif - if(retval & ~PPW_SHADOW) { - conv_sendmsg(appconv,"Error: Password NOT changed",PAM_ERROR_MSG); - return PAM_AUTHTOK_ERR; - } else { - conv_sendmsg(appconv,"Password changed",PAM_TEXT_INFO); - return PAM_SUCCESS; - } + if (remark) { + _make_remark(pamh, ctrl, PAM_ERROR_MSG, remark); + retval = PAM_AUTHTOK_ERR; + } + return retval; } -/* _do_checkpass() returns 0 on success, non-0 on failure */ -STATIC int _do_checkpass(const char *entered, char *listed) + +PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, + int argc, const char **argv) { - char salt[3]; - if ((strlen(listed) == 0) &&(strlen(entered) == 0)) { - /* no password in database; no password entered */ - return (0); - } - salt[0]=listed[0]; salt[1]=listed[1]; salt[2]='\0'; - return strcmp(crypt(entered,salt),listed); -} + unsigned int ctrl, lctrl; + int retval, i; + int remember = -1; -STATIC char mksalt(int seed) { - int num = seed % 64; + /* */ + const char *user; + char *pass_old, *pass_new; + /* */ - if (num < 26) - return 'a' + num; - else if (num < 52) - return 'A' + (num - 26); - else if (num < 62) - return '0' + (num - 52); - else if (num == 63) - return '.'; - else - return '/'; -} + D(("called.")); -STATIC int _do_setpass(char *forwho, char *towhat,int flags) -{ - struct passwd *pwd=NULL, *tmpent=NULL; - FILE *pwfile,*opwfile; - char thesalt[3]; - int retval=0; - struct timeval time1; - int err = 0; -#ifdef HAVE_SHADOW_H - struct spwd *spwdent=NULL, *stmpent=NULL; -#endif - if(flags & PPW_SHADOW) { retval |= PPW_SHADOW; } - gettimeofday(&time1, NULL); - srand(time1.tv_usec); - thesalt[0]=mksalt(rand()); - thesalt[1]=mksalt(rand()); - thesalt[2]='\0'; - - /* lock the entire password subsystem */ #ifdef USE_LCKPWDF - lckpwdf(); + /* our current locking system requires that we lock the + entire password database. This avoids both livelock + and deadlock. */ + /* These values for the number of attempts and the sleep time + are, of course, completely arbitrary. + My reading of the PAM docs is that, once pam_chauthtok() has been + called with PAM_UPDATE_AUTHTOK, we are obliged to take any + reasonable steps to make sure the token is updated; so retrying + for 1/10 sec. isn't overdoing it. + The other possibility is to call lckpwdf() on the first + pam_chauthtok() pass, and hold the lock until released in the + second pass--but is this guaranteed to work? -SRL */ + i=0; + while((retval = lckpwdf()) != 0 && i < 100) { + usleep(1000); + } + if(retval != 0) { + return PAM_AUTHTOK_LOCK_BUSY; + } #endif - setpwent(); - pwd = getpwnam(forwho); -#ifdef DEBUG - printf("Got %p, for %s (salt %s)\n",pwd, - forwho,thesalt); -#endif - if(pwd == NULL) - return PPW_NOSUCHUSER; - endpwent(); + ctrl = _set_ctrl(pamh, flags, &remember, argc, argv); -#ifdef HAVE_SHADOW_H - if(flags & PPW_SHADOW) { - spwdent = getspnam(forwho); - if(spwdent == NULL) - return PPW_NOSUCHUSER; - spwdent->sp_pwdp = towhat; - spwdent->sp_lstchg = time(NULL)/(60*60*24); - pwfile = fopen(SH_TMPFILE,"w"); - opwfile = fopen("/etc/shadow","r"); - if(pwfile == NULL || opwfile == NULL) - return PPW_ERROR; - chown(SH_TMPFILE,0,0); - chmod(SH_TMPFILE,0600); - stmpent=fgetspent(opwfile); - while(stmpent) { - if(!strcmp(stmpent->sp_namp,forwho)) { - stmpent->sp_pwdp = crypt(towhat,thesalt); - stmpent->sp_lstchg = time(NULL)/(60*60*24); -#ifdef DEBUG - fprintf(stderr,"Set password %s for %s\n",stmpent->sp_pwdp, - forwho); -#endif - } - if (putspent(stmpent,pwfile)) { - fprintf(stderr, "error writing entry to shadow file: %s\n", - strerror(errno)); - err = 1; - retval = PPW_ERROR; - break; - } - stmpent=fgetspent(opwfile); - } - fclose(opwfile); - - if (fclose(pwfile)) { - fprintf(stderr, "error writing entries to shadow file: %s\n", - strerror(errno)); - retval = PPW_ERROR; - err = 1; - } - - if (!err) - rename(SH_TMPFILE,"/etc/shadow"); - else - unlink(SH_TMPFILE); - } else { - pwd->pw_passwd = towhat; - pwfile = fopen(PW_TMPFILE,"w"); - opwfile = fopen("/etc/passwd","r"); - if(pwfile == NULL || opwfile == NULL) - return PPW_ERROR; - chown(PW_TMPFILE,0,0); - chmod(PW_TMPFILE,0644); - tmpent=fgetpwent(opwfile); - while(tmpent) { - if(!strcmp(tmpent->pw_name,forwho)) { - tmpent->pw_passwd = crypt(towhat,thesalt); - } - if (putpwent(tmpent,pwfile)) { - fprintf(stderr, "error writing entry to password file: %s\n", - strerror(errno)); - err = 1; - retval = PPW_ERROR; - break; - } - tmpent=fgetpwent(opwfile); - } - fclose(opwfile); - - if (fclose(pwfile)) { - fprintf(stderr, "error writing entries to password file: %s\n", - strerror(errno)); - retval = PPW_ERROR; - err = 1; - } - - if (!err) - rename(PW_TMPFILE,"/etc/passwd"); - else - unlink(PW_TMPFILE); - } -#else - pwd->pw_passwd = towhat; - pwfile = fopen(PW_TMPFILE,"w"); - opwfile = fopen("/etc/passwd","r"); - if(pwfile == NULL || opwfile == NULL) - return PPW_ERROR; - chown(PW_TMPFILE,0,0); - chmod(PW_TMPFILE,0644); - tmpent=fgetpwent(opwfile); - while(tmpent) { - if(!strcmp(tmpent->pw_name,forwho)) { - tmpent->pw_passwd = crypt(towhat,thesalt); - } - if (putpwent(tmpent,pwfile)) { - fprintf(stderr, "error writing entry to shadow file: %s\n", - strerror(errno)); - err = 1; - retval = PPW_ERROR; - break; - } - tmpent=fgetpwent(opwfile); - } - fclose(opwfile); - - if (fclose(pwfile)) { - fprintf(stderr, "error writing entries to password file: %s\n", - strerror(errno)); - retval = PPW_ERROR; - err = 1; - } - - if (!err) - rename(PW_TMPFILE,"/etc/passwd"); - else - unlink(PW_TMPFILE); -#endif - /* unlock the entire password subsystem */ + /* + * First get the name of a user + */ + retval = pam_get_user(pamh, &user, "Username: "); + if (retval == PAM_SUCCESS) { + /* + * Various libraries at various times have had bugs related to + * '+' or '-' as the first character of a user name. Don't take + * any chances here. Require that the username starts with an + * alphanumeric character. + */ + if (user == NULL || !isalnum(*user)) { + _log_err(LOG_ERR, pamh, "bad username [%s]", user); #ifdef USE_LCKPWDF - ulckpwdf(); + ulckpwdf(); #endif - return retval; + return PAM_USER_UNKNOWN; + } + if (retval == PAM_SUCCESS && on(UNIX_DEBUG, ctrl)) + _log_err(LOG_DEBUG, pamh, "username [%s] obtained", + user); + } else { + if (on(UNIX_DEBUG, ctrl)) + _log_err(LOG_DEBUG, pamh, + "password - could not identify user"); +#ifdef USE_LCKPWDF + ulckpwdf(); +#endif + return retval; + } + + D(("Got username of %s", user)); + + /* + * This is not an AUTH module! + */ + if (on(UNIX__NONULL, ctrl)) + set(UNIX__NULLOK, ctrl); + + if (on(UNIX__PRELIM, ctrl)) { + /* + * obtain and verify the current password (OLDAUTHTOK) for + * the user. + */ + char *Announce; + + D(("prelim check")); + + if (_unix_blankpasswd(ctrl, user)) { +#ifdef USE_LCKPWDF + ulckpwdf(); +#endif + return PAM_SUCCESS; + } else if (off(UNIX__IAMROOT, ctrl)) { + + /* instruct user what is happening */ +#define greeting "Changing password for " + Announce = (char *) malloc(sizeof(greeting) + strlen(user)); + if (Announce == NULL) { + _log_err(LOG_CRIT, pamh, + "password - out of memory"); +#ifdef USE_LCKPWDF + ulckpwdf(); +#endif + return PAM_BUF_ERR; + } + (void) strcpy(Announce, greeting); + (void) strcpy(Announce + sizeof(greeting) - 1, user); +#undef greeting + + lctrl = ctrl; + set(UNIX__OLD_PASSWD, lctrl); + retval = _unix_read_password(pamh, lctrl + ,Announce + ,"(current) UNIX password: " + ,NULL + ,_UNIX_OLD_AUTHTOK + ,(const char **) &pass_old); + free(Announce); + + if (retval != PAM_SUCCESS) { + _log_err(LOG_NOTICE, pamh + ,"password - (old) token not obtained"); +#ifdef USE_LCKPWDF + ulckpwdf(); +#endif + return retval; + } + /* verify that this is the password for this user */ + + retval = _unix_verify_password(pamh, user, pass_old, ctrl); + } else { + D(("process run by root so do nothing this time around")); + pass_old = NULL; + retval = PAM_SUCCESS; /* root doesn't have too */ + } + + if (retval != PAM_SUCCESS) { + D(("Authentication failed")); + pass_old = NULL; +#ifdef USE_LCKPWDF + ulckpwdf(); +#endif + return retval; + } + retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old); + pass_old = NULL; + if (retval != PAM_SUCCESS) { + _log_err(LOG_CRIT, pamh, + "failed to set PAM_OLDAUTHTOK"); + } + retval = _unix_verify_shadow(user, ctrl); + if (retval == PAM_AUTHTOK_ERR) { + if (off(UNIX__IAMROOT, ctrl)) + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + "You must wait longer to change your password"); + else + retval = PAM_SUCCESS; + } + } else if (on(UNIX__UPDATE, ctrl)) { + /* + * tpass is used below to store the _pam_md() return; it + * should be _pam_delete()'d. + */ + + char *tpass = NULL; + int retry = 0; + + /* + * obtain the proposed password + */ + + D(("do update")); + + /* + * get the old token back. NULL was ok only if root [at this + * point we assume that this has already been enforced on a + * previous call to this function]. + */ + + if (off(UNIX_NOT_SET_PASS, ctrl)) { + retval = pam_get_item(pamh, PAM_OLDAUTHTOK + ,(const void **) &pass_old); + } else { + retval = pam_get_data(pamh, _UNIX_OLD_AUTHTOK + ,(const void **) &pass_old); + if (retval == PAM_NO_MODULE_DATA) { + retval = PAM_SUCCESS; + pass_old = NULL; + } + } + D(("pass_old [%s]", pass_old)); + + if (retval != PAM_SUCCESS) { + _log_err(LOG_NOTICE, pamh, "user not authenticated"); +#ifdef USE_LCKPWDF + ulckpwdf(); +#endif + return retval; + } + retval = _unix_verify_shadow(user, ctrl); + if (retval != PAM_SUCCESS) { + _log_err(LOG_NOTICE, pamh, "user not authenticated 2"); +#ifdef USE_LCKPWDF + ulckpwdf(); +#endif + return retval; + } + D(("get new password now")); + + lctrl = ctrl; + + if (on(UNIX_USE_AUTHTOK, lctrl)) { + set(UNIX_USE_FIRST_PASS, lctrl); + } + retry = 0; + retval = PAM_AUTHTOK_ERR; + while ((retval != PAM_SUCCESS) && (retry++ < MAX_PASSWD_TRIES)) { + /* + * use_authtok is to force the use of a previously entered + * password -- needed for pluggable password strength checking + */ + + retval = _unix_read_password(pamh, lctrl + ,NULL + ,"Enter new UNIX password: " + ,"Retype new UNIX password: " + ,_UNIX_NEW_AUTHTOK + ,(const char **) &pass_new); + + if (retval != PAM_SUCCESS) { + if (on(UNIX_DEBUG, ctrl)) { + _log_err(LOG_ALERT, pamh + ,"password - new password not obtained"); + } + pass_old = NULL; /* tidy up */ +#ifdef USE_LCKPWDF + ulckpwdf(); +#endif + return retval; + } + D(("returned to _unix_chauthtok")); + + /* + * At this point we know who the user is and what they + * propose as their new password. Verify that the new + * password is acceptable. + */ + + if (pass_new[0] == '\0') { /* "\0" password = NULL */ + pass_new = NULL; + } + retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new); + } + + if (retval != PAM_SUCCESS) { + _log_err(LOG_NOTICE, pamh, + "new password not acceptable"); + _pam_overwrite(pass_new); + _pam_overwrite(pass_old); + pass_new = pass_old = NULL; /* tidy up */ +#ifdef USE_LCKPWDF + ulckpwdf(); +#endif + return retval; + } + /* + * By reaching here we have approved the passwords and must now + * rebuild the password database file. + */ + + /* + * First we encrypt the new password. + */ + + if (on(UNIX_MD5_PASS, ctrl)) { + tpass = crypt_md5_wrapper(pass_new); + } else { + /* + * Salt manipulation is stolen from Rick Faith's passwd + * program. Sorry Rick :) -- alex + */ + + time_t tm; + char salt[3]; + + time(&tm); + salt[0] = bin_to_ascii(tm & 0x3f); + salt[1] = bin_to_ascii((tm >> 6) & 0x3f); + salt[2] = '\0'; + + if (off(UNIX_BIGCRYPT, ctrl) && strlen(pass_new) > 8) { + /* + * to avoid using the _extensions_ of the bigcrypt() + * function we truncate the newly entered password + */ + char *temp = malloc(9); + char *e; + + if (temp == NULL) { + _log_err(LOG_CRIT, pamh, + "out of memory for password"); + _pam_overwrite(pass_new); + _pam_overwrite(pass_old); + pass_new = pass_old = NULL; /* tidy up */ +#ifdef USE_LCKPWDF + ulckpwdf(); +#endif + return PAM_BUF_ERR; + } + /* copy first 8 bytes of password */ + strncpy(temp, pass_new, 8); + temp[8] = '\0'; + + /* no longer need cleartext */ + e = bigcrypt(temp, salt); + tpass = x_strdup(e); + + _pam_overwrite(e); + _pam_delete(temp); /* tidy up */ + } else { + char *e; + + /* no longer need cleartext */ + e = bigcrypt(pass_new, salt); + tpass = x_strdup(e); + + _pam_overwrite(e); + } + } + + D(("password processed")); + + /* update the password database(s) -- race conditions..? */ + + retval = _do_setpass(pamh, user, pass_old, tpass, ctrl, + remember); + _pam_overwrite(pass_new); + _pam_overwrite(pass_old); + _pam_delete(tpass); + pass_old = pass_new = NULL; + } else { /* something has broken with the module */ + _log_err(LOG_ALERT, pamh, + "password received unknown request"); + retval = PAM_ABORT; + } + + D(("retval was %d", retval)); + +#ifdef USE_LCKPWDF + ulckpwdf(); +#endif + return retval; } -STATIC int _do_getpass(char *forwho, char **theirpass) -{ - struct passwd *pwd=NULL; /* Password and shadow password */ -#ifdef HAVE_SHADOW_H - struct spwd *spwdent=NULL; /* file entries for the user */ - time_t curdays; -#endif - int retval=0; - /* UNIX passwords area */ - setpwent(); - pwd = getpwnam(forwho); /* Get password file entry... */ - endpwent(); - if(pwd == NULL) - return PPW_NOSUCHUSER; /* We don't need to do the rest... */ -#ifdef HAVE_SHADOW_H - if(!strcmp(pwd->pw_passwd,"x")) { - /* ...and shadow password file entry for this user, if shadowing - is enabled */ - retval |= PPW_SHADOW; - setspent(); - spwdent = getspnam(forwho); - endspent(); - if(spwdent == NULL) - return PPW_NOSUCHUSER; - *theirpass = x_strdup(spwdent->sp_pwdp); - /* We have the user's information, now let's check if their account - has expired (60 * 60 * 24 = number of seconds in a day) */ - - /* Get the current number of days since 1970 */ - curdays = time(NULL)/(60*60*24); - if((curdays < (spwdent->sp_lstchg + spwdent->sp_min)) - && (spwdent->sp_min != -1)) - retval |= PPW_TOOEARLY; - else if((curdays - > (spwdent->sp_lstchg + spwdent->sp_max + spwdent->sp_inact)) - && (spwdent->sp_max != -1) && (spwdent->sp_inact != -1)) - /* Their password change has been put off too long, - OR their account has just plain expired */ - retval |= PPW_EXPIRED; - else if((curdays > (spwdent->sp_lstchg + spwdent->sp_max)) - && (spwdent->sp_max != -1)) - /* Their passwd needs to be changed */ - retval |= PPW_EXPIRING; - else if((curdays > (spwdent->sp_lstchg - + spwdent->sp_max - spwdent->sp_warn)) - && (spwdent->sp_max != -1) && (spwdent->sp_warn != -1)) - retval |= PPW_WILLEXPIRE; -/* if(spwdent->sp_lstchg < 0) - retval &= ~(PPW_WILLEXPIRE | PPW_EXPIRING | PPW_EXPIRED); - if(spwdent->sp_max < 0) - retval &= ~(PPW_EXPIRING | PPW_EXPIRED); */ - } else { - *theirpass = (char *)x_strdup(pwd->pw_passwd); - } - -#else - *theirpass = (char *) x_strdup(pwd->pw_passwd); +/* static module data */ +#ifdef PAM_STATIC +struct pam_module _pam_unix_passwd_modstruct = { + "pam_unix_passwd", + NULL, + NULL, + NULL, + NULL, + NULL, + pam_sm_chauthtok, +}; #endif - return retval; -} - -STATIC int conv_sendmsg(struct pam_conv *aconv, const char *message, int style) -{ - struct pam_message msg,*pmsg; - struct pam_response *resp; - int retval; - - /* Get the password from the user... */ - pmsg = &msg; - - msg.msg_style = style; - msg.msg = message; - resp = NULL; - - retval = aconv->conv(1, (const struct pam_message **) &pmsg, - &resp, aconv->appdata_ptr); - if (resp) { - _pam_drop_reply(resp, 1); - } - return retval; -} - - -STATIC int conv_getitem(struct pam_conv *aconv, char *message, int style, - char **result) -{ - struct pam_message msg,*pmsg; - struct pam_response *resp; - int retval; - - D(("called.")); - - /* Get the password from the user... */ - pmsg = &msg; - msg.msg_style = style; - msg.msg = message; - resp = NULL; - - retval = aconv->conv(1, (const struct pam_message **) &pmsg, - &resp, aconv->appdata_ptr); - if(retval != PAM_SUCCESS) - return retval; - if(resp != NULL) { - *result = resp->resp; free(resp); - return PAM_SUCCESS; - } - else - return PAM_SERVICE_ERR; -} diff --git a/contrib/libpam/modules/pam_unix/pam_unix_sess.c b/contrib/libpam/modules/pam_unix/pam_unix_sess.c index 319b2ed6288e..d0785006772c 100644 --- a/contrib/libpam/modules/pam_unix/pam_unix_sess.c +++ b/contrib/libpam/modules/pam_unix/pam_unix_sess.c @@ -1,9 +1,8 @@ -/* - * $Header: /home/morgan/pam/Linux-PAM-0.53/modules/pam_unix/RCS/pam_unix_sess.c,v 1.1 1996/11/09 19:44:35 morgan Exp $ - */ - /* + * $Id: pam_unix_sess.c,v 1.3 2000/12/20 05:15:05 vorlon Exp $ + * * Copyright Alexander O. Yuriev, 1996. All rights reserved. + * Copyright Jan Rêkorajski, 1999. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,145 +36,106 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * $Log: pam_unix_sess.c,v $ - * Revision 1.1 1996/11/09 19:44:35 morgan - * Initial revision - * - * Revision 1.4 1996/05/21 03:55:17 morgan - * added "const" to definition of rcsid[] - * - * Revision 1.3 1996/04/23 16:32:28 alex - * nothing really got changed. - * - * Revision 1.2 1996/04/19 03:23:33 alex - * session code implemented. account management moved into pam_unix_acct.c - * - */ - -#include +#include + #include -#include -#include - -#ifndef LINUX /* AGM added this as of 0.2 */ - - #include - -#endif /* ditto */ - -#include -#include +#include +#include #include -#ifndef LOG_AUTHPRIV -#define LOG_AUTHPRIV LOG_AUTH +#include +#include +#include +#include + +/* indicate the following groups are defined */ + +#define PAM_SM_SESSION + +#include +#include + +#ifndef LINUX_PAM +#include +#endif /* LINUX_PAM */ + +#include "support.h" + +/* + * PAM framework looks for these entry-points to pass control to the + * session module. + */ + +PAM_EXTERN int pam_sm_open_session(pam_handle_t * pamh, int flags, + int argc, const char **argv) +{ + char *user_name, *service; + unsigned int ctrl; + int retval; + + D(("called.")); + + ctrl = _set_ctrl(pamh, flags, NULL, argc, argv); + + retval = pam_get_item(pamh, PAM_USER, (void *) &user_name); + if (user_name == NULL || retval != PAM_SUCCESS) { + _log_err(LOG_CRIT, pamh, + "open_session - error recovering username"); + return PAM_SESSION_ERR; /* How did we get authenticated with + no username?! */ + } + retval = pam_get_item(pamh, PAM_SERVICE, (void *) &service); + if (service == NULL || retval != PAM_SUCCESS) { + _log_err(LOG_CRIT, pamh, + "open_session - error recovering service"); + return PAM_SESSION_ERR; + } + _log_err(LOG_INFO, pamh, "session opened for user %s by %s(uid=%d)" + ,user_name + ,PAM_getlogin() == NULL ? "" : PAM_getlogin(), getuid()); + + return PAM_SUCCESS; +} + +PAM_EXTERN int pam_sm_close_session(pam_handle_t * pamh, int flags, + int argc, const char **argv) +{ + char *user_name, *service; + unsigned int ctrl; + int retval; + + D(("called.")); + + ctrl = _set_ctrl(pamh, flags, NULL, argc, argv); + + retval = pam_get_item(pamh, PAM_USER, (void *) &user_name); + if (user_name == NULL || retval != PAM_SUCCESS) { + _log_err(LOG_CRIT, pamh, + "close_session - error recovering username"); + return PAM_SESSION_ERR; /* How did we get authenticated with + no username?! */ + } + retval = pam_get_item(pamh, PAM_SERVICE, (void *) &service); + if (service == NULL || retval != PAM_SUCCESS) { + _log_err(LOG_CRIT, pamh, + "close_session - error recovering service"); + return PAM_SESSION_ERR; + } + _log_err(LOG_INFO, pamh, "session closed for user %s" + ,user_name); + + return PAM_SUCCESS; +} + +/* static module data */ +#ifdef PAM_STATIC +struct pam_module _pam_unix_session_modstruct = { + "pam_unix_session", + NULL, + NULL, + NULL, + pam_sm_open_session, + pam_sm_close_session, + NULL, +}; #endif -static const char rcsid[] = "$Id: pam_unix_sess.c,v 1.1 1996/11/09 19:44:35 morgan Exp $ pam_unix session management. alex@bach.cis.temple.edu"; - -/* Define internal functions */ - -static int _get_log_level( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ); - -int _pam_unix_open_session( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ); - -int _pam_unix_close_session( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ); - -/* Implementation */ - -static int _get_log_level( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ) -{ - int i = argc; - int log_level = LOG_DEBUG; - - while ( i-- ) - { - if ( strcmp( *argv, "debug" ) == 0 ) - log_level = LOG_DEBUG; - else if ( strcmp ( *argv, "trace" ) == 0 ) - log_level = LOG_AUTHPRIV; - argv++; - } - - return log_level; -} - -int _pam_unix_open_session( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ) -{ - int log_level; - char *user_name, *service; - - - log_level = _get_log_level( pamh, flags, argc, argv ); - - pam_get_item( pamh, PAM_USER, (void*) &user_name ); - if ( !user_name ) - return PAM_CONV_ERR; /* How did we get authenticated with - no username?! */ - - pam_get_item( pamh, PAM_SERVICE, (void*) &service ); - if ( !service ) - return PAM_CONV_ERR; - - syslog ( log_level, - "pam_unix authentication session started, user %s, service %s\n", - user_name, service ); - - return PAM_SUCCESS; -} - -int _pam_unix_close_session( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ) -{ - int log_level; - char *user_name, *service; - - log_level = _get_log_level( pamh, flags, argc, argv ); - - pam_get_item( pamh, PAM_USER, (void*) &user_name ); - if ( !user_name ) - return PAM_CONV_ERR; /* How did we get authenticated with - no username?! */ - - pam_get_item( pamh, PAM_SERVICE, (void*) &service ); - if ( !service ) - return PAM_CONV_ERR; - - syslog ( log_level, - "pam_unix authentication session finished, user %s, service %s\n", - user_name, service ); - - return PAM_SUCCESS; -} - -int pam_sm_open_session( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ) -{ - return _pam_unix_open_session( pamh, flags, argc, argv ) ; -} - -int pam_sm_close_session(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - return _pam_unix_close_session( pamh, flags, argc, argv ) ; -} - diff --git a/contrib/libpam/modules/pam_unix/support.c b/contrib/libpam/modules/pam_unix/support.c index a2fafcd2c13e..f7d221f18006 100644 --- a/contrib/libpam/modules/pam_unix/support.c +++ b/contrib/libpam/modules/pam_unix/support.c @@ -1,10 +1,853 @@ /* - * $Header: /home/morgan/pam/Linux-PAM-0.53/modules/pam_unix/RCS/support.c,v 1.1 1996/11/09 19:44:35 morgan Exp $ + * $Id: support.c,v 1.8 2001/02/11 06:33:53 agmorgan Exp $ + * + * Copyright information at end of file. */ - + +#define _BSD_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "md5.h" +#include "support.h" + +extern char *crypt(const char *key, const char *salt); +extern char *bigcrypt(const char *key, const char *salt); + +/* syslogging function for errors and other information */ + +void _log_err(int err, pam_handle_t *pamh, const char *format,...) +{ + char *service = NULL; + char logname[256]; + va_list args; + + pam_get_item(pamh, PAM_SERVICE, (const void **) &service); + if (service) { + strncpy(logname, service, sizeof(logname)); + logname[sizeof(logname) - 1 - strlen("(pam_unix)")] = '\0'; + strncat(logname, "(pam_unix)", strlen("(pam_unix)")); + } else { + strncpy(logname, "pam_unix", sizeof(logname) - 1); + } + + va_start(args, format); + openlog(logname, LOG_CONS | LOG_PID, LOG_AUTH); + vsyslog(err, format, args); + va_end(args); + closelog(); +} + +/* this is a front-end for module-application conversations */ + +static int converse(pam_handle_t * pamh, int ctrl, int nargs + ,struct pam_message **message + ,struct pam_response **response) +{ + int retval; + struct pam_conv *conv; + + D(("begin to converse")); + + retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv); + if (retval == PAM_SUCCESS) { + + retval = conv->conv(nargs, (const struct pam_message **) message + ,response, conv->appdata_ptr); + + D(("returned from application's conversation function")); + + if (retval != PAM_SUCCESS && on(UNIX_DEBUG, ctrl)) { + _log_err(LOG_DEBUG, pamh, "conversation failure [%s]" + ,pam_strerror(pamh, retval)); + } + } else if (retval != PAM_CONV_AGAIN) { + _log_err(LOG_ERR, pamh + ,"couldn't obtain coversation function [%s]" + ,pam_strerror(pamh, retval)); + } + D(("ready to return from module conversation")); + + return retval; /* propagate error status */ +} + +int _make_remark(pam_handle_t * pamh, unsigned int ctrl + ,int type, const char *text) +{ + int retval = PAM_SUCCESS; + + if (off(UNIX__QUIET, ctrl)) { + struct pam_message *pmsg[1], msg[1]; + struct pam_response *resp; + + pmsg[0] = &msg[0]; + msg[0].msg = text; + msg[0].msg_style = type; + + resp = NULL; + retval = converse(pamh, ctrl, 1, pmsg, &resp); + + if (resp) { + _pam_drop_reply(resp, 1); + } + } + return retval; +} + + /* + * Beacause getlogin() is braindead and sometimes it just + * doesn't work, we reimplement it here. + */ +char *PAM_getlogin(void) +{ + struct utmp *ut, line; + char *curr_tty, *retval; + static char curr_user[sizeof(ut->ut_user) + 4]; + + retval = NULL; + + curr_tty = ttyname(0); + if (curr_tty != NULL) { + D(("PAM_getlogin ttyname: %s", curr_tty)); + curr_tty += 5; + setutent(); + strncpy(line.ut_line, curr_tty, sizeof line.ut_line); + if ((ut = getutline(&line)) != NULL) { + strncpy(curr_user, ut->ut_user, sizeof(ut->ut_user)); + retval = curr_user; + } + endutent(); + } + D(("PAM_getlogin retval: %s", retval)); + + return retval; +} + /* - * Copyright Andrew Morgan, 1996. All rights reserved. - * Modified by Alexander O. Yuriev + * set the control flags for the UNIX module. + */ + +int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int argc, + const char **argv) +{ + unsigned int ctrl; + + D(("called.")); + + ctrl = UNIX_DEFAULTS; /* the default selection of options */ + + /* set some flags manually */ + + if (getuid() == 0 && !(flags & PAM_CHANGE_EXPIRED_AUTHTOK)) { + D(("IAMROOT")); + set(UNIX__IAMROOT, ctrl); + } + if (flags & PAM_UPDATE_AUTHTOK) { + D(("UPDATE_AUTHTOK")); + set(UNIX__UPDATE, ctrl); + } + if (flags & PAM_PRELIM_CHECK) { + D(("PRELIM_CHECK")); + set(UNIX__PRELIM, ctrl); + } + if (flags & PAM_DISALLOW_NULL_AUTHTOK) { + D(("DISALLOW_NULL_AUTHTOK")); + set(UNIX__NONULL, ctrl); + } + if (flags & PAM_SILENT) { + D(("SILENT")); + set(UNIX__QUIET, ctrl); + } + /* now parse the arguments to this module */ + + while (argc-- > 0) { + int j; + + D(("pam_unix arg: %s", *argv)); + + for (j = 0; j < UNIX_CTRLS_; ++j) { + if (unix_args[j].token + && !strncmp(*argv, unix_args[j].token, strlen(unix_args[j].token))) { + break; + } + } + + if (j >= UNIX_CTRLS_) { + _log_err(LOG_ERR, pamh, + "unrecognized option [%s]", *argv); + } else { + ctrl &= unix_args[j].mask; /* for turning things off */ + ctrl |= unix_args[j].flag; /* for turning things on */ + + if (remember != NULL) { + if (j == UNIX_REMEMBER_PASSWD) { + *remember = strtol(*argv + 9, NULL, 10); + if ((*remember == LONG_MIN) || (*remember == LONG_MAX)) + *remember = -1; + if (*remember > 400) + *remember = 400; + } + } + } + + ++argv; /* step to next argument */ + } + + /* auditing is a more sensitive version of debug */ + + if (on(UNIX_AUDIT, ctrl)) { + set(UNIX_DEBUG, ctrl); + } + /* return the set of flags */ + + D(("done.")); + return ctrl; +} + +static void _cleanup(pam_handle_t * pamh, void *x, int error_status) +{ + _pam_delete(x); +} + +/* ************************************************************** * + * Useful non-trivial functions * + * ************************************************************** */ + + /* + * the following is used to keep track of the number of times a user fails + * to authenticate themself. + */ + +#define FAIL_PREFIX "-UN*X-FAIL-" +#define UNIX_MAX_RETRIES 3 + +struct _pam_failed_auth { + char *user; /* user that's failed to be authenticated */ + char *name; /* attempt from user with name */ + int uid; /* uid of calling user */ + int euid; /* euid of calling process */ + int count; /* number of failures so far */ +}; + +#ifndef PAM_DATA_REPLACE +#error "Need to get an updated libpam 0.52 or better" +#endif + +static void _cleanup_failures(pam_handle_t * pamh, void *fl, int err) +{ + int quiet; + const char *service = NULL; + const char *ruser = NULL; + const char *rhost = NULL; + const char *tty = NULL; + struct _pam_failed_auth *failure; + + D(("called")); + + quiet = err & PAM_DATA_SILENT; /* should we log something? */ + err &= PAM_DATA_REPLACE; /* are we just replacing data? */ + failure = (struct _pam_failed_auth *) fl; + + if (failure != NULL) { + + if (!quiet && !err) { /* under advisement from Sun,may go away */ + + /* log the number of authentication failures */ + if (failure->count > 1) { + (void) pam_get_item(pamh, PAM_SERVICE, + (const void **)&service); + (void) pam_get_item(pamh, PAM_RUSER, + (const void **)&ruser); + (void) pam_get_item(pamh, PAM_RHOST, + (const void **)&rhost); + (void) pam_get_item(pamh, PAM_TTY, + (const void **)&tty); + _log_err(LOG_NOTICE, pamh, + "%d more authentication failure%s; " + "logname=%s uid=%d euid=%d " + "tty=%s ruser=%s rhost=%s " + "%s%s", + failure->count - 1, failure->count == 2 ? "" : "s", + failure->name, failure->uid, failure->euid, + tty ? tty : "", ruser ? ruser : "", + rhost ? rhost : "", + (failure->user && failure->user[0] != '\0') + ? " user=" : "", failure->user + ); + + if (failure->count > UNIX_MAX_RETRIES) { + _log_err(LOG_ALERT, pamh + ,"service(%s) ignoring max retries; %d > %d" + ,service == NULL ? "**unknown**" : service + ,failure->count + ,UNIX_MAX_RETRIES); + } + } + } + _pam_delete(failure->user); /* tidy up */ + _pam_delete(failure->name); /* tidy up */ + free(failure); + } +} + +/* + * _unix_blankpasswd() is a quick check for a blank password + * + * returns TRUE if user does not have a password + * - to avoid prompting for one in such cases (CG) + */ + +int _unix_blankpasswd(unsigned int ctrl, const char *name) +{ + struct passwd *pwd = NULL; + struct spwd *spwdent = NULL; + char *salt = NULL; + int retval; + + D(("called")); + + /* + * This function does not have to be too smart if something goes + * wrong, return FALSE and let this case to be treated somewhere + * else (CG) + */ + + if (on(UNIX__NONULL, ctrl)) + return 0; /* will fail but don't let on yet */ + + /* UNIX passwords area */ + pwd = getpwnam(name); /* Get password file entry... */ + + if (pwd != NULL) { + if (strcmp( pwd->pw_passwd, "*NP*" ) == 0) + { /* NIS+ */ + uid_t save_euid, save_uid; + + save_euid = geteuid(); + save_uid = getuid(); + if (save_uid == pwd->pw_uid) + setreuid( save_euid, save_uid ); + else { + setreuid( 0, -1 ); + if (setreuid( -1, pwd->pw_uid ) == -1) { + setreuid( -1, 0 ); + setreuid( 0, -1 ); + if(setreuid( -1, pwd->pw_uid ) == -1) + /* Will fail elsewhere. */ + return 0; + } + } + + spwdent = getspnam( name ); + if (save_uid == pwd->pw_uid) + setreuid( save_uid, save_euid ); + else { + if (setreuid( -1, 0 ) == -1) + setreuid( save_uid, -1 ); + setreuid( -1, save_euid ); + } + } else if (strcmp(pwd->pw_passwd, "x") == 0) { + /* + * ...and shadow password file entry for this user, + * if shadowing is enabled + */ + spwdent = getspnam(name); + } + if (spwdent) + salt = x_strdup(spwdent->sp_pwdp); + else + salt = x_strdup(pwd->pw_passwd); + } + /* Does this user have a password? */ + if (salt == NULL) { + retval = 0; + } else { + if (strlen(salt) == 0) + retval = 1; + else + retval = 0; + } + + /* tidy up */ + + if (salt) + _pam_delete(salt); + + return retval; +} + +/* + * verify the password of a user + */ + +#include +#include + +static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd, + unsigned int ctrl, const char *user) +{ + int retval, child, fds[2]; + + D(("called.")); + /* create a pipe for the password */ + if (pipe(fds) != 0) { + D(("could not make pipe")); + return PAM_AUTH_ERR; + } + + /* fork */ + child = fork(); + if (child == 0) { + static char *envp[] = { NULL }; + char *args[] = { NULL, NULL, NULL }; + + /* XXX - should really tidy up PAM here too */ + + /* reopen stdin as pipe */ + close(fds[1]); + dup2(fds[0], STDIN_FILENO); + + /* exec binary helper */ + args[0] = x_strdup(CHKPWD_HELPER); + args[1] = x_strdup(user); + + execve(CHKPWD_HELPER, args, envp); + + /* should not get here: exit with error */ + D(("helper binary is not available")); + exit(PAM_AUTHINFO_UNAVAIL); + } else if (child > 0) { + /* wait for child */ + /* if the stored password is NULL */ + if (off(UNIX__NONULL, ctrl)) { /* this means we've succeeded */ + write(fds[1], "nullok\0\0", 8); + } else { + write(fds[1], "nonull\0\0", 8); + } + if (passwd != NULL) { /* send the password to the child */ + write(fds[1], passwd, strlen(passwd)+1); + passwd = NULL; + } else { + write(fds[1], "", 1); /* blank password */ + } + close(fds[0]); /* close here to avoid possible SIGPIPE above */ + close(fds[1]); + (void) waitpid(child, &retval, 0); /* wait for helper to complete */ + retval = (retval == 0) ? PAM_SUCCESS:PAM_AUTH_ERR; + } else { + D(("fork failed")); + retval = PAM_AUTH_ERR; + } + + D(("returning %d", retval)); + return retval; +} + +int _unix_verify_password(pam_handle_t * pamh, const char *name + ,const char *p, unsigned int ctrl) +{ + struct passwd *pwd = NULL; + struct spwd *spwdent = NULL; + char *salt = NULL; + char *pp = NULL; + char *data_name; + int retval; + + D(("called")); + +#ifdef HAVE_PAM_FAIL_DELAY + if (off(UNIX_NODELAY, ctrl)) { + D(("setting delay")); + (void) pam_fail_delay(pamh, 2000000); /* 2 sec delay for on failure */ + } +#endif + + /* locate the entry for this user */ + + D(("locating user's record")); + + /* UNIX passwords area */ + pwd = getpwnam(name); /* Get password file entry... */ + + if (pwd != NULL) { + if (strcmp( pwd->pw_passwd, "*NP*" ) == 0) + { /* NIS+ */ + uid_t save_euid, save_uid; + + save_euid = geteuid(); + save_uid = getuid(); + if (save_uid == pwd->pw_uid) + setreuid( save_euid, save_uid ); + else { + setreuid( 0, -1 ); + if (setreuid( -1, pwd->pw_uid ) == -1) { + setreuid( -1, 0 ); + setreuid( 0, -1 ); + if(setreuid( -1, pwd->pw_uid ) == -1) + return PAM_CRED_INSUFFICIENT; + } + } + + spwdent = getspnam( name ); + if (save_uid == pwd->pw_uid) + setreuid( save_uid, save_euid ); + else { + if (setreuid( -1, 0 ) == -1) + setreuid( save_uid, -1 ); + setreuid( -1, save_euid ); + } + } else if (strcmp(pwd->pw_passwd, "x") == 0) { + /* + * ...and shadow password file entry for this user, + * if shadowing is enabled + */ + spwdent = getspnam(name); + } + if (spwdent) + salt = x_strdup(spwdent->sp_pwdp); + else + salt = x_strdup(pwd->pw_passwd); + } + + data_name = (char *) malloc(sizeof(FAIL_PREFIX) + strlen(name)); + if (data_name == NULL) { + _log_err(LOG_CRIT, pamh, "no memory for data-name"); + } else { + strcpy(data_name, FAIL_PREFIX); + strcpy(data_name + sizeof(FAIL_PREFIX) - 1, name); + } + + retval = PAM_SUCCESS; + if (pwd == NULL || salt == NULL || !strcmp(salt, "x")) { + if (geteuid()) { + /* we are not root perhaps this is the reason? Run helper */ + D(("running helper binary")); + retval = _unix_run_helper_binary(pamh, p, ctrl, name); + if (pwd == NULL && !on(UNIX_AUDIT,ctrl) + && retval != PAM_SUCCESS) + { + name = NULL; + } + } else { + D(("user's record unavailable")); + if (on(UNIX_AUDIT, ctrl)) { + /* this might be a typo and the user has given a password + instead of a username. Careful with this. */ + _log_err(LOG_ALERT, pamh, + "check pass; user (%s) unknown", name); + } else { + name = NULL; + _log_err(LOG_ALERT, pamh, + "check pass; user unknown"); + } + p = NULL; + retval = PAM_AUTHINFO_UNAVAIL; + } + } else { + if (!strlen(salt)) { + /* the stored password is NULL */ + if (off(UNIX__NONULL, ctrl)) { /* this means we've succeeded */ + D(("user has empty password - access granted")); + retval = PAM_SUCCESS; + } else { + D(("user has empty password - access denied")); + retval = PAM_AUTH_ERR; + } + } else if (!p) { + retval = PAM_AUTH_ERR; + } else { + if (!strncmp(salt, "$1$", 3)) { + pp = Goodcrypt_md5(p, salt); + if (strcmp(pp, salt) != 0) { + pp = Brokencrypt_md5(p, salt); + } + } else { + pp = bigcrypt(p, salt); + } + p = NULL; /* no longer needed here */ + + /* the moment of truth -- do we agree with the password? */ + D(("comparing state of pp[%s] and salt[%s]", pp, salt)); + + if (strcmp(pp, salt) == 0) { + retval = PAM_SUCCESS; + } else { + retval = PAM_AUTH_ERR; + } + } + } + + if (retval == PAM_SUCCESS) { + if (data_name) /* reset failures */ + pam_set_data(pamh, data_name, NULL, _cleanup_failures); + } else { + if (data_name != NULL) { + struct _pam_failed_auth *new = NULL; + const struct _pam_failed_auth *old = NULL; + + /* get a failure recorder */ + + new = (struct _pam_failed_auth *) + malloc(sizeof(struct _pam_failed_auth)); + + if (new != NULL) { + + new->user = x_strdup(name ? name : ""); + new->uid = getuid(); + new->euid = geteuid(); + new->name = x_strdup(PAM_getlogin()? PAM_getlogin() : ""); + + /* any previous failures for this user ? */ + pam_get_data(pamh, data_name, (const void **) &old); + + if (old != NULL) { + new->count = old->count + 1; + if (new->count >= UNIX_MAX_RETRIES) { + retval = PAM_MAXTRIES; + } + } else { + const char *service=NULL; + const char *ruser=NULL; + const char *rhost=NULL; + const char *tty=NULL; + + (void) pam_get_item(pamh, PAM_SERVICE, + (const void **)&service); + (void) pam_get_item(pamh, PAM_RUSER, + (const void **)&ruser); + (void) pam_get_item(pamh, PAM_RHOST, + (const void **)&rhost); + (void) pam_get_item(pamh, PAM_TTY, + (const void **)&tty); + + _log_err(LOG_NOTICE, pamh, + "authentication failure; " + "logname=%s uid=%d euid=%d " + "tty=%s ruser=%s rhost=%s " + "%s%s", + new->name, new->uid, new->euid, + tty ? tty : "", + ruser ? ruser : "", + rhost ? rhost : "", + (new->user && new->user[0] != '\0') + ? " user=" : "", + new->user + ); + new->count = 1; + } + + pam_set_data(pamh, data_name, new, _cleanup_failures); + + } else { + _log_err(LOG_CRIT, pamh, + "no memory for failure recorder"); + } + } + } + + if (data_name) + _pam_delete(data_name); + if (salt) + _pam_delete(salt); + if (pp) + _pam_overwrite(pp); + + D(("done [%d].", retval)); + + return retval; +} + +/* + * obtain a password from the user + */ + +int _unix_read_password(pam_handle_t * pamh + ,unsigned int ctrl + ,const char *comment + ,const char *prompt1 + ,const char *prompt2 + ,const char *data_name + ,const char **pass) +{ + int authtok_flag; + int retval; + const char *item; + char *token; + + D(("called")); + + /* + * make sure nothing inappropriate gets returned + */ + + *pass = token = NULL; + + /* + * which authentication token are we getting? + */ + + authtok_flag = on(UNIX__OLD_PASSWD, ctrl) ? PAM_OLDAUTHTOK : PAM_AUTHTOK; + + /* + * should we obtain the password from a PAM item ? + */ + + if (on(UNIX_TRY_FIRST_PASS, ctrl) || on(UNIX_USE_FIRST_PASS, ctrl)) { + retval = pam_get_item(pamh, authtok_flag, (const void **) &item); + if (retval != PAM_SUCCESS) { + /* very strange. */ + _log_err(LOG_ALERT, pamh + ,"pam_get_item returned error to unix-read-password" + ); + return retval; + } else if (item != NULL) { /* we have a password! */ + *pass = item; + item = NULL; + return PAM_SUCCESS; + } else if (on(UNIX_USE_FIRST_PASS, ctrl)) { + return PAM_AUTHTOK_RECOVER_ERR; /* didn't work */ + } else if (on(UNIX_USE_AUTHTOK, ctrl) + && off(UNIX__OLD_PASSWD, ctrl)) { + return PAM_AUTHTOK_RECOVER_ERR; + } + } + /* + * getting here implies we will have to get the password from the + * user directly. + */ + + { + struct pam_message msg[3], *pmsg[3]; + struct pam_response *resp; + int i, replies; + + /* prepare to converse */ + + if (comment != NULL && off(UNIX__QUIET, ctrl)) { + pmsg[0] = &msg[0]; + msg[0].msg_style = PAM_TEXT_INFO; + msg[0].msg = comment; + i = 1; + } else { + i = 0; + } + + pmsg[i] = &msg[i]; + msg[i].msg_style = PAM_PROMPT_ECHO_OFF; + msg[i++].msg = prompt1; + replies = 1; + + if (prompt2 != NULL) { + pmsg[i] = &msg[i]; + msg[i].msg_style = PAM_PROMPT_ECHO_OFF; + msg[i++].msg = prompt2; + ++replies; + } + /* so call the conversation expecting i responses */ + resp = NULL; + retval = converse(pamh, ctrl, i, pmsg, &resp); + + if (resp != NULL) { + + /* interpret the response */ + + if (retval == PAM_SUCCESS) { /* a good conversation */ + + token = x_strdup(resp[i - replies].resp); + if (token != NULL) { + if (replies == 2) { + + /* verify that password entered correctly */ + if (!resp[i - 1].resp + || strcmp(token, resp[i - 1].resp)) { + _pam_delete(token); /* mistyped */ + retval = PAM_AUTHTOK_RECOVER_ERR; + _make_remark(pamh, ctrl + ,PAM_ERROR_MSG, MISTYPED_PASS); + } + } + } else { + _log_err(LOG_NOTICE, pamh + ,"could not recover authentication token"); + } + + } + /* + * tidy up the conversation (resp_retcode) is ignored + * -- what is it for anyway? AGM + */ + + _pam_drop_reply(resp, i); + + } else { + retval = (retval == PAM_SUCCESS) + ? PAM_AUTHTOK_RECOVER_ERR : retval; + } + } + + if (retval != PAM_SUCCESS) { + if (on(UNIX_DEBUG, ctrl)) + _log_err(LOG_DEBUG, pamh, + "unable to obtain a password"); + return retval; + } + /* 'token' is the entered password */ + + if (off(UNIX_NOT_SET_PASS, ctrl)) { + + /* we store this password as an item */ + + retval = pam_set_item(pamh, authtok_flag, token); + _pam_delete(token); /* clean it up */ + if (retval != PAM_SUCCESS + || (retval = pam_get_item(pamh, authtok_flag + ,(const void **) &item)) + != PAM_SUCCESS) { + + _log_err(LOG_CRIT, pamh, "error manipulating password"); + return retval; + + } + } else { + /* + * then store it as data specific to this module. pam_end() + * will arrange to clean it up. + */ + + retval = pam_set_data(pamh, data_name, (void *) token, _cleanup); + if (retval != PAM_SUCCESS) { + _log_err(LOG_CRIT, pamh + ,"error manipulating password data [%s]" + ,pam_strerror(pamh, retval)); + _pam_delete(token); + return retval; + } + item = token; + token = NULL; /* break link to password */ + } + + *pass = item; + item = NULL; /* break link to password */ + + return PAM_SUCCESS; +} + +/* ****************************************************************** * + * Copyright (c) Jan Rêkorajski 1999. + * Copyright (c) Andrew G. Morgan 1996-8. + * Copyright (c) Alex O. Yuriev, 1996. + * Copyright (c) Cristian Gafton 1996. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,116 +880,3 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ - -/* - * $Log: support.c,v $ - * Revision 1.1 1996/11/09 19:44:35 morgan - * Initial revision - * - * Revision 1.1 1996/04/17 01:11:08 alex - * Initial revision - * - */ - -#include /* define NULL */ - -#ifndef LINUX - - #include - -#endif /* LINUX */ - -#include - - -#ifndef NDEBUG - - #include - -#endif /* NDEBUG */ - - -/* Phototype declarations */ - -int converse( pam_handle_t *pamh, - int nargs, - struct pam_message **message, - struct pam_response **response ); - -int _set_auth_tok( pam_handle_t *pamh, - int flags, - int argc, - const char **argv ); - -/* Implementation */ - -int converse( pam_handle_t *pamh, - int nargs, - struct pam_message **message, - struct pam_response **response ) - -{ - int retval; - struct pam_conv *conv; - - retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ; - if ( retval == PAM_SUCCESS ) - { - retval = conv->conv( nargs, - ( const struct pam_message ** ) message, - response, - conv->appdata_ptr ); - } - return retval; -} - -/***************************************************************************/ -/* prompt user for a using conversation calls */ -/***************************************************************************/ - -int _set_auth_tok( pam_handle_t *pamh, - int flags, int argc, - const char **argv ) -{ - int retval; - char *p; - - struct pam_message msg[1],*pmsg[1]; - struct pam_response *resp; - - /* set up conversation call */ - - pmsg[0] = &msg[0]; - msg[0].msg_style = PAM_PROMPT_ECHO_OFF; - msg[0].msg = "Password: "; - resp = NULL; - - if ( ( retval = converse( pamh, 1 , pmsg, &resp ) ) != PAM_SUCCESS ) - return retval; - - if ( resp ) - { - if ( ( flags & PAM_DISALLOW_NULL_AUTHTOK ) && - resp[0].resp == NULL ) - { - free( resp ); - return PAM_AUTH_ERR; - } - - p = resp[ 0 ].resp; - - /* This could be a memory leak. If resp[0].resp - is malloc()ed, then it has to be free()ed! - -- alex - */ - - resp[ 0 ].resp = NULL; - - } - else - return PAM_CONV_ERR; - - free( resp ); - pam_set_item( pamh, PAM_AUTHTOK, p ); - return PAM_SUCCESS; -} diff --git a/contrib/libpam/modules/pam_unix/support.h b/contrib/libpam/modules/pam_unix/support.h new file mode 100644 index 000000000000..80f0b405d8bb --- /dev/null +++ b/contrib/libpam/modules/pam_unix/support.h @@ -0,0 +1,144 @@ +/* + * $Id: support.h,v 1.3 2000/12/20 05:15:05 vorlon Exp $ + */ + +#ifndef _PAM_UNIX_SUPPORT_H +#define _PAM_UNIX_SUPPORT_H + + +/* + * here is the string to inform the user that the new passwords they + * typed were not the same. + */ + +#define MISTYPED_PASS "Sorry, passwords do not match" + +/* type definition for the control options */ + +typedef struct { + const char *token; + unsigned int mask; /* shall assume 32 bits of flags */ + unsigned int flag; +} UNIX_Ctrls; + +/* + * macro to determine if a given flag is on + */ + +#define on(x,ctrl) (unix_args[x].flag & ctrl) + +/* + * macro to determine that a given flag is NOT on + */ + +#define off(x,ctrl) (!on(x,ctrl)) + +/* + * macro to turn on/off a ctrl flag manually + */ + +#define set(x,ctrl) (ctrl = ((ctrl)&unix_args[x].mask)|unix_args[x].flag) +#define unset(x,ctrl) (ctrl &= ~(unix_args[x].flag)) + +/* the generic mask */ + +#define _ALL_ON_ (~0U) + +/* end of macro definitions definitions for the control flags */ + +/* ****************************************************************** * + * ctrl flags proper.. + */ + +/* + * here are the various options recognized by the unix module. They + * are enumerated here and then defined below. Internal arguments are + * given NULL tokens. + */ + +#define UNIX__OLD_PASSWD 0 /* internal */ +#define UNIX__VERIFY_PASSWD 1 /* internal */ +#define UNIX__IAMROOT 2 /* internal */ + +#define UNIX_AUDIT 3 /* print more things than debug.. + some information may be sensitive */ +#define UNIX_USE_FIRST_PASS 4 +#define UNIX_TRY_FIRST_PASS 5 +#define UNIX_NOT_SET_PASS 6 /* don't set the AUTHTOK items */ + +#define UNIX__PRELIM 7 /* internal */ +#define UNIX__UPDATE 8 /* internal */ +#define UNIX__NONULL 9 /* internal */ +#define UNIX__QUIET 10 /* internal */ +#define UNIX_USE_AUTHTOK 11 /* insist on reading PAM_AUTHTOK */ +#define UNIX_SHADOW 12 /* signal shadow on */ +#define UNIX_MD5_PASS 13 /* force the use of MD5 passwords */ +#define UNIX__NULLOK 14 /* Null token ok */ +#define UNIX_DEBUG 15 /* send more info to syslog(3) */ +#define UNIX_NODELAY 16 /* admin does not want a fail-delay */ +#define UNIX_NIS 17 /* wish to use NIS for pwd */ +#define UNIX_BIGCRYPT 18 /* use DEC-C2 crypt()^x function */ +#define UNIX_LIKE_AUTH 19 /* need to auth for setcred to work */ +#define UNIX_REMEMBER_PASSWD 20 /* Remember N previous passwords */ +/* -------------- */ +#define UNIX_CTRLS_ 21 /* number of ctrl arguments defined */ + + +static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = +{ +/* symbol token name ctrl mask ctrl * + * ----------------------- ------------------- --------------------- -------- */ + +/* UNIX__OLD_PASSWD */ {NULL, _ALL_ON_, 01}, +/* UNIX__VERIFY_PASSWD */ {NULL, _ALL_ON_, 02}, +/* UNIX__IAMROOT */ {NULL, _ALL_ON_, 04}, +/* UNIX_AUDIT */ {"audit", _ALL_ON_, 010}, +/* UNIX_USE_FIRST_PASS */ {"use_first_pass", _ALL_ON_^(060), 020}, +/* UNIX_TRY_FIRST_PASS */ {"try_first_pass", _ALL_ON_^(060), 040}, +/* UNIX_NOT_SET_PASS */ {"not_set_pass", _ALL_ON_, 0100}, +/* UNIX__PRELIM */ {NULL, _ALL_ON_^(0600), 0200}, +/* UNIX__UPDATE */ {NULL, _ALL_ON_^(0600), 0400}, +/* UNIX__NONULL */ {NULL, _ALL_ON_, 01000}, +/* UNIX__QUIET */ {NULL, _ALL_ON_, 02000}, +/* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 04000}, +/* UNIX_SHADOW */ {"shadow", _ALL_ON_, 010000}, +/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(0400000), 020000}, +/* UNIX__NULLOK */ {"nullok", _ALL_ON_^(01000), 0}, +/* UNIX_DEBUG */ {"debug", _ALL_ON_, 040000}, +/* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0100000}, +/* UNIX_NIS */ {"nis", _ALL_ON_^(010000), 0200000}, +/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(020000), 0400000}, +/* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000}, +/* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000}, +}; + +#define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag) + + +/* use this to free strings. ESPECIALLY password strings */ + +#define _pam_delete(xx) \ +{ \ + _pam_overwrite(xx); \ + _pam_drop(xx); \ +} + +extern char *PAM_getlogin(void); +extern void _log_err(int err, pam_handle_t *pamh, const char *format,...); +extern int _make_remark(pam_handle_t * pamh, unsigned int ctrl + ,int type, const char *text); +extern int _set_ctrl(pam_handle_t * pamh, int flags, int *remember, int argc, + const char **argv); +extern int _unix_blankpasswd(unsigned int ctrl, const char *name); +extern int _unix_verify_password(pam_handle_t * pamh, const char *name + ,const char *p, unsigned int ctrl); +extern int _unix_read_password(pam_handle_t * pamh + ,unsigned int ctrl + ,const char *comment + ,const char *prompt1 + ,const char *prompt2 + ,const char *data_name + ,const char **pass); + +#endif /* _PAM_UNIX_SUPPORT_H */ + diff --git a/contrib/libpam/modules/pam_unix/unix_chkpwd.c b/contrib/libpam/modules/pam_unix/unix_chkpwd.c new file mode 100644 index 000000000000..e232e759453c --- /dev/null +++ b/contrib/libpam/modules/pam_unix/unix_chkpwd.c @@ -0,0 +1,314 @@ +/* + * $Id: unix_chkpwd.c,v 1.3 2001/02/11 06:33:53 agmorgan Exp $ + * + * This program is designed to run setuid(root) or with sufficient + * privilege to read all of the unix password databases. It is designed + * to provide a mechanism for the current user (defined by this + * process' uid) to verify their own password. + * + * The password is read from the standard input. The exit status of + * this program indicates whether the user is authenticated or not. + * + * Copyright information is located at the end of the file. + * + */ + +#include + +#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 000000000000..6b414be09a57 --- /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 000000000000..b1a60b4ce11e --- /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 000000000000..ebdcff9cd335 --- /dev/null +++ b/contrib/libpam/modules/pam_userdb/Makefile @@ -0,0 +1,35 @@ +# +# This Makefile controls a build process of $(TITLE) module for +# Linux-PAM. You should not modify this Makefile (unless you know +# what you are doing!). + +# $Id: Makefile,v 1.4 2001/02/18 03:03:31 agmorgan Exp $ +# Created by Cristian Gafton + +include ../../Make.Rules + +TITLE=pam_userdb + +ifeq ($(HAVE_NDBM_H),yes) + WHICH_DB=ndbm + MODULE_SIMPLE_EXTRALIBS = -lndbm +else +ifeq ($(HAVE_LIBDB),yes) + WHICH_DB=db + MODULE_SIMPLE_EXTRALIBS = -ldb +else + WHICH_DB=none +endif +endif + +ifeq ($(WHICH_DB),none) + +include ../dont_makefile + +else + +MODULE_SIMPLE_EXTRAFILES = conv + +include ../Simple.Rules + +endif diff --git a/contrib/libpam/modules/pam_userdb/README b/contrib/libpam/modules/pam_userdb/README new file mode 100644 index 000000000000..af78d47b1309 --- /dev/null +++ b/contrib/libpam/modules/pam_userdb/README @@ -0,0 +1,30 @@ +pam_userdb: + Look up users in a .db database and verify their password against + what is contained in that database. + +RECOGNIZED ARGUMENTS: + debug write a message to syslog indicating success or + failure. + + db=[path] use the [path] database for performing lookup. There + is no default; the module will return PAM_IGNORE if + no database is provided. + + icase make the password verification to be case insensitive + (ie when working with registration numbers and such) + + dump dump all the entries in the database to the log (eek, + don't do this by default!) + +MODULE SERVICES PROVIDED: + auth _authetication and _setcred (blank) + +EXAMPLE USE: + auth sufficient pam_userdb.so icase db=/tmp/dbtest.db + +AUTHOR: + Cristian Gafton + + + +$Id: README,v 1.1.1.1 2000/06/20 22:12:09 agmorgan Exp $ diff --git a/contrib/libpam/modules/pam_userdb/conv.c b/contrib/libpam/modules/pam_userdb/conv.c new file mode 100644 index 000000000000..0f13d03a4fc4 --- /dev/null +++ b/contrib/libpam/modules/pam_userdb/conv.c @@ -0,0 +1,125 @@ +/* + * Conversation related functions + */ + +/* $Id */ +/* Copyright at the end of the file */ + +#define _BSD_SOURCE + +#include +#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 000000000000..0e1687dfef65 --- /dev/null +++ b/contrib/libpam/modules/pam_userdb/create.pl @@ -0,0 +1,23 @@ +#!/usr/bin/perl +# this program creates a database in ARGV[1] from pairs given on +# stdandard input +# +# $Id: create.pl,v 1.1.1.1 2000/06/20 22:12:09 agmorgan Exp $ + +use DB_File; + +my $database = $ARGV[0]; +die "Use: check,pl \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 000000000000..9da93705e514 --- /dev/null +++ b/contrib/libpam/modules/pam_userdb/pam_userdb.c @@ -0,0 +1,304 @@ +/* pam_userdb module */ + +/* + * $Id: pam_userdb.c,v 1.4 2000/12/04 15:02:16 baggins Exp $ + * Written by Cristian Gafton 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 000000000000..542cdf57943f --- /dev/null +++ b/contrib/libpam/modules/pam_userdb/pam_userdb.h @@ -0,0 +1,61 @@ + +#ifndef _PAM_USERSDB_H +#define _PAM_USERSDB_H +/* $Id: pam_userdb.h,v 1.1.1.1 2000/06/20 22:12:09 agmorgan Exp $ */ + +/* Header files */ +#include + +/* 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. + */ diff --git a/contrib/libpam/modules/pam_warn/Makefile b/contrib/libpam/modules/pam_warn/Makefile index 167af5a370ac..b1420538d577 100644 --- a/contrib/libpam/modules/pam_warn/Makefile +++ b/contrib/libpam/modules/pam_warn/Makefile @@ -1,96 +1,15 @@ # -# $Id: Makefile,v 1.2 1997/04/05 06:20:16 morgan Exp $ +# $Id: Makefile,v 1.2 2000/11/19 23:54:06 agmorgan Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# $Log: Makefile,v $ -# Revision 1.2 1997/04/05 06:20:16 morgan -# fixed fakeroot -# -# Revision 1.1 1996/12/01 03:12:22 morgan -# Initial revision -# -# -# Created by Andrew Morgan 1996/11/14 +# Created by Andrew Morgan 2000/08/27 # +include ../../Make.Rules + TITLE=pam_warn -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< - +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_warn/README b/contrib/libpam/modules/pam_warn/README index f45b271c0d77..3c4bde8af20d 100644 --- a/contrib/libpam/modules/pam_warn/README +++ b/contrib/libpam/modules/pam_warn/README @@ -1,4 +1,4 @@ -# $Id: README,v 1.1 1996/12/01 03:12:22 morgan Exp $ +# $Id: README,v 1.1.1.1 2000/06/20 22:12:10 agmorgan Exp $ # This module is an authentication module that does not authenticate. @@ -15,7 +15,10 @@ Recognized arguments: module services provided: - auth _autheticate and _setcred (blank) + auth _authenticate and _setcred (blank) + acct _acct_mgmt [mapped to _authenticate] + session _open_session and + _close_session [mapped to _authenticate ] password _chauthtok [mapped to _authenticate] diff --git a/contrib/libpam/modules/pam_warn/pam_warn.c b/contrib/libpam/modules/pam_warn/pam_warn.c index 2a0a23d6e989..a9bcc9e70c5c 100644 --- a/contrib/libpam/modules/pam_warn/pam_warn.c +++ b/contrib/libpam/modules/pam_warn/pam_warn.c @@ -1,20 +1,13 @@ /* pam_warn module */ /* - * $Id: pam_warn.c,v 1.2 1997/02/15 17:19:08 morgan Exp $ - * - * Written by Andrew Morgan 1996/3/11 - * - * $Log: pam_warn.c,v $ - * Revision 1.2 1997/02/15 17:19:08 morgan - * corrected many bugs and removed fixed buffer logging - * - * Revision 1.1 1996/12/01 03:12:22 morgan - * Initial revision - * + * $Id: pam_warn.c,v 1.1.1.1 2000/06/20 22:12:10 agmorgan Exp $ * + * Written by Andrew Morgan 1996/3/11 */ +#define _BSD_SOURCE + #include #include #include @@ -93,18 +86,45 @@ int pam_sm_chauthtok(pam_handle_t *pamh,int flags,int argc return pam_sm_authenticate(pamh, flags, argc, argv); } +PAM_EXTERN int +pam_sm_acct_mgmt (pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + /* map to the authentication function... */ + + return pam_sm_authenticate(pamh, flags, argc, argv); +} + +PAM_EXTERN int +pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + /* map to the authentication function... */ + + return pam_sm_authenticate(pamh, flags, argc, argv); +} + +PAM_EXTERN int +pam_sm_close_session (pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + /* map to the authentication function... */ + + return pam_sm_authenticate(pamh, flags, argc, argv); +} + #ifdef PAM_STATIC /* static module data */ struct pam_module _pam_warn_modstruct = { - "pam_warn", - pam_sm_authenticate, - pam_sm_setcred, - NULL, - NULL, - NULL, - pam_sm_chauthtok, + "pam_warn", + pam_sm_authenticate, + pam_sm_setcred, + pam_sm_acct_mgmt, + pam_sm_open_session, + pam_sm_close_session, + pam_sm_chauthtok, }; #endif diff --git a/contrib/libpam/modules/pam_wheel/Makefile b/contrib/libpam/modules/pam_wheel/Makefile index 553e32199668..67947f814101 100644 --- a/contrib/libpam/modules/pam_wheel/Makefile +++ b/contrib/libpam/modules/pam_wheel/Makefile @@ -1,94 +1,15 @@ # +# $Id: Makefile,v 1.2 2000/11/19 23:54:06 agmorgan Exp $ +# # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know # what you are doing!). # -# Created by Cristian Gafton 1996/09/10 +# Created by Andrew Morgan 2000/08/27 # -ifeq ($(HAVE_PWDBLIB),yes) +include ../../Make.Rules TITLE=pam_wheel -CFLAGS += -DHAVE_PWDBLIB -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -#LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -EXTRALS = -lpwdb - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -#static/%.o : %.c -# $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -#ifdef STATIC -#LIBSTATIC = lib$(TITLE).o -#endif - -####################### don't edit below ####################### - -dummy: - - @echo "**** This is not a top-level Makefile " - exit - -all: dirs $(LIBSHARED) $(LIBSTATIC) register - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -#ifdef STATIC -# $(MKDIR) ./static -#endif - -register: -#ifdef STATIC -# ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -#endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) $(EXTRALS) -endif - -#ifdef STATIC -#$(LIBOBJS): $(LIBSRC) -# -#$(LIBSTATIC): $(LIBOBJS) -# $(LD) -r -o $@ $(LIBOBJS) $(EXTRALS) -#endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) core *~ *.so - -extraclean: clean - rm -f *.a *.o *.so *.bak dynamic/* static/* - -.c.o: - $(CC) $(CFLAGS) -c $< - -else -include ../dont_makefile -endif +include ../Simple.Rules diff --git a/contrib/libpam/modules/pam_wheel/pam_wheel.c b/contrib/libpam/modules/pam_wheel/pam_wheel.c index db262d83d8c9..add72bc43f48 100644 --- a/contrib/libpam/modules/pam_wheel/pam_wheel.c +++ b/contrib/libpam/modules/pam_wheel/pam_wheel.c @@ -21,20 +21,16 @@ * a wheel member. */ +#define _BSD_SOURCE + #include -#define __USE_BSD #include #include #include #include #include -#ifdef HAVE_PWDBLIB -# include -#else -# include -# include -#endif - +#include +#include /* * here, we make a definition for the externally accessible function @@ -47,9 +43,6 @@ #include -/* variables */ -static char use_group[BUFSIZ]; - /* some syslogging */ static void _pam_log(int err, const char *format, ...) @@ -82,7 +75,7 @@ static int is_on_list(char * const *list, const char *member) #define PAM_TRUST_ARG 0x0004 #define PAM_DENY_ARG 0x0010 -static int _pam_parse(int argc, const char **argv) +static int _pam_parse(int argc, const char **argv, char *use_group) { int ctrl=0; @@ -122,11 +115,12 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc struct passwd *pwd, *tpwd; struct group *grp; int retval = PAM_AUTH_ERR; + char use_group[BUFSIZ]; /* Init the optional group */ - bzero(use_group,sizeof(use_group)); + bzero(use_group,BUFSIZ); - ctrl = _pam_parse(argc, argv); + ctrl = _pam_parse(argc, argv, use_group); retval = pam_get_user(pamh,&username,NULL); if ((retval != PAM_SUCCESS) || (!username)) { if (ctrl & PAM_DEBUG_ARG) @@ -171,10 +165,12 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc } } - if (!use_group[0]) - grp = getgrgid(0); - else - grp = getgrnam(use_group); + if (!use_group[0]) { + if ((grp = getgrnam("wheel")) == NULL) { + grp = getgrgid(0); + } + } else + grp = getgrnam(use_group); if (!grp || !grp->gr_mem) { if (ctrl & PAM_DEBUG_ARG) {