diff -Nur pam_skey-1.1.4/INSTALL pam_skey/INSTALL --- pam_skey-1.1.4/INSTALL 2005-06-18 14:11:24.000000000 +0200 +++ pam_skey/INSTALL 2006-03-06 09:26:55.000000000 +0100 @@ -1,5 +1,39 @@ $Id: INSTALL,v 1.1.1.1 2005/06/18 12:11:24 kreator Exp $ +Gentoo patch +------------ +Most everything below still holds, though the libraries required are now +those used by Gentoo. Other S/Key libraries may work with a bit of +tweaking. + +The options listed for the module below are no longer valid. See the +Gentoo patch section in README for details. + +The intended method for configuring PAM is by using the newer module +specification, with a line like: + +auth [success=done ignore=ignore auth_err=die default=bad] /lib/security/pam_skey.so + +This is a combination of the standard "sufficient" and "requisite" +specifications: + +- If the module returns PAM_SUCCESS, we are authenticated and no other + modules should be tested. +- If the module returns PAM_IGNORE, then the module didn't accept its + input as an S/Key response, and the next module should try using + the input (using the try_first_pass option). +- If the module returns PAM_AUTH_ERR, then the module accepted an + S/Key input but it was invalid. Do not try any more modules in the + stack; the user already chose S/Key authentication. +- If the module returns any other code, it is a simple error in processing. + Set the error flag but try other modules, just in case. + +The module is intended to be placed before another authentication module, +like pam_unix.so; if not, it should be placed before pam_deny.so. + +If the newer module specification is unavailable in your version of PAM, +the "sufficient" specification will work. + Required -------- For building this package you will probably need original Wietse Venema's diff -Nur pam_skey-1.1.4/Makefile.in pam_skey/Makefile.in --- pam_skey-1.1.4/Makefile.in 2005-06-18 14:11:24.000000000 +0200 +++ pam_skey/Makefile.in 2006-03-06 09:26:55.000000000 +0100 @@ -12,42 +12,26 @@ LIBS=@LIBS@ @SKEYLIB@ @PAMLIB@ LDFLAGS=@LDFLAGS@ -INSTALL=@INSTALL@ -m 644 +INSTALL=@INSTALL@ +INSTALL_LIB=${INSTALL} -m 755 RM=@RM@ -f CP=@CP@ -f LN=@LN@ -s AWK=@AWK@ -PAM_FILES=pam_skey.so.1 pam_skey_access.so.1 +PAM_FILES=pam_skey.so all: $(PAM_FILES) -pam_skey.so.1: pam_skey.o - $(CC) $(CFLAGS) -o $@ $< $(LIBS) $(LDFLAGS) - -pam_skey_access.so.1: pam_skey_access.o +pam_skey.so: pam_skey.o $(CC) $(CFLAGS) -o $@ $< $(LIBS) $(LDFLAGS) lint-pam_skey: lclint $(CFLAGS) pam_skey.c -lint-pam_skey_access: - lclint $(CFLAGS) pam_skey_access.c - -install: - @if test ! -d $(INSTALLDIR); then \ - echo "Missing $(INSTALLDIR). Problem with PAM installation?"; \ - else \ - for file in $(PAM_FILES); do \ - if test ! -f "$(INSTALLDIR)/$$file"; then \ - echo "Installing $$file in $(INSTALLDIR)"; \ - $(INSTALL) "$$file" "$(INSTALLDIR)/$$file"; \ - (cd $(INSTALLDIR) && $(LN) "$$file" `echo $$file | cut -d. -f1,2`); \ - else \ - echo "$$file exists - will not overwrite it"; \ - fi \ - done \ - fi +install: all + $(INSTALL) -d $(INSTALLDIR) + $(INSTALL_LIB) $(PAM_FILES) $(INSTALLDIR) clean: $(RM) a.out core *.so.1 *.o *.bak diff -Nur pam_skey-1.1.4/README pam_skey/README --- pam_skey-1.1.4/README 2005-06-18 14:36:18.000000000 +0200 +++ pam_skey/README 2006-03-06 09:26:55.000000000 +0100 @@ -1,5 +1,77 @@ $Id: README,v 1.2 2005/06/18 12:36:18 kreator Exp $ +Gentoo patch +------------ + +The Gentoo pam_skey patch changes the original module in a number of ways. +The behavior of the module is changed to make it more consistent with the +PAM design, and several changes were made throughout the code to make the +module interact better with the skey library used by Gentoo. Many of +these changes will break pam_skey's compatibility with other systems and +libraries, but this is, after all, the Gentoo patch. + +A (not necessarily) exhaustive list of the changes is as follows: +- pam_skey_access.so is completely removed, since the Gentoo skey library + does not support the skey_access() call. +- The pam_skey.so authentication code is completely rewritten. The + original code contained many references to the standard I/O library + (writing to stderr, etc.), as well as inconsistent communication with + the PAM libraries. Also, the authentication process is different, as + described below. +- The options accepted by the pam_skey.so module are different, as + described below. + +Four options are accepted by the pam_skey.so module: + debug - This option turns on debug logging. + try_first_pass - This option tells the module to first try using + the authentication token passed from the + previous module as an S/Key response, before + informing the user of the challenge. If the + token is not valid, the module will proceed with + the standard process of challenging the user + and requesting a response, subject to the + no_default_skey option below. + use_first_pass - This option is identical to the try_first_pass + option, except that if the token is not valid, + it will return silently without challenging the + user. + no_default_skey - This flag changes the behavior of pam_skey. + Instead of immediately challenging the user with + an S/Key challenge, it will present the user with + a standard "Password: " prompt. If the user enters + the password "s/key" (case insensitive), it will + then challenge the user. Any other input will + cause the module to pass the given password to the + next module in the authentication stack (usually + pam_unix.so with the try_first_pass option). + +The exact behavior of pam_skey.so is detailed below: + +1. Retrieve username from PAM, possibly querying the user for it. +2. If the user does not have any S/Key information, return PAM_IGNORE to + proceed to the next module in the stack. +3. If *_first_pass is enabled, check the given authentication token to see + if it is a valid response to the current S/Key challenge. If so, + return PAM_SUCCESS. + 3a. If the token is invalid and use_first_pass is enabled, return + PAM_IGNORE. +4. If no_default_skey is enabled, issue a "Password: " prompt. + 4a. If the response is anything besides "s/key" (case insensitive), + store it as the authentication token and return PAM_IGNORE. +5. Display the current S/Key challenge and request a response, with + input not echoed. If no_default_skey is enabled, this will only be + an S/Key response request; otherwise, it will request either an + S/Key response or a system passsword. + 5a. If an empty response is given, request the S/Key response again, + this time with input echoed. + 5b. If the response is a valid S/Key response, return PAM_SUCCESS. + Otherwise, return PAM_AUTHERR. +6. If the response is a valid S/Key response, return PAM_SUCCESS. +7. Otherwise, if no_default_skey is enabled (the user specifically + requested "s/key" authentication), return PAM_AUTHERR. +8. Otherwise, store the response as the authentication token and + return PAM_IGNORE. + About ----- This is complete pam_skey modul as interface to existing S/Key diff -Nur pam_skey-1.1.4/autoconf/acconfig.h pam_skey/autoconf/acconfig.h --- pam_skey-1.1.4/autoconf/acconfig.h 2005-06-18 14:11:24.000000000 +0200 +++ pam_skey/autoconf/acconfig.h 2006-03-06 09:26:55.000000000 +0100 @@ -1,17 +1,2 @@ /* Define if we can include both string.h and strings.h */ #undef STRING_WITH_STRINGS - -/* Define if you have Linux */ -#undef LINUX - -/* Define if you have *BSD */ -#undef BSD - -/* Define if not missing skeyaccess() */ -#undef HAVE_SKEYACCESS - -/* Define if not missing skeyinfo() */ -#undef HAVE_SKEYINFO - -/* Define if you have skeylookup() instead of skeyinfo() */ -#undef HAVE_SKEYLOOKUP diff -Nur pam_skey-1.1.4/autoconf/configure.in pam_skey/autoconf/configure.in --- pam_skey-1.1.4/autoconf/configure.in 2005-06-18 14:11:24.000000000 +0200 +++ pam_skey/autoconf/configure.in 2006-03-06 09:26:55.000000000 +0100 @@ -10,21 +10,9 @@ AC_LANG_C AC_LANG_SAVE -dnl Get system type -AC_CANONICAL_HOST -MYHOST=$host_os -case "$host_os" in -*linux*) - AC_DEFINE(LINUX) - ;; -*bsd*) - AC_DEFINE(BSD) - ;; -esac - dnl Package information PACKAGE=pam_skey -VERSION=1.1 +VERSION=1.4r1 dnl Standard installation path AC_PREFIX_DEFAULT(/usr) @@ -65,13 +53,9 @@ AC_ARG_WITH(skey-inc, [ --with-skey-inc=DIR Directory containing skey include files], CFLAGS="${CFLAGS} -I${withval}") dnl Check for skey library -AC_CHECK_LIB(socket, socket) -AC_CHECK_LIB(nsl, gethostbyname) +AC_CHECK_LIB(socket, socket, LIBS="${LIBS} -lsocket") +AC_CHECK_LIB(nsl, gethostbyname, LIBS="${LIBS} -lnsl") AC_CHECK_LIB(skey, skeyverify, SKEYLIB="-lskey", AC_MSG_ERROR(skey library not found or unknown interface)) -AC_CHECK_LIB(skey, skeyaccess, AC_DEFINE(HAVE_SKEYACCESS)) -AC_CHECK_LIB(skey, skeyinfo, AC_DEFINE(HAVE_SKEYINFO), - AC_CHECK_LIB(skey, skeylookup, AC_DEFINE(HAVE_SKEYLOOKUP)) -) dnl Check against -G linker flag hold_ldflags=$LDFLAGS diff -Nur pam_skey-1.1.4/configure pam_skey/configure --- pam_skey-1.1.4/configure 2005-06-18 14:36:18.000000000 +0200 +++ pam_skey/configure 2006-03-06 09:27:41.000000000 +0100 @@ -310,7 +310,7 @@ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT SET_MAKE RM LN CP AWK INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CPP EGREP SKEYLIB PAMLIB MYHOST PACKAGE VERSION LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT SET_MAKE RM LN CP AWK INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CPP EGREP SKEYLIB PAMLIB MYHOST PACKAGE VERSION LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -720,13 +720,13 @@ /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` srcdir=$ac_confdir - if test ! -r $srcdir/$ac_unique_file; then + 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 ! -r "$srcdir/$ac_unique_file"; then if test "$ac_srcdir_defaulted" = yes; then { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 { (exit 1); exit 1; }; } @@ -735,7 +735,7 @@ { (exit 1); exit 1; }; } fi fi -(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || +(cd $srcdir && test -r "./$ac_unique_file") 2>/dev/null || { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 { (exit 1); exit 1; }; } srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` @@ -831,10 +831,6 @@ _ACEOF cat <<\_ACEOF - -System types: - --build=BUILD configure for building on BUILD [guessed] - --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi @@ -948,7 +944,7 @@ else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi - cd "$ac_popdir" + cd $ac_popdir done fi @@ -1333,78 +1329,8 @@ -# Make sure we can run config.sub. -$ac_config_sub sun4 >/dev/null 2>&1 || - { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 -echo "$as_me: error: cannot run $ac_config_sub" >&2;} - { (exit 1); exit 1; }; } - -echo "$as_me:$LINENO: checking build system type" >&5 -echo $ECHO_N "checking build system type... $ECHO_C" >&6 -if test "${ac_cv_build+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_build_alias=$build_alias -test -z "$ac_cv_build_alias" && - ac_cv_build_alias=`$ac_config_guess` -test -z "$ac_cv_build_alias" && - { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 -echo "$as_me: error: cannot guess build type; you must specify one" >&2;} - { (exit 1); exit 1; }; } -ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || - { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 -echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} - { (exit 1); exit 1; }; } - -fi -echo "$as_me:$LINENO: result: $ac_cv_build" >&5 -echo "${ECHO_T}$ac_cv_build" >&6 -build=$ac_cv_build -build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` - - -echo "$as_me:$LINENO: checking host system type" >&5 -echo $ECHO_N "checking host system type... $ECHO_C" >&6 -if test "${ac_cv_host+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_host_alias=$host_alias -test -z "$ac_cv_host_alias" && - ac_cv_host_alias=$ac_cv_build_alias -ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || - { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 -echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} - { (exit 1); exit 1; }; } - -fi -echo "$as_me:$LINENO: result: $ac_cv_host" >&5 -echo "${ECHO_T}$ac_cv_host" >&6 -host=$ac_cv_host -host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` - - -MYHOST=$host_os -case "$host_os" in -*linux*) - cat >>confdefs.h <<\_ACEOF -#define LINUX 1 -_ACEOF - - ;; -*bsd*) - cat >>confdefs.h <<\_ACEOF -#define BSD 1 -_ACEOF - - ;; -esac - PACKAGE=pam_skey -VERSION=1.1 +VERSION=1.4r1 @@ -1976,7 +1902,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2034,7 +1961,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2150,7 +2078,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2204,7 +2133,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2249,7 +2179,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2293,7 +2224,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2881,7 +2813,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3051,7 +2984,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3124,7 +3058,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3278,7 +3213,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3431,7 +3367,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3533,7 +3470,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3583,7 +3521,6 @@ CFLAGS="${CFLAGS} -I${withval}" fi; - echo "$as_me:$LINENO: checking for socket in -lsocket" >&5 echo $ECHO_N "checking for socket in -lsocket... $ECHO_C" >&6 if test "${ac_cv_lib_socket_socket+set}" = set; then @@ -3622,7 +3559,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3648,15 +3586,9 @@ echo "$as_me:$LINENO: result: $ac_cv_lib_socket_socket" >&5 echo "${ECHO_T}$ac_cv_lib_socket_socket" >&6 if test $ac_cv_lib_socket_socket = yes; then - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBSOCKET 1 -_ACEOF - - LIBS="-lsocket $LIBS" - + LIBS="${LIBS} -lsocket" fi - echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5 echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6 if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then @@ -3695,7 +3627,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3721,12 +3654,7 @@ echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5 echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6 if test $ac_cv_lib_nsl_gethostbyname = yes; then - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBNSL 1 -_ACEOF - - LIBS="-lnsl $LIBS" - + LIBS="${LIBS} -lnsl" fi echo "$as_me:$LINENO: checking for skeyverify in -lskey" >&5 @@ -3767,7 +3695,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3800,218 +3729,6 @@ { (exit 1); exit 1; }; } fi -echo "$as_me:$LINENO: checking for skeyaccess in -lskey" >&5 -echo $ECHO_N "checking for skeyaccess in -lskey... $ECHO_C" >&6 -if test "${ac_cv_lib_skey_skeyaccess+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lskey $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char skeyaccess (); -int -main () -{ -skeyaccess (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_skey_skeyaccess=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_skey_skeyaccess=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_skey_skeyaccess" >&5 -echo "${ECHO_T}$ac_cv_lib_skey_skeyaccess" >&6 -if test $ac_cv_lib_skey_skeyaccess = yes; then - cat >>confdefs.h <<\_ACEOF -#define HAVE_SKEYACCESS 1 -_ACEOF - -fi - -echo "$as_me:$LINENO: checking for skeyinfo in -lskey" >&5 -echo $ECHO_N "checking for skeyinfo in -lskey... $ECHO_C" >&6 -if test "${ac_cv_lib_skey_skeyinfo+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lskey $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char skeyinfo (); -int -main () -{ -skeyinfo (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_skey_skeyinfo=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_skey_skeyinfo=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_skey_skeyinfo" >&5 -echo "${ECHO_T}$ac_cv_lib_skey_skeyinfo" >&6 -if test $ac_cv_lib_skey_skeyinfo = yes; then - cat >>confdefs.h <<\_ACEOF -#define HAVE_SKEYINFO 1 -_ACEOF - -else - echo "$as_me:$LINENO: checking for skeylookup in -lskey" >&5 -echo $ECHO_N "checking for skeylookup in -lskey... $ECHO_C" >&6 -if test "${ac_cv_lib_skey_skeylookup+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lskey $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char skeylookup (); -int -main () -{ -skeylookup (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_skey_skeylookup=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_skey_skeylookup=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_skey_skeylookup" >&5 -echo "${ECHO_T}$ac_cv_lib_skey_skeylookup" >&6 -if test $ac_cv_lib_skey_skeylookup = yes; then - cat >>confdefs.h <<\_ACEOF -#define HAVE_SKEYLOOKUP 1 -_ACEOF - -fi - - -fi - hold_ldflags=$LDFLAGS echo "$as_me:$LINENO: checking for the ld -shared flag" >&5 @@ -4041,7 +3758,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4099,7 +3817,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4747,14 +4466,6 @@ s,@ECHO_N@,$ECHO_N,;t t s,@ECHO_T@,$ECHO_T,;t t s,@LIBS@,$LIBS,;t t -s,@build@,$build,;t t -s,@build_cpu@,$build_cpu,;t t -s,@build_vendor@,$build_vendor,;t t -s,@build_os@,$build_os,;t t -s,@host@,$host,;t t -s,@host_cpu@,$host_cpu,;t t -s,@host_vendor@,$host_vendor,;t t -s,@host_os@,$host_os,;t t s,@CC@,$CC,;t t s,@CFLAGS@,$CFLAGS,;t t s,@LDFLAGS@,$LDFLAGS,;t t @@ -4945,6 +4656,11 @@ *) ac_INSTALL=$ac_top_builddir$INSTALL ;; esac + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ @@ -4983,12 +4699,6 @@ fi;; esac done` || { (exit 1); exit 1; } - - if test x"$ac_file" != x-; then - { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - rm -f "$ac_file" - fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub diff -Nur pam_skey-1.1.4/defs.h.in pam_skey/defs.h.in --- pam_skey-1.1.4/defs.h.in 2005-06-18 14:36:18.000000000 +0200 +++ pam_skey/defs.h.in 2006-03-06 09:26:55.000000000 +0100 @@ -1,96 +1,49 @@ -/* defs.h.in. Generated from configure.in by autoheader. */ -/* Define if we can include both string.h and strings.h */ -#undef STRING_WITH_STRINGS - -/* Define if you have Linux */ -#undef LINUX - -/* Define if you have *BSD */ -#undef BSD +/* defs.h.in. Generated automatically from configure.in by autoheader. */ -/* Define if not missing skeyaccess() */ -#undef HAVE_SKEYACCESS - -/* Define if not missing skeyinfo() */ -#undef HAVE_SKEYINFO +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS -/* Define if you have skeylookup() instead of skeyinfo() */ -#undef HAVE_SKEYLOOKUP +/* Define if we can include both string.h and strings.h */ +#undef STRING_WITH_STRINGS -/* Define to 1 if you have the `fprintf' function. */ +/* Define if you have the fprintf function. */ #undef HAVE_FPRINTF -/* Define to 1 if you have the header file. */ -#undef HAVE_INTTYPES_H +/* Define if you have the gethostbyname function. */ +#undef HAVE_GETHOSTBYNAME -/* Define to 1 if you have the `nsl' library (-lnsl). */ -#undef HAVE_LIBNSL +/* Define if you have the snprintf function. */ +#undef HAVE_SNPRINTF -/* Define to 1 if you have the `socket' library (-lsocket). */ -#undef HAVE_LIBSOCKET +/* Define if you have the strncmp function. */ +#undef HAVE_STRNCMP -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H +/* Define if you have the syslog function. */ +#undef HAVE_SYSLOG -/* Define to 1 if you have the header file. */ +/* Define if you have the header file. */ #undef HAVE_PWD_H -/* Define to 1 if you have the header file. */ +/* Define if you have the header file. */ #undef HAVE_SECURITY_PAM_APPL_H -/* Define to 1 if you have the header file. */ +/* Define if you have the header file. */ #undef HAVE_SECURITY_PAM_MODULES_H -/* Define to 1 if you have the `snprintf' function. */ -#undef HAVE_SNPRINTF - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the header file. */ +/* Define if you have the header file. */ #undef HAVE_STDLIB_H -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ +/* Define if you have the header file. */ #undef HAVE_STRING_H -/* Define to 1 if you have the `strncmp' function. */ -#undef HAVE_STRNCMP - -/* Define to 1 if you have the `syslog' function. */ -#undef HAVE_SYSLOG - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYSLOG_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_STAT_H +/* Define if you have the header file. */ +#undef HAVE_STRINGS_H -/* Define to 1 if you have the header file. */ +/* Define if you have the header file. */ #undef HAVE_SYS_SYSLOG_H -/* Define to 1 if you have the header file. */ +/* Define if you have the header file. */ #undef HAVE_SYS_TYPES_H -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS +/* Define if you have the header file. */ +#undef HAVE_SYSLOG_H diff -Nur pam_skey-1.1.4/pam_skey.c pam_skey/pam_skey.c --- pam_skey-1.1.4/pam_skey.c 2005-06-18 14:36:18.000000000 +0200 +++ pam_skey/pam_skey.c 2006-03-06 09:26:55.000000000 +0100 @@ -1,5 +1,6 @@ /* - * (c) 2001 Dinko Korunic, kreator@srce.hr + * Rewrite (c) 2005 Dani Church, dani.church@gmail.com + * Original (c) 2001 Dinko Korunic, kreator@srce.hr * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF @@ -33,272 +34,146 @@ #include #include #include +#include #define PAM_EXTERN extern #undef PAM_STATIC #include #include +#include #include "skey.h" #include "pam_skey.h" #include "misc.h" +#define LOGDEBUG(x) if (mod_opt & _MOD_DEBUG) { syslog x ;} +#define QUERY_USERNAME NULL /* Use default username prompt */ +#define QUERY_PASSWORD "Password: " +#define QUERY_RESPONSE_OR_PASSWORD "S/Key response or system password: " +#define QUERY_RESPONSE "S/Key response: " + PAM_EXTERN int pam_sm_setcred (pam_handle_t *pamh, int flags, int argc, const char **argv) { return PAM_SUCCESS; } +/* + * The authentication module will return the following status codes: + * PAM_SUCCESS: Successful authentication via S/Key. + * PAM_IGNORE: The user doesn't have S/Key or doesn't want to use it. + * Continue with the next module, using try_first_pass. + * PAM_AUTH_ERR: The user asked to use S/Key, but failed the authentication. + * Don't try any more PAM modules. + * others: random errors, try next authentication method + */ + PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { - char challenge[CHALLENGE_MAXSIZE]; /* challenge to print in conv */ - char msg_text[PAM_MAX_MSG_SIZE]; /* text for pam conv */ - char *username = NULL; /* username spacer */ + const char *challenge; /* challenge to print in conv */ + const char *username = NULL; /* username spacer */ char *response = NULL; /* response spacer */ - struct skey skey; /* structure that contains skey information */ int status; /* return status spacer */ - unsigned mod_opt = _MOD_NONE_ON; /* module options */ + unsigned mod_opt=_MOD_NONE_ON; /* module options */ /* Get module options */ mod_getopt(&mod_opt, argc, argv); - /* Get username */ -#if defined LINUX || defined BSD - if (pam_get_user(pamh, (const char **)&username, "login:") -#else - if (pam_get_user(pamh, (char **)&username, "login:") -#endif - != PAM_SUCCESS) - { - fprintf(stderr, "cannot determine username\n"); - if (mod_opt & _MOD_DEBUG) - syslog(LOG_DEBUG, "cannot determine username"); - return PAM_USER_UNKNOWN; - } - - if (mod_opt & _MOD_DEBUG) - syslog(LOG_DEBUG, "got username %s", username); - -#ifdef HAVE_SKEYACCESS - /* Check S/Key access permissions - user, host and port. Also include - * sanity checks */ - if (mod_opt & _MOD_ACCESS_CHECK) - { - char *host; /* points to host */ - char *port; /* points to port */ - struct passwd *pwuser; /* structure for getpw() */ - - /* Get host.. */ -#if defined LINUX || defined BSD - if (pam_get_item(pamh, PAM_RHOST, (const void **)&host) -#else - if (pam_get_item(pamh, PAM_RHOST, (void **)&host) -#endif - != PAM_SUCCESS) - host = NULL; /* couldn't get host */ - /* ..and port */ -#if defined LINUX || defined BSD - if (pam_get_item(pamh, PAM_TTY, (const void **)&port) -#else - if (pam_get_item(pamh, PAM_TTY, (void **)&port) -#endif - != PAM_SUCCESS) - port = NULL; /* couldn't get port */ - - if (mod_opt & _MOD_DEBUG) - syslog(LOG_DEBUG, "checking s/key access for user %s," - " host %s, port %s", username, - (host != NULL) ? host : "*unknown*", - (port != NULL) ? port : "*unknown*"); - - /* Get information from passwd file */ - if ((pwuser = getpwnam(username)) == NULL) - { - fprintf(stderr, "no such user\n"); - syslog(LOG_NOTICE, "cannot find user %s", username); - return PAM_USER_UNKNOWN; /* perhaps even return PAM_ABORT here? */ + /* Get username (taken mainly from pam_unix) */ + status = pam_get_user(pamh, &username, QUERY_USERNAME); + if (status == PAM_SUCCESS) { + if (username == NULL || !isalnum(*username)) { + syslog(LOG_ERR, "bad username [%s]", username); + return PAM_USER_UNKNOWN; } + LOGDEBUG((LOG_DEBUG, "username [%s] obtained", username)); + } else { + LOGDEBUG((LOG_DEBUG, "trouble reading username")); + if (status == PAM_CONV_AGAIN) + return PAM_INCOMPLETE; + return status; + } - /* Do actual checking - we assume skeyaccess() returns PERMIT which is - * by default 1. Notice 4th argument is NULL - we will not perform - * address checks on host itself */ - if (skeyaccess(pwuser, port, host, NULL) != 1) - { - fprintf(stderr, "no s/key access permissions\n"); - syslog(LOG_NOTICE, "no s/key access permissions for %s", - username); - return PAM_AUTH_ERR; - } + /* Check whether or not this user has an S/Key */ + if (skey_haskey(username) != 0) { + LOGDEBUG((LOG_DEBUG, "user [%s] has no S/Key entry", username)); + return PAM_IGNORE; } - else -#endif /* HAVE_SKEYACCESS */ - - /* Only do check whether user has passwd entry */ - if (getpwnam(username) == NULL) - { - fprintf(stderr, "no such user\n"); - if (mod_opt & _MOD_DEBUG) - syslog(LOG_DEBUG, "cannot find user %s", - username); - return PAM_USER_UNKNOWN; + if ((mod_opt & _MOD_TRY_FIRST_PASS) || (mod_opt & _MOD_USE_FIRST_PASS)) { + status = pam_get_item(pamh, PAM_AUTHTOK, (const void **) &response); + if (status != PAM_SUCCESS) { + syslog(LOG_ALERT, "pam_get_item returned error to pam_skey"); + return status; + } else if (response != NULL) { + if (skey_passcheck(username, response) != -1) { + return PAM_SUCCESS; + } else if (mod_opt & _MOD_USE_FIRST_PASS) { + return PAM_IGNORE; + } + } else if (mod_opt & _MOD_USE_FIRST_PASS) { + return PAM_AUTHTOK_RECOVER_ERR; } - - /* Get S/Key information on user with skeyinfo() */ -#ifdef HAVE_SKEYINFO - switch (skeyinfo(&skey, username, NULL)) -#else -#ifdef HAVE_SKEYLOOKUP - switch (skeylookup(&skey, username)) -#endif /* HAVE_SKEYLOOKUP */ -#endif /* HAVE_SKEYINFO */ - { - /* 0: OK */ - case 0: - break; - /* -1: File error */ - case -1: -#if 0 - /* XXX- This seems broken in (at least) logdaemon-5.8. It returns -1 - * when user not found in keyfile. -kre */ - fprintf(stderr, "s/key database error\n"); - syslog(LOG_NOTICE, "s/key database error"); - return PAM_AUTH_ERR; -#endif - /* 1: No such user in database */ - case 1: - /* We won't confuse the ordinary user telling him about missing skeys - * -kre */ -#if 0 - fprintf(stderr, "no s/key for %s\n", username); -#endif - if (mod_opt & _MOD_DEBUG) - syslog(LOG_DEBUG, "no s/key for %s\n", username); - return PAM_AUTH_ERR; } - - /* Make challenge string */ -#if defined(SKEY_MAX_HASHNAME_LEN) && defined(SKEY_MAX_SEED_LEN) - snprintf(challenge, CHALLENGE_MAXSIZE, "otp-%.*s %d %.*s", - SKEY_MAX_HASHNAME_LEN, skey_get_algorithm(), skey.n - 1, SKEY_MAX_SEED_LEN, skey.seed); -#else - snprintf(challenge, CHALLENGE_MAXSIZE, "s/key %d %s", - skey.n - 1, skey.seed); -#endif - - if (mod_opt & _MOD_DEBUG) - syslog(LOG_DEBUG, "got challenge %s for %s", challenge, - username); - - /* Read response from last module's PAM_AUTHTOK */ - if (mod_opt & _MOD_USE_FIRST_PASS) - { - /* Try to extract authtoken */ -#if defined LINUX || defined BSD - if (pam_get_item(pamh, PAM_AUTHTOK, (const void **)&response) -#else - if (pam_get_item(pamh, PAM_AUTHTOK, (void **)&response) -#endif - != PAM_SUCCESS) - { - if (mod_opt & _MOD_DEBUG) - syslog(LOG_DEBUG, "could not get PAM_AUTHTOK"); - mod_opt &= ~_MOD_USE_FIRST_PASS; + + if (mod_opt & _MOD_NO_DEFAULT_SKEY) { + status = mod_talk_touser(pamh, mod_opt, NULL, QUERY_PASSWORD, 0, &response); + if (status != PAM_SUCCESS) { + _pam_delete(response) + return status; } - else - { - /* Got AUTHTOK, but it was empty */ - if (empty_authtok(response)) - { - if (mod_opt & _MOD_DEBUG) - syslog(LOG_DEBUG, "empty PAM_AUTHTOK"); - mod_opt &= ~_MOD_USE_FIRST_PASS; - } - else - /* All OK, print challenge information */ - fprintf(stderr, "challenge %s\n", challenge); + if (strcasecmp(response,"s/key")!=0) { + status = pam_set_item(pamh, PAM_AUTHTOK, response); + if (status != PAM_SUCCESS) + return status; + return PAM_IGNORE; } + _pam_delete(response); } - /* There was no PAM_AUTHTOK, or there was no such option in pam-conf - * file */ - if (!(mod_opt & _MOD_USE_FIRST_PASS)) - { - /* Prepare a complete message for conversation */ - snprintf(msg_text, PAM_MAX_MSG_SIZE, - "challenge %s\npassword: ", challenge); - - /* Talk with user */ - if (mod_talk_touser(pamh, &mod_opt, msg_text, &response) - != PAM_SUCCESS) - return PAM_SERVICE_ERR; - - /* Simulate standard S/Key login procedure - if empty token, turn on - * ECHO and prompt again */ - if (empty_authtok(response) && !(mod_opt & _MOD_ONLY_ONE_TRY)) - { - /* Was there echo off? */ - if (mod_opt & _MOD_ECHO_OFF) - { - _pam_delete(response); - fprintf(stderr, "(turning echo on)\n"); - mod_opt &= ~_MOD_ECHO_OFF; - - /* Prepare a complete message for conversation */ - snprintf(msg_text, PAM_MAX_MSG_SIZE, "password: "); - - /* Talk with user */ - if (mod_talk_touser(pamh, &mod_opt, msg_text, &response) - != PAM_SUCCESS) - return PAM_SERVICE_ERR; - - /* Got again empty response. Bailout and don't save auth token */ - if (empty_authtok(response)) - return PAM_AUTH_ERR; - } - else - /* There was echo on already - just get out and don't save auth token - * for other modules */ - return PAM_AUTH_ERR; - } + challenge = skey_keyinfo(username); + if (challenge == NULL) { + syslog(LOG_ALERT, "Could not retrieve S/Key challenge for [%s]", username); + return PAM_AUTHINFO_UNAVAIL; + } - /* XXX - ECHO ON puts '\n' at the end in Solaris 2.7! This is - * cludge to get rid of this nasty `feature' -kre */ - _pam_degarbage(response); - - /* Store auth token - that next module can use with `use_first_pass' */ - if (pam_set_item(pamh, PAM_AUTHTOK, response) != PAM_SUCCESS) - { - syslog(LOG_NOTICE, "unable to save auth token"); - return PAM_SERVICE_ERR; - } + if (mod_opt & _MOD_NO_DEFAULT_SKEY) + status = mod_talk_touser(pamh, mod_opt, challenge, QUERY_RESPONSE, 0, &response); + else + status = mod_talk_touser(pamh, mod_opt, challenge, QUERY_RESPONSE_OR_PASSWORD, 0, &response); - /* cleanup conversation */ + if (status != PAM_SUCCESS) + return status; + + if (*response == '\0') { _pam_delete(response); - } - - /* Verify S/Key */ - status = skeyverify(&skey, response); + status = mod_talk_touser(pamh, mod_opt, NULL, QUERY_RESPONSE, 1, &response); + if (status != PAM_SUCCESS) + return status; + status = pam_set_item(pamh, PAM_AUTHTOK, response); + status = skey_passcheck(username, response); + _pam_delete(response); + if (status != -1) + return PAM_SUCCESS; + return PAM_AUTH_ERR; + } - switch (status) - { - /* 0: Verify successful, database updated */ - case 0: - break; - /* -1: Error of some sort; database unchanged */ - /* 1: Verify failed, database unchanged */ - case -1: - case 1: - if (mod_opt & _MOD_DEBUG) - syslog(LOG_DEBUG, "verify for %s failed, database" - " unchanged", username); - return PAM_AUTH_ERR; + status = pam_set_item(pamh, PAM_AUTHTOK, response); + status = skey_passcheck(username, response); + if (status != -1) { + _pam_delete(response); + return PAM_SUCCESS; + } + + if (mod_opt & _MOD_NO_DEFAULT_SKEY) { + _pam_delete(response); + return PAM_AUTH_ERR; } - /* Success by default */ - return PAM_SUCCESS; + status = pam_set_item(pamh, PAM_AUTHTOK, response); + return PAM_IGNORE; } /* Get module optional parameters */ @@ -332,50 +207,43 @@ } /* This will talk to user through PAM_CONV */ -static int mod_talk_touser(pam_handle_t *pamh, unsigned *mod_opt, - char *msg_text, char **response) +static int mod_talk_touser(pam_handle_t *pamh, unsigned mod_opt, + const char *info_text, const char *prompt_text, int echo_on, char **response) { - struct pam_message message; - const struct pam_message *pmessage = &message; + struct pam_message message[2], *pmessage[2]; struct pam_conv *conv = NULL; struct pam_response *presponse = NULL; - + int i=0; + /* Better safe than sorry */ *response = NULL; /* Be paranoid */ memset(&message, 0, sizeof(message)); - /* Turn on/off PAM echo */ - if (*mod_opt & _MOD_ECHO_OFF) - message.msg_style = PAM_PROMPT_ECHO_OFF; - else - message.msg_style = PAM_PROMPT_ECHO_ON; + pmessage[0] = &message[0]; + pmessage[1] = &message[1]; + + /* Set info text, if any */ + if (info_text) { + message[i].msg = info_text; + message[i].msg_style = PAM_TEXT_INFO; + i++; + } - /* Point to conversation text */ - message.msg = msg_text; + /* Set prompt text */ + message[i].msg = prompt_text; + message[i].msg_style = echo_on ? PAM_PROMPT_ECHO_ON : PAM_PROMPT_ECHO_OFF; + i++; /* Do conversation and see if all is OK */ -#if defined LINUX || defined BSD - if (pam_get_item(pamh, PAM_CONV, (const void **)&conv) -#else - if (pam_get_item(pamh, PAM_CONV, (void **)&conv) -#endif - != PAM_SUCCESS) - { - if (*mod_opt & _MOD_DEBUG) - syslog(LOG_DEBUG, "error in conversation"); + if (pam_get_item(pamh, PAM_CONV, (const void **)&conv) != PAM_SUCCESS) { + LOGDEBUG((LOG_DEBUG, "error in conversation")); return PAM_SERVICE_ERR; } - - /* Convert into pam_response - only 1 reply expected */ -#if defined LINUX || defined BSD - if (conv->conv(1, &pmessage, &presponse, + /* Convert into pam_response */ + if (conv->conv(i, (const struct pam_message **)pmessage, &presponse, conv->appdata_ptr) -#else - if (conv->conv(1, (struct pam_message **)&pmessage, &presponse, - conv->appdata_ptr) -#endif != PAM_SUCCESS) { _pam_delete(presponse->resp); @@ -385,10 +253,10 @@ if (presponse != NULL) { /* Save address */ - *response = presponse->resp; + *response = presponse[i-1].resp; /* To ensure that response address will not be erased */ - presponse->resp = NULL; - _pam_drop(presponse); + presponse[i-1].resp = NULL; + _pam_drop_reply(presponse,i); } else return PAM_SERVICE_ERR; diff -Nur pam_skey-1.1.4/pam_skey.h pam_skey/pam_skey.h --- pam_skey-1.1.4/pam_skey.h 2005-06-18 14:36:18.000000000 +0200 +++ pam_skey/pam_skey.h 2006-03-06 09:26:55.000000000 +0100 @@ -22,29 +22,25 @@ */ /* Prototypes */ -#ifndef BSD -extern int skeyinfo(struct skey *, char *, char *); /* ORGH! Not in skey.h */ -#endif - static void mod_getopt(unsigned *, int, const char **); -static int mod_talk_touser(pam_handle_t *, unsigned *, char *, char **); +static int mod_talk_touser(pam_handle_t *, unsigned, const char *, const char *, int, char **); /* free() macro */ -#define _pam_drop(X) \ +/*#define _pam_drop(X) \ if (X != NULL) \ { \ free(X); \ X = NULL; \ -} +}*/ /* Secure overwrite */ -#define _pam_overwrite(x) \ +/*#define _pam_overwrite(x) \ { \ register char *__xx__; \ if ((__xx__ = (x))) \ while (*__xx__) \ *__xx__++ = '\0'; \ -} +}*/ /* Drop-in secure replacement - we do not want cleartext passwords lying * scattered around */ @@ -56,7 +52,7 @@ /* This will get us rid of first '\n' in response string and cut-off the * rest of the string. It should be ASCIIZ, of course */ -#define _pam_degarbage(x) \ +/*#define _pam_degarbage(x) \ { \ register char *__xx__; \ if ((__xx__ = (x))) \ @@ -70,30 +66,25 @@ else \ __xx__++; \ } \ -} +}*/ /* Handy empty AUTHTOK macro */ #define empty_authtok(a) (a == NULL || !*a || *a == '\n') -/* Maximum challenge size. It should be 64, but be sure */ -#define CHALLENGE_MAXSIZE 128 - /* Define module flags */ -#define _MOD_NONE_ON 0x0000 /* Generic flag */ -#define _MOD_ALL_ON (~_MOD_NONE_ON) /* Generic mask */ -#define _MOD_DEBUG 0x0001 /* Debugging options on */ -#define _MOD_ECHO_OFF 0x0002 /* PAM_ECHO_OFF */ -#define _MOD_ACCESS_CHECK 0x0004 /* Check S/Key access permissions */ -#define _MOD_USE_FIRST_PASS 0x0008 /* Use PAM_AUTHTOK */ -#define _MOD_ONLY_ONE_TRY 0x0010 /* Only one try, no matter of echo */ -#define _MOD_SPACER 0x0020 /* Currently unused */ +#define _MOD_NONE_ON 0x0000 /* Generic flag */ +#define _MOD_ALL_ON (~_MOD_NONE_ON) /* Generic mask */ +#define _MOD_DEBUG 0x0001 /* Debugging options on */ +#define _MOD_TRY_FIRST_PASS 0x0002 /* Attempt using PAM_AUTHTOK */ +#define _MOD_USE_FIRST_PASS 0x0004 /* Only use PAM_AUTHTOK */ +#define _MOD_NO_DEFAULT_SKEY 0x0008 /* Don't use S/Key by default */ /* Setup defaults - use echo off only */ -#define _MOD_DEFAULT_FLAG _MOD_ECHO_OFF +#define _MOD_DEFAULT_FLAG _MOD_NONE_ON #define _MOD_DEFAULT_MASK _MOD_ALL_ON /* Number of parameters currently known */ -#define _MOD_ARGS 8 +#define _MOD_ARGS 4 /* Structure for flexible argument parsing */ typedef struct @@ -108,11 +99,7 @@ { /* String Mask Flag */ {"debug", _MOD_ALL_ON, _MOD_DEBUG}, - {"echo=off", _MOD_ALL_ON, _MOD_ECHO_OFF}, - {"echo=on", _MOD_ALL_ON^_MOD_ECHO_OFF, _MOD_NONE_ON}, - {"access_check=on", _MOD_ALL_ON, _MOD_ACCESS_CHECK}, - {"access_check=off", _MOD_ALL_ON^_MOD_ACCESS_CHECK, _MOD_NONE_ON}, + {"try_first_pass", _MOD_ALL_ON, _MOD_TRY_FIRST_PASS}, {"use_first_pass", _MOD_ALL_ON, _MOD_USE_FIRST_PASS}, - {"try_first_pass", _MOD_ALL_ON, _MOD_USE_FIRST_PASS}, - {"only_one_try", _MOD_ALL_ON, _MOD_ONLY_ONE_TRY} + {"no_default_skey", _MOD_ALL_ON, _MOD_NO_DEFAULT_SKEY} }; diff -Nur pam_skey-1.1.4/pam_skey_access.c pam_skey/pam_skey_access.c --- pam_skey-1.1.4/pam_skey_access.c 2005-06-18 14:36:18.000000000 +0200 +++ pam_skey/pam_skey_access.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,161 +0,0 @@ -/* - * (c) 2001 Dinko Korunic, kreator@srce.hr - * - * 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. - * - * S/KEY is a trademark of Bellcore. - * Mink is the former name of the S/KEY authentication system. - * - * Programs that had some influence in development of this source: - * Wietse Venema's logdaemon package - * Olaf Kirch's Linux S/Key package - * Linux-PAM modules and templates - * Wyman Miles' pam_securid module - * - * Should you choose to use and/or modify this source code, please do so - * under the terms of the GNU General Public License under which this - * program is distributed. - */ - -static char rcsid[] = "$Id: pam_skey_access.c,v 1.2 2005/06/18 12:36:18 kreator Exp $"; - -#include "defs.h" - -#include -#include -#include -#ifdef STRING_WITH_STRINGS -# include -#endif -#include -#include -#include -#include - -#define PAM_EXTERN extern -#undef PAM_STATIC - -#include -#include - -#include "skey.h" -#include "pam_skey.h" -#include "misc.h" - -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_authenticate(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - char *username = NULL; /* will point to username */ - unsigned mod_opt = _MOD_NONE_ON; /* module options */ - char *host; /* will point to host */ - char *port; /* will point to port */ - struct passwd *pwuser; - - /* Get module options */ - mod_getopt(&mod_opt, argc, argv); - - /* Get username */ -#if defined LINUX || defined BSD - if (pam_get_user(pamh, (const char **)&username, "login:")!=PAM_SUCCESS) -#else - if (pam_get_user(pamh, (char **)&username, "login:")!=PAM_SUCCESS) -#endif - { - fprintf(stderr, "cannot determine username\n"); - if (mod_opt & _MOD_DEBUG) - syslog(LOG_DEBUG, "cannot determine username"); - return PAM_AUTHINFO_UNAVAIL; - } - - if (mod_opt & _MOD_DEBUG) - syslog(LOG_DEBUG, "got username %s", username); - - /* Check S/Key access permissions - user, host and port. Also include - * sanity checks */ - /* Get host.. */ -#if defined LINUX || defined BSD - if (pam_get_item(pamh, PAM_RHOST, (const void **)&host) -#else - if (pam_get_item(pamh, PAM_RHOST, (void **)&host) -#endif - != PAM_SUCCESS) - host = NULL; - /* ..and port */ -#ifdef LINUX - if (pam_get_item(pamh, PAM_TTY, (const void **)&port) -#else - if (pam_get_item(pamh, PAM_TTY, (void **)&port) -#endif - != PAM_SUCCESS) - port = NULL; - - if (mod_opt & _MOD_DEBUG) - syslog(LOG_DEBUG, "checking s/key access for user %s," - " host %s, port %s", username, - (host != NULL) ? host : "*unknown*", - (port != NULL) ? port : "*unknown*"); - - /* Get information from passwd file */ - if ((pwuser = getpwnam(username)) == NULL) - { - fprintf(stderr, "no such user\n"); - syslog(LOG_NOTICE, "cannot find user %s", - username); - return PAM_AUTHINFO_UNAVAIL; - } - -#ifdef HAVE_SKEYACCESS - - /* Do actual checking - we assume skeyaccess() returns PERMIT which is - * by default 1. Notice 4th argument is NULL - we will not perform - * address checks on host itself */ - if (skeyaccess(pwuser, port, host, NULL) != 1) - { - fprintf(stderr, "no s/key access permissions\n"); - syslog(LOG_NOTICE, "no s/key access permissions for %s", - username); - return PAM_AUTH_ERR; - } - -#endif /* HAVE_SKEYACCESS */ - - return PAM_SUCCESS; -} - -/* Get module optional parameters */ -static void mod_getopt(unsigned *mod_opt, int mod_argc, const char **mod_argv) -{ - int i; - - /* Setup runtime defaults */ - *mod_opt |= _MOD_DEFAULT_FLAG; - *mod_opt &= _MOD_DEFAULT_MASK; - - /* Setup runtime options */ - while (mod_argc--) - { - for (i = 0; i < _MOD_ARGS; ++i) - { - if (mod_args[i].token != NULL && - !strncmp(*mod_argv, mod_args[i].token, - strlen(mod_args[i].token))) - break; - } - if (i >= _MOD_ARGS) - syslog(LOG_ERR, "unknown option %s", *mod_argv); - else - { - *mod_opt &= mod_args[i].mask; /* Turn off */ - *mod_opt |= mod_args[i].flag; /* Turn on */ - } - ++mod_argv; - } -}