diff -Nru libpam-sshauth-0.1/ChangeLog libpam-sshauth-0.3.1/ChangeLog --- libpam-sshauth-0.1/ChangeLog 1970-01-01 00:00:00.000000000 +0000 +++ libpam-sshauth-0.3.1/ChangeLog 2013-07-04 18:17:23.000000000 +0000 @@ -0,0 +1,329 @@ + 97 Scott Balneaves 2013-03-26 {libpam-sshauth-0.3.1} + Stamp out segfault under KDM + + 96 Vagrant Cascadian 2013-03-22 {debian/libpam-sshauth_0.3-1} + Upload libpam-sshauth 0.3-1 to debian. + + 95 Vagrant Cascadian 2013-03-15 {libpam-sshauth-0.3} + man/waitfor.1: Escape minus signs, otherwise they're rendered + as hyphens. + + 94 Vagrant Cascadian 2013-03-15 + debian/rules: Install pam_sshauth.so into /lib//security/. + + 93 Scott Balneaves 2013-03-14 + Succeed for system accounts + + 92 Vagrant Cascadian 2013-03-12 + debian/control: Add Build-Depends on pkg-config. + + 91 Vagrant Cascadian 2013-03-12 + debian/compat: Re-enable compatibility level 9, enabling hardening + build flags. + + 90 Scott Balneaves 2013-03-12 + More hardening + + 89 Scott Balneaves 2013-03-12 + Fix for hardening + + 88 Scott Balneaves 2013-03-12 + known_host processing now works; skip over keys we can't handle + + 87 Scott Balneaves 2013-03-12 + working keyboard_interactive, broken known_hosts checking + + 86 Scott Balneaves 2013-03-12 + Revert vagrantc's change; needed to set library variables. Also, + added --with-pam-dir variable + + 85 Vagrant Cascadian 2013-03-11 + Set debian/compat to 8, to disable hardening build flags. :( + + 84 Vagrant Cascadian 2013-03-11 + Use AC_CHECK_HEADER with libssh2.h rather than PKG_CHECK_MODULES, + otherwise it wouldn't build for me. + + 83 Vagrant Cascadian 2013-03-11 + Add Build-Depends on libssh2-1-dev, drop libssh-dev. + + 82 Scott Balneaves 2013-03-11 + ssh2 keyboard interactive + + 81 Scott Balneaves 2013-03-11 + Initial change to libssh2 + + 80 Scott Balneaves 2013-02-25 + updated pammodir. Not working correctly, but this is what its + 'supposed' to be + + 79 Scott Balneaves 2013-02-24 + Bump to version 0.3 + + 78 Scott Balneaves 2013-02-24 + Move to dir for storage, add waitfor command + + 77 Scott Balneaves 2013-02-23 + Bug in not always returning pam_result + + 76 Scott Balneaves 2013-02-21 + Improve debugging logging + + 75 Scott Balneaves 2013-02-21 + Add pam_sshauth.h to SOURCES so it will be included in a make dist + + 74 Vagrant Cascadian 2013-02-15 + Debian: Update years in debian/copyright. + + 73 Vagrant Cascadian 2013-02-15 {debian/libpam-sshauth_0.2-1} + Upload libpam-sshauth 0.2-1 to Debian experimental. + + 72 Vagrant Cascadian 2013-02-15 + Debian: Add Vcs-Browser and Vcs-Bzr to debian/control. + http://bugs.debian.org/692637 + + 71 Vagrant Cascadian 2013-02-15 + Debian: Bump Standards-Version to 3.9.4, no changes necessary. + + 70 Vagrant Cascadian 2013-02-15 + Debian: set debian/compat and build-depends on debhelper 9, to + enable hardening build flags. + + 69 Scott Balneaves 2013-02-15 {libpam-sshauth-0.2} + More code cleanup; better return values, fixed memory leak, port + variable no longer required. + + 68 Scott Balneaves 2013-02-13 + Make packaging match autoconf name + + 67 Scott Balneaves 2013-02-13 + Updated some docs, bumped version to 0.2 + + 66 Scott Balneaves 2013-02-12 + Update to build infrastructure + + 65 Scott Balneaves 2013-02-12 + Move to simpler shell based shm_askpass + + 64 Scott Balneaves 2013-02-12 + Implement different askpass functionality + + 63 Scott Balneaves 2013-02-12 + Code cleanup, generalization of env storing routines + + 62 Scott Balneaves 2013-02-11 + More cleanup + + 61 Scott Balneaves 2013-02-11 + Break up into multiple files + + 60 Scott Balneaves 2012-10-06 + Set the environment variables earlier + + 59 Scott Balneaves 2012-10-06 + Very fragile, but now setting environment variables for use + with libnss-env so that we can spawn the ssh tunnel as part of + the session. + + 58 Scott Balneaves 2012-10-05 + Also handle shadow + + 57 Scott Balneaves 2012-10-05 + Added initial cut of bringing over user geometry from the remote + end. Depends on nss_extrausers + + 56 Scott Balneaves 2012-10-05 + Updated README + + 55 Scott Balneaves 2012-10-05 + Clean up some of the ltsp-session handling because of nss_sshsock + library; properly handle PAM_XDISPLAY variable. + + 54 Scott Balneaves 2012-10-01 + Removed some code in the example, as the libnss_sshsock NSS module + can now be used instead. + + 53 vagrant@freegeek.org 2011-10-28 {debian/libpam-sshauth_0.1-1} + added debian dir for initial packaging. + + 52 Scott Balneaves 2011-10-28 {libpam-sshauth-0.1} + Added shm_askpass manual page + + 51 Scott Balneaves 2011-10-28 + Added try_first_pass functionality + + 50 Scott Balneaves 2011-09-29 + Moved both hostname and port to using pam_set/get_data routines. + + 49 Scott Balneaves 2011-08-03 + Fixed some potential buffer overflows, some code refactoring, + addes syslog support to shm_askpass + + 48 Scott Balneaves 2011-07-19 + Quick code audit revealed a missing return value test. Also cleaned + up some unneeded initializers. + + 47 Scott Balneaves 2011-07-13 + Integrated the chown as part of the shm_askpass program, making it + dependent on some pam variables. Simplifies the code, and makes + things more secure. + + 46 Scott Balneaves 2011-07-11 + Added a test for daemon in the example script + + 45 Scott Balneaves 2011-07-11 + Made some cleanups to the session script + + 44 Scott Balneaves 2011-04-05 + Removed flarp from the EXTRA_DIST line in the extras dir. + + 43 Scott Balneaves 2011-04-05 + Removed ChangeLog: bzr log gives history, and the makefile hooks + create ChangeLog before a dist. + + 42 Scott Balneaves 2011-04-05 + Removed the pamtest program: libpam-dotfiles provides it, if + you'd like to test, or now that libpam_sshauth is becoming stable, + just test it in place. + + 41 Scott Balneaves 2011-04-04 + added some ignores + + 40 Scott Balneaves 2011-04-04 + Added authtries parameter, moved to setting the port via the string + value, and not atoi()'ing it, remove the display variable handling, + set STRICTHOSTKEYCHECK if available + + 39 Scott Balneaves 2011-03-30 + Added manpage, updated changelog + + 38 Scott Balneaves 2011-03-30 + Add handling for starting the tunnel twice: once as root, second + time as user. + + 37 Scott Balneaves 2011-03-30 + Add in --chown function to shm_askpass so that root may change + ownership for the user. + + 36 Scott Balneaves 2011-03-29 + Handle both /etc/ssh/ssh_known_hosts and ~/.ssh/known_hosts + + 35 Scott Balneaves 2011-03-28 + Move to using the /etc/ssh/ssh_known_hosts file, shorten prompts + to better fit on screen + + 34 Scott Balneaves 2011-03-28 + Fixed up a couple of errors in ltsp-session + + 33 Scott Balneaves 2011-03-28 + More cleanup in the ltsp-session file. Handle bringing over the + shadow file. + + 32 Scott Balneaves 2011-03-25 + Session script now launches socket during auth phase. Pulls across + user and group info for nss_extrauser + + 31 Scott Balneaves 2011-03-25 + Added examples directory glue to autoconf, make dist now works + correctly + + 30 Scott Balneaves 2011-03-22 + updated some documentation + + 29 Scott Balneaves 2011-03-21 + Properly handle DISPLAY, fix up example session script + + 28 Scott Balneaves 2011-03-21 + Added in the shm_askpass helper, example session files + + 27 Scott Balneaves 2011-03-20 + Remove spawning code: we'll do this with pam_exec. + + 26 Scott Balneaves 2010-11-19 + Spit out an ssh message on failed password, and change a couple + more PAM_SSHLIB for PAM_SSHAUTH + + 25 Scott Balneaves 2010-11-19 + Whoops, environment variables should be PAM_SSHAUTH_* + + 24 Scott Balneaves 2010-11-19 + Standardized on either pam_result or ssh_result to indicate which + result code I'm dealing with. Refactored do_sshauth code to allow + for 3 tries at the password. + + 23 Scott Balneaves 2010-11-18 + Make send-pam-msg a varargs function, so we can format the messages + we're sending like printf + + 22 Scott Balneaves 2010-11-16 + Added handling of unknown servers. Will now prompt user via + pam mechanism. + + 21 Scott Balneaves 2010-11-16 + Move away from LTSP specific names to pam_sshlib unique names + + 20 Scott Balneaves 2010-11-15 + Zero out password after it's used, so it's not hanging around + in memory. + + 19 Scott Balneaves 2010-11-15 + Check more return values, handle command lines. Added debug option + + 18 Scott Balneaves 2010-11-10 + Some cleanup around the password handling, use poll() instead of + select(), make sure stderr of ssh's goes to /dev/null as well + + 17 Scott Balneaves 2010-11-10 + Switch to static character array. When we need to exit because + of errors, we don't have to worry about freeing character strings. + + 16 Scott Balneaves 2010-11-08 + Add creating socket for public key authentication + + 15 Scott Balneaves 2010-11-08 + Check openpty() return code, some strdups. + + 14 Scott Balneaves 2010-11-08 + Added missing file NEWS, check result of strdup, minor cleanup on + the test program + + 13 Scott Balneaves 2010-11-04 + Fix a couple of errors. + + 12 Scott Balneaves 2010-11-04 + Move to pam_syslog so we don't have to manage openlog and closelog + + 11 Scott Balneaves 2010-11-04 + Some cleanup. Lots more work to do: need to parse command lines, + check more error codes, etc. + + 10 Scott Balneaves 2010-10-30 + Full implementation at hackfest; first cut + + 9 Scott Balneaves 2010-01-13 + Why not just use syslog directly? + + 8 Scott Balneaves 2010-01-13 + Generalized some functions, added proper port support + + 7 Scott Balneaves 2010-01-11 + Fixed some errors + + 6 Scott Balneaves 2010-01-11 + Added public key authentication method + + 5 Scott Balneaves 2010-01-10 + Updated README with some useful instructions + + 4 Scott Balneaves 2010-01-10 + Little more logging + + 3 Scott Balneaves 2010-01-10 + First success + + 2 Scott Balneaves 2010-01-10 + More work, added initial libssh functionality + + 1 Scott Balneaves 2010-01-09 + Initial commit: laying out some infrastructure + diff -Nru libpam-sshauth-0.1/Makefile.am libpam-sshauth-0.3.1/Makefile.am --- libpam-sshauth-0.1/Makefile.am 2011-10-28 22:04:37.000000000 +0000 +++ libpam-sshauth-0.3.1/Makefile.am 2013-07-04 18:17:23.000000000 +0000 @@ -1,7 +1,8 @@ AUTOMAKE_OPTIONS = dist-bzip2 DISTCLEANFILES = ChangeLog +EXTRA_DIST = autogen.sh -SUBDIRS = src examples man +SUBDIRS = src examples man scripts .PHONY: ChangeLog dist-up ChangeLog: diff -Nru libpam-sshauth-0.1/README libpam-sshauth-0.3.1/README --- libpam-sshauth-0.1/README 2011-10-28 22:04:37.000000000 +0000 +++ libpam-sshauth-0.3.1/README 2013-07-04 18:17:23.000000000 +0000 @@ -10,17 +10,19 @@ pam_sshauth requires: - * libssh version 4 or better + * libssh version 4 or better Configuration: -------------- -The pam_sshauth module understands 4 pam command line options: +The pam_sshauth module understands 6 pam command line options: * host= * port= * nostrict * authtries= + * try_first_pass + * shm_askpass So, in the pam file for the service you're using pam_sshauth with, you could specify: @@ -33,6 +35,9 @@ default is that this option will not be offered to you, and any attempt to authenticate against a machine you don't have the host key for will fail. +The shm_askpass option will cause the pam module to work with the ssh ASKPASS +helper shm_askpass. + The pam_sshauth module will ALSO check for the presence of two environment variables: PAM_SSHAUTH_HOST and PAM_SSHAUTH_PORT. It isn't necessary on either the pam command line OR the environment variable to set the port: it will @@ -60,11 +65,7 @@ mechanism, as well as an example script which can be used in conjunction with pam_exec to create the tunnel. -The shm_askpass program is an SSH-ASKPASS compliant program which can accept a -password on it's stdin, and store it in POSIX shared memory. Then, it can be -called via ssh using the SSH-ASKPASS mechanism, at which point it provides the -password, zeros the password in shared memory, and deletes the shared memory -segment. +The shm_askpass program is an SSH-ASKPASS compliant shell script. In the examples directory of this archive I've provided an example session script for use with pam_exec which will handle storing the password, launching @@ -75,8 +76,7 @@ -------- To test, create an example service file in /etc/pam.d. You can use the -"pamtest" utility provided by the libpam_dotfile package (check your distro) to -test the libpam_sshauth module. +"pamtester" utility available at pamtester.sourceforge.net. The service file should contain the following lines: @@ -91,16 +91,17 @@ ./configure --prefix=/usr && make && sudo make install -Then, using libpam-dotfile's pamtest utility: +Then, using pamtester utility: -pamtest user +pamtester service user authenticate open_session close_session You should see something along the lines of: -sbalneav@phobos:~$ pamtest flarp scbal -Trying to authenticate for service . +sbalneav@eris:~$ pamtester flarp sbalneav authenticate open_session close_session Password: -Authentication successful. +pamtester: successfully authenticated +pamtester: sucessfully opened a session +pamtester: session has successfully been closed. pam_sshauth logs to authlog: @@ -118,3 +119,5 @@ ------- pam_sshauth is licensed under the GNU GPL 2 or later license. + +(C) 2010-2013 Scott Balneaves diff -Nru libpam-sshauth-0.1/autogen.sh libpam-sshauth-0.3.1/autogen.sh --- libpam-sshauth-0.1/autogen.sh 1970-01-01 00:00:00.000000000 +0000 +++ libpam-sshauth-0.3.1/autogen.sh 2013-07-04 18:17:23.000000000 +0000 @@ -0,0 +1,2 @@ +#!/bin/sh +autoreconf --force --install diff -Nru libpam-sshauth-0.1/configure.ac libpam-sshauth-0.3.1/configure.ac --- libpam-sshauth-0.1/configure.ac 2011-10-28 22:04:37.000000000 +0000 +++ libpam-sshauth-0.3.1/configure.ac 2013-07-04 18:17:23.000000000 +0000 @@ -1,4 +1,4 @@ -AC_INIT([pam_sshauth], [0.1], [sbalneav@ltsp.org]) +AC_INIT([libpam-sshauth], [0.3], [sbalneav@ltsp.org]) AC_CONFIG_HEADER(config.h) AM_MAINTAINER_MODE @@ -8,6 +8,7 @@ AC_PREREQ([2.59]) AC_PROG_CC +AC_PROG_CC_STDC AM_PROG_CC_C_O AC_CHECK_HEADER([security/pam_modules.h], , @@ -16,11 +17,18 @@ AC_MSG_ERROR([PAM library missing])) AC_SUBST(PAM_LIBS) -AC_CHECK_HEADER([libssh/libssh.h], , - [AC_MSG_ERROR([libssh headers missing])]) -AC_CHECK_LIB(ssh, ssh_new, [SSH_LIBS="-lssh"], - AC_MSG_ERROR([libssh library missing])) -AC_SUBST(SSH_LIBS) +AC_SUBST(PAMDIR, "\$(exec_prefix)/lib/security") +AC_ARG_WITH(pam-dir, + AC_HELP_STRING([--with-pam-dir=DIR], + [Where to install PAM module [[PREFIX/lib/security]]]), + [case "${withval}" in + /*) PAMDIR="${withval}";; + ./*|../*) AC_MSG_ERROR(Bad value for --with-pam-dir);; + *) PAMDIR="\$(exec_prefix)/lib/${withval}";; + esac]) +AC_MSG_NOTICE([PAM installation path $PAMDIR]) -AC_CONFIG_FILES([Makefile] [src/Makefile] [examples/Makefile] [man/Makefile]) +PKG_CHECK_MODULES([SSH2], [libssh2]) + +AC_CONFIG_FILES([Makefile] [src/Makefile] [examples/Makefile] [man/Makefile] [scripts/Makefile]) AC_OUTPUT diff -Nru libpam-sshauth-0.1/debian/changelog libpam-sshauth-0.3.1/debian/changelog --- libpam-sshauth-0.1/debian/changelog 2011-10-29 00:26:50.000000000 +0000 +++ libpam-sshauth-0.3.1/debian/changelog 2013-07-04 18:16:58.000000000 +0000 @@ -1,3 +1,28 @@ +libpam-sshauth (0.3.1-1) unstable; urgency=low + + * New upstream version: + - Fix segfault under KDM + + -- Vagrant Cascadian Tue, 26 Mar 2013 14:09:32 -0700 + +libpam-sshauth (0.3-1) experimental; urgency=low + + * New upstream version. + - Switch to using libssh2. + * Add Build-Depends on libssh2-1-dev and pkg-config, drop libssh-dev. + * debian/rules: Install pam_sshauth.so into /lib//security/. + + -- Vagrant Cascadian Fri, 22 Mar 2013 12:31:56 -0700 + +libpam-sshauth (0.2-1) experimental; urgency=low + + * New upstream version. + * Set debian/compat to 9, to enable hardening flags. + * Bump Standards-Version to 3.9.4, no changes necessary. + * Add Vcs-Browser and Vcs-Bzr to debian/control (Closes: #692637). + + -- Vagrant Cascadian Fri, 15 Feb 2013 11:48:57 -0800 + libpam-sshauth (0.1-1) unstable; urgency=low * Initial release. diff -Nru libpam-sshauth-0.1/debian/compat libpam-sshauth-0.3.1/debian/compat --- libpam-sshauth-0.1/debian/compat 2011-10-28 22:15:21.000000000 +0000 +++ libpam-sshauth-0.3.1/debian/compat 2013-03-12 22:10:34.000000000 +0000 @@ -1 +1 @@ -8 +9 diff -Nru libpam-sshauth-0.1/debian/control libpam-sshauth-0.3.1/debian/control --- libpam-sshauth-0.1/debian/control 2011-10-29 00:24:57.000000000 +0000 +++ libpam-sshauth-0.3.1/debian/control 2013-03-15 22:27:05.000000000 +0000 @@ -3,8 +3,10 @@ Priority: extra Maintainer: LTSP Debian Maintainers Uploaders: Vagrant Cascadian -Build-Depends: debhelper (>= 8.0.0), libssh-dev, libpam0g-dev | libpam-dev, dh-autoreconf -Standards-Version: 3.9.2 +Build-Depends: debhelper (>= 9), libssh2-1-dev, libpam0g-dev | libpam-dev, dh-autoreconf, pkg-config +Standards-Version: 3.9.4 +Vcs-Browser: https://bazaar.launchpad.net/~ltsp-upstream/ltsp/libpam-sshauth/files +Vcs-Bzr: lp:~ltsp-upstream/ltsp/libpam-sshauth Package: libpam-sshauth Architecture: any diff -Nru libpam-sshauth-0.1/debian/copyright libpam-sshauth-0.3.1/debian/copyright --- libpam-sshauth-0.1/debian/copyright 2011-10-29 00:25:58.000000000 +0000 +++ libpam-sshauth-0.3.1/debian/copyright 2013-02-15 20:23:14.000000000 +0000 @@ -3,11 +3,11 @@ Source: http://bazaar.launchpad.net/~sbalneav/ltsp/libpam-sshauth/ Files: * -Copyright: 2011 Scott Balneaves +Copyright: 2011-2013 Scott Balneaves License: GPL-2.0+ Files: debian/* -Copyright: 2011 Vagrant Cascadian +Copyright: 2011-2013 Vagrant Cascadian License: GPL-2.0+ License: GPL-2.0+ diff -Nru libpam-sshauth-0.1/debian/rules libpam-sshauth-0.3.1/debian/rules --- libpam-sshauth-0.1/debian/rules 2011-10-28 23:41:24.000000000 +0000 +++ libpam-sshauth-0.3.1/debian/rules 2013-03-15 22:38:49.000000000 +0000 @@ -1,6 +1,10 @@ #!/usr/bin/make -f # -*- makefile -*- +DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH). + %: dh $@ --with autoreconf +override_dh_auto_configure: + dh_auto_configure -- --with-pam-dir=/lib/$(DEB_HOST_MULTIARCH)/security diff -Nru libpam-sshauth-0.1/examples/ltsp-session libpam-sshauth-0.3.1/examples/ltsp-session --- libpam-sshauth-0.1/examples/ltsp-session 2011-10-28 22:04:37.000000000 +0000 +++ libpam-sshauth-0.3.1/examples/ltsp-session 2013-07-04 18:17:23.000000000 +0000 @@ -1,76 +1,22 @@ #!/bin/sh -export PATH=/bin:/usr/bin:/sbin:/usr/sbin -VARLIB="/var/lib/pam_sshauth" -EXTRAUSERS="/var/lib/extrausers" -SOCKETDIR="${VARLIB}/${PAM_SSHAUTH_HOST}/${PAM_USER}" -SOCKET="${SOCKETDIR}/socket" -export DISPLAY=${PAM_TTY} +SOCKETDIR="/tmp" +SOCKET="${SOCKETDIR}/${PAM_USER}-${PAM_XDISPLAY}" +export DISPLAY=${PAM_XDISPLAY} export SSH_ASKPASS="/usr/bin/shm_askpass" test -x /usr/bin/daemon || exit 1 -# -# waitfor -# -# Wait for our socket to appear. -# - -waitfor () { - S=$1 - - while [ ! -S "${S}" ]; do - sleep 1 - done -} - -# -# get_extrafiles_user -# -# get our /etc/passwd entry, and store where nss_extrafiles wants -# them to be stored. -# - -get_extrafiles_user () { - S=$1 - - ssh -S ${S} ${PAM_SSHAUTH_HOST} getent passwd ${PAM_USER} \ - >> ${EXTRAUSERS}/passwd - ssh -S ${S} ${PAM_SSHAUTH_HOST} getent shadow ${PAM_USER} \ - >> ${EXTRAUSERS}/shadow -} - -# -# get_extrafiles_group -# -# get our /etc/group entries for our user, and store where -# nss_extrafiles wants them to be stored. -# - -get_extrafiles_group () { - S=$1 - - GROUPS=$(ssh -S ${S} ${PAM_SSHAUTH_HOST} id -G ${PAM_USER}) - ssh -S ${S} ${PAM_SSHAUTH_HOST} getent group ${GROUPS} \ - >> ${EXTRAUSERS}/group -} - -# -# cleanup_user -# -# Remove all mention of a user from ${EXTRAFILES} -# - -cleanup_user () { - U=$1 - - sed -i "/${U}/d" ${EXTRAUSERS}/passwd - sed -i "/${U}/d" ${EXTRAUSERS}/shadow - sed -i "/${U}/d" ${EXTRAUSERS}/group +print_env () { + logger "PAM_USER=${PAM_USER}" + logger "PAM_SSHAUTH_HOST=${PAM_SSHAUTH_HOST}" + logger "SOCKET=${SOCKET}" + logger "DISPLAY=${DISPLAY}" + W=$(whoami) + logger "whoami: ${W}" } open_socket () { - S=$1 if [ -n "${DISPLAY}" ]; then # @@ -84,21 +30,12 @@ # shm_askpass will pass it to ssh for it to authenticate with. # - daemon -i -- ssh -q -N -X -M -S "${S}" -l ${PAM_USER} \ - ${PAM_SSHAUTH_HOST} - - # - # Wait for the socket to actually become available before returning. - # - - waitfor "${S}" + daemon -i -- ssh -q -N -X -M -S "${SOCKET}" -l ${PAM_USER} ${PAM_SSHAUTH_HOST} fi } close_socket () { - S=$1 - ssh -q -S "$S" -O exit ${PAM_SSHAUTH_HOST} - rm -rf "${SOCKETDIR}" + ssh -q -S "${SOCKET}" -O exit ${PAM_SSHAUTH_HOST} } # @@ -110,24 +47,8 @@ auth) - logger "ltsp-session: start auth" - - # - # Make sure our /var/lib/ directory exists. - # - - if [ ! -d "${VARLIB}" ]; then - mkdir -p "${VARLIB}" - chmod 777 "${VARLIB}" - fi - - # - # Construct our socket directory. - # - - if [ ! -d "${SOCKETDIR}" ]; then - mkdir -p "${SOCKETDIR}" - fi + logger "___ Begin Auth ___" + print_env # # We're authenticating, so we'll store the auth token using shm_askpass @@ -137,41 +58,23 @@ shm_askpass --write - open_socket "${SOCKET}" + logger "___ End Auth ___" - if [ -S "${SOCKET}" ]; then - - # - # Use the socket to pull across the user geometries. - # - - get_extrafiles_user "${SOCKET}" - get_extrafiles_group "${SOCKET}" - - # - # We're done bringing the user geometries across. Close the socket as - # root. - # - - close_socket "${SOCKET}" - - else - logger "ltsp-session: no \$DISPLAY" - fi - - logger "ltsp-session: end auth" ;; open_session) + logger "___ Begin Open_Session ___" + print_env + # - # opening a session as user. Re-spawn our ssh socket, this time as the + # opening a session as user. Spawn our ssh socket, this time as the # user. # - logger "ltsp-session: start open_session" - open_socket "${SOCKET}" - logger "ltsp-session: end open_session" + open_socket + + logger "___ End Open_Session ___" ;; @@ -181,14 +84,13 @@ # We're closing the session down, so cause the socket to exit. # - logger "ltsp-session: start close_session" - close_socket "${SOCKET}" - cleanup_user ${PAM_USER} - logger "ltsp-session: end close_session" + logger "___ Begin Close_Session ___" + print_env + close_socket + logger "___ End Close_Session ___" ;; esac -logger "ltsp-session: exiting" exit 0 diff -Nru libpam-sshauth-0.1/man/Makefile.am libpam-sshauth-0.3.1/man/Makefile.am --- libpam-sshauth-0.1/man/Makefile.am 2011-10-28 22:04:37.000000000 +0000 +++ libpam-sshauth-0.3.1/man/Makefile.am 2013-07-04 18:17:23.000000000 +0000 @@ -1 +1 @@ -dist_man_MANS = pam_sshauth.8 shm_askpass.1 +dist_man_MANS = pam_sshauth.8 shm_askpass.1 waitfor.1 diff -Nru libpam-sshauth-0.1/man/pam_sshauth.8 libpam-sshauth-0.3.1/man/pam_sshauth.8 --- libpam-sshauth-0.1/man/pam_sshauth.8 2011-10-28 22:04:37.000000000 +0000 +++ libpam-sshauth-0.3.1/man/pam_sshauth.8 2013-07-04 18:17:23.000000000 +0000 @@ -1,11 +1,11 @@ -.TH "PAM_SSHAUTH" "8" "2011/03/30" +.TH "PAM_SSHAUTH" "8" "2013/02/13" .nh .ad l .SH "NAME" pam_sshauth \- PAM module which authenticates against an ssh server .SH "SYNOPSIS" .HP \w'\fBpam_sshauth\&.so\fR\ 'u -\fBpam_sshauth\&.so\fR [debug] [nostrict] [authtries=\fItries\fR] [try_first_pass] [host=\fIhost\fR] [port=\fIport\fR] +\fBpam_sshauth\&.so\fR [debug] [nostrict] [shm_askpass] [authtries=\fItries\fR] [try_first_pass] [host=\fIhost\fR] [port=\fIport\fR] .SH "DESCRIPTION" .PP pam_sshauth is a PAM module that can be used to authenticate a user based on @@ -40,6 +40,12 @@ known_hosts file\&. The default will be to fail the authentication\&. .RE .PP +\fBshm_askpass\fR +.RS 4 +Properly handle interaction with the ASKPASS helper shm_askpass to allow +you to spawn ssh sockets\&. +.RE +.PP \fBhost=\fR\fB\fIhost\fR\fR .RS 4 Specifies the host we're to authenticate with\&. diff -Nru libpam-sshauth-0.1/man/shm_askpass.1 libpam-sshauth-0.3.1/man/shm_askpass.1 --- libpam-sshauth-0.1/man/shm_askpass.1 2011-10-28 22:04:37.000000000 +0000 +++ libpam-sshauth-0.3.1/man/shm_askpass.1 2013-07-04 18:17:23.000000000 +0000 @@ -1,48 +1,18 @@ -.TH "SHM_ASKPASS" "1" "2011/10/28" +.TH "SHM_ASKPASS" "1" "2013/02/13" .nh .ad l .SH "NAME" shm_askpass \- An SSH-ASKPASS compliant helper for use with pam_sshauth .SH "SYNOPSIS" .HP \w'\fBshm_askpass\fR\ 'u -\fBshm_askpass\fR [--write] [--delete] [--help] +\fBshm_askpass\fR .SH "DESCRIPTION" .PP -\fBshm_askpass\fR is a small SSH-ASKPASS compliant password helper that -will allow you read passwords from stdin, and store them in shared memory\&. +\fBshm_askpass\fR is a small SSH-ASKPASS compliant password helper\&. Upon providing the password to ssh as a regular user, it will automatically delete the password\&. If it provides the password as root, it will not clear the password\&. .PP -The default shared memory path it will use will be \fI/shm_askpass\fR\&. If -you wish to use a different path, simply set the \fISHM_ASKPASS_PATH\fR to -an appropriate path. Note that the path must begin with '/'\&. -.PP -.SH "OPTIONS" -.PP -.PP -\fB--write\fR -.RS 4 -Reads a password from \fBstdin\fR and stores it as a shared memory -object. -.RE -.PP -\fB--delete\fR -.RS 4 -If \fBshm_askpass\fR is called with no command line options as a regular -user, it will provide the stored password on \fBstdout\fR (followed by -a newline) and delete the password from shared memory\&. If called as -root with no options, it will provide the password on \fBstdout\fR, but -not delete the password\&. If you would like to manually delete the password, -you may call shm_askpass with the \fI--delete\fR option to manually delete -the password from shared memory\&. -.RE -.PP -\fB--help\fR -.RS 4 -Provides a short summary of options on \fBstderr\fR\&. -.RE -.PP .SH "SEE ALSO" .PP \fBpam_sshauth\fR(8), diff -Nru libpam-sshauth-0.1/man/waitfor.1 libpam-sshauth-0.3.1/man/waitfor.1 --- libpam-sshauth-0.1/man/waitfor.1 1970-01-01 00:00:00.000000000 +0000 +++ libpam-sshauth-0.3.1/man/waitfor.1 2013-07-04 18:17:23.000000000 +0000 @@ -0,0 +1,27 @@ +.TH "WAITFOR" "1" "2013/02/24" +.nh +.ad l +.SH "NAME" +waitfor \- wait for a file action, with timeout. +.SH "SYNOPSIS" +.HP \w'\fBwaitfor\&.so\fR\ 'u +\fBwaitfor\fR [\-t \fIseconds\fR] [\-n] file +.SH "DESCRIPTION" +.PP +\fBwaitfor\fR will wait for a file to appear, or with the \-n option, for a file +to disappear\&. If a timeout is provided, with the [\-t] option, if the file +action doesn't happen within the time specified, the program will exit\&. +.PP +.SH "RETURN VALUES" +.PP +The program will return 0 if the file action happens\&. If no timeout is +specified, \fBwaitfor\fR will wait forever\&. If a timeout is specified, and +the file action does not happen within the timeout specified, \fBwaitfor\fR +will return 1\&. +.PP +.SH "SEE ALSO" +.PP +\fBpam_sshauth\fR(8), +.SH "AUTHOR" +.PP +waitfor was written by Scott Balneaves \&. diff -Nru libpam-sshauth-0.1/scripts/Makefile.am libpam-sshauth-0.3.1/scripts/Makefile.am --- libpam-sshauth-0.1/scripts/Makefile.am 1970-01-01 00:00:00.000000000 +0000 +++ libpam-sshauth-0.3.1/scripts/Makefile.am 2013-07-04 18:17:23.000000000 +0000 @@ -0,0 +1 @@ +dist_bin_SCRIPTS = shm_askpass diff -Nru libpam-sshauth-0.1/scripts/shm_askpass libpam-sshauth-0.3.1/scripts/shm_askpass --- libpam-sshauth-0.1/scripts/shm_askpass 1970-01-01 00:00:00.000000000 +0000 +++ libpam-sshauth-0.3.1/scripts/shm_askpass 2013-07-04 18:17:23.000000000 +0000 @@ -0,0 +1,13 @@ +#!/bin/sh + +[ -z "${PAM_SSHAUTH_DIR}" ] && exit 1 + +PASSWORD=$(cat "${PAM_SSHAUTH_DIR}/.passwd") + +echo "${PASSWORD}" + +ID=$(id -u) + +if [ "${ID}" != "0" ]; then + rm "${PAM_SSHAUTH_DIR}/.passwd" +fi diff -Nru libpam-sshauth-0.1/src/Makefile.am libpam-sshauth-0.3.1/src/Makefile.am --- libpam-sshauth-0.1/src/Makefile.am 2011-10-28 22:04:37.000000000 +0000 +++ libpam-sshauth-0.3.1/src/Makefile.am 2013-07-04 18:17:23.000000000 +0000 @@ -1,11 +1,10 @@ -bin_PROGRAMS = shm_askpass +bin_PROGRAMS = waitfor pammod_PROGRAMS = pam_sshauth.so -pammoddir=/lib/security +pammoddir=$(PAMDIR) -pam_sshauth_so_SOURCES = pam_sshauth.c -pam_sshauth_so_CFLAGS = -fpic $(GLIB_CFLAGS) -pam_sshauth_so_LDFLAGS = -shared -pam_sshauth_so_LDADD = $(PAM_LIBS) $(SSH_LIBS) $(GLIB_LIBS) $(UTIL_LIBS) +waitfor_SOURCES = waitfor.c -shm_askpass_SOURCES = shm_askpass.c -shm_askpass_LDADD = -lrt +pam_sshauth_so_SOURCES = pam_sshauth.c pam_util.c auth_funcs.c sess_funcs.c pam_sshauth.h +pam_sshauth_so_CFLAGS = -fpic -Wall $(GLIB_CFLAGS) $(SSH2_CFLAGS) +pam_sshauth_so_LDFLAGS = -shared +pam_sshauth_so_LDADD = $(PAM_LIBS) $(SSH2_LIBS) $(GLIB_LIBS) $(UTIL_LIBS) diff -Nru libpam-sshauth-0.1/src/auth_funcs.c libpam-sshauth-0.3.1/src/auth_funcs.c --- libpam-sshauth-0.1/src/auth_funcs.c 1970-01-01 00:00:00.000000000 +0000 +++ libpam-sshauth-0.3.1/src/auth_funcs.c 2013-07-04 18:17:23.000000000 +0000 @@ -0,0 +1,459 @@ +/* + * pam_sshauth: PAM module for authentication via a remote ssh server. + * Copyright (C) 2010-2013 Scott Balneaves + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pam_sshauth.h" + +#define SSH_AUTH_METHOD_PASSWORD 1 +#define SSH_AUTH_METHOD_INTERACTIVE 2 + +#define SSH_AUTH_SUCCESS 0 +#define SSH_AUTH_ERROR 1 + +static void +kbd_callback (const char *name, int name_len, + const char *instruction, int instruction_len, int num_prompts, + const LIBSSH2_USERAUTH_KBDINT_PROMPT * prompts, + LIBSSH2_USERAUTH_KBDINT_RESPONSE * responses, void **abstract) +{ + pam_handle_t *pamh = *abstract; + int i; + + /* + * Get any instructions the ssh session has generted, + * and send them to the user via the pam message system. + */ + + if (instruction_len > 0) + { + send_pam_msg (pamh, PAM_TEXT_INFO, instruction); + } + + /* + * Loop through the prompts that ssh has given us, and ask the + * user via pam prompts for the answers. + */ + + for (i = 0; i < num_prompts; i++) + { + int style = prompts[i].echo ? PAM_PROMPT_ECHO_ON : PAM_PROMPT_ECHO_OFF; + int pam_retval; + char *buf, *response; + + if ((buf = malloc (prompts[i].length + 1)) == NULL) + { + return; + } + strncpy (buf, prompts[i].text, prompts[i].length); + *(buf + prompts[i].length) = '\0'; + pam_retval = pam_prompt (pamh, style, &response, "%s", buf); + free (buf); + if (pam_retval != PAM_SUCCESS) + { + return; + } + + responses[i].text = strdup (response); + responses[i].length = strlen (response); + + if (pam_set_item (pamh, PAM_AUTHTOK, response) != PAM_SUCCESS) + { + return; + } + } +} + +/* + * auth_pw () + * + * conduct an ssh simple password based authentication + */ + +static int +auth_pw (pam_handle_t * pamh, const char *username, LIBSSH2_SESSION * session) +{ + int ssh_result; + char *password = NULL; + + /* + * try_first_pass works with simple password authentication. + */ + + if (try_first_pass) + { + if (pam_get_item (pamh, PAM_AUTHTOK, (const void **) &password) != + PAM_SUCCESS) + { + pam_syslog (pamh, LOG_ERR, + "Couldn't obtain PAM_AUTHTOK from the pam stack."); + password = NULL; + } + } + + if (password == NULL) + { + if (pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &password, "Password:") != + PAM_SUCCESS) + { + pam_syslog (pamh, LOG_ERR, + "Couldn't obtain password from pam_prompt."); + return SSH_AUTH_ERROR; + } + } + + ssh_result = libssh2_userauth_password (session, username, password); + if (ssh_result == SSH_AUTH_SUCCESS) + { + /* + * The very last response we've gotten should be the password. Store it + * as the AUTHTOK + */ + + if (!try_first_pass + && pam_set_item (pamh, PAM_AUTHTOK, password) != PAM_SUCCESS) + { + pam_syslog (pamh, LOG_ERR, + "Couldn't store password as PAM_AUTHTOK."); + return SSH_AUTH_ERROR; + } + + return ssh_result; + } + else + { + char *errmsg; + int len; + + libssh2_session_last_error (session, &errmsg, &len, 0); + + send_pam_msg (pamh, PAM_TEXT_INFO, errmsg); + return ssh_result; + } +} + +/* + * do_sshauth () + * + * Authenticate by attempting an ssh connection + */ + +int +do_sshauth (pam_handle_t * pamh, const char *username) +{ + int method = 0; + int ssh_result = SSH_AUTH_ERROR; + int pam_result; + int count; + int iport; + int sockfd = 0; + int type; + const char *fingerprint = NULL; + const char *host; + const char *port; + char *userauthlist; + struct hostent *server; + struct sockaddr_in serv_addr; + LIBSSH2_SESSION *session = NULL; + LIBSSH2_KNOWNHOSTS *nh = NULL; + size_t len; + FILE *khf; + + pam_result = pam_get_data (pamh, HOST, (const void **) &host); + if (pam_result != PAM_SUCCESS) + { + pam_syslog (pamh, LOG_ERR, + "Couldn't retrieve hostname from pam handle."); + return pam_result; + } + + pam_result = pam_get_data (pamh, PORT, (const void **) &port); + if (pam_result != PAM_SUCCESS) + { + /* Couldn't retrieve port. Fallback to 22 */ + iport = 22; + } + else + { + iport = atoi (port); + } + + /* + * Establish our socket + */ + + sockfd = socket (AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) + { + pam_syslog (pamh, LOG_ERR, "Couldn't create socket."); + return PAM_SYSTEM_ERR; + } + + server = gethostbyname (host); + if (server == NULL) + { + pam_syslog (pamh, LOG_ERR, "Couldn't resolve hostname %s.", host); + return PAM_SYSTEM_ERR; + } + bzero ((char *) &serv_addr, sizeof serv_addr); + serv_addr.sin_family = AF_INET; + bcopy ((char *) server->h_addr, + (char *) &serv_addr.sin_addr.s_addr, server->h_length); + serv_addr.sin_port = htons (iport); + if (connect (sockfd, (struct sockaddr *) &serv_addr, sizeof serv_addr) < 0) + { + pam_syslog (pamh, LOG_ERR, "Couldn't connect to %s.", host); + return PAM_SYSTEM_ERR; + } + + /* + * Begin the authentication loop. Loop until we're successfully + * authenticated, or AUTHTRIES times, whichever comes first. + */ + + count = authtries; + + session = libssh2_session_init_ex (NULL, NULL, NULL, (void *) pamh); + + if (session == NULL) + { + pam_syslog (pamh, LOG_ERR, + "Couldn't allocate ssh session structure for host %s", + host); + goto fail; + } + + /* + * tell libssh2 we want communications to use blocking + */ + + libssh2_session_set_blocking (session, 1); + + /* + * Start the connection. + */ + + if (libssh2_session_handshake (session, sockfd) != 0) + { + pam_syslog (pamh, LOG_ERR, "Couldn't handshake ssh session."); + goto fail; + } + + nh = libssh2_knownhost_init (session); + if (!nh) + { + pam_syslog (pamh, LOG_ERR, "Couldn't allocate known_host structure."); + goto fail; + } + + pam_debug (pamh, "Connected to host %s", host); + + /* + * Load known hosts from the system file. + */ + + khf = fopen (SYSTEM_KNOWNHOSTS, "r"); + + if (khf) + { + char buf[2048]; + + while (fgets (buf, sizeof (buf), khf)) + { + if (libssh2_knownhost_readline (nh, buf, strlen (buf), LIBSSH2_KNOWNHOST_FILE_OPENSSH)) + { + /* Skip over any keys libssh2 doesn't support */ + continue; + } + } + fclose (khf); + } + + /* + * Obtain our hosts fingerprint. + */ + + fingerprint = libssh2_session_hostkey (session, &len, &type); + + /* + * Is this server known to us? Try our /etc/ssh/ssh_known_hosts file + * first. + */ + + if (fingerprint) + { + int check = libssh2_knownhost_check (nh, host, fingerprint, len, + LIBSSH2_KNOWNHOST_TYPE_PLAIN | + LIBSSH2_KNOWNHOST_KEYENC_RAW, + NULL); + + if (check == LIBSSH2_KNOWNHOST_CHECK_FAILURE) + { + goto fail; + } + + if ((check == LIBSSH2_KNOWNHOST_CHECK_NOTFOUND) && nostrict) + { + char *response = NULL; + /* + * Unknown server. Ask the user, via the pam prompts, if they'd + * like to connect. + */ + pam_debug (pamh, "Server not in known_hosts file."); + send_pam_msg (pamh, PAM_TEXT_INFO, "Server unknown. Trust?"); + pam_prompt (pamh, PAM_PROMPT_ECHO_ON, &response, + "Type 'yes' to continue: "); + if (!response || (strncasecmp (response, "yes", 3) != 0)) + { + pam_debug (pamh, "User does not trust host."); + goto fail; + } + } + else if ((check == LIBSSH2_KNOWNHOST_CHECK_NOTFOUND) && !nostrict) + { + pam_debug (pamh, + "Unknown server and strict host checking. Connection denied."); + send_pam_msg (pamh, PAM_TEXT_INFO, + "Server is unknown, and strict checking enabled. Connection denied."); + goto fail; + } + else if (check == LIBSSH2_KNOWNHOST_CHECK_MISMATCH) + { + pam_debug (pamh, "Host key for %s changed. Connection terminated.", + host); + pam_syslog (pamh, LOG_ERR, "Host key for %s changed.", host); + send_pam_msg (pamh, PAM_TEXT_INFO, + "Server's host key has changed."); + send_pam_msg (pamh, PAM_TEXT_INFO, + "Possible man-in-the-middle attack. Connection terminated."); + goto fail; + } + } + + + /* + * Find out what methods the ssh server supports for authentication. + */ + + userauthlist = libssh2_userauth_list (session, username, strlen (username)); + + /* + * List auth methods that have been returned. + */ + + pam_debug (pamh, "Authentication methods supported: %s", userauthlist); + + if (strstr (userauthlist, "password") != NULL) + { + method |= SSH_AUTH_METHOD_PASSWORD; + } + if (strstr (userauthlist, "keyboard-interactive") != NULL) + { + method |= SSH_AUTH_METHOD_INTERACTIVE; + } + + do + { + /* + * Try keyboard interactive next, if supported. + */ + + if (method & SSH_AUTH_METHOD_INTERACTIVE) + { + /* + * SSH_AUTH_METHOD_INTERACTIVE requires + * ChallengeResponseAuthentication to be set to "yes" + * in /etc/ssh/sshd_config. + */ + pam_debug (pamh, "Trying keyboard interactive authentication."); + ssh_result = + libssh2_userauth_keyboard_interactive (session, username, + &kbd_callback); + if (ssh_result == SSH_AUTH_SUCCESS) + { + break; + } + } + + /* + * Finally, plain password authentication. + */ + + if (method & SSH_AUTH_METHOD_PASSWORD) + { + /* + * SSH_AUTH_METHOD_PASSWORD is simpler, and + * won't handle password expiry. + */ + pam_debug (pamh, "Trying simple password authentication."); + ssh_result = auth_pw (pamh, username, session); + if (ssh_result == SSH_AUTH_SUCCESS) + { + break; + } + } + + count--; + } + while (count); + +fail: + + if (nh != NULL) + { + libssh2_knownhost_free (nh); + } + + if (session != NULL) + { + libssh2_session_disconnect (session, "Shutdown"); + libssh2_session_free (session); + libssh2_exit (); + } + + if (sockfd) + { + close (sockfd); + } + + if (ssh_result == SSH_AUTH_SUCCESS) + { + pam_debug (pamh, "Authenticated successfully."); + return PAM_SUCCESS; + } + else + { + pam_debug (pamh, "Authentication failed."); + return PAM_AUTH_ERR; + } +} diff -Nru libpam-sshauth-0.1/src/pam_sshauth.c libpam-sshauth-0.3.1/src/pam_sshauth.c --- libpam-sshauth-0.1/src/pam_sshauth.c 2011-10-28 22:04:37.000000000 +0000 +++ libpam-sshauth-0.3.1/src/pam_sshauth.c 2013-07-04 18:17:23.000000000 +0000 @@ -1,6 +1,6 @@ /* * pam_sshauth: PAM module for authentication via a remote ssh server. - * Copyright (C) 2010 Scott Balneaves + * Copyright (C) 2010-2013 Scott Balneaves * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,701 +38,198 @@ #include #include -#include #include -#include #include -#include - #include +#include /* * PAM_SM_* define. */ #define PAM_SM_AUTH /* supports Authentication */ +#define PAM_SM_SESSION /* supports Session management */ #include +#include -/* - * Our defines - */ - -#define HOST "PAM_SSHAUTH_HOST" -#define PORT "PAM_SSHAUTH_PORT" - -#define SYSTEM_KNOWNHOSTS "/etc/ssh/ssh_known_hosts" -#define AUTHTRIES 3 /* Three chances to get password right */ +#include "pam_sshauth.h" /* * Globals. */ -static int debug; /* Debug flag */ -static int nostrict; /* nostrict flag */ -static int authtries; /* Number of times we'll try to authenticate */ -static int try_first_pass; /* Try to obtain auth token from pam stack */ +int psadebug; /* Debug flag */ +int nostrict; /* nostrict flag */ +int authtries = AUTHTRIES; /* Number of times we'll try to authenticate */ +int try_first_pass; /* Try to obtain auth token from pam stack */ +int askpass; /* Support shm_askpass */ /* - * Send a message through pam's conv stack. - * - * for PAM_TEXT_INFO, and PAM_ERROR_MSG messages. + * Authentication function */ -static int -send_pam_msg (pam_handle_t * pamh, int style, const char *format, ...) +PAM_EXTERN int +pam_sm_authenticate (pam_handle_t * pamh, int flags, int argc, + const char **argv) { - char msgbuf[BUFSIZ]; - const struct pam_message mymsg = - { - .msg_style = style, - .msg = msgbuf, - }; - - const struct pam_message *msgp = &mymsg; - const struct pam_conv *pc; - struct pam_response *resp; + const char *username; int pam_result; - va_list ap; + char *host = getenv (HOST); + char *port = getenv (PORT); + char *display = getenv ("DISPLAY"); + struct passwd *pwent; /* - * Start our varargs list, so we can format our message. + * Valid pam handle? */ - va_start (ap, format); - if (vsnprintf (msgbuf, sizeof msgbuf, format, ap) >= sizeof msgbuf) + if (pamh == NULL) { - /* - * Message was truncated. Make sure we're NULL terminated, - * and log an error. - */ - - msgbuf[(sizeof msgbuf) - 1] = '\0'; - pam_syslog (pamh, LOG_ERR, "send_pam_msg () truncated a message."); + return PAM_SYSTEM_ERR; } - va_end (ap); + /* + * Get the username. + */ - pam_result = pam_get_item (pamh, PAM_CONV, (const void **) &pc); + pam_result = pam_get_user (pamh, &username, NULL); if (pam_result != PAM_SUCCESS) { + pam_syslog (pamh, LOG_ERR, "Couldn't determine username."); return pam_result; } - if (!pc || !pc->conv) - { - return PAM_CONV_ERR; - } - - return pc->conv (1, &msgp, &resp, pc->appdata_ptr); -} - -/* - * auth_kbinit () - * - * conduct an ssh login based authentication - */ - -static int -auth_kbdint (pam_handle_t * pamh, ssh_session session) -{ - int ssh_result; - int i, n; - const char *message; - const char *prompt; - char *response; - char echo; - - ssh_result = ssh_userauth_kbdint (session, NULL, NULL); - - while (ssh_result == SSH_AUTH_INFO) - { - - /* - * Get any interactive prompts the ssh session has generted, - * and send them to the user via the pam message system. - */ - - message = ssh_userauth_kbdint_getinstruction (session); - n = ssh_userauth_kbdint_getnprompts (session); - if (message && *message != '\0') - { - send_pam_msg (pamh, PAM_TEXT_INFO, message); - } - - /* - * Loop through the prompts that ssh has given us, and ask the - * user via pam prompts for the answers. - */ - - for (i = 0; i < n; ++i) - { - prompt = ssh_userauth_kbdint_getprompt (session, i, &echo); - - if (pam_prompt (pamh, echo ? PAM_PROMPT_ECHO_ON : PAM_PROMPT_ECHO_OFF, &response, prompt) != PAM_SUCCESS) - { - return SSH_AUTH_ERROR; - } - - ssh_userauth_kbdint_setanswer (session, i, response); - } - - ssh_result = ssh_userauth_kbdint (session, NULL, NULL); - } - /* - * The very last response we've gotten should be the password. Store it - * as the AUTHTOK for stacking in other pam modules. + * Is it a system user? Succeed. */ - if (ssh_result == SSH_AUTH_SUCCESS) + pam_debug (pamh, "username %s", username); + + if ((pwent = getpwnam (username)) != NULL) { - if (pam_set_item (pamh, PAM_AUTHTOK, response) != PAM_SUCCESS) + if (pwent->pw_uid < UID_MIN) { - return SSH_AUTH_ERROR; + return PAM_SUCCESS; } } - return ssh_result; -} - -/* - * auth_pw () - * - * conduct an ssh simple password based authentication - */ - -static int -auth_pw (pam_handle_t * pamh, ssh_session session) -{ - int ssh_result; - const void *password = NULL; + pam_process_args (pamh, argc, argv, &host, &port); + pam_debug (pamh, "Authentication begins."); /* - * try_first_pass works with simple password authentication. + * Process the hostname */ - if (try_first_pass) - { - if (pam_get_item (pamh, PAM_AUTHTOK, &password) != PAM_SUCCESS) - { - pam_syslog (pamh, LOG_ERR, "Couldn't obtain PAM_AUTHTOK from the pam stack."); - password = NULL; - } - } - - if (password == NULL) + if ((pam_result = sshauth_pam_env (pamh, HOST, host, NOCLEANUP)) != PAM_SUCCESS) { - if (pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &password, "Password:") != PAM_SUCCESS) - { - pam_syslog (pamh, LOG_ERR, "Couldn't obtain password from pam_prompt."); - return SSH_AUTH_ERROR; - } + return pam_result; } - ssh_result = ssh_userauth_password (session, NULL, password); - if (ssh_result == SSH_AUTH_SUCCESS) - { - /* - * The very last response we've gotten should be the password. Store it - * as the AUTHTOK - */ - - if (!try_first_pass && pam_set_item (pamh, PAM_AUTHTOK, password) != PAM_SUCCESS) - { - pam_syslog (pamh, LOG_ERR, "Couldn't store password as PAM_AUTHTOK."); - return SSH_AUTH_ERROR; - } + /* + * Process the port + */ - return ssh_result; - } - else + if ((pam_result = sshauth_pam_env (pamh, PORT, port, NOCLEANUP)) != PAM_SUCCESS) { - send_pam_msg (pamh, PAM_TEXT_INFO, ssh_get_error (session)); - return ssh_result; + return pam_result; } -} - -/* - * do_sshauth () - * - * Authenticate by attempting an ssh connection - */ -static int -do_sshauth (pam_handle_t * pamh, const char *username) -{ - ssh_session session; - int method; - int ssh_result; - int pam_result; - char *response = NULL; - unsigned char *hash; - int count; - const char *host; - const char *port; + /* + * Process the DISPLAY. Set PAM_XDISPLAY if applicable. + */ - if (pam_get_data (pamh, HOST, (const void **) &host) != PAM_SUCCESS) + if ((pam_result = sshauth_pam_env (pamh, PAMXDISPLAY, display, NOCLEANUP)) != PAM_SUCCESS) { - pam_syslog (pamh, LOG_ERR, "Couldn't retrieve hostname from pam handle."); - return PAM_SYSTEM_ERR; + return pam_result; } - if (pam_get_data (pamh, PORT, (const void **) &port) != PAM_SUCCESS) + /* + * Create our temp dir. + */ + + pam_result = create_sshauthdir (pamh, username); + if (pam_result != PAM_SUCCESS) { - /* Couldn't retrieve port. Fallback to NULL */ - port = NULL; + pam_syslog (pamh, LOG_ERR, "Couldn't create sshauthdir."); + return pam_result; } /* - * Begin the authentication loop. Loop until we're successfully - * authenticated, or AUTHTRIES times, whichever comes first. + * Perform the authentication. */ - count = authtries; + pam_result = do_sshauth (pamh, username); - do + pam_debug (pamh, "Authentication finished."); + if (pam_result == PAM_SUCCESS && askpass > 0) { - session = ssh_new (); - - if (!session) - { - pam_syslog (pamh, LOG_ERR, "Couldn't allocate ssh session structure for host %s", host); - return PAM_SYSTEM_ERR; - } - - ssh_options_set (session, SSH_OPTIONS_USER, username); - ssh_options_set (session, SSH_OPTIONS_HOST, host); -#ifdef SSH_OPTIONS_STRICTHOSTKEYCHECK - if (nostrict) - { - ssh_options_set (session, SSH_OPTIONS_STRICTHOSTKEYCHECK, 0); - } - else - { - ssh_options_set (session, SSH_OPTIONS_STRICTHOSTKEYCHECK, 1); - } -#endif - - if (port) - { - ssh_options_set (session, SSH_OPTIONS_PORT_STR, port); - } - - if (ssh_connect (session) != SSH_OK) - { - pam_syslog (pamh, LOG_ERR, "Couldn't contact host %s", host); - return PAM_SYSTEM_ERR; - } - - /* - * Is this server known to us? Try our /etc/ssh/ssh_known_hosts file - * first. - */ - - ssh_options_set (session, SSH_OPTIONS_KNOWNHOSTS, SYSTEM_KNOWNHOSTS); - ssh_result = ssh_is_server_known (session); - - if (ssh_result != SSH_SERVER_KNOWN_OK) - { - /* - * Re-try with the user's ~/.ssh/known_hosts - */ - - ssh_options_set (session, SSH_OPTIONS_KNOWNHOSTS, NULL); - ssh_result = ssh_is_server_known (session); - - if ((ssh_result == SSH_SERVER_NOT_KNOWN) && nostrict) - { - /* - * Unknown server. Ask the user, via the pam prompts, if they'd - * like to connect. - */ - send_pam_msg (pamh, PAM_TEXT_INFO, - "Server unknown. Trust?"); - ssh_get_pubkey_hash (session, &hash); - pam_prompt (pamh, PAM_PROMPT_ECHO_ON, &response, - "Type 'yes' to continue: "); - if (strncasecmp (response, "yes", 3) != 0) - { - ssh_disconnect (session); - ssh_free (session); - return PAM_SYSTEM_ERR; - } - - send_pam_msg (pamh, PAM_TEXT_INFO, - "Save in known_hosts?"); - pam_prompt (pamh, PAM_PROMPT_ECHO_ON, &response, - "Type 'yes' to continue: "); - if (strncasecmp (response, "yes", 3) == 0) - { - if (ssh_write_knownhost (session)) - { - ssh_disconnect (session); - ssh_free (session); - return PAM_SYSTEM_ERR; - } - } - } - else if ((ssh_result == SSH_SERVER_NOT_KNOWN) && !nostrict) - { - send_pam_msg (pamh, PAM_TEXT_INFO, - "Server is unknown, and strict checking enabled. Connection denied."); - ssh_disconnect (session); - ssh_free (session); - return PAM_SYSTEM_ERR; - } - else if (ssh_result == SSH_SERVER_ERROR) - { - pam_syslog (pamh, LOG_ERR, - "ssh_is_server_known() returned an error for %s.", - host); - send_pam_msg (pamh, PAM_TEXT_INFO, "Error connecting to server."); - ssh_disconnect (session); - ssh_free (session); - return PAM_SYSTEM_ERR; - } - else if (ssh_result == SSH_SERVER_KNOWN_CHANGED) - { - pam_syslog (pamh, LOG_ERR, "Host key for %s changed.", host); - send_pam_msg (pamh, PAM_TEXT_INFO, - "Server's host key has changed."); - send_pam_msg (pamh, PAM_TEXT_INFO, - "Possible man-in-the-middle attack. Connection terminated."); - ssh_disconnect (session); - ssh_free (session); - return PAM_SYSTEM_ERR; - } - else if (ssh_result == SSH_SERVER_FOUND_OTHER) - { - send_pam_msg (pamh, PAM_TEXT_INFO, - "Server's host key was different from expected."); - send_pam_msg (pamh, PAM_TEXT_INFO, - "Possible attack. Connection terminated."); - ssh_disconnect (session); - ssh_free (session); - return PAM_SYSTEM_ERR; - } - } - - /* - * Try ssh_userauth none first. This will initiate the authentication - * system, so we can determine a list of methods the server supports. - */ - - ssh_result = ssh_userauth_none (session, NULL); - if (ssh_result == SSH_AUTH_ERROR) - { - pam_syslog (pamh, LOG_ERR, "ssh_userauth_none() returned %s", - ssh_get_error (session)); - ssh_disconnect (session); - ssh_free (session); - return PAM_AUTH_ERR; - } - - /* - * Find out what methods the ssh server supports for authentication. - */ - - method = ssh_auth_list (session); - - /* - * List auth methods that have been returned. - */ - - if (method == SSH_AUTH_METHOD_UNKNOWN && debug) - { - pam_syslog (pamh, LOG_INFO, "Auth method UNKNOWN."); - } - if (method & SSH_AUTH_METHOD_NONE && debug) - { - pam_syslog (pamh, LOG_INFO, "Server supports auth method NONE."); - } - if (method & SSH_AUTH_METHOD_PASSWORD && debug) - { - pam_syslog (pamh, LOG_INFO, - "Server supports auth method PASSWORD."); - } - if (method & SSH_AUTH_METHOD_HOSTBASED && debug) - { - pam_syslog (pamh, LOG_INFO, - "Server supports auth method HOSTBASED."); - } - if (method & SSH_AUTH_METHOD_INTERACTIVE && debug) - { - pam_syslog (pamh, LOG_INFO, - "Server supports auth method INTERACTIVE."); - } - if (method & SSH_AUTH_METHOD_PUBLICKEY && debug) - { - pam_syslog (pamh, LOG_INFO, - "Server supports auth method PUBLICKEY."); - } - - - /* - * Authenticate depending on the method available. - * Try public key first. - */ - - if (method & SSH_AUTH_METHOD_PUBLICKEY) - { - if (debug) - { - pam_syslog (pamh, LOG_INFO, - "Trying public key authentication."); - } - ssh_result = ssh_userauth_autopubkey (session, NULL); - if (ssh_result == SSH_AUTH_SUCCESS) - { - ssh_disconnect (session); - ssh_free (session); - break; - } - } - - /* - * Try keyboard interactive next, if supported. - */ - - if (method & SSH_AUTH_METHOD_INTERACTIVE) - { - /* - * SSH_AUTH_METHOD_INTERACTIVE requires - * ChallengeResponseAuthentication to be set to "yes" - * in /etc/ssh/sshd_config. - */ - if (debug) - { - pam_syslog (pamh, LOG_INFO, - "Trying keyboard interactive authentication."); - } - ssh_result = auth_kbdint (pamh, session); - if (ssh_result == SSH_AUTH_SUCCESS) - { - ssh_disconnect (session); - ssh_free (session); - break; - } - } - - /* - * Finally, plain password authentication. - */ - - if (method & SSH_AUTH_METHOD_PASSWORD) - { - /* - * SSH_AUTH_METHOD_PASSWORD is simpler, and - * won't handle password expiry. - */ - if (debug) - { - pam_syslog (pamh, LOG_INFO, - "Trying simple password authentication."); - } - ssh_result = auth_pw (pamh, session); - if (ssh_result == SSH_AUTH_SUCCESS) - { - ssh_disconnect (session); - ssh_free (session); - break; - } - } - - count--; - - if (ssh_result == SSH_AUTH_ERROR) - { - pam_syslog (pamh, LOG_ERR, "auth_pw returned %s.", - ssh_get_error (session)); - } - - ssh_disconnect (session); - ssh_free (session); + pam_debug (pamh, "Handling shm_askpass support."); + pam_result = askpass_create (pamh); } - while (count); - if (ssh_result == SSH_AUTH_SUCCESS) - { - if (debug) - { - pam_syslog (pamh, LOG_INFO, "Authenticated successfully."); - } + return pam_result; +} - return PAM_SUCCESS; - } - else - { - if (debug) - { - pam_syslog (pamh, LOG_INFO, "Authentication failed."); - } - return PAM_AUTH_ERR; - } +PAM_EXTERN int +pam_sm_setcred (pam_handle_t * pamh, int flags, int argc, const char **argv) +{ + return PAM_SUCCESS; } -/* - * Authentication function - */ +PAM_EXTERN int +pam_sm_open_session (pam_handle_t * pamh, int flags, int argc, const char **argv) +{ + return PAM_SUCCESS; +} PAM_EXTERN int -pam_sm_authenticate (pam_handle_t * pamh, int flags, int argc, - const char **argv) +pam_sm_close_session (pam_handle_t * pamh, int flags, int argc, const char **argv) { - const char *username; int pam_result; - char *host; - char *port; - - authtries = AUTHTRIES; /* default number of authtries unless passed */ - host = getenv (HOST); - port = getenv (PORT); - - for (; argc-- > 0; ++argv) - { - if (!strncmp (*argv, "debug", 5)) - { - debug++; - } - - if (!strncmp (*argv, "authtries", 9)) - { - authtries = atoi ((char *)(*argv + 10)); /* authtries=x */ - } - - if (!strncmp (*argv, "host", 4)) - { - host = (char *)(*argv + 5); /* host=foo.bar.com */ - } - - if (!strncmp (*argv, "port", 4)) - { - port = (char *)(*argv + 5); /* port=x */ - } - - if (!strncmp (*argv, "nostrict", 8)) - { - nostrict++; - } - - if (!strncmp (*argv, "try_first_pass", 14)) - { - try_first_pass++; - } - } + const char *username; + struct passwd *pwent; + char *host, *port; /* - * Process the hostname + * Valid pam handle? */ - if (host && *host != '\0') - { - char host_env[BUFSIZ]; - - if (pam_set_data(pamh, HOST, host, NULL) != PAM_SUCCESS) - { - pam_syslog (pamh, LOG_ERR, "Couldn't store hostname in pam handle."); - return PAM_SYSTEM_ERR; - } - - /* - * Export host as pam environment variable for scripts to use. - */ - - if (snprintf(host_env, sizeof host_env, HOST "=%s", host) >= sizeof host_env) - { - pam_syslog (pamh, LOG_ERR, "Hostname truncated due to size."); - return PAM_SYSTEM_ERR; - } - - if (pam_putenv(pamh, host_env) != PAM_SUCCESS) - { - pam_syslog (pamh, LOG_ERR, "Could not set " HOST " in pam environment."); - return PAM_SYSTEM_ERR; - } - } - else + if (pamh == NULL) { - pam_syslog (pamh, LOG_ERR, "No valid hostname specified."); return PAM_SYSTEM_ERR; } /* - * Process the hostname - */ - - if (port && *port != '\0') - { - char port_env[BUFSIZ]; - - if (pam_set_data (pamh, PORT, port, NULL) != PAM_SUCCESS) - { - pam_syslog (pamh, LOG_ERR, "Couldn't store port in pam handle."); - return PAM_SYSTEM_ERR; - } - - /* - * Export port as pam environment variable for scripts to use. - */ - - if (snprintf (port_env, sizeof port_env, PORT "=%s", port) >= sizeof port_env) - { - pam_syslog (pamh, LOG_ERR, "port truncated due to size."); - return PAM_SYSTEM_ERR; - } - - if (pam_putenv (pamh, port_env) != PAM_SUCCESS) - { - pam_syslog (pamh, LOG_ERR, "Could not set " PORT " in pam environment."); - return PAM_SYSTEM_ERR; - } - } - - if (debug) - { - pam_syslog (pamh, LOG_INFO, "Beginning authentication."); - } - - if (debug) - { - if (host) - { - pam_syslog (pamh, LOG_INFO, "Host provided on command line: %s", host); - } - - if (port) - { - pam_syslog (pamh, LOG_INFO, "Port provided on command line: %s", port); - } - } - - /* * Get the username. */ - if (pam_get_user (pamh, &username, NULL) != PAM_SUCCESS) + pam_result = pam_get_user (pamh, &username, NULL); + if (pam_result != PAM_SUCCESS) { pam_syslog (pamh, LOG_ERR, "Couldn't determine username."); - return PAM_AUTHINFO_UNAVAIL; + return pam_result; } /* - * Perform the authentication. + * Is it a system user? Succeed. */ - pam_result = do_sshauth (pamh, username); - if (debug) + if ((pwent = getpwnam (username)) != NULL) { - pam_syslog (pamh, LOG_INFO, "Authentication finished."); + if (pwent->pw_uid < UID_MIN) + { + return PAM_SUCCESS; + } } - return pam_result; -} + pam_process_args (pamh, argc, argv, &host, &port); + + if (askpass) + { + return askpass_remove (pamh); + } -PAM_EXTERN int -pam_sm_setcred (pam_handle_t * pamh, int flags, int argc, const char **argv) -{ return PAM_SUCCESS; } diff -Nru libpam-sshauth-0.1/src/pam_sshauth.h libpam-sshauth-0.3.1/src/pam_sshauth.h --- libpam-sshauth-0.1/src/pam_sshauth.h 1970-01-01 00:00:00.000000000 +0000 +++ libpam-sshauth-0.3.1/src/pam_sshauth.h 2013-07-04 18:17:23.000000000 +0000 @@ -0,0 +1,60 @@ +/* + * pam_sshauth: PAM module for authentication via a remote ssh server. + * Copyright (C) 2010 Scott Balneaves + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#define HOST "PAM_SSHAUTH_HOST" +#define PORT "PAM_SSHAUTH_PORT" +#define SSHAUTHDIR "PAM_SSHAUTH_DIR" +#define PAMXDISPLAY "PAM_XDISPLAY" +#define NOCLEANUP 0 +#define CLEANUP 1 +#define UID_MIN 500 + +#define SSH_AUTH_METHOD_PASSWORD 1 +#define SSH_AUTH_METHOD_INTERACTIVE 2 +#define SSH_AUTH_METHOD_PUBLICKEY 4 + +#define SSH_AUTH_SUCCESS 0 +#define SSH_AUTH_ERROR 1 + +#define SYSTEM_KNOWNHOSTS "/etc/ssh/ssh_known_hosts" +#define AUTHTRIES 3 /* Three chances to get password right */ + +/* + * Globals. + */ + +extern int psadebug; /* Debug flag */ +extern int nostrict; /* nostrict flag */ +extern int authtries; /* Number of times we'll try to authenticate */ +extern int try_first_pass; /* Try to obtain auth token from pam stack */ +extern int askpass; /* Support shm_askpass */ + +/* + * Prototypes + */ + +void cleanup (pam_handle_t * pamh, void * data, int error_status); +void pam_debug (pam_handle_t * pamh, const char *format, ...); +int send_pam_msg (pam_handle_t * pamh, int style, const char *format, ...); +void pam_process_args (pam_handle_t * pamh, int argc, const char **argv, char **host, char **port); +int sshauth_pam_env (pam_handle_t * pamh, char *envname, char *envvalue, int cleanup); +int do_sshauth (pam_handle_t * pamh, const char *username); +int create_sshauthdir (pam_handle_t * pamh, const char *username); +int askpass_create (pam_handle_t * pamh); +int askpass_remove (pam_handle_t * pamh); diff -Nru libpam-sshauth-0.1/src/pam_util.c libpam-sshauth-0.3.1/src/pam_util.c --- libpam-sshauth-0.1/src/pam_util.c 1970-01-01 00:00:00.000000000 +0000 +++ libpam-sshauth-0.3.1/src/pam_util.c 2013-07-04 18:17:23.000000000 +0000 @@ -0,0 +1,228 @@ +/* + * pam_sshauth: PAM module for authentication via a remote ssh server. + * Copyright (C) 2010-2013 Scott Balneaves + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pam_sshauth.h" + +/* + * pam_cleanup + * + * String cleanup function. + */ + +void +pam_cleanup (pam_handle_t * pamh, void * data, int error_status) +{ + free (data); +} + +/* + * pam_debug + * + * Log a message if debug active. + */ + +void +pam_debug (pam_handle_t * pamh, const char *format, ...) +{ + char msgbuf[BUFSIZ]; + va_list ap; + + if (psadebug) + { + va_start (ap, format); + if (vsnprintf (msgbuf, sizeof msgbuf, format, ap) >= sizeof msgbuf) + { + /* + * Message was truncated. Make sure we're NULL terminated + */ + + msgbuf[(sizeof msgbuf) - 1] = '\0'; + } + pam_syslog (pamh, LOG_INFO, "%s", msgbuf); + va_end (ap); + } +} + + +/* + * Send a message through pam's conv stack. + * + * for PAM_TEXT_INFO, and PAM_ERROR_MSG messages. + */ + +int +send_pam_msg (pam_handle_t * pamh, int style, const char *format, ...) +{ + char msgbuf[BUFSIZ]; + const struct pam_message mymsg = + { + .msg_style = style, + .msg = msgbuf, + }; + + const struct pam_message *msgp = &mymsg; + const struct pam_conv *pc; + struct pam_response *resp; + int pam_result; + va_list ap; + + /* + * Start our varargs list, so we can format our message. + */ + + va_start (ap, format); + if (vsnprintf (msgbuf, sizeof msgbuf, format, ap) >= sizeof msgbuf) + { + /* + * Message was truncated. Make sure we're NULL terminated, + * and log an error. + */ + + msgbuf[(sizeof msgbuf) - 1] = '\0'; + pam_syslog (pamh, LOG_ERR, "send_pam_msg () truncated a message."); + } + + va_end (ap); + + pam_result = pam_get_item (pamh, PAM_CONV, (const void **) &pc); + if (pam_result != PAM_SUCCESS) + { + return pam_result; + } + + if (!pc || !pc->conv) + { + return PAM_CONV_ERR; + } + + return pc->conv (1, &msgp, &resp, pc->appdata_ptr); +} + +/* + * pam_process_args + * + * Process pam module command line arguments, and set global flags. + */ + +void +pam_process_args (pam_handle_t * pamh, int argc, const char **argv, char **host, char **port) +{ + int i; + psadebug = 0; + nostrict = 0; + askpass = 0; + try_first_pass = 0; + for (i = 0; i < argc; i++) + { + if (!strcmp (argv[i], "debug")) + { + psadebug++; + } + else if (!strcmp (argv[i], "nostrict")) + { + nostrict++; + } + else if (!strcmp (argv[i], "shm_askpass")) + { + askpass++; + } + else if (!strcmp (argv[i], "try_first_pass")) + { + try_first_pass++; + } + else if (!strncmp (argv[i], "authtries=", 10)) + { + authtries = atoi ((char *)(argv[i] + 10)); /* authtries=x */ + } + else if (!strncmp (argv[i], "host=", 5)) + { + *host = (char *)(argv[i] + 5); /* host=foo.bar.com */ + } + else if (!strncmp (argv[i], "port=", 5)) + { + *port = (char *)(argv[i] + 5); /* port=x */ + } + } +} + +int +sshauth_pam_env (pam_handle_t * pamh, char *envname, char *envvalue, int cleanup) +{ + /* + * Process the var + */ + + if (envvalue && *envvalue != '\0') + { + char *new_env; + size_t len; + int pam_result; + + if (cleanup) + { + pam_result = pam_set_data (pamh, envname, envvalue, pam_cleanup); + } + else + { + pam_result = pam_set_data (pamh, envname, envvalue, NULL); + } + + if (pam_result != PAM_SUCCESS) + { + pam_syslog (pamh, LOG_ERR, "Couldn't store %s in pam handle.", envname); + return pam_result; + } + + /* + * Export envname as pam environment variable for scripts to use. + */ + + len = strlen (envname) + strlen (envvalue) + 2; /* Length of env name + value + 2 for =, NULL */ + if ((new_env = (char *) malloc (len)) == NULL) + { + pam_syslog (pamh, LOG_ERR, "Could not allocate memory for %s variable.", envname); + return PAM_BUF_ERR; + } + + snprintf (new_env, len, "%s=%s", envname, envvalue); + pam_result = pam_putenv (pamh, new_env); + free (new_env); + + if (pam_result != PAM_SUCCESS) + { + pam_syslog (pamh, LOG_ERR, "Could not set %s in pam environment.", envname); + } + + return pam_result; + } + else + { + return PAM_SUCCESS; + } +} diff -Nru libpam-sshauth-0.1/src/sess_funcs.c libpam-sshauth-0.3.1/src/sess_funcs.c --- libpam-sshauth-0.1/src/sess_funcs.c 1970-01-01 00:00:00.000000000 +0000 +++ libpam-sshauth-0.3.1/src/sess_funcs.c 2013-07-04 18:17:23.000000000 +0000 @@ -0,0 +1,133 @@ +/* + * pam_sshauth: PAM module for authentication via a remote ssh server. + * Copyright (C) 2010-2013 Scott Balneaves + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pam_sshauth.h" + +/* + * create_sshauthdir + * + */ + +int +create_sshauthdir (pam_handle_t * pamh, const char *username) +{ + char *dirname; + + if (asprintf (&dirname, "/tmp/%s.XXXXXX", username) < 0) + { + pam_syslog (pamh, LOG_ERR, "Couldn't allocate space to store authdir name"); + return PAM_BUF_ERR; + } + + if (mkdtemp (dirname) == NULL) + { + pam_syslog (pamh, LOG_ERR, "Couldn't generate unique store authdir name"); + return PAM_BUF_ERR; + } + + return sshauth_pam_env (pamh, SSHAUTHDIR, dirname, CLEANUP); +} + +/* + * askpass_create + * + * Create the secure password file needed by the shm_askpass utility. + */ + +int +askpass_create (pam_handle_t * pamh) +{ + char *password; + char *authdir; + char pw_filename[BUFSIZ]; + int pam_result; + int f; + + pam_result = pam_get_data (pamh, SSHAUTHDIR, (const void **)&authdir); + if (pam_result != PAM_SUCCESS) + { + pam_syslog (pamh, LOG_ERR, "Couldn't obtain authdir name from the pam stack."); + return pam_result; + } + + sprintf (pw_filename, "%s/.passwd", authdir); + + pam_result = pam_get_item (pamh, PAM_AUTHTOK, (const void **)&password); + if (pam_result != PAM_SUCCESS) + { + pam_syslog (pamh, LOG_ERR, "Couldn't obtain PAM_AUTHTOK from the pam stack."); + return pam_result; + } + + if ((f = creat (pw_filename, S_IRUSR | S_IWUSR)) < 0) + { + pam_syslog (pamh, LOG_ERR, "Couldn't create tmpfile"); + return PAM_SYSTEM_ERR; + } + + write (f, password, strlen (password)); + close (f); + + return PAM_SUCCESS; +} + +/* + * askpass_remove + * + * Remove the password file needed by shm_askpass + */ + +int +askpass_remove (pam_handle_t * pamh) +{ + char *authdir; + char pw_filename[BUFSIZ]; + int pam_result; + + pam_result = pam_get_data (pamh, SSHAUTHDIR, (const void **)&authdir); + if (pam_result != PAM_SUCCESS) + { + pam_syslog (pamh, LOG_ERR, "Couldn't obtain authdir name from the pam stack."); + return pam_result; + } + + sprintf (pw_filename, "%s/.passwd", authdir); + + if (unlink (pw_filename) < 0) + { + pam_debug (pamh, "tmpfile already removed."); + } + + return PAM_SUCCESS; +} diff -Nru libpam-sshauth-0.1/src/shm_askpass.c libpam-sshauth-0.3.1/src/shm_askpass.c --- libpam-sshauth-0.1/src/shm_askpass.c 2011-10-28 22:04:37.000000000 +0000 +++ libpam-sshauth-0.3.1/src/shm_askpass.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,256 +0,0 @@ -/* - * shm_askpass: SSH-ASKPASS helper using shared POSIX shared memory. - * Copyright (C) 2011 Scott Balneaves - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DEFAULTPATH "/shm_askpass" -#define PWSIZE BUFSIZ - -void -cleanup (void) -{ - closelog(); -} - -void -shm_read (char *path) -{ - int fd; - char *ptr; - - if ((fd = shm_open (path, O_RDONLY, S_IREAD)) < 0) - { - int errsv = errno; - syslog (LOG_ERR, "shm_open() of %s failed: %s", path, strerror (errsv)); - exit (1); - } - - if ((ptr = (char *) mmap (NULL, PWSIZE, PROT_READ, - MAP_SHARED, fd, 0)) == MAP_FAILED) - { - int errsv = errno; - syslog (LOG_ERR, "mmap of %s failed: %s", path, strerror (errsv)); - exit (1); - } - - printf ("%s\n", ptr); - - close (fd); - - if (getuid () != 0) - { - if (shm_unlink (path) < 0) - { - int errsv = errno; - syslog (LOG_ERR, "shm_unlink of of %s failed: %s", path, strerror (errsv)); - exit (1); - } - } -} - -void -shm_write (char *path) -{ - char *ptr; - struct passwd *pwd; - char *uname; - int fd; - - if ((uname = getenv ("PAM_USER")) == NULL) - { - syslog (LOG_ERR, "No PAM_USER environment variable"); - exit (1); - } - - if ((pwd = getpwnam (uname)) == NULL) - { - int errsv = errno; - syslog (LOG_ERR, "No user %s found: %s", uname, strerror (errsv)); - exit (1); - } - - if ((fd = shm_open (path, (O_CREAT | O_EXCL | O_RDWR), - (S_IREAD | S_IWRITE))) < 0) - { - int errsv = errno; - syslog (LOG_ERR, "shm_open() of %s failed: %s", path, strerror (errsv)); - exit (1); - } - - if (fchown (fd, pwd->pw_uid, pwd->pw_gid) < 0) - { - int errsv = errno; - syslog (LOG_ERR, "fchown failed: %s", strerror (errsv)); - exit (1); - } - - if (ftruncate (fd, PWSIZE) < 0) - { - int errsv = errno; - syslog (LOG_ERR, "ftruncate failed: %s", strerror (errsv)); - exit (1); - } - - if ((ptr = (char *) mmap (0, PWSIZE, (PROT_READ | PROT_WRITE), - MAP_SHARED, fd, 0)) == MAP_FAILED) - { - int errsv = errno; - syslog (LOG_ERR, "mmap of %s failed: %s", path, strerror (errsv)); - exit (1); - } - - bzero (ptr, PWSIZE); - - if (read (STDIN_FILENO, ptr, (PWSIZE - 1)) < 0) - { - int errsv = errno; - syslog (LOG_ERR, "read from stdin failed: %s", strerror (errsv)); - exit (1); - } - - close (fd); -} - -void -shm_delete (char *path) -{ - if (shm_unlink (path) != 0) - { - int errsv = errno; - syslog (LOG_ERR, "shm_unlink of of %s failed: %s", path, strerror (errsv)); - exit (1); - } -} - -void -usage () -{ - fprintf (stderr, -"shm_askpass - An SSH-ASKPASS compliant helper using POSIX shared memory.\n" -" Requires that the PAM_USER environment variable be set,\n" -" see manpage for details.\n" -"\n" -"USAGE:\n" -"shm_askpass --write - Reads password from stdin, stores as user ${PAM_USER}\n" -" --delete - Deletes the shared memory segment\n" -" --help - This message\n" -" - with no options returns the stored password. If run\n" -" as root, password is kept. If run as a non-root id,\n" -" password is wiped from memory and removed.\n" - ); - exit (0); -} - -int -main (int argc, char **argv) -{ - char *path = getenv ("SHM_ASKPASS_PATH"); - - /* - * Open log - */ - - openlog (argv[0], LOG_NDELAY | LOG_PID, LOG_AUTHPRIV); - - /* - * Register exit funtion to close log on exit. - */ - - if (atexit (cleanup) != 0) - { - fprintf (stderr, "Couldn't register exit handler\n"); - exit (1); - } - - /* - * If a path has been set, make sure it starts with a '/' - */ - - if (path && *path != '/') - { - syslog (LOG_ERR, "SHM_ASKPASS_PATH must start with a '/'"); - exit (1); - } - - /* - * handle command line - */ - - while (1) - { - static struct option long_options[] = { - { - "help", no_argument, NULL, 'h'}, - { - "write", no_argument, NULL, 'w'}, - { - "delete", no_argument, NULL, 'd'}, - { - NULL, 0, NULL, 0} - }; - /* getopt_long stores the option - * index here. */ - int option_index = 0; - int c; - - c = getopt_long (argc, argv, "hwd", long_options, &option_index); - - if (c == -1) - { - break; - } - - switch (c) - { - case 'h': - usage (); - exit (0); - - case 'w': - shm_write (path ? path : DEFAULTPATH); - exit (0); - - case 'd': - shm_delete (path ? path : DEFAULTPATH); - exit (0); - - case '?': - usage (); - exit (0); - - default: - usage (); - exit (0); - } - } - - shm_read (path ? path : DEFAULTPATH); - exit (0); -} diff -Nru libpam-sshauth-0.1/src/waitfor.c libpam-sshauth-0.3.1/src/waitfor.c --- libpam-sshauth-0.1/src/waitfor.c 1970-01-01 00:00:00.000000000 +0000 +++ libpam-sshauth-0.3.1/src/waitfor.c 2013-07-04 18:17:23.000000000 +0000 @@ -0,0 +1,89 @@ +/* + * waitfor: small shell helper for waiting for files to appear. + * Copyright (C) 2013 Scott Balneaves + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include + +/* + * waitfor + * + * Simple program to check for a file either appearing, or disappeating, every + * .2 seconds. Optional timeout. returns 1 if timeout, 0 if waited for event + * happened. + * + * No timeout specified = wait indefinitely. + */ + +int +main (int argc, char **argv) +{ + int exist = 1; + int timeout = 0; + const char *path; + struct stat statbuf; + int c; + int st; + int count; + + opterr = 0; + + while ((c = getopt (argc, argv, "nt:")) != -1) + switch (c) + { + case 'n': + exist = 0; + break; + case 't': + timeout = atoi (optarg); + break; + default: + exit (1); + } + + path = argv[optind]; + + timeout *= 5; + + for (count = 0; count <= timeout;) + { + st = stat (path, &statbuf); + + if (exist && st == 0) + { + return 0; + } + + if (!exist && st < 0) + { + return 0; + } + + usleep (200000); + if (timeout) + { + count++; + } + } + + return 1; +}