public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] dev/ulm:master commit in: patchsets/pam_skey/1.1.5/
  2015-09-04  8:33 [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-6 commit in: patchsets/pam_skey/1.1.5/ Ulrich Müller
@ 2015-09-04  8:29 ` Ulrich Müller
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:motif-2.3.4-patches-1 " Ulrich Müller
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Ulrich Müller @ 2015-09-04  8:29 UTC (permalink / raw
  To: gentoo-commits

commit:     f82014b946f3925667a127cea05a068b52e6d371
Author:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
AuthorDate: Wed Sep  8 18:29:54 2010 +0000
Commit:     Ulrich Müller <ulm <AT> gentoo <DOT> 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 <pwd.h> 
+ #include <sys/types.h>
+ #include <syslog.h>
++#include <ctype.h>
+ 
+ #define PAM_SM_AUTH
+ 
+ #include <security/pam_appl.h>
+ #include <security/pam_modules.h>
++#include <security/_pam_macros.h>
+ 
+ #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}
+ };


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [gentoo-commits] dev/ulm:motif-2.3.4-patches-1 commit in: patchsets/pam_skey/1.1.5/
  2015-09-04  8:33 [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-6 commit in: patchsets/pam_skey/1.1.5/ Ulrich Müller
  2015-09-04  8:29 ` [gentoo-commits] dev/ulm:master " Ulrich Müller
@ 2015-09-04  8:33 ` Ulrich Müller
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:openmotif-2.2.3-patches-4 " Ulrich Müller
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Ulrich Müller @ 2015-09-04  8:33 UTC (permalink / raw
  To: gentoo-commits

commit:     f82014b946f3925667a127cea05a068b52e6d371
Author:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
AuthorDate: Wed Sep  8 18:29:54 2010 +0000
Commit:     Ulrich Müller <ulm <AT> gentoo <DOT> 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 <pwd.h> 
+ #include <sys/types.h>
+ #include <syslog.h>
++#include <ctype.h>
+ 
+ #define PAM_SM_AUTH
+ 
+ #include <security/pam_appl.h>
+ #include <security/pam_modules.h>
++#include <security/_pam_macros.h>
+ 
+ #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}
+ };


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [gentoo-commits] dev/ulm:openmotif-2.2.3-patches-4 commit in: patchsets/pam_skey/1.1.5/
  2015-09-04  8:33 [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-6 commit in: patchsets/pam_skey/1.1.5/ Ulrich Müller
  2015-09-04  8:29 ` [gentoo-commits] dev/ulm:master " Ulrich Müller
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:motif-2.3.4-patches-1 " Ulrich Müller
@ 2015-09-04  8:33 ` Ulrich Müller
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:openmotif-2.2.3-patches-5 " Ulrich Müller
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Ulrich Müller @ 2015-09-04  8:33 UTC (permalink / raw
  To: gentoo-commits

commit:     f82014b946f3925667a127cea05a068b52e6d371
Author:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
AuthorDate: Wed Sep  8 18:29:54 2010 +0000
Commit:     Ulrich Müller <ulm <AT> gentoo <DOT> 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 <pwd.h> 
+ #include <sys/types.h>
+ #include <syslog.h>
++#include <ctype.h>
+ 
+ #define PAM_SM_AUTH
+ 
+ #include <security/pam_appl.h>
+ #include <security/pam_modules.h>
++#include <security/_pam_macros.h>
+ 
+ #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}
+ };


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [gentoo-commits] dev/ulm:openmotif-2.2.3-patches-5 commit in: patchsets/pam_skey/1.1.5/
  2015-09-04  8:33 [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-6 commit in: patchsets/pam_skey/1.1.5/ Ulrich Müller
                   ` (2 preceding siblings ...)
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:openmotif-2.2.3-patches-4 " Ulrich Müller
@ 2015-09-04  8:33 ` Ulrich Müller
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-3 " Ulrich Müller
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Ulrich Müller @ 2015-09-04  8:33 UTC (permalink / raw
  To: gentoo-commits

commit:     f82014b946f3925667a127cea05a068b52e6d371
Author:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
AuthorDate: Wed Sep  8 18:29:54 2010 +0000
Commit:     Ulrich Müller <ulm <AT> gentoo <DOT> 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 <pwd.h> 
+ #include <sys/types.h>
+ #include <syslog.h>
++#include <ctype.h>
+ 
+ #define PAM_SM_AUTH
+ 
+ #include <security/pam_appl.h>
+ #include <security/pam_modules.h>
++#include <security/_pam_macros.h>
+ 
+ #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}
+ };


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-2 commit in: patchsets/pam_skey/1.1.5/
  2015-09-04  8:33 [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-6 commit in: patchsets/pam_skey/1.1.5/ Ulrich Müller
                   ` (4 preceding siblings ...)
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-3 " Ulrich Müller
@ 2015-09-04  8:33 ` Ulrich Müller
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-4 " Ulrich Müller
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Ulrich Müller @ 2015-09-04  8:33 UTC (permalink / raw
  To: gentoo-commits

commit:     f82014b946f3925667a127cea05a068b52e6d371
Author:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
AuthorDate: Wed Sep  8 18:29:54 2010 +0000
Commit:     Ulrich Müller <ulm <AT> gentoo <DOT> 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 <pwd.h> 
+ #include <sys/types.h>
+ #include <syslog.h>
++#include <ctype.h>
+ 
+ #define PAM_SM_AUTH
+ 
+ #include <security/pam_appl.h>
+ #include <security/pam_modules.h>
++#include <security/_pam_macros.h>
+ 
+ #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}
+ };


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-3 commit in: patchsets/pam_skey/1.1.5/
  2015-09-04  8:33 [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-6 commit in: patchsets/pam_skey/1.1.5/ Ulrich Müller
                   ` (3 preceding siblings ...)
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:openmotif-2.2.3-patches-5 " Ulrich Müller
@ 2015-09-04  8:33 ` Ulrich Müller
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-2 " Ulrich Müller
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Ulrich Müller @ 2015-09-04  8:33 UTC (permalink / raw
  To: gentoo-commits

commit:     f82014b946f3925667a127cea05a068b52e6d371
Author:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
AuthorDate: Wed Sep  8 18:29:54 2010 +0000
Commit:     Ulrich Müller <ulm <AT> gentoo <DOT> 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 <pwd.h> 
+ #include <sys/types.h>
+ #include <syslog.h>
++#include <ctype.h>
+ 
+ #define PAM_SM_AUTH
+ 
+ #include <security/pam_appl.h>
+ #include <security/pam_modules.h>
++#include <security/_pam_macros.h>
+ 
+ #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}
+ };


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-2 commit in: patchsets/pam_skey/1.1.5/
  2015-09-04  8:33 [gentoo-commits] dev/ulm:skey-1.1.5-patches-2 " Ulrich Müller
@ 2015-09-04  8:33 ` Ulrich Müller
  0 siblings, 0 replies; 14+ messages in thread
From: Ulrich Müller @ 2015-09-04  8:33 UTC (permalink / raw
  To: gentoo-commits

commit:     8c73745ca7b76a04976116de9320f75e88654058
Author:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
AuthorDate: Wed Sep  8 18:31:38 2010 +0000
Commit:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
CommitDate: Wed Sep  8 18:31:38 2010 +0000
URL:        https://gitweb.gentoo.org/dev/ulm.git/commit/?id=8c73745c

Patchset corresponding to pam_skey-1.1.5-gentoo-1.patch.bz2.

 patchsets/pam_skey/1.1.5/01_all_gentoo.patch | 40 ++++++++++++++++++----------
 1 file changed, 26 insertions(+), 14 deletions(-)

diff --git a/patchsets/pam_skey/1.1.5/01_all_gentoo.patch b/patchsets/pam_skey/1.1.5/01_all_gentoo.patch
index 117fb94..d9562c8 100644
--- a/patchsets/pam_skey/1.1.5/01_all_gentoo.patch
+++ b/patchsets/pam_skey/1.1.5/01_all_gentoo.patch
@@ -231,8 +231,9 @@
 --- 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
   *
@@ -264,7 +265,7 @@
 +#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_OR_PASSWORD "S/Key response or password: "
 +#define QUERY_RESPONSE "S/Key response: "
  
  PAM_EXTERN int pam_sm_setcred (pam_handle_t *pamh, int flags,
@@ -600,14 +601,15 @@
  }
  
  /* Get module optional parameters */
-@@ -328,13 +207,13 @@
+@@ -328,13 +207,15 @@
  }
  
  /* 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)
++    const char *info_text, const char *prompt_text, int echo_on,
++    char **response)
  {
 -  struct pam_message message;
 -  const struct pam_message *pmessage = &message;
@@ -615,10 +617,11 @@
    struct pam_conv *conv = NULL;
    struct pam_response *presponse = NULL;
 +  int i=0;
++  int status;
  
    /* Better safe than sorry */
    *response = NULL;
-@@ -342,26 +221,30 @@
+@@ -342,40 +223,45 @@
    /* Be paranoid */
    memset(&message, 0, sizeof(message));
  
@@ -632,7 +635,9 @@
 -  message.msg = msg_text;
 +  pmessage[0] = &message[0];
 +  pmessage[1] = &message[1];
-+
+ 
+-  /* Do conversation and see if all is OK */
+-  if (pam_get_item(pamh, PAM_CONV, (_PAM_CONST void **)&conv)
 +  /* Set info text, if any */
 +  if (info_text) {
 +    message[i].msg = info_text;
@@ -644,9 +649,8 @@
 +  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)
++
++  /* Get conversation function */
 +  if (pam_get_item(pamh, PAM_CONV, (const void **)(void *)&conv)
        != PAM_SUCCESS)
    {
@@ -658,12 +662,20 @@
 -
 -  /* 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)
+-        conv->appdata_ptr)
+-    != PAM_SUCCESS)
++  /* Do conversation and see if all is OK */
++  status = conv->conv(i, (const struct pam_message **)pmessage,
++		      &presponse, conv->appdata_ptr);
++  if (status != PAM_SUCCESS)
    {
-@@ -372,10 +255,10 @@
+-    _pam_delete(presponse->resp);
+-    return PAM_SERVICE_ERR;
++    if (presponse != NULL)
++      _pam_delete(presponse->resp);
++    return status;
+   }
+ 
    if (presponse != NULL)
    {
      /* Save address */


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-2 commit in: patchsets/pam_skey/1.1.5/
  2015-09-04  8:33 [gentoo-commits] dev/ulm:skey-1.1.5-patches-3 " Ulrich Müller
@ 2015-09-04  8:33 ` Ulrich Müller
  0 siblings, 0 replies; 14+ messages in thread
From: Ulrich Müller @ 2015-09-04  8:33 UTC (permalink / raw
  To: gentoo-commits

commit:     295467f44f529af7472811397576672569922b02
Author:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
AuthorDate: Wed Sep  8 18:42:38 2010 +0000
Commit:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
CommitDate: Wed Sep  8 18:42:38 2010 +0000
URL:        https://gitweb.gentoo.org/dev/ulm.git/commit/?id=295467f4

Patchset 2, add 02_all_require_skey.patch.

 patchsets/pam_skey/1.1.5/02_all_require_skey.patch | 130 +++++++++++++++++++++
 1 file changed, 130 insertions(+)

diff --git a/patchsets/pam_skey/1.1.5/02_all_require_skey.patch b/patchsets/pam_skey/1.1.5/02_all_require_skey.patch
new file mode 100644
index 0000000..3eab29d
--- /dev/null
+++ b/patchsets/pam_skey/1.1.5/02_all_require_skey.patch
@@ -0,0 +1,130 @@
+http://bugs.gentoo.org/336449
+Patch contributed by Jan Sembera <fis@bofh.cz>
+
+In my environment, I'd like to use pam_skey as optional authentication
+measure that wouldn't replace the password, but would complement it.
+Ie. when the user sets the S/Key, he should be afterwards asked to
+provide the S/Key _and_ his password, without the possibility to just
+enter his password and circumvent S/Keys. On the other hand, when the
+user doesn't have S/Key set, he should be able to login with his
+password only.
+
+Why PAM would generally allow this, with the current internals of
+pam_skey, this setup isn't possible. You simply cannot distinguish
+between "user has no S/Key set" case (it returns IGNORE) and "user
+doesn't want to provide S/Key" (it returns IGNORE as well).
+
+I'm attaching a patch that will add option require_skey to pam_skey.
+When this option is set, module will require the user to successfully
+authenticate using S/key, and will return IGNORE only in case the user
+didn't set up his key. If this option isn't provided, the behaviour of
+the module doesn't change.
+
+--- pam_skey-orig/README
++++ pam_skey/README
+@@ -21,7 +21,7 @@
+ - The options accepted by the pam_skey.so module are different, as
+   described below.
+ 
+-Four options are accepted by the pam_skey.so module:
++Five 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
+@@ -44,6 +44,12 @@
+ 			   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).
++  require_skey           - This options tells the module to require S/Key
++			   authentication if the user has S/Key set.  When
++			   this option is set, it is possible to require both
++			   S/Key and another authentication method (like
++			   password) for successful login.  This is mutually
++			   exclusive with no_default_skey.
+ 
+ The exact behavior of pam_skey.so is detailed below:
+ 
+@@ -54,21 +60,22 @@
+    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.
++     PAM_IGNORE (or PAM_AUTHERR if require_skey is set).
+ 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.
++   input not echoed.  If no_default_skey or require_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.
++7. Otherwise, if no_default_skey is enabled (and the user specifically
++   requested "s/key" authentication), or if require_skey is enabled,
++   return PAM_AUTHERR.
+ 8. Otherwise, store the response as the authentication token and
+    return PAM_IGNORE.
+ 
+--- pam_skey-orig/pam_skey.c
++++ pam_skey/pam_skey.c
+@@ -110,7 +110,7 @@
+       if (skey_passcheck(username, response) != -1) {
+ 	return PAM_SUCCESS;
+       } else if (mod_opt & _MOD_USE_FIRST_PASS) {
+-	return PAM_IGNORE;
++	return (mod_opt & _MOD_REQUIRE_SKEY) ? PAM_AUTH_ERR : PAM_IGNORE;
+       }
+     } else if (mod_opt & _MOD_USE_FIRST_PASS) {
+       return PAM_AUTHTOK_RECOVER_ERR;
+@@ -138,7 +138,7 @@
+     return PAM_AUTHINFO_UNAVAIL;
+   }
+ 
+-  if (mod_opt & _MOD_NO_DEFAULT_SKEY)
++  if ((mod_opt & _MOD_NO_DEFAULT_SKEY) || (mod_opt & _MOD_REQUIRE_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);
+@@ -166,7 +166,7 @@
+     return PAM_SUCCESS;
+   }
+ 
+-  if (mod_opt & _MOD_NO_DEFAULT_SKEY) {
++  if ((mod_opt & _MOD_NO_DEFAULT_SKEY) || (mod_opt & _MOD_REQUIRE_SKEY)) {
+     _pam_delete(response);
+     return PAM_AUTH_ERR;
+   }
+--- pam_skey-orig/pam_skey.h
++++ pam_skey/pam_skey.h
+@@ -78,13 +78,14 @@
+ #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 */
++#define _MOD_REQUIRE_SKEY    0x0010	/* Require S/Key if set */
+ 
+ /* Setup defaults - use echo off only */
+ #define _MOD_DEFAULT_FLAG   _MOD_NONE_ON
+ #define _MOD_DEFAULT_MASK   _MOD_ALL_ON
+ 
+ /* Number of parameters currently known */
+-#define _MOD_ARGS           4
++#define _MOD_ARGS           5
+ 
+ /* Structure for flexible argument parsing */
+ typedef struct
+@@ -101,5 +102,6 @@
+   {"debug",            _MOD_ALL_ON,                   _MOD_DEBUG},
+   {"try_first_pass",   _MOD_ALL_ON,                   _MOD_TRY_FIRST_PASS},
+   {"use_first_pass",   _MOD_ALL_ON,                   _MOD_USE_FIRST_PASS},
+-  {"no_default_skey",  _MOD_ALL_ON,                   _MOD_NO_DEFAULT_SKEY}
++  {"no_default_skey",  _MOD_ALL_ON & ~_MOD_REQUIRE_SKEY, _MOD_NO_DEFAULT_SKEY},
++  {"require_skey",     _MOD_ALL_ON & ~_MOD_NO_DEFAULT_SKEY, _MOD_REQUIRE_SKEY}
+ };


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-4 commit in: patchsets/pam_skey/1.1.5/
  2015-09-04  8:33 [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-6 commit in: patchsets/pam_skey/1.1.5/ Ulrich Müller
                   ` (5 preceding siblings ...)
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-2 " Ulrich Müller
@ 2015-09-04  8:33 ` Ulrich Müller
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-5 " Ulrich Müller
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Ulrich Müller @ 2015-09-04  8:33 UTC (permalink / raw
  To: gentoo-commits

commit:     f82014b946f3925667a127cea05a068b52e6d371
Author:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
AuthorDate: Wed Sep  8 18:29:54 2010 +0000
Commit:     Ulrich Müller <ulm <AT> gentoo <DOT> 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 <pwd.h> 
+ #include <sys/types.h>
+ #include <syslog.h>
++#include <ctype.h>
+ 
+ #define PAM_SM_AUTH
+ 
+ #include <security/pam_appl.h>
+ #include <security/pam_modules.h>
++#include <security/_pam_macros.h>
+ 
+ #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}
+ };


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-5 commit in: patchsets/pam_skey/1.1.5/
  2015-09-04  8:33 [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-6 commit in: patchsets/pam_skey/1.1.5/ Ulrich Müller
                   ` (6 preceding siblings ...)
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-4 " Ulrich Müller
@ 2015-09-04  8:33 ` Ulrich Müller
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:skey-1.1.5-patches-1 " Ulrich Müller
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Ulrich Müller @ 2015-09-04  8:33 UTC (permalink / raw
  To: gentoo-commits

commit:     f82014b946f3925667a127cea05a068b52e6d371
Author:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
AuthorDate: Wed Sep  8 18:29:54 2010 +0000
Commit:     Ulrich Müller <ulm <AT> gentoo <DOT> 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 <pwd.h> 
+ #include <sys/types.h>
+ #include <syslog.h>
++#include <ctype.h>
+ 
+ #define PAM_SM_AUTH
+ 
+ #include <security/pam_appl.h>
+ #include <security/pam_modules.h>
++#include <security/_pam_macros.h>
+ 
+ #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}
+ };


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-6 commit in: patchsets/pam_skey/1.1.5/
@ 2015-09-04  8:33 Ulrich Müller
  2015-09-04  8:29 ` [gentoo-commits] dev/ulm:master " Ulrich Müller
                   ` (10 more replies)
  0 siblings, 11 replies; 14+ messages in thread
From: Ulrich Müller @ 2015-09-04  8:33 UTC (permalink / raw
  To: gentoo-commits

commit:     f82014b946f3925667a127cea05a068b52e6d371
Author:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
AuthorDate: Wed Sep  8 18:29:54 2010 +0000
Commit:     Ulrich Müller <ulm <AT> gentoo <DOT> 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 <pwd.h> 
+ #include <sys/types.h>
+ #include <syslog.h>
++#include <ctype.h>
+ 
+ #define PAM_SM_AUTH
+ 
+ #include <security/pam_appl.h>
+ #include <security/pam_modules.h>
++#include <security/_pam_macros.h>
+ 
+ #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}
+ };


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [gentoo-commits] dev/ulm:skey-1.1.5-patches-1 commit in: patchsets/pam_skey/1.1.5/
  2015-09-04  8:33 [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-6 commit in: patchsets/pam_skey/1.1.5/ Ulrich Müller
                   ` (7 preceding siblings ...)
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-5 " Ulrich Müller
@ 2015-09-04  8:33 ` Ulrich Müller
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:skey-1.1.5-patches-2 " Ulrich Müller
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:skey-1.1.5-patches-3 " Ulrich Müller
  10 siblings, 0 replies; 14+ messages in thread
From: Ulrich Müller @ 2015-09-04  8:33 UTC (permalink / raw
  To: gentoo-commits

commit:     f82014b946f3925667a127cea05a068b52e6d371
Author:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
AuthorDate: Wed Sep  8 18:29:54 2010 +0000
Commit:     Ulrich Müller <ulm <AT> gentoo <DOT> 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 <pwd.h> 
+ #include <sys/types.h>
+ #include <syslog.h>
++#include <ctype.h>
+ 
+ #define PAM_SM_AUTH
+ 
+ #include <security/pam_appl.h>
+ #include <security/pam_modules.h>
++#include <security/_pam_macros.h>
+ 
+ #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}
+ };


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [gentoo-commits] dev/ulm:skey-1.1.5-patches-2 commit in: patchsets/pam_skey/1.1.5/
  2015-09-04  8:33 [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-6 commit in: patchsets/pam_skey/1.1.5/ Ulrich Müller
                   ` (8 preceding siblings ...)
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:skey-1.1.5-patches-1 " Ulrich Müller
@ 2015-09-04  8:33 ` Ulrich Müller
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:skey-1.1.5-patches-3 " Ulrich Müller
  10 siblings, 0 replies; 14+ messages in thread
From: Ulrich Müller @ 2015-09-04  8:33 UTC (permalink / raw
  To: gentoo-commits

commit:     f82014b946f3925667a127cea05a068b52e6d371
Author:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
AuthorDate: Wed Sep  8 18:29:54 2010 +0000
Commit:     Ulrich Müller <ulm <AT> gentoo <DOT> 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 <pwd.h> 
+ #include <sys/types.h>
+ #include <syslog.h>
++#include <ctype.h>
+ 
+ #define PAM_SM_AUTH
+ 
+ #include <security/pam_appl.h>
+ #include <security/pam_modules.h>
++#include <security/_pam_macros.h>
+ 
+ #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}
+ };


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [gentoo-commits] dev/ulm:skey-1.1.5-patches-3 commit in: patchsets/pam_skey/1.1.5/
  2015-09-04  8:33 [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-6 commit in: patchsets/pam_skey/1.1.5/ Ulrich Müller
                   ` (9 preceding siblings ...)
  2015-09-04  8:33 ` [gentoo-commits] dev/ulm:skey-1.1.5-patches-2 " Ulrich Müller
@ 2015-09-04  8:33 ` Ulrich Müller
  10 siblings, 0 replies; 14+ messages in thread
From: Ulrich Müller @ 2015-09-04  8:33 UTC (permalink / raw
  To: gentoo-commits

commit:     f82014b946f3925667a127cea05a068b52e6d371
Author:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
AuthorDate: Wed Sep  8 18:29:54 2010 +0000
Commit:     Ulrich Müller <ulm <AT> gentoo <DOT> 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 <pwd.h> 
+ #include <sys/types.h>
+ #include <syslog.h>
++#include <ctype.h>
+ 
+ #define PAM_SM_AUTH
+ 
+ #include <security/pam_appl.h>
+ #include <security/pam_modules.h>
++#include <security/_pam_macros.h>
+ 
+ #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}
+ };


^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2015-09-04  8:37 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-09-04  8:33 [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-6 commit in: patchsets/pam_skey/1.1.5/ Ulrich Müller
2015-09-04  8:29 ` [gentoo-commits] dev/ulm:master " Ulrich Müller
2015-09-04  8:33 ` [gentoo-commits] dev/ulm:motif-2.3.4-patches-1 " Ulrich Müller
2015-09-04  8:33 ` [gentoo-commits] dev/ulm:openmotif-2.2.3-patches-4 " Ulrich Müller
2015-09-04  8:33 ` [gentoo-commits] dev/ulm:openmotif-2.2.3-patches-5 " Ulrich Müller
2015-09-04  8:33 ` [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-3 " Ulrich Müller
2015-09-04  8:33 ` [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-2 " Ulrich Müller
2015-09-04  8:33 ` [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-4 " Ulrich Müller
2015-09-04  8:33 ` [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-5 " Ulrich Müller
2015-09-04  8:33 ` [gentoo-commits] dev/ulm:skey-1.1.5-patches-1 " Ulrich Müller
2015-09-04  8:33 ` [gentoo-commits] dev/ulm:skey-1.1.5-patches-2 " Ulrich Müller
2015-09-04  8:33 ` [gentoo-commits] dev/ulm:skey-1.1.5-patches-3 " Ulrich Müller
  -- strict thread matches above, loose matches on Subject: below --
2015-09-04  8:33 [gentoo-commits] dev/ulm:skey-1.1.5-patches-2 " Ulrich Müller
2015-09-04  8:33 ` [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-2 " Ulrich Müller
2015-09-04  8:33 [gentoo-commits] dev/ulm:skey-1.1.5-patches-3 " Ulrich Müller
2015-09-04  8:33 ` [gentoo-commits] dev/ulm:pam_skey-1.1.5-patches-2 " Ulrich Müller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox