From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) by finch.gentoo.org (Postfix) with ESMTP id 0B1801399E6 for ; Fri, 4 Sep 2015 08:35:33 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 0948395873; Fri, 4 Sep 2015 08:33:44 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 9E64795871 for ; Fri, 4 Sep 2015 08:33:29 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 4E9E5340A66 for ; Fri, 4 Sep 2015 08:33:28 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 773321AF for ; Fri, 4 Sep 2015 08:33:24 +0000 (UTC) From: "Ulrich Müller" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Ulrich Müller" Message-ID: <1283970594.f82014b946f3925667a127cea05a068b52e6d371.ulm@gentoo> Subject: [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-4 commit in: patchsets/pam_skey/1.1.5/ X-VCS-Repository: dev/ulm X-VCS-Files: patchsets/pam_skey/1.1.5/01_all_gentoo.patch X-VCS-Directories: patchsets/pam_skey/1.1.5/ X-VCS-Committer: ulm X-VCS-Committer-Name: Ulrich Müller X-VCS-Revision: f82014b946f3925667a127cea05a068b52e6d371 X-VCS-Branch: pam_skey-1.1.5-patches-4 Date: Fri, 4 Sep 2015 08:33:24 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Archives-Salt: b80eb715-c44c-4aab-ad42-e44e7a155fc8 X-Archives-Hash: d9d3a69b7408bb934d84aa00a23235e5 Message-ID: <20150904083324.rbAP6w1_h6C6CArTjmHHhxILM6TcMCQUxc5fJlx9fJY@z> commit: f82014b946f3925667a127cea05a068b52e6d371 Author: Ulrich Müller gentoo org> AuthorDate: Wed Sep 8 18:29:54 2010 +0000 Commit: Ulrich Müller gentoo org> CommitDate: Wed Sep 8 18:29:54 2010 +0000 URL: https://gitweb.gentoo.org/dev/ulm.git/commit/?id=f82014b9 Patchset corresponding to pam_skey-1.1.5-gentoo.patch.bz2. patchsets/pam_skey/1.1.5/01_all_gentoo.patch | 779 +++++++++++++++++++++++++++ 1 file changed, 779 insertions(+) diff --git a/patchsets/pam_skey/1.1.5/01_all_gentoo.patch b/patchsets/pam_skey/1.1.5/01_all_gentoo.patch new file mode 100644 index 0000000..117fb94 --- /dev/null +++ b/patchsets/pam_skey/1.1.5/01_all_gentoo.patch @@ -0,0 +1,779 @@ +--- pam_skey-1.1.5/INSTALL ++++ pam_skey/INSTALL +@@ -1,5 +1,39 @@ + $Id$ + ++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 +--- pam_skey-1.1.5/Makefile.in ++++ pam_skey/Makefile.in +@@ -12,41 +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 \ +- mkdir -p $(INSTALLDIR); \ +- fi +- @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 \ ++install: all ++ $(INSTALL) -d $(INSTALLDIR) ++ $(INSTALL_LIB) $(PAM_FILES) $(INSTALLDIR) + + clean: + $(RM) a.out core *.so.1 *.o *.bak +--- pam_skey-1.1.5/README ++++ pam_skey/README +@@ -1,5 +1,77 @@ + $Id$ + ++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 +--- pam_skey-1.1.5/autoconf/acconfig.h ++++ pam_skey/autoconf/acconfig.h +@@ -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 +--- pam_skey-1.1.5/autoconf/configure.in ++++ pam_skey/autoconf/configure.in +@@ -10,18 +10,6 @@ + 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.5 +@@ -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 +--- pam_skey-1.1.5/pam_skey.c ++++ pam_skey/pam_skey.c +@@ -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,23 +34,23 @@ + #include + #include + #include ++#include + + #define PAM_SM_AUTH + + #include + #include ++#include + + #include "skey.h" + #include "pam_skey.h" + #include "misc.h" + +-#if defined linux || defined BSD +-#define _PAM_CONST const +-#define _PAM_MSG_CAST +-#else +-#define _PAM_CONST +-#define _PAM_MSG_CAST (struct pam_message **) +-#endif ++#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) +@@ -57,243 +58,121 @@ + 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 */ + + /* Get module options */ + mod_getopt(&mod_opt, argc, argv); + +- /* Get username */ +- if (pam_get_user(pamh, (_PAM_CONST char **)&username, "login:") +- != 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 (pam_get_item(pamh, PAM_RHOST, (_PAM_CONST void **)&host) +- != PAM_SUCCESS) +- host = NULL; /* couldn't get host */ +- /* ..and port */ +- if (pam_get_item(pamh, PAM_TTY, (_PAM_CONST void **)&port) +- != 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 **)(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 (pam_get_item(pamh, PAM_AUTHTOK, (_PAM_CONST void **)&response) +- != 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); + +- /* Verify S/Key */ +- status = skeyverify(&skey, response); ++ if (status != PAM_SUCCESS) ++ return status; + +- 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); +- +- /* cleanup conversation (error occured) */ +- _pam_delete(response); ++ if (*response == '\0') { ++ _pam_delete(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; ++ } + +- 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; + } + +- /* cleanup conversation (it was valid) */ +- _pam_delete(response); ++ 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 */ +@@ -328,13 +207,13 @@ + } + + /* 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; +@@ -342,26 +221,30 @@ + /* 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; +- +- /* Point to conversation text */ +- message.msg = msg_text; ++ 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++; ++ } ++ ++ /* 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 (pam_get_item(pamh, PAM_CONV, (_PAM_CONST void **)&conv) ++ if (pam_get_item(pamh, PAM_CONV, (const void **)(void *)&conv) + != PAM_SUCCESS) + { +- if (*mod_opt & _MOD_DEBUG) +- syslog(LOG_DEBUG, "error in conversation"); ++ LOGDEBUG((LOG_DEBUG, "error in conversation")); + return PAM_SERVICE_ERR; + } +- +- /* Convert into pam_response - only 1 reply expected */ +- if (conv->conv(1, _PAM_MSG_CAST &pmessage, &presponse, ++ /* Convert into pam_response */ ++ if (conv->conv(i, (const struct pam_message **)pmessage, &presponse, + conv->appdata_ptr) + != PAM_SUCCESS) + { +@@ -372,10 +255,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; +--- pam_skey-1.1.5/pam_skey.h ++++ pam_skey/pam_skey.h +@@ -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} + };